Большой список параметров для SQL-запроса - PullRequest
8 голосов
/ 25 октября 2010

У меня большой список параметров int для SQL-запроса:

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

Моя проблема в том, что в SQL Server 2000 есть ограничение на параметры. Я мог бы также выполнить этот запрос на SQL Server 2008.

Какой лучший способ сделать это.

Edit:

Список идентификаторов взят из C # программы. Не из другого стола.

Ответы [ 7 ]

2 голосов
/ 26 октября 2010

Альтернативный подход, который работает с 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, TMPJ чувствительны к регистру.

2 голосов
/ 29 октября 2010

Лучшим рабочим решением для меня было SQL Server 2008: табличные параметры

100000 идентификаторов нужно 14-20 с, 1000 идентификаторов ~ 140мс.

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();

Определяемый пользователем тип таблицы:

CREATE TYPE [dbo].[IntTable] AS TABLE(
    [id] [int] NULL
)
GO
2 голосов
/ 25 октября 2010

Вы можете вставить целые числа во временную таблицу, а затем выполнить запрос следующим образом:

update mytable m set col='xyz' 
where exists (select * from #MyTempTable where id = m.id)
1 голос
/ 25 октября 2010

Любой ценой, ИЗБЕГАТЬ IN; особенно если вы после 2000 года. моя резервная копия


Вместо этого используйте EXISTS

UPDATE myTable
SET col = 'newValue'
FROM myTable 
WHERE EXISTS (
      SELECT * 
      FROM @myTempTable temp
      WHERE myTable.ID = temp.ID)
0 голосов
/ 26 октября 2010

Я думаю, что вы, вероятно, хотите создать временную таблицу на основе памяти с индексом.Предполагая, что таблица, к которой вы обращаетесь, велика, вы не захотите делать сканирование таблицы, сравнивая каждую строку с каждым из ваших 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;

SQL на основе MySQL, см .:
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

0 голосов
/ 26 октября 2010

Если целые числа каким-либо образом последовательны (более двух одновременно), вы можете превратить их в пары BETWEEN.

Но в этом случае просто создайте строку из этих целых и передайте ее как один varchar(max) параметр.

0 голосов
/ 26 октября 2010

Разделите данные на более мелкие группы и выполните несколько запросов на обновление.

Нет смысла использовать временную таблицу, поскольку вы извлекаете данные извне БД, поэтому нет способа избежать их передачи в БД.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...