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 ?
CodePudding user response:
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;
CodePudding user response:
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;