将多选选定项目传递到 SQL Server 2008
Passing multiselect selected items into SQL Server 2008
我似乎无法在网上找到一个很好的例子。我想要做的是将多选列表框的所有值传递到 SQL 存储过程中,以将它们写入 table.
我知道如果我想将一个选定的值传递给 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 端我有一个函数将创建一个 table 值参数:
SELECT * FROM dbo.CSVToTable(@UserPreferences)
只需要一些帮助来完成 SQL 方面以及我需要包含的 2 个附加字段;用户 ID 和匹配字段。
- 不要使用
sp_
作为 procs 的前缀(这会损害性能,因为它会导致 SQL 服务器首先查看 [master]
数据库)
- 使用
SqlDbType.VarChar
- 指定最大长度(
-1
用于 MAX
,但我非常怀疑你甚至需要 8000 个字符)
@UserPreferences
的输入参数定义应具有匹配的最大长度(同样,没有理由使用 MAX
)
- 不要只是为了查找而传入
@UserName
。改为传入 @UserID
。如果在多个页面上使用它,请事先查找并将其存储在 Session 或 ViewState 中,否则在加载初始页面时获取它。
- 为什么要实例化一个
DataAdapter
?
- 您的 SQL 拆分函数不会创建 Table 值参数。它只是 returns 一个结果集。
INSERT INTO SchemaName.tmpUserMatch (
UserID,
MatchField,
MatchValue
)
SELECT
@UserID,
'MatchPreferences',
csv.SplitVal
FROM dbo.SplitCSV(@UserPreferences) csv;
从多选中获取列表:
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 服务器中,我使用这个 table 值函数:
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)))
我认为这可能对您有所帮助。
我似乎无法在网上找到一个很好的例子。我想要做的是将多选列表框的所有值传递到 SQL 存储过程中,以将它们写入 table.
我知道如果我想将一个选定的值传递给 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 端我有一个函数将创建一个 table 值参数:
SELECT * FROM dbo.CSVToTable(@UserPreferences)
只需要一些帮助来完成 SQL 方面以及我需要包含的 2 个附加字段;用户 ID 和匹配字段。
- 不要使用
sp_
作为 procs 的前缀(这会损害性能,因为它会导致 SQL 服务器首先查看[master]
数据库) - 使用
SqlDbType.VarChar
- 指定最大长度(
-1
用于MAX
,但我非常怀疑你甚至需要 8000 个字符) @UserPreferences
的输入参数定义应具有匹配的最大长度(同样,没有理由使用MAX
)- 不要只是为了查找而传入
@UserName
。改为传入@UserID
。如果在多个页面上使用它,请事先查找并将其存储在 Session 或 ViewState 中,否则在加载初始页面时获取它。 - 为什么要实例化一个
DataAdapter
? - 您的 SQL 拆分函数不会创建 Table 值参数。它只是 returns 一个结果集。
INSERT INTO SchemaName.tmpUserMatch (
UserID,
MatchField,
MatchValue
)
SELECT
@UserID,
'MatchPreferences',
csv.SplitVal
FROM dbo.SplitCSV(@UserPreferences) csv;
从多选中获取列表:
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 服务器中,我使用这个 table 值函数:
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)))
我认为这可能对您有所帮助。