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
在标量函数中也可以