【问题标题】:Passing multiselect selected items into SQL Server 2008将多选选定项传递到 SQL Server 2008
【发布时间】:2015-07-10 16:33:11
【问题描述】:

我似乎无法在网上找到一个很好的例子。我想要做的是将多选列表框的所有值传递到 SQL 存储过程中以将它们写入表。

我知道如果我想将一个选定的值传递给 SQL,我会这样做:

C#:

using (SqlCommand cmd = new SqlCommand("sp_RegisterUser", conn))
{
    cmd.CommandType = CommandType.StoredProcedure;
    using (SqlDataAdapter da = new SqlDataAdapter(cmd))
        cmd.Parameters.Add("@UserPreferences", SqlDbType.Char).Value = MatchPrefs.SelectedValue;
        cmd.Parameters.Add("@UserName", SqlDbType.Char).Value = UserName.Text;

    conn.Open();
    cmd.ExecuteNonQuery();

SQL:

ALTER PROCEDURE [dbo].[sp_RegisterUser]
    @UserPreferences varchar(max),
    @UserName varchar(25)

AS
BEGIN

INSERT INTO tmpUserMatch (
    UserID,
    MatchField,
    MatchValue

    )
VALUES (
    (SELECT Top 1 UserID FROM tmpUsers WHERE UserName = @UserName),
    'MatchPreferences',
    @UserPreferences
    )

END     

但是如果 MatchPrefs 是多选,我该怎么做呢?

编辑

通过替换,我将 C# 部分关闭:

cmd.Parameters.Add("@UserPreferences", SqlDbType.Char).Value = MatchPrefs.SelectedValue;

与:

var selectedInterests = MatchPrefs.Items.Cast<ListItem>().Where(item => item.Selected).Select(item => item.Value).ToList();
string strInterests = String.Join(",", selectedInterests).TrimEnd();
cmd.Parameters.Add("@UserPreferences", SqlDbType.Char).Value = strInterests;

在 SQL 端,我有一个函数将创建一个表值参数:

SELECT * FROM dbo.CSVToTable(@UserPreferences)

只需要一些帮助来完成我需要包含的 2 个附加字段的 SQL 方面; UserID 和 MatchField。

【问题讨论】:

  • 您想查看 ADO.NET 中的结构化参数以及 SQL Server SP 中的等效表值参数。基本上,它允许您将强类型的对象列表推送到 SQL Server SP/查询。这里和互联网上有很多例子。
  • 那么如何使用我需要添加到 SQL 表(UserID 和 MatchField)的 2 个附加字段来完成?
  • 附带说明,您应该避免使用 sp_ 前缀,因为它是微软保留的,可能会导致一些性能问题。 sqlperformance.com/2012/10/t-sql-queries/sp_prefix 或者事件更好,完全去掉前缀。
  • 我将参数作为 XML 传递。您可以在您的应用程序中以多种不同的方式创建它,并且在 SQL 中处理 XML 相当容易。这为您提供了最佳的灵活性...

标签: c# sql asp.net sql-server multi-select


【解决方案1】:
  1. 不要在 procs 前加上 sp_(这会损害性能,因为它会导致 SQL Server 首先查看 [master] DB)
  2. 使用SqlDbType.VarChar
  3. 指定最大长度(-1 用于 MAX,但我非常怀疑您是否需要 8000 个字符)
  4. @UserPreferences 的输入参数定义应具有匹配的最大长度(同样,没有理由使用 MAX
  5. 不要传入@UserName,只是为了方便您查找。改为传入@UserID。如果您在多个页面上使用它,请预先查找并将其存储在 Session 或 ViewState 中,否则在加载初始页面时获取它。
  6. 为什么要实例化DataAdapter
  7. 您的 SQL 拆分函数不会创建表值参数。它只是返回一个结果集。
INSERT INTO SchemaName.tmpUserMatch (
    UserID,
    MatchField,
    MatchValue
)
SELECT
    @UserID,
    'MatchPreferences',
    csv.SplitVal
 FROM dbo.SplitCSV(@UserPreferences) csv;

【讨论】:

    【解决方案2】:

    从多选中获取列表:

        private string GetList(ListItemCollection list)
        {
            string separadosporcoma = "";
    
            if (list.Count > 0)
            {
                foreach (ListItem item in list)
                    separadosporcoma += item.Value + ",";
                separadosporcoma = separadosporcoma.TrimEnd(',');
            }
            return separadosporcoma;
        }
    

    在 SQL Server 中,我使用这个表值函数:

    ALTER function [dbo].[fn_ParseCSVString]
    (
    @CSVString  varchar(8000) ,
    @Delimiter  varchar(10)
    )
    returns @tbl table (s varchar(1000))
    as
    begin
    declare @i int ,
        @j int
        select  @i = 1
        while @i <= len(@CSVString)
        begin
            select  @j = charindex(@Delimiter, @CSVString, @i)
            if @j = 0
            begin
                select  @j = len(@CSVString) + 1
            end
            insert  @tbl select substring(@CSVString, @i, @j - @i)
            select  @i = @j + len(@Delimiter)
        end
        return
    end
    

    在 where 子句中的存储过程中,我像这样调用 sql 函数:

    ALTER PROCEDURE [dbo].[GetValuesWithList] 
    @MyList AS VARCHAR(1000)
    SELECT values
    FROM MyTable
    WHERE items in (SELECT * FROM dbo.fn_ParseCSVString(@MyList, ',') fn_ParseCSVString)))
    

    我想这可能会对你有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-01-10
      • 2013-09-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-19
      • 1970-01-01
      相关资源
      最近更新 更多