SQL-是否有更好的方法可以将在where子句中使用的键列表传递到存储过程中?

问题描述

我使用XML列表。

我使用这种存储过程:

CREATE PROCEDURE [dbo].[GetUsersInList]
    @UserList nvarchar(MAX)
AS
BEGIN
    DECLARE @DocHandle int
    DECLARE @UsersListTable table (
        [UserID] bigint
    )

    EXEC sp_xml_preparedocument @DocHandle OUTPUT, @UserList

    INSERT INTO
        @UsersListTable ([UserID])
    SELECT
        doc.Value [UserID]
    FROM
        OPENXML(@DocHandle, '/List/Item', 1) WITH ([Value] int) doc

    EXEC sp_xml_removedocument @DocHandle

    SELECT
        *,
        IsNull(cast(TechID as varchar) + ' - ' + displayName, displayName) [FriendlyName]
    FROM
        dbo.[Users]
    WHERE
        [ID] IN (SELECT [UserID] FROM @UsersListTable)
END

要创建这种列表:

var list =
    new XElement("List",
        users.Select(user =>
            new XElement("Item", new XAttribute("Value", user.Id))
        )
    );

解决方法

这是场景;我有具有相关 OrderIdsCustomerIds (1、2、3)的 列表
。我有一个存储过程Delete_OrdersByCustomerIds,它将删除与指定的 CustomerId 相关的所有订单。

当前,我执行此操作的方法是将 CustomerIds 连接到一个字符串,即“
1,2,3”。然后,我将此字符串传递给我的存储过程,并使用以下函数创建一个可以连接的Int表:

CREATE FUNCTION [dbo].[iter$simple_intlist_to_tbl] (@list nvarchar(MAX))
   RETURNS @tbl TABLE (number int NOT NULL) AS
BEGIN
   DECLARE @pos        int,@nextpos    int,@valuelen   int

   SELECT @pos = 0,@nextpos = 1

   WHILE @nextpos > 0
   BEGIN
      SELECT @nextpos = charindex(',',@list,@pos + 1)
      SELECT @valuelen = CASE WHEN @nextpos > 0
                              THEN @nextpos
                              ELSE len(@list) + 1
                         END - @pos - 1
      INSERT @tbl (number)
         VALUES (convert(int,substring(@list,@pos + 1,@valuelen)))
      SELECT @pos = @nextpos
   END
  RETURN
END

然后我就做一个DELETE FROM Orders WHERE CustomerId IN iter$simple_intlist_to_tbl(@CustomerIds).number。(语法可能不正确,我正在大声思考。)

我忍不住觉得这很 糟糕 。有没有更好的方法来实现相同的目标?我不想自己建立SQL语句,我目前正在使用标准的.Net ADO包装器。