我有一个SQL查询的大型int参数列表:
update mytable set col='xyz'
where id in (/* thousands of ints */)
我的问题是在SQL Server 2000中有参数限制。 我也可以在SQL Server 2008上运行此查询。
更好的方法是什么。
编辑:
ID列表来自 C#程序。不是从另一张桌子。
答案 0 :(得分:2)
您可以将整数插入临时表,然后像这样查询:
update mytable m set col='xyz'
where exists (select * from #MyTempTable where id = m.id)
答案 1 :(得分:2)
与SQL 2000一起使用的另一种方法是使用XML。
让程序/应用程序格式如下所示:
'<root><TMP J="111"/><TMP J="222"/><TMP J="333"/></root>'
。
然后创建以下存储过程:
CREATE PROCEDURE UpDateIntsFromXML (
@sXML TEXT
)
AS
DECLARE @iDoc INT
EXEC sp_xml_preparedocument @iDoc OUTPUT, @sXML
UPDATE YourTable
SET YourColumn = 'fixed value'
FROM OPENXML (@iDoc, '/root/TMP', 1) WITH (J INT) AS X
WHERE X.J = YourTable.IntColumn
EXEC sp_xml_removedocument @iDoc
RETURN
。
然后你的应用程序可以调用该SP,传递一个潜在的大块文本/ XML。
观察root
,TMP
和J
都是区分大小写的。
答案 2 :(得分:2)
对我来说最好的解决方案是SQL Server 2008: Table Valued Parameters
100000 Ids需要14-20s,1000 Ids需要~140 ms。
sql = @"
update MyTable
set Col1 = 1
where ID in (select * from @ids)
";
sqlCmd = new SqlCommand {Connection = _sqlConn, CommandText = sql};
//Create a DataTable with one Column("id") and all ids as DataRows
DataTable listOfLeadIDs = new DataTable();
listOfIDs.Columns.Add("id", typeof(int));
Ids.ToList<string>().ForEach(x => listOfIDs.Rows.Add(new object[] { int.Parse(x) }));
//Bind this DataTable to the Command-object
// Node: "IntTable" is an User-Defined-Table-Typ (new feature with SQL-2008)
sqlCmd.Parameters.Add(
new System.Data.SqlClient.SqlParameter("@ids", listOfIDs) {
TypeName = "IntTable"
});
//Execute the Query
sqlCmd.ExecuteNonQuery();
User-Defined-Table-Typ:
CREATE TYPE [dbo].[IntTable] AS TABLE(
[id] [int] NULL
)
GO
答案 3 :(得分:1)
不惜一切代价,避免 IN
;特别是如果你是2000年后。 my backup
相反,请使用EXISTS
UPDATE myTable
SET col = 'newValue'
FROM myTable
WHERE EXISTS (
SELECT *
FROM @myTempTable temp
WHERE myTable.ID = temp.ID)
答案 4 :(得分:0)
将数据划分为更小的组,并执行多个更新查询。
没有理由使用临时表,因为您从数据库外部检索数据,因此无法避免将数据传输到数据库。
答案 5 :(得分:0)
如果整数以任何方式连续(一次超过两个),您可以将它们变为BETWEEN
对。
但是在这种情况下,只需创建一个这些整数的字符串并将其作为单个varchar(max)
参数传递。
答案 6 :(得分:-2)
我认为你可能想要创建一个带索引的基于内存的临时表。假设您要查询的表很大,您不希望进行表扫描,将每行与5000个匹配项进行比较。您希望在两个索引的帮助下进行连接。
CREATE TEMPORARY TABLE IF NOT EXISTS inputlist
(i INT PRIMARY KEY) ENGINE = MEMORY;
INSERT INTO inputlist (i) VALUES (1),(2),(3),(1000),(2000),(5000);
SELECT * FROM your_table JOIN inputlist ON your_table.intvalues = inputlist.i;
DROP TEMPORARY TABLE inputlist;
基于MySQL的SQL,请参阅:
http://dev.mysql.com/doc/refman/5.1/en/memory-storage-engine.html
http://dev.mysql.com/doc/refman/5.1/en/insert.html
http://dev.mysql.com/doc/refman/5.1/en/create-table.html