在 C# 的 SQL 语句中使用来自 int[] 的值
Use values from int[] in SQL statement in C#
我有以下 SQL 我想要的声明 运行:
string sql = @"DECLARE @a udt;" +
"INSERT INTO @a (id) VALUES @params;";
我有以下整数数组:
int[] array1 = {10,20,30,40,50,60};
重要的是,上面的数组大小在我的程序中不是动态的。
我想将数组中的值添加到 SQL 语句中的 @params
,以便 SqlCommand
中执行的 SQL 看起来像这样:
sql = @"DECLARE @a udt;" +
"INSERT INTO @a (id) VALUES (10),(20),(30),(40),(50),(60);" +
"EXEC sp @a;";
我尝试了以下方法,但不断收到异常:
SqlConnection con = new SqlConnection("connectionString");
SqlCommand cmnd = new SqlCommand(sql, con);
for (int i = 0; i < array1.Count; i++)
{
cmnd.Parameters.AddWithValue("@params" , array1[i]);
}
con.open().
cmnd.ExecuteNonQuery();
请有人解释我做错了什么。我还需要确保防止 SQL 注入。
根据@params
参数加入Int数组进行格式化:
int[] intArr = { 10, 20, 30 };
string intStr = string.Join(",", intArr.Select(i => "(" + i.ToString() + ")"));
intStr
的格式为 (10),(20),(30)
,您将其传递给 sql。创建动态语句并执行。
-- declared here for sample
declare @params varchar(50) = '(10),(20),(30)'
declare @sql varchar(max) =
'declare @a table (id int)' + ';' +
'insert into @a (id) values ' + @params + ';' +
'exec sp @a'
exec (@sql)
您可以为您的值子句使用生成动态 SQL。由于计划缓存重用不佳,这将导致一些性能开销,具体取决于此代码 运行 的频率。
我会将数组作为定界字符串传递给过程,并使用 SQL 字符串拆分器将字符串转换为 table。这允许您将单个参数传递给过程并可能绕过 UDT。
Web 搜索提供了多种字符串拆分器。您发现使用循环的任何方法都会很慢,但会起作用。我个人更喜欢 Jeff Moden 的内联 table 值函数 [DelimitedSplit8K](需要免费注册,但我认为这是非常值得的)这可能是最快的 TSQL 字符串拆分器。
任何拆分器的用法与此类似:
DECLARE @a udt;
INSERT INTO @a([id])
SELECT [Item]
FROM [dbo].[DelimitedSplit8K](@params)
这会将 {10,20,30,40,50,60} 转换为每行一个值的 table。
另一种用法是加入:
SELECT
[col1],
[col2],
[ItemNumber] -- position in array
FROM [dbo].[MyTable] A
INNER JOIN [dbo].[DelimitedSplit8K](@params) B
ON A.[col3] = B.[Item] -- join on array value
您已接近您的解决方案,但您需要在 sql 字符串中明确引用每个数组索引参数。例如:
List<int> tests = new List<int>() { 10, 11, 12};
var command = new MySqlCommand();
List<string> parameterNames = new List<string>();
for (int i = 0; i < tests.Count; i++)
{
string parameterName = String.Format("@test{0}", i);
command.Parameters.AddWithValue(parameterName, tests[i]);
parameterNames.Add("(" + parameterName + ")");
}
string insertSql = @"insert into test(id) values {0}";
command.CommandText = String.Format(insertSql, String.Join(", ", parameterNames));
command.Connection = connection;
int result = command.ExecuteNonQuery();
生成的 sql 命令文本将是:
"insert into test(id) values (@test0), (@test1), (@test2)"
我有以下 SQL 我想要的声明 运行:
string sql = @"DECLARE @a udt;" +
"INSERT INTO @a (id) VALUES @params;";
我有以下整数数组:
int[] array1 = {10,20,30,40,50,60};
重要的是,上面的数组大小在我的程序中不是动态的。
我想将数组中的值添加到 SQL 语句中的 @params
,以便 SqlCommand
中执行的 SQL 看起来像这样:
sql = @"DECLARE @a udt;" +
"INSERT INTO @a (id) VALUES (10),(20),(30),(40),(50),(60);" +
"EXEC sp @a;";
我尝试了以下方法,但不断收到异常:
SqlConnection con = new SqlConnection("connectionString");
SqlCommand cmnd = new SqlCommand(sql, con);
for (int i = 0; i < array1.Count; i++)
{
cmnd.Parameters.AddWithValue("@params" , array1[i]);
}
con.open().
cmnd.ExecuteNonQuery();
请有人解释我做错了什么。我还需要确保防止 SQL 注入。
根据@params
参数加入Int数组进行格式化:
int[] intArr = { 10, 20, 30 };
string intStr = string.Join(",", intArr.Select(i => "(" + i.ToString() + ")"));
intStr
的格式为 (10),(20),(30)
,您将其传递给 sql。创建动态语句并执行。
-- declared here for sample
declare @params varchar(50) = '(10),(20),(30)'
declare @sql varchar(max) =
'declare @a table (id int)' + ';' +
'insert into @a (id) values ' + @params + ';' +
'exec sp @a'
exec (@sql)
您可以为您的值子句使用生成动态 SQL。由于计划缓存重用不佳,这将导致一些性能开销,具体取决于此代码 运行 的频率。
我会将数组作为定界字符串传递给过程,并使用 SQL 字符串拆分器将字符串转换为 table。这允许您将单个参数传递给过程并可能绕过 UDT。
Web 搜索提供了多种字符串拆分器。您发现使用循环的任何方法都会很慢,但会起作用。我个人更喜欢 Jeff Moden 的内联 table 值函数 [DelimitedSplit8K](需要免费注册,但我认为这是非常值得的)这可能是最快的 TSQL 字符串拆分器。
任何拆分器的用法与此类似:
DECLARE @a udt;
INSERT INTO @a([id])
SELECT [Item]
FROM [dbo].[DelimitedSplit8K](@params)
这会将 {10,20,30,40,50,60} 转换为每行一个值的 table。
另一种用法是加入:
SELECT
[col1],
[col2],
[ItemNumber] -- position in array
FROM [dbo].[MyTable] A
INNER JOIN [dbo].[DelimitedSplit8K](@params) B
ON A.[col3] = B.[Item] -- join on array value
您已接近您的解决方案,但您需要在 sql 字符串中明确引用每个数组索引参数。例如:
List<int> tests = new List<int>() { 10, 11, 12};
var command = new MySqlCommand();
List<string> parameterNames = new List<string>();
for (int i = 0; i < tests.Count; i++)
{
string parameterName = String.Format("@test{0}", i);
command.Parameters.AddWithValue(parameterName, tests[i]);
parameterNames.Add("(" + parameterName + ")");
}
string insertSql = @"insert into test(id) values {0}";
command.CommandText = String.Format(insertSql, String.Join(", ", parameterNames));
command.Connection = connection;
int result = command.ExecuteNonQuery();
生成的 sql 命令文本将是:
"insert into test(id) values (@test0), (@test1), (@test2)"