Reputation:
I'm pretty new to SQL Server, so bear with me. All I'm trying to do is create a function that returns a table if a certain condition is met, the condition being the discount amount being greater than zero. If the discount amount is not greater than zero, then another table should be returned. I keep receiving the following errors though:
Incorrect syntax near the keyword 'IF'," and "a RETURN statement with a return value cannot be used in this context.
Any help would be appreciated. Here's my code so far:
IF OBJECT_ID(N'dbo.fn_PopulateDiscountTable', N'FN') IS NOT NULL
DROP FUNCTION dbo.fn_PopulateDiscountTable;
GO
CREATE FUNCTION dbo.fn_PopulateDiscountTable(@FolioID smallint)
RETURNS TABLE
AS
IF((SELECT D.DiscountAmount
FROM Discount D, Folio F
WHERE D.DiscountID = F.DiscountID
AND FolioID = @FolioID) > 0)
RETURN (SELECT F.QuotedRate AS "QuotedRate", D.DiscountAmount AS "DiscountAmount"
FROM Discount D, Folio F
WHERE D.DiscountID = F.DiscountID
AND FolioID = @FolioID)
ELSE
RETURN(SELECT F.QuotedRate AS "QuotedRate", D.DiscountPercent AS "DiscountPercent"
FROM Discount D, Folio F
WHERE D.DiscountID = F.DiscountID
AND FolioID = @FolioID)
Upvotes: 1
Views: 382
Reputation: 9309
Actually simple CASE
does all the work:
SELECT
F.QuotedRate AS "QuotedRate",
CASE WHEN D.DiscountAmount > 0 THEN D.DiscountAmount ELSE D.DiscountPercend END AS "Discount"
FROM Discount D
INNER JOIN Folio F ON D.DiscountID = F.DiscountID
WHERE F.FolioID = @FolioID
But note, such a result does not make sense: amount and percent are not the same. In most scenarios it's impossible to replace one with another.
0.5
, 1.25
, 30.00
- which one is what? amount or percent?
Upvotes: 0
Reputation: 58715
You can't include branching logic in table valued functions, because from the compiler's point of view, that introduces uncertainty as to what the result schema will look like.
For example, you might decide to return a single column of strings with one branch, and twelve columns of xml from the other. The table-valued function must have a definite schema in order to be treated as a table. The rule you are bumping up against is what the compiler uses to guarantee to users of your function that they can count on the same result columns coming back every time.
In this case, however, you can move the logic to a CASE statement in the SELECT, as shown below.
Note: I also took the liberty of updating the joins to the more modern ANSI 92 syntax.
IF OBJECT_ID(N'dbo.fn_PopulateDiscountTable', N'FN') IS NOT NULL
DROP FUNCTION dbo.fn_PopulateDiscountTable;
GO
CREATE FUNCTION dbo.fn_PopulateDiscountTable(@FolioID smallint)
RETURNS TABLE
AS
RETURN(
SELECT
F.QuotedRate AS "QuotedRate"
,case when 0 < (
SELECT D.DiscountAmount
FROM
Discount D
inner join Folio F on f.discountid = d.discountid
WHERE FolioID = @FolioID
)
then D.DiscountAmount
else d.DiscountPercent
end AS "Discount"
FROM
Discount D
inner join Folio F on d.discountid = f.discountid
WHERE f.FolioID = @FolioID
)
Upvotes: 2
Reputation: 8584
You can define the table you will return and insert into that:
CREATE FUNCTION dbo.fn_PopulateDiscountTable(@FolioID smallint)
RETURNS @Result TABLE
(
QuotedRate varchar(20), DiscountAmount int
)
AS
BEGIN
IF((SELECT D.DiscountAmount FROM Discount D, Folio F WHERE D.DiscountID = F.DiscountID AND FolioID = @FolioID) > 0)
Insert into @Result
SELECT F.QuotedRate AS "QuotedRate", D.DiscountAmount AS "DiscountAmount"
FROM Discount D, Folio F
WHERE D.DiscountID = F.DiscountID
AND FolioID = @FolioID
ELSE
Insert into @Result
SELECT F.QuotedRate AS "QuotedRate", D.DiscountPercent AS "DiscountPercent"
FROM Discount D, Folio F
WHERE D.DiscountID = F.DiscountID
AND FolioID = @FolioID
Return --will return @Result
END
Upvotes: 2