SQL查询的大参数列表

时间:2010-10-25 16:08:18

标签: c# sql-server sql-server-2008 sql-server-2000

我有一个SQL查询的大型int参数列表:

update mytable set col='xyz'
where id in (/* thousands of ints */)

我的问题是在SQL Server 2000中有参数限制。 我也可以在SQL Server 2008上运行此查询。

更好的方法是什么。

编辑:

ID列表来自 C#程序。不是从另一张桌子。

7 个答案:

答案 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。

观察rootTMPJ都是区分大小写的。

答案 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