I have a SQL Server table-valued function which is created by me I have pasted the create script below
CREATE FUNCTION [dbo].[getTableFromString]
(
#String AS nvarchar(max)
)
RETURNS #ReturnTable TABLE ( StringValues nvarchar(10) )
AS begin
if (SELECT CHARINDEX(',', #String)) = 0
begin
insert into #ReturnTable (StringValues) values (subString(#String,1,len(#String)));
end
else
begin
while (SELECT CHARINDEX(',', #String)) > 0
begin
insert into #ReturnTable (StringValues) values (subString(#String,1,CHARINDEX(',', #String)-1));
set #String = subString(#String,CHARINDEX(',', #String)+1,len(#String));
if (SELECT CHARINDEX(',', #String)) = 0
begin
insert into #ReturnTable (StringValues) values (subString(#String,1,len(#String)));
end
end
end
return ;
end
and I am using this function like below
Select sum(NetSales)
from vwxsalesall
where Company = 'rs'
and storecode = (select cPrimaryStockRoomCode from CompanyMaster.CompanyProfileDetail where cCompanyNo = 'rs' and cSecondaryStockRoomCode = 'R01B')
and trandate >= '2012-01-01'
and trandate <= '2012-01-31'
and (
brand in (
select StringValues from dbo.getTableFromString(
select vIncludedBrandCodes
from StockRoomTargetData.MonthlyTarget
where cCompanyNo = 'rs'
and cSecondaryStockRoomCode = 'R01B'
and nYear = 2012
and nMonth = 8
)
)
)
Unfortunately I am getting this error
Msg 156, Level 15, State 1, Line 10
Incorrect syntax near the keyword 'select'.
Msg 102, Level 15, State 1, Line 16
Incorrect syntax near ')'.
please help me
You need to add another set of parenthesis around subquery, for instance
select StringValues from dbo.getTableFromString(( { your-subquery }))
^ ^
(parenthesis added)
First set of parenthessis syntactically belong to TVF invocation, and second denote a subquery.
And now your query:
Select sum(NetSales)
from vwxsalesall
where Company = 'rs'
and storecode = (select cPrimaryStockRoomCode from CompanyMaster.CompanyProfileDetail where cCompanyNo = 'rs' and cSecondaryStockRoomCode = 'R01B')
and trandate >= '2012-01-01'
and trandate <= '2012-01-31'
and (
brand in (
select StringValues from dbo.getTableFromString((
select vIncludedBrandCodes
from StockRoomTargetData.MonthlyTarget
where cCompanyNo = 'rs'
and cSecondaryStockRoomCode = 'R01B'
and nYear = 2012
and nMonth = 8
))
)
)
Related
sql server 2012
i have created a SP to create view dynamically with Parameter i supplied.
below is the code
i am not sure why i am getting the below error.
Msg 102, Level 15, State 1, Procedure uspCreateView, Line 10
Incorrect syntax near '#VIEWNM'.
Code:
CREATE PROCEDURE uspCreateView
#VIEWNM VARCHAR(50),
#COMP INT,
#TODT DATE = 9999-12-31
AS
EXEC ('
CREATE VIEW +'#VIEWNM'
AS
(
SELECT
COL1,
COL2,
COL3,
DATE,
SKU,
CASE WHEN IsRowCurrent = 1 THEN '#TODT' ELSE dateadd(MILLISECOND, -1000 - datepart(MILLISECOND, FMDT), FMDT) END AS TODT,
FROM MYTABLE mt
OUTER APPLY ( SELECT MAX(DATEADD(second, -1, FMDT)) TO_DATE
FROM MYTABLE mt2
WHERE mt2.COL1 = mt.COL1
AND mt2.COL2 = mt.COL2
AND mt2.FMDT > mt.FMDT
AND mt.COL3 = '#COMPID' ) oa
WHERE mt.COL3 = '#COMPID'
)
please help me to fix the below error.
Thanks
I am not sure, why you want to create views dynamically, ideally views should be created before hand only, and you will be required to fetch the data depending on the condition.
Still if you want to proceed, you should do it proper way to avoid any issues. I can see there are issues with your implementation. Ideally you should make it parameterized, like following sample query to avoid any SQL injection.
There are issues with your provided code also, I tried to fix some of these.
CREATE PROCEDURE uspCreateView
(
#VIEWNM VARCHAR(50),
#COMP INT,
#TODT DATE = '9999-12-31'
)
AS
BEGIN
DECLARE #Query NVARCHAR(MAX)
DECLARE #ParmDefinition nvarchar(MAX);
SET #Query = N'CREATE VIEW #VIEWNM_I AS ( SELECT COL1, COL2, COL3, DATE, SKU,
CASE WHEN IsRowCurrent = 1 THEN #TODT_I ELSE
dateadd(MILLISECOND, -1000 - datepart(MILLISECOND, FMDT)
, FMDT) END AS TODT, FROM MYTABLE mt OUTER APPLY (
SELECT MAX(DATEADD(second, -1, FMDT)) TO_DATE
FROM MYTABLE mt2
WHERE mt2.COL1 = mt.COL1
AND mt2.COL2 = mt.COL2
AND mt2.FMDT > mt.FMDT
AND mt.COL3 = #COMPID_I ) oa
WHERE mt.COL3 = #COMPID_I)'
SET #ParmDefinition = N'#VIEWNM VARCHAR(100),#TODT_I DATETIME,#COMP_I INT';
EXECUTE sp_executesql #Query,#ParmDefinition, #VIEWNM_I=#VIEWNM, #COMP_I=#COMP, #TODT_I=#TODT
END
Try this
Command(s) completed successfully.
CREATE PROCEDURE uspCreateView
#VIEWNM VARCHAR(50),
#COMP INT,
#TODT DATE = '9999-12-31'
AS
EXEC ('
CREATE VIEW '+#VIEWNM+'
AS
(
SELECT
COL1,
COL2,
COL3,
DATE,
SKU,
CASE WHEN IsRowCurrent = 1 THEN '+#TODT+' ELSE dateadd(MILLISECOND, -1000 - datepart(MILLISECOND, FMDT), FMDT) END AS TODT,
FROM MYTABLE mt
OUTER APPLY ( SELECT MAX(DATEADD(second, -1, FMDT)) TO_DATE
FROM MYTABLE mt2
WHERE mt2.COL1 = mt.COL1
AND mt2.COL2 = mt.COL2
AND mt2.FMDT > mt.FMDT
AND mt.COL3 = '+#COMP+' ) oa
WHERE mt.COL3 = '+#COMP+'
) ')
It should be
CREATE VIEW ' + #VIEWNM + ' AS...
I want to query a comma-separated list of values. But I get an error:
SELECT
nCmpID, cCompanyName
FROM
(SELECT *
FROM tbl_CompanyMaster
WHERE nCmpID IN (SELECT *
FROM dbo.fnsplit((SELECT can_AccessCompanyID
FROM tbl_UserMenuRelations
WHERE nUserID = 0
AND Is_Active = 1
AND Is_Available = 1), ',') a)
AND Is_Active = 1) t
My function FNSplit:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER FUNCTION [dbo].[fnSplit]
(#sInputList VARCHAR(8000), -- List of delimited items
#sDelimiter VARCHAR(8000) = ',' -- delimiter that separates items
)
RETURNS #List TABLE (item VARCHAR(8000))
BEGIN
DECLARE #sItem VARCHAR(8000)
WHILE CHARINDEX(#sDelimiter, #sInputList, 0) <> 0
BEGIN
SELECT
#sItem = RTRIM(LTRIM(SUBSTRING(#sInputList, 1, CHARINDEX(#sDelimiter, #sInputList, 0) - 1))),
#sInputList = RTRIM(LTRIM(SUBSTRING(#sInputList, CHARINDEX(#sDelimiter, #sInputList, 0) + LEN(#sDelimiter), LEN(#sInputList))))
IF LEN(#sItem) > 0
INSERT INTO #List
SELECT #sItem
END
IF LEN(#sInputList) > 0
INSERT INTO #List
SELECT #sInputList -- Put the last item in
RETURN
END
I get these errors:
Msg 102, Level 15, State 1, Line 2
Incorrect syntax near '('.
Msg 102, Level 15, State 1, Line 3
Incorrect syntax near ','.
try this
SELECT
nCmpID, cCompanyName
FROM
(SELECT *
FROM tbl_CompanyMaster
WHERE nCmpID IN (SELECT *
FROM dbo.fnsplit((SELECT can_AccessCompanyID
FROM tbl_UserMenuRelations
WHERE nUserID = 0
AND Is_Active = 1
AND Is_Available = 1), ','))
AND Is_Active = 1) t
there's a useless a) in your code
Answer
Will require making use if dynamic Query
Declare #Query varchar(8000)
Declare #CommaSeparatedList varchar(8000)
-- Use a string variable to store the result of the split function.
Set #CommaSeparatedList =(SELECT *
FROM dbo.fnsplit((SELECT can_AccessCompanyID
FROM tbl_UserMenuRelations
WHERE nUserID = 0
AND Is_Active = 1
AND Is_Available = 1), ','))
SET #Query='SELECT
nCmpID, cCompanyName
FROM
(SELECT *
FROM tbl_CompanyMaster
WHERE nCmpID IN ('+#CommaSeparatedList+') a)
AND Is_Active = 1) t'
Exec(#Query)
your syntax is wrong where you are using user defined function dbo.fnsplit.
You should use cursor for rows by rows execution.
DECLARE #name VARCHAR(100)
DECLARE record CURSOR FOR SELECT name FROM emp
OPEN record
FETCH NEXT FROM record INTO #name
WHILE ##FETCH_STATUS = 0 BEGIN
select * from dbo.fnsplit(#name,',')
FETCH NEXT FROM record INTO #name
END
CLOSE record
DEALLOCATE record
Do not reinvent the wheel if you do not have to.
Example CSV string splitter table-valued function by Jeff Moden:
create function [dbo].[delimitedsplit8K] (
#pstring varchar(8000)
, #pdelimiter char(1)
)
returns table with schemabinding as
return
with e1(N) as (
select 1 union all select 1 union all select 1 union all
select 1 union all select 1 union all select 1 union all
select 1 union all select 1 union all select 1 union all select 1
)
, e2(N) as (select 1 from e1 a, e1 b)
, e4(N) as (select 1 from e2 a, e2 b)
, ctetally(N) as (
select top (isnull(datalength(#pstring),0))
row_number() over (order by (select null)) from e4
)
, ctestart(N1) as (
select 1 union all
select t.N+1 from ctetally t where substring(#pstring,t.N,1) = #pdelimiter
)
, ctelen(N1,L1) as (
select s.N1,
isnull(nullif(charindex(#pdelimiter,#pstring,s.N1),0)-s.N1,8000)
from ctestart s
)
select itemnumber = row_number() over(order by l.N1)
, item = substring(#pstring, l.N1, l.L1)
from ctelen l
;
go
And use like so:
select cm.nCmpID, cm.cCompanyName
from tbl_CompanyMaster cm
where cm.Is_Active = 1
and cm.nCmpId in (
select s.Item
from tbl_UserMenuRelations umr
cross apply dbo.delimitedsplit8K(umr.can_AccessCompanyId,',') s
where umr.nUserId = 0
and umr.Is_Active = 1
and umr.Is_Available = 1
)
splitting strings reference:
Tally OH! An Improved SQL 8K “CSV Splitter” Function - Jeff Moden
Splitting Strings : A Follow-Up - Aaron Bertrand
Split strings the right way – or the next best way - Aaron Bertrand
string_split() in SQL Server 2016 : Follow-Up #1 - Aaron Bertrand
Ordinal workaround for **string_split()** - Solomon Rutzky
I have this condition in my stored procedure to determine which WHERE clause to use:
IF (#communityDesc = 'All Areas')
BEGIN
WHERE V_CONSTAT_ACTUAL_DATES.AREA_DESC IN (SELECT name
FROM dbo.splitstring(#communityDesc))
AND V_CONSTAT_ACTUAL_DATES.DATE_TO_END >= GETDATE()
END
ELSE
BEGIN
WHERE V_CONSTAT_ACTUAL_DATES.DATE_TO_END >= GETDATE()
END
ORDER BY V_CONSTAT_ACTUAL_DATES.DATE_TO_END
but I get a long list of errors:
Msg 156, Level 15, State 1, Procedure GetProductionSchedule, Line 256
Incorrect syntax near the keyword 'WHERE'.
Msg 156, Level 15, State 1, Procedure GetProductionSchedule, Line 256
Incorrect syntax near the keyword 'AND'.
What am I doing wrong?
You can't separate out a query by a conditional. You'd have to do something like.
if(#communityDesc = 'All Areas')
BEGIN
SELECT * FROM Table
WHERE V_CONSTAT_ACTUAL_DATES.AREA_DESC IN
(select name from dbo.splitstring(#communityDesc))
AND V_CONSTAT_ACTUAL_DATES.DATE_TO_END>=GETDATE()
ORDER BY V_CONSTAT_ACTUAL_DATES.DATE_TO_END
END
else
BEGIN
SELECT * FROM Table
WHERE V_CONSTAT_ACTUAL_DATES.DATE_TO_END>=GETDATE()
ORDER BY V_CONSTAT_ACTUAL_DATES.DATE_TO_END
END
Your other option would be to conditionally build the query:
DECLARE #Query VARCHAR(1000)
SET #Query = 'SELECT * FROM TABLE '
if(#communityDesc = 'All Areas')
BEGIN
SET #Query = #Query +
'WHERE V_CONSTAT_ACTUAL_DATES.AREA_DESC IN (select name from dbo.splitstring(#communityDesc)) AND V_CONSTAT_ACTUAL_DATES.DATE_TO_END>=GETDATE() '
END
ELSE
SET #Query = #Query +
'WHERE V_CONSTAT_ACTUAL_DATES.DATE_TO_END>=GETDATE() '
BEGIN
SET #Query = #Query + 'ORDER BY V_CONSTAT_ACTUAL_DATES.DATE_TO_END'
END
exec sp_executesql #Query
Or just put all of the logic into a single WHERE
SELECT *
FROM [Table]
WHERE V_CONSTAT_ACTUAL_DATES.DATE_TO_END >= GETDATE()
AND (#communityDesc = 'All Areas'
OR V_CONSTAT_ACTUAL_DATES.AREA_DESC IN (SELECT name
FROM dbo.splitstring(#communityDesc)))
Im not sure you have your logic right.. You probably want to split #communityDesc if it's not equal to All Areas I've updated my answer to reflect what I mean.
You should probably write it like this
-- your preceding select statements followed by this line
SELECT * FROM V_CONSTAT_ACTUAL_DATES
WHERE
(
#communityDesc = 'All Areas' AND
V_CONSTAT_ACTUAL_DATES.AREA_DESC IN (select name from dbo.splitstring(#communityDesc)) AND
V_CONSTAT_ACTUAL_DATES.DATE_TO_END>=GETDATE()
)
OR
( #communityDesc <> 'All Areas' AND V_CONSTAT_ACTUAL_DATES.DATE_TO_END>=GETDATE()
)
ORDER BY V_CONSTAT_ACTUAL_DATES.DATE_TO_END
This can also be simplified as
-- your preceding select statements followed by this line
SELECT * FROM V_CONSTAT_ACTUAL_DATES
WHERE
V_CONSTAT_ACTUAL_DATES.DATE_TO_END>=GETDATE()
AND NOT
(
#communityDesc <> 'All Areas' OR
V_CONSTAT_ACTUAL_DATES.AREA_DESC not IN (select name from dbo.splitstring(#communityDesc))
)
ORDER BY V_CONSTAT_ACTUAL_DATES.DATE_TO_END
which can be further optimized like below
-- your preceding select statements followed by this line
SELECT * FROM V_CONSTAT_ACTUAL_DATES
LEFT JOIN (select name from dbo.splitstring(#communityDesc) Temp
ON Temp.name=V_CONSTAT_ACTUAL_DATES.AREA_DESC
WHERE
V_CONSTAT_ACTUAL_DATES.DATE_TO_END>=GETDATE()
AND NOT
(
#communityDesc <> 'All Areas' OR Temp.Name is null
)
)
ORDER BY V_CONSTAT_ACTUAL_DATES.DATE_TO_END
I am attempting to execute this query but I keep receiving error message
Msg 102, Level 15, State1
Incorrect syntax near ')'.
Would you please look over my query? I believe with every SQL keyword I've added the appropriate parenthesis.
USE [db]
GO
SET NOCOUNT ON
DECLARE #AlertDateTime date
, #HostName varchar(50)
, #Program varchar(100)
, #Event varchar(100)
, #Entity varchar(50)
, #Class tinyint
, #Severity tinyint
, #AlertMessage varchar(1024)
, #SkipFlag char(1)
select cast(getdate() as date)
IF EXISTS
(SELECT * FROM SendAlertLog
WHERE EXISTS
(
SELECT SendAlertLog.Event
FROM SendAlertLog
GROUP BY SendAlertLog.Event
HAVING COUNT (1) >= 2
)
AND SendAlertLog.SkipFlag != 'Y'
AND AlertDateTime <= DATEADD (mi,-30,#AlertDateTime)
)
I do not know what I am including or excluding wrong. Please help
Looks like you have an if, but no statement to do if the expression is true. You have
IF EXISTS(...)
But you need
IF EXISTS(...)
DO_SOMETHING
Try this one (without double usage of SendAlertLog) -
DECLARE #AlertDateTime DATE
IF EXISTS (
SELECT 1
FROM (
SELECT
cnt = COUNT(1)
, SkipFlag = MAX(l.SkipFlag)
, AlertDateTime = MAX(l.AlertDateTime)
FROM dbo.SendAlertLog l
GROUP BY l.[Event]
) l
WHERE cnt >= 2
AND l.SkipFlag != 'Y'
AND l.AlertDateTime <= DATEADD(mi, -30, #AlertDateTime)
) BEGIN
PRINT 'Do something'
END
So I have this working properly:
CREATE FUNCTION dbo.GetLiveStream(#UserName NVARCHAR(MAX)) RETURNS TABLE
AS
RETURN (
SELECT DISTINCT l.*
FROM StreamView l
JOIN Friendships f ON f.Sender = #UserName OR f.Recipient = #UserName
WHERE l.Sender <> #UserName
AND l.Recipient <> #UserName
AND ( l.Sender = f.Recipient
OR l.Sender = f.Sender
OR l.Recipient = f.Sender
OR l.Recipient = f.Recipient)
)
GO
But when trying to do the following query:
SELECT ROW_NUMBER() OVER(ORDER BY DateTime DESC) AS RowNumber,
*
FROM dbo.GetLiveStream('jason')
WHERE RowNumber >= 0
AND RowNumber < 0+ 10;
I get the following error:
Msg 207, Level 16, State 1, Line 4
Invalid column name 'RowNumber'.
Msg 207, Level 16, State 1, Line 5
Invalid column name 'RowNumber'.
Note that specifying l.* returns this error:
Msg 107, Level 15, State 1, Line 2
The column prefix 'l' does not match with a table name or alias name used in the query.
GetLiveStream is a function:
RETURN (
SELECT DISTINCT l.*
FROM StreamView l
JOIN Friendships f ON f.Sender = #UserName OR f.Recipient = #UserName
WHERE l.Sender <> #UserName
AND l.Recipient <> #UserName
AND ( l.Sender = f.Recipient
OR l.Sender = f.Sender
OR l.Recipient = f.Sender
OR l.Recipient = f.Recipient) AND f.IsPending = 0
)
How can this be resolved? Thank you.
You can't reference an alias in the WHERE clause. Do this:
select *
from
(
SELECT ROW_NUMBER() OVER(ORDER BY DateTime DESC) AS RowNumber,
*
FROM dbo.GetLiveStream('jason')
) a
WHERE RowNumber >= 0
AND RowNumber < 0+ 10;
As for your l.* error, that's because that alias is local to the function and its query definition and can't be referenced outside of it.
Don't use * in a stored procedure or function because it gets compiled into a list of columns, which can change over time and thus break the compiled code. SQL Server doesn't warn you when that happens.