【问题标题】:Pass List of strings to a stored procedure [duplicate]将字符串列表传递给存储过程[重复]
【发布时间】:2015-02-16 12:06:08
【问题描述】:

使用 SQL Server 2012,我想创建一个存储过程,它传入一个字符串列表并检查每个条目。Iv 将该列表添加到一个逗号分隔的字符串“UserGroupsAllowedToViewMap”中。这适用于一个条目,但我需要检查它的多个条目。

public DataTable GetMapsWithWorkspaceForUserGroups(int workspaceID, string UserGroupsAllowedToViewMap)
{
        DataTable mapDets = new DataTable();

        SqlCommand oComm = new SqlCommand();
        SqlParameter spParam_WrkSpaceId = new SqlParameter();
        SqlParameter spParam_ViewMap = new SqlParameter();
        SqlParameter[] spParams = new SqlParameter[2];

        SqlDataAdapter daUserMaps = new SqlDataAdapter();
        try
        {
            spParam_WrkSpaceId.ParameterName = "@workspaceID";
            spParam_WrkSpaceId.Value = workspaceID;
            spParams[0] = spParam_WrkSpaceId;

            spParam_ViewMap.ParameterName = "@ViewMap";
            spParam_ViewMap.Value = UserGroupsAllowedToViewMap;
            spParams[1] = spParam_ViewMap;

            oComm = CreateCommand("GetWorkspaceMapDetailsForUserByGroups", spParams, TypeOfConnectionString.GeoAppBuilder);
            daUserMaps.SelectCommand = oComm;
            daUserMaps.Fill(mapDets);
        }
        catch (Exception e)
        {
            throw (e);
        }
        finally
        {
            CloseConnection();
        }

        return mapDets;
}




  USE [App]
GO
/****** Object:  StoredProcedure [dbo].[GetWorkspaceMapDetailsForUserByGroups]    Script Date: 16/02/2015 10:37:46 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[GetWorkspaceMapDetailsForUserByGroups]   
    @workspaceID int,
    @viewMap nvarchar(256)
 AS 

SELECT 
  m.*
FROM 
  GeoAppMapDef m
WHERE
 m.workspaceID = @workspaceID
 and m.IsDeleted = 0
 and m.ViewMap = @viewMap

我不确定如何遍历 SQL 中的字符串。我看过Passing List<> to SQL Stored ProcedureC# SQL Server - Passing a list to a stored procedure,但仍然没有更聪明。任何帮助表示赞赏。

【问题讨论】:

  • 不要传递字符串。这从来都不是一个好主意。您可以传递带有所需值的表值参数,并将其视为存储过程中的表。事实上,您发布的两个链接都提出了这一点。您在实施它们时遇到问题吗?如果是这样,您需要找到解决此问题的方法,而不是放弃好的解决方案并回到......不太好的解决方案。

标签: c# sql stored-procedures sql-server-2012


【解决方案1】:

这实际上是您发布的链接的副本。与其尝试解析值列表,不如传递一个表值参数。

首先在数据库中创建参数的类型(仅一次)。

CREATE TYPE [dbo].[IdList] AS TABLE(
    [Id] int NULL
);

然后创建一个接受这个参数的过程:

CREATE PROCEDURE [dbo].[GetWorkspaceMapDetailsForUserByGroups]
    @workspaceID int,
    @groupIds IdList READONLY
AS
BEGIN
SELECT 
  m.*
FROM GeoAppMapDef m 
    inner join @groupIds on m.ViewMap=@groupIds.Id
WHERE
    m.workspaceID = @workspaceID
    and m.IsDeleted = 0
END

在客户端,创建一个 DataTable,其中包含一个名为 Id 的单个 int 类型列,用所需的 ID 填充它,然后将其用作 @groupIds 参数的值

var table = new DataTable();
table.Columns.Add("Id", typeof(int));

for (int i = 0; i < 10; i++)
    table.Rows.Add(i);

var pList = new SqlParameter("@groupIds", SqlDbType.Structured);
pList.TypeName = "dbo.IdList";
pList.Value = table;

我从重复的问题中复制了这个并做了一些修改。

【讨论】:

  • 感谢您的回复,但走了另一条路。该表也是 STRING 而不是 ID
  • 为什么?您从未提到最佳解决方案(或表模式)有什么问题。如果你坚持使用字符串的变通方法,至少传递一个 XML 类型的值,而不是在 T-SQL 中转换和拆分。
【解决方案2】:

使用 XML 将逗号分隔值转换为表格。使用这个更新的程序。

USE [App]
GO
/****** Object:  StoredProcedure [dbo].[GetWorkspaceMapDetailsForUserByGroups]    
     Script Date: 16/02/2015 10:37:46 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[GetWorkspaceMapDetailsForUserByGroups]   
    @workspaceID int,
    @viewMap nvarchar(256)
 AS 

SELECT 
  m.*
FROM 
  GeoAppMapDef m
WHERE
 m.workspaceID = @workspaceID
 and m.IsDeleted = 0
 and m.ViewMap IN 
 (
  SELECT 
     Split.a.value('.', 'VARCHAR(100)') AS CVS  
  FROM  
  (
    SELECT CAST ('<M>' + REPLACE(@viewMap, ',', '</M><M>') + '</M>' AS XML) AS CVS 
  ) AS A CROSS APPLY CVS.nodes ('/M') AS Split(a)
)

【讨论】:

  • 当 SQL Server 已经支持表值参数时,为什么要这样做?更不用说,拆分字符串的方法比通过 XML 更简单。即使你这样做了,最好使用 XML 类型的参数并避免解析和转换的开销。
  • @kumar 感谢您的回复,此标记错误消息 2209,级别 16,状态 1,过程 GetWorkspaceMapDetailsForUserByGroups,第 19 行 XQuery [A.CVS.value()]: ',' 附近的语法错误 I不明白为什么
  • @John:我已经更新了结果。检查它并更新状态。
  • @Kumar 为您的帮助欢​​呼。效果很好!
  • 只有在100%确定字符串不包含任何 xml 字符的情况下,您才应该使用 xml 扩展来拆分字符串,例如,如果您尝试拆分 @987654323 @你会得到一个错误。但是,您仍然应该使用其他答案,这充其量是一种解决方法,而正确的解决方案是使用表值参数。您应该阅读this article 以及其中引用的文章。
猜你喜欢
  • 1970-01-01
  • 2017-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-20
  • 1970-01-01
  • 2018-09-22
  • 2011-07-13
相关资源
最近更新 更多