Sql server 尝试在IF语句中使用函数参数时出错
我有以下Sql server 尝试在IF语句中使用函数参数时出错,sql-server,sql-function,Sql Server,Sql Function,我有以下创建函数: CREATE FUNCTION ufnTotalSales (@StartDate datetime, @EndDate datetime = GETDATE(), @FoodName nvarchar(50) = '') RETURNS TABLE AS RETURN ( IF @FoodName = ''; BEGIN SELECT f.FoodID, FoodName, (FoodPrice * Q
创建函数
:
CREATE FUNCTION ufnTotalSales (@StartDate datetime, @EndDate datetime = GETDATE(), @FoodName nvarchar(50) = '')
RETURNS TABLE
AS
RETURN
(
IF @FoodName = '';
BEGIN
SELECT f.FoodID, FoodName, (FoodPrice * Quantity) AS TotalSales FROM Food f, OrderFoodRel ofr
WHERE (Date_Time BETWEEN @StartDate AND @EndDate)
END
ELSE
BEGIN
SELECT f.FoodID, FoodName, (FoodPrice * Quantity) AS TotalSales FROM Food f, OrderFoodRel ofr
WHERE (Date_Time BETWEEN @StartDate AND @EndDate) AND @FoodName = FoodName
END
);
第一个错误发生在@EndDate datetime=GETDATE()
,它表示“()”附近的语法不正确。如果用户选择使用默认值,我试图为@EndDate
参数指定当前datetime
的默认值,但不知怎的,我得到了一个错误
第二个错误发生在我在中使用的所有参数上,如果。。。ELSE
块(@FoodName
,@StartDate
和@EndDate
)。它说我必须声明标量变量“@…”
。这是一个参数而不是标量变量,我该如何解决这个问题
此函数的思想是返回食品的总销售额,有两个选项:一个是从一个日期到另一个日期(如果您指定了食品名称),名称为X的食品的总销售额;二是从一个日期到另一个日期的食品总销售额,不考虑食品名称。您不能在ITVF中使用过程逻辑,而只能使用某种类型的查询返回结果集
参考:
以下内容有望与您所寻找的内容接近:
CREATE FUNCTION ufnTotalSales
(
@StartDate datetime
, @EndDate datetime
, @FoodName nvarchar(50)
)
RETURNS TABLE
AS
RETURN
SELECT f.FoodID, FoodName, (FoodPrice * Quantity) AS TotalSales FROM Food f, OrderFoodRel ofr
WHERE (Date_Time BETWEEN @StartDate AND coalesce(@EndDate,getdate()))
and coalesce(@FoodName,'') = ''
union all
SELECT f.FoodID, FoodName, (FoodPrice * Quantity) AS TotalSales FROM Food f, OrderFoodRel ofr
WHERE (Date_Time BETWEEN @StartDate AND coalesce(@EndDate,getdate()))
AND coalesce(@FoodName,'') = FoodName
使用以下功能
CREATE FUNCTION ufnTotalSales
( @StartDate datetime,
@EndDate datetime,
@FoodName nvarchar(50)
)
RETURNS TABLE
AS
RETURN
(
SELECT f.FoodID, FoodName, (FoodPrice * Quantity) AS TotalSales
FROM Food f
JOIN OrderFoodRel ofr on f.FoodID = ofr.FoodID
WHERE (Date_Time BETWEEN @StartDate AND ISNULL(@EndDate,GETDATE()))
AND ISNULL(@FoodName,'') = FoodName
);
这个函数有几个问题
首先,不能将默认值指定给函数,如果..则不能使用。。函数内部的ELSE
其次表Food
和OrderFoodRel
未合并
。你在这里做交叉连接
它不喜欢将getdate()作为默认值,您可以将@EndDate
的默认值设置为NULL,并在@EndDate
上使用ISNULL()
这是将创建函数的步骤。我假设这两个表通过FoodID
CREATE FUNCTION ufnTotalSales
(
@StartDate datetime,
@EndDate datetime = NULL,
@FoodName nvarchar(50) = ''
)
RETURNS TABLE
AS
RETURN
(
SELECT f.FoodID, FoodName, (FoodPrice * Quantity) AS TotalSales
FROM Food f
INNER JOIN OrderFoodRel ofr on f.FoodID = ofr.FoodID
WHERE Date_Time BETWEEN @StartDate AND ISNULL(@EndDate, GETDATE())
AND (
@FoodName = ''
OR f.FoodName = @FoodName
)
);
GO
因此,要在输入中使用默认值,需要使用关键字default
select *
from dbo.ufnTotalSales('2018-10-01', default , default)
但这对ITVF中存在过程逻辑这一事实没有帮助。@WealthyPlayer请现在试一试,尽管有一篇关于默认参数的帖子。或者这只适用于标量值函数吗?你是对的,对不起,你可以有默认值,但默认值必须是静态值,而不是像getdate()这样的函数调用。但我会按照我的方式来做,并传入null,或者如果您不想传入参数,则将默认值设置为null。如果我希望@EndDate是现在的datetime,并且我调用了不带该参数的函数,它不会返回与所述链接中的问题相同的错误(“提供的参数数量不足”)?很抱歉,您很抱歉(有点)同样正确,最好阅读参考链接,因为它告诉你如何做。你可以设置默认值(比如null)然后,当你调用函数时,你必须传入关键字default
,而不是一个值。就我个人而言,我只传入null,不使用默认值,但这取决于你。我明白了,谢谢你的回答!你怎么知道我不能在ITVF中使用过程逻辑?这是有经验的,还是有明确的解释这条规则?食物和食物的秩序如何related@SanalSunny它们使用来自Food的主键(FoodID)进行关联。OrderFoodRel有一个指向所述主键的外键FoodID。但是,这里有一个关于为参数指定默认值的帖子:编辑了查询。确定。它与getdate()不同
作为默认值。只有最后一部分FoodName=''或f.FoodName=FoodName的常量,如果我说最后一部分的意思是:if FoodName是一个空字符串(默认值),是否正确,则任何FoodName都满足该条件;如果不满足,则检查第二个条件,该条件将“我的食物表”中的FoodName与插入的参数(不再是空字符串)进行比较?编辑答案以包含该条件。是ISNULL()
和COALESCE()
在这种情况下也适用,或者更具体地说,不能在表值函数中使用IF..ELSE
在标量函数中也可以