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.
Related
I have a function in SQL Server with a select statement and I want to return one row calculated inside the select statement - ORDER_VALUE_ADJUSTED.
CREATE FUNCTION order_value
(#date DATE,
#client VARCHAR(50),
#order_number VARCHAR(50))
RETURNS DECIMAL(13,2)
AS
BEGIN
SELECT
EKKO.EBELN,
SUM(CASE WHEN EKPO.NETWR = CDPOS.VALUE_NEW AND CDHDR.UDATE >= #date THEN CDPOS.VALUE_OLD ELSE EKPO.NETWR END) AS ORDER_VALUE_ADJUSTED
FROM
EKKO
INNER JOIN
EKPO_C AS EKPO ON EKKO.EBELN = EKPO.EBELN
AND EKKO.MANDT = EKPO.MANDT
LEFT JOIN
CDPOS_C AS CDPOS ON (EKPO.MANDT + EKPO.EBELN + EKPO.EBELP) = CDPOS.TABKEY
LEFT JOIN
CDHDR ON CDHDR.CHANGENR = CDPOS.CHANGENR
WHERE
EKKO.MANDT = #client
AND EKKO.EBELN = #order_number
GROUP BY
EKKO.EBELN
RETURN ORDER_VALUE_ADJUSTED
END;
I am getting these errors:
Msg 444, Level 16, State 2, Procedure order_value, Line 6 [Batch Start Line 0]
Select statements included within a function cannot return data to a client.
Msg 207, Level 16, State 1, Procedure order_value, Line 22 [Batch Start Line 0]
Invalid column name 'ORDER_VALUE_ADJUSTED'.
How can I solve this issue ? Do I need to rewrite it into a stored procedure ?
Your primary issues are that you are trying to SELECT straight out of the function, and you are not storing the data into variables to RETURN.
But it sounds like you actually need an inline Table Valued Function, rather than a Scalar Function, these are in any case much faster
CREATE OR ALTER FUNCTION dbo.order_value
(#date DATE,
#client VARCHAR(50),
#order_number VARCHAR(50))
RETURNS TABLE
AS RETURN
SELECT
EKKO.EBELN,
SUM(CASE WHEN EKPO.NETWR = CDPOS.VALUE_NEW AND CDHDR.UDATE >= #date THEN CDPOS.VALUE_OLD ELSE EKPO.NETWR END) AS ORDER_VALUE_ADJUSTED
FROM
EKKO
INNER JOIN
EKPO_C AS EKPO ON EKKO.EBELN = EKPO.EBELN
AND EKKO.MANDT = EKPO.MANDT
LEFT JOIN
CDPOS_C AS CDPOS ON (EKPO.MANDT + EKPO.EBELN + EKPO.EBELP) = CDPOS.TABKEY
LEFT JOIN
CDHDR ON CDHDR.CHANGENR = CDPOS.CHANGENR
WHERE
EKKO.MANDT = #client
AND EKKO.EBELN = #order_number
GROUP BY
EKKO.EBELN
;
An inline table function must be a single RETURN SELECT statement.
You use it like this
SELECT *
FROM dbo.order_value(GETDATE(), 'SomeClient', 'SomeOrder') ov;
Or
SELECT *
FROM dbo.Orders o
CROSS APPLY dbo.order_value(o.Date, o.Client, o.Number) ov;
A guess, can't verify the syntax at the moment:
CREATE FUNCTION order_value
(#date DATE,
#client VARCHAR(50),
#order_number VARCHAR(50))
RETURNS DECIMAL(13,2)
RETURN
SELECT SUM(CASE WHEN EKPO.NETWR = CDPOS.VALUE_NEW AND CDHDR.UDATE >= #date
THEN CDPOS.VALUE_OLD
ELSE EKPO.NETWR
END) AS ORDER_VALUE_ADJUSTED
FROM EKKO
INNER JOIN EKPO_C AS EKPO
ON EKKO.EBELN = EKPO.EBELN
AND EKKO.MANDT = EKPO.MANDT
LEFT JOIN CDPOS_C AS CDPOS
ON (EKPO.MANDT + EKPO.EBELN + EKPO.EBELP) = CDPOS.TABKEY
LEFT JOIN CDHDR
ON CDHDR.CHANGENR = CDPOS.CHANGENR
WHERE EKKO.MANDT = #client
AND EKKO.EBELN = #order_number;
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
Getting this error with the following query in SQL Server 2012.
An expression of non-boolean type specified in a context where a condition is expected, near 'RETURN'.
CREATE FUNCTION [dbo].[GetPMResources](#UserResourceNo nvarchar(250))
RETURNS #Resources TABLE (
ResourceNo nvarchar(250) COLLATE Latin1_General_CS_AS not null,
Name nvarchar(250) COLLATE Latin1_General_CS_AS not null
)
AS
BEGIN
Declare #RoleID int, #UserDivision nvarchar(20)
SELECT TOP(1) #RoleID = r.ReportingRole, #UserDivision = r.DivisionCode
FROM Resource r
WHERE r.ResourceNo = #UserResourceNo
INSERT #Resources
SELECT r.ResourceNo,Name = r.ResourceNo + ' ' + r.Name
FROM Resource r WHERE r.ResourceNo IN
(
SELECT m.ResourceNo FROM JobMember m
JOIN Job j ON j.JobNo = m.JobNo
WHERE j.ProjectManagerNo = #UserResourceNo
OR
j.AlternateProjectManagerNo = #UserResourceNo
)
OR
(
SELECT m.ResourceNo FROM JobMember m
JOIN JobTask t ON t.JobTaskNo = m.JobTaskNo
WHERE t.TaskManagerNo = #UserResourceNo
OR
t.AlternateTaskManagerNo = #UserResourceNo
)
RETURN
END
An expression of non-boolean type specified in a context where a condition is expected
I also got this error when I forgot to add ON condition when specifying my join clause.
That is invalid syntax. You are mixing relational expressions with scalar operators (OR). Specifically you cannot combine expr IN (select ...) OR (select ...). You probably want expr IN (select ...) OR expr IN (select ...). Using union would also work: expr IN (select... UNION select...)
Your problem might be here:
OR
(
SELECT m.ResourceNo FROM JobMember m
JOIN JobTask t ON t.JobTaskNo = m.JobTaskNo
WHERE t.TaskManagerNo = #UserResourceNo
OR
t.AlternateTaskManagerNo = #UserResourceNo
)
try changing to
OR r.ResourceNo IN
(
SELECT m.ResourceNo FROM JobMember m
JOIN JobTask t ON t.JobTaskNo = m.JobTaskNo
WHERE t.TaskManagerNo = #UserResourceNo
OR
t.AlternateTaskManagerNo = #UserResourceNo
)
You can also rewrite it like this
FROM Resource r WHERE r.ResourceNo IN
(
SELECT m.ResourceNo FROM JobMember m
JOIN Job j ON j.JobNo = m.JobNo
WHERE j.ProjectManagerNo = #UserResourceNo
OR
j.AlternateProjectManagerNo = #UserResourceNo
Union All
SELECT m.ResourceNo FROM JobMember m
JOIN JobTask t ON t.JobTaskNo = m.JobTaskNo
WHERE t.TaskManagerNo = #UserResourceNo
OR
t.AlternateTaskManagerNo = #UserResourceNo
)
Also a return table is expected in your RETURN statement
I have written this query to get data for special keyword:
ALTER procedure [dbo].[GetAllSpecialPaperTags]
#PKeyword nvarchar(200)
as
begin
select
Papers.PID, Papers.PTitle, Papers.PaperSummary
from
PaperKeywords
left join
PaperTags on PaperKeywords.PKeyID = PaperTags.PKeyID
left join
Papers on PaperTags.PID = Papers.PID
where
PaperKeywords.PKeyword = #PKeyword
end
I want use this article for custom paging : Custom Paging using SQL Server Stored Procedure
I wrote this query but I'm getting an error:
create procedure [dbo].[GetAllSpecialPaperTags]
#PageIndex INT = 1
,#PageSize INT = 10
,#RecordCount INT OUTPUT
,#PKeyword nvarchar(200)
as
BEGIN
SET NOCOUNT ON;
SELECT ROW_NUMBER() OVER
(
ORDER BY [Papers.PID] ASC
)AS RowNumber
,Papers.PID , Papers.PTitle , Papers.PaperSummary
INTO #Results
from PaperKeywords
left join PaperTags on PaperKeywords.PKeyID = PaperTags.PKeyID
left join Papers on PaperTags.PID = Papers.PID where PaperKeywords.PKeyword = #PKeyword
SELECT #RecordCount = COUNT(*)
FROM #Results
SELECT * FROM #Results
WHERE RowNumber BETWEEN(#PageIndex -1) * #PageSize + 1 AND(((#PageIndex -1) * #PageSize + 1) + #PageSize) - 1
DROP TABLE #Results
end
Error:
Msg 207, Level 16, State 1, Procedure GetAllSpecialPaperTags, Line 11
Invalid column name 'Papers.PID'.
Why?
This is your order by expression:
ORDER BY [Papers.PID] ASC
It is looking for a column named in its entirety "Papers.PID". It is not looking for the PID column in Papers. Just drop the braces:
ORDER BY Papers.PID ASC
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
))
)
)