执行存储过程时,当我的输入是多个值时出现此错误

时间:2018-07-20 07:42:50

标签: sql sql-server

这是我的SP。 我收到此错误-“子查询返回了多个值。当子查询遵循=,!=,<,<=,>,> =或当子查询用作表达式时,不允许这样做。”

enter code here

ALTER PROCEDURE GetToDoDetails
@ClientID VARCHAR(MAX) = NULL
AS
DECLARE @Sql VARCHAR(MAX)
SET @ClientID = REPLACE(@ClientID,',',''',''')
SET @Sql=
'SELECT
 C.ClientID,
C.ClientToDoID,
C.AssignedToID,
C.ToBeCompletedBy,
C.ToDoTypeID,
S.UDDescription,
(CL.LastName +'',''+ CL.FirstName) "Client Name",
(Select count(ClientID) from c_ToDo WHERE ClientID IN (''' + @ClientID+''') GROUP BY ClientID) "CountRow"
FROM c_ToDo C
INNER JOIN s_UserDefinedOptions S ON C.ToDoTypeID = S.UDID
INNER JOIN c_Client CL ON C.ClientID = CL.ClientID
WHERE 
C.ClientID IN (''' + @ClientID + ''')
ORDER BY C.ClientID ASC'
EXEC (@Sql)
GO

如果我写

EXEC GetToDoDetails '1566'

,我得到这个结果(参考图片)

enter image description here

现在如果我写

EXEC GetToDoDetails '1566,1697'

它显示了我所讲述的错误。 在子查询中将TOP 1添加为

之后
(Select TOP 1 count(ClientID) from c_ToDo WHERE ClientID IN (''' + @ClientID + ''') 

我仅针对不同的clientID(1566和1697)获得第一条记录的计数。(请参阅图片) enter image description here

ClientID = 1566的第45条记录之后(1566的总行数为45), 我希望为ClientID = 1697(即63)更改计数。 我不知道该如何处理。我是新手。请帮忙。

2 个答案:

答案 0 :(得分:3)

其中存在一些猜测,但是SQL Injection不是您的朋友。现在需要走了。因此,我改用了表类型参数。

关于错误,这是由于以下原因引起的:

(Select count(ClientID) from c_ToDo WHERE ClientID IN (''' + @ClientID+''') GROUP BY ClientID) "CountRow"

如果您在@ClientID中有多个值,它将返回多行。另外,SQL Server中对象的引号运算符是括号([]),而不是双引号(")。

无论如何,这是一个猜测,但这应该可以使您走上正确的道路(我希望如此):

CREATE TYPE ClientList AS TABLE (ClientID int); --Datatype is GUESSED
GO

CREATE PROCEDURE GetToDoDetails @Client ClientList READONLY
AS
    SELECT C.ClientID,
           C.ClientToDoID,
           C.AssignedToID,
           C.ToBeCompletedBy,
           C.ToDoTypeID,
           S.UDDescription,
           (CL.LastName + ',' + CL.FirstName) AS [Client Name],
           COUNT(C.ClientID) OVER (PARTITION BY C.ClientID) AS [CountRow] --Total guess here
                                                                          --If this is meant to just be a count of EVERY row, remove the PARTITION BY clause (so just OVER())
    FROM c_ToDo C
         INNER JOIN s_UserDefinedOptions S ON C.ToDoTypeID = S.UDID
         INNER JOIN c_Client CL ON C.ClientID = CL.ClientID
    WHERE EXISTS (SELECT 1 FROM @Client e WHERE C.ClientID = e.ClientID) --Changed from IN to EXISTS
    ORDER BY C.ClientID ASC;
GO

答案 1 :(得分:0)

在select语句中有一个用于计数的子查询是不理想的,在您的查询中您将获得多个值,因为client id具有多个值,我希望将其放在join语句中。 Print @sql应该可以检查语句是否有效。这将为您解决问题

    DECLARE @ClientID VARCHAR(MAX) = NULL
    DECLARE @Sql VARCHAR(MAX)
    SET @ClientID = REPLACE('1566,1697,2467',',',''',''') 
    SET @Sql=
    'SELECT
     C.ClientID,
    C.ClientToDoID,
    C.AssignedToID,
    C.ToBeCompletedBy,
    C.ToDoTypeID,
    S.UDDescription,
    (CL.LastName +'',''+ CL.FirstName) "Client Name",
     "CountRow"
    FROM c_ToDo C
    INNER JOIN s_UserDefinedOptions S ON C.ToDoTypeID = S.UDID
    INNER JOIN c_Client CL ON C.ClientID = CL.ClientID
    INNER JOIN (Select count(*) CountRow,ClientID from c_ToDo WHERE ClientID IN (''' + @ClientID+''') GROUP BY ClientID) CO
    on C.ClientID = CO.ClientID
    WHERE 
    C.ClientID IN (''' + @ClientID + ''')
    ORDER BY C.ClientID ASC'
    PRINT (@Sql)

您的SP:

ALTER PROCEDURE GetToDoDetails
    @ClientID VARCHAR(MAX) = NULL
    AS
   BEGIN 
          DECLARE @Sql VARCHAR(MAX)
            SET @ClientID = REPLACE(@ClientID,',',''',''') 
            SET @Sql=
            'SELECT
             C.ClientID,
            C.ClientToDoID,
            C.AssignedToID,
            C.ToBeCompletedBy,
            C.ToDoTypeID,
            S.UDDescription,
            (CL.LastName +'',''+ CL.FirstName) "Client Name",
             "CountRow"
            FROM c_ToDo C
            INNER JOIN s_UserDefinedOptions S ON C.ToDoTypeID = S.UDID
            INNER JOIN c_Client CL ON C.ClientID = CL.ClientID
            INNER JOIN (Select count(*) CountRow,ClientID from c_ToDo WHERE ClientID IN (''' + @ClientID+''') GROUP BY ClientID) CO
            on C.ClientID = CO.ClientID
            WHERE 
            C.ClientID IN (''' + @ClientID + ''')
            ORDER BY C.ClientID ASC'
            PRINT (@Sql)
            EXEC  (@Sql)
END