我的SQL Server存储过程出错

时间:2017-11-09 19:55:02

标签: sql-server stored-procedures

我是SQL新手并尝试创建存储过程以了解参数和变量的工作原理。当我创建下面的存储过程时,我分配了2个参数和2个变量。我设置了变量的值。

创建存储过程但是当我将其作为

运行时
EXECUTE anniversary_file @year = 2017, @month = 3

我收到此错误:

  

Msg 512,Level 16,State 1,Procedure anniversary_file,Line 53
  子查询返回的值超过1。当子查询遵循=,!=,<,< =,>,> =或子查询用作表达式时,不允许这样做。

我做错了什么?

这是我的代码:

CREATE PROCEDURE anniversary_file
    @year DATETIME,
    @month DATETIME
AS
BEGIN
    DECLARE @month1 AS DATETIME,
            @year1 AS DATETIME

    SET @month1 = (SELECT MONTH(C.OrderCompletionDate) FROM dbo.Customers AS   C)
    SET @year1 = (SELECT  YEAR(C.OrderCompletionDate) FROM dbo.Customers AS C)

    SELECT DISTINCT 
        CustomerID,
        BAN_ADSL_TN,
        LandlinePhoneNumber,
        MobilePhoneNumber,
        FirstName, LastName,
        ServiceAddress,
        ServiceAddressAptNo,
        ServiceAddressCity,
        ServiceAddressState,
        ServiceAddressZip,
        --MailingAddress,
        --MailingAddressAptNo,
        --MailingAddressCity,
        --MailingAddressState,
        --MailingAddressZip,
        --LanguageID,
        --OrderStatus,
        OrderCompletionDate 
    FROM 
        dbo.Customers AS C (NOLOCK)
    WHERE 
        StatusID = 115
        AND @year = @year1
        AND @month = @month1
END

2 个答案:

答案 0 :(得分:0)

在您的代码中,这些行是您的问题:

SET @month1 = (SELECT MONTH(C.OrderCompletionDate) FROM dbo.Customers AS C)
SET @year1 = (SELECT  YEAR(C.OrderCompletionDate) FROM dbo.Customers AS C)

如果您分别运行这些语句,您会注意到至少有一个语句返回多个值

SELECT MONTH(C.OrderCompletionDate) FROM dbo.Customers 
SELECT  YEAR(C.OrderCompletionDate) FROM dbo.Customers

因此,您尝试将结果设置插入到需要单个值的变量中。这可以通过几种方式纠正。

使用相应的TOP 1

添加ORDER BY
SET @month1 = (SELECT TOP 1 MONTH(C.OrderCompletionDate) FROM dbo.Customers AS C ORDER BY C.OrderCompletionDate DESC)
SET @year1 = (SELECT  TOP 1 YEAR(C.OrderCompletionDate) FROM dbo.Customers AS C ORDER BY C.OrderCompletionDate DESC)

添加WHERE条款......

SET @month1 = (SELECT MONTH(C.OrderCompletionDate) FROM dbo.Customers AS C WHERE <some clause to limit the result set>)
SET @year1 = (SELECT  YEAR(C.OrderCompletionDate) FROM dbo.Customers AS C WHERE <some clause to limit the result set>)

此外,您已将变量声明为DATETIME但传入INTEGER

DECLARE @month1 AS DATETIME
DECLARE @year1 AS DATETIME

这些应该是INT,因为MONTH()YEAR()会返回INTEGER

最后,您的程序可能不会按照您的想法执行。您可以简化代码并在WHERE子句中使用它。

WHERE StatusID = 115
AND year(OrderCompletionDate) = year(@year)
AND month(OrderCompletionDate)= month(@month)

此外,当您可以使用DATETIME然后不在INTEGER子句中使用强制转换时,将@year和@month参数声明为WHERE

答案 1 :(得分:0)

无需设置变量。试试这个。删除您正在设置的变量并更新 Where 子句。

&#xA;&#xA;

将输入变量声明为INT。

&# xA;&#xA;

更新

&#xA;&#xA;
  CREATE PROCEDURE anniversary_file&#xA; @year INT,&#xA; @month INT&#xA;&#xA; AS&#XA;开始&#xA;&#xA; ******删除这些线路&#xA;&#xA; DECLARE @ month1 AS DATETIME,&#xA; @ year1 AS DATETIME&#xA;&#xA;&#xA; SET @ month1 =(SELECT MONTH(C.OrderCompletionDate)FROM dbo.Customers AS C)&#xA; SET @ year1 =(SELECT YEAR(C.OrderCompletionDate)FROM dbo.Customers AS C)&#xA; *************************&#xA; SELECT DISTINCT&#xA;客户ID,&#XA; BAN_ADSL_TN,&#XA; LandlinePhoneNumber,&#XA; MobilePhoneNumber,&#XA;名字,&#XA;姓氏,&#XA; ServiceAddress,&#XA; ServiceAddressAptNo,&#XA; ServiceAddressCity,&#XA; ServiceAddressState,&#XA; ServiceAddressZip,&#XA; --MailingAddress,&#XA; --MailingAddressAptNo,&#XA; --MailingAddressCity,&#XA; --MailingAddressState,&#XA; --MailingAddressZip,&#XA; --LanguageID,&#XA; --OrderStatus,&#XA; OrderCompletionDate&#xA;来自dbo.Customers AS C(NOLOCK)&#xA; WHERE StatusID = 115&#xA; AND @year = YEAR(C.OrderCompletionDate)&#xA; AND @month = MONTH(C.OrderCompletionDate)&#xA;&#xA; END&#XA;  
&#XA;