在我用C#编写的应用程序中,我正在编写一个SQL查询。以下是查询
SELECT [Resource No_] where [Resource No_] In (@resources)
@resources
是具有一个或多个一个字符串的用户输入参数。
我的查询失败没有显示错误
据我所知,查询失败,因为正在传递@resources
参数
"'123,'124','125'"
(开头和结尾都有 2个引号“,但我的查询失败了。)
[Resource No_]
在数据库中的类型为NVARCHAR
。
在谷歌搜索之后,我在这个主题上找到了一些帮助,但是当[Resource No_]
的类型为Integer
答案 0 :(得分:5)
虽然我不同意“重复问题”的选定答案(或许多棘手的答案),here is an answer to it显示的方法与我的以下建议非常相似。
(我已经投票将此问题视为重复,因为是这样的答案,即使被埋没了。)
只有一个 SQL值可以绑定到任何给定的占位符。
虽然有办法将所有数据作为“一个值”发送,但我建议动态创建占位符:它简单,干净,并且在大多数情况下都能可靠地工作。
考虑一下:
ICollection<string> resources = GetResources();
if (!resources.Any()) {
// "[Resource No_] IN ()" doesn't make sense
throw new Exception("Whoops, have to use different query!");
}
// If there is 1 resource, the result would be "@res0" ..
// If there were 3 resources, the result would be "@res0,@res1,@res2" .. etc
var resourceParams = string.Join(",",
resources.Select((r, i) => "@res" + i));
// This is NOT vulnerable to classic SQL Injection because resourceParams
// does NOT contain user data; only the parameter names.
// However, a large number of items in resources could result in degenerate
// or "too many parameter" queries so limit guards should be used.
var sql = string.Format("SELECT [Resource No_] where [Resource No_] In ({0})",
resourceParams);
var cmd = conn.CreateCommand();
cmd.CommandText = sql;
// Assign values to placeholders, using the same naming scheme.
// Parameters prevent SQL Injection (accidental or malicious).
int i = 0;
foreach (var r in resources) {
cmd.Parameters.AddWithValue("@res" + i, r);
i++;
}
答案 1 :(得分:2)
SQL2005 +:我会使用XML参数。例如:
CREATE PROCEDURE dbo.MyProc (
@IntArrayAsXML XML
)
AS
BEGIN
DECLARE @IntArray TABLE(IntValue INT);
INSERT INTO @IntArray (IntValue)
SELECT x.XmlCol.value('(@IntValue)[1]', 'INT')
FROM @IntArrayAsXML.nodes('/root/row') x(XmlCol)
SELECT ... FROM dbo.MyTable t WHERE t.ID IN (SELECT v.IntValue FROM @IntArray v)
END;
GO
EXEC dbo.MyProc @IntArrayAsXML = N'<root> <row IntValue="11" /> <row IntValue="22" /> </root>'
GO
SQL2008 +:我会使用表类型参数。例如:
CREATE TYPE dbo.IntArray AS TABLE(IntValue INT) ;;
GO
CREATE PROCEDURE dbo.MyProc (
@IntArrayAsTable dbo.IntArray READONLY
)
AS
BEGIN
SELECT ... FROM dbo.MyTable t WHERE t.ID IN (SELECT v.IntValue FROM @IntArrayAsTable v)
END;
GO
DECLARE @p dbo.IntArray;
INSERT @p VALUES (11), (22);
EXEC dbo.MyProc @IntArrayAsTable = @p;
GO
另请参阅此MSDN example。
答案 2 :(得分:1)
使用用户定义的表类型接受您的参数,然后使用select中的JOIN子句来限制结果集。见http://social.msdn.microsoft.com/Forums/en-US/2f466c93-43cd-436d-8a7c-e458feae71a0/how-to-use-user-defined-table-types
答案 3 :(得分:-1)
执行类似
的操作resources.Aggregate(r1, r2 => r1 + "', '" + r2 + "'")
并将列表传递给一个字符串。