Я всегда использовал бы
WHERE id IN (1,2,3,4,.....10000)
, если Ваш в пункте не был глупо большой, которого не должно действительно происходить от ввода данных пользователем.
редактирование: Например, направляющие делает это много негласно
, определенно не было бы лучше сделать отдельные операторы обновления в единственной транзакции.
Другая альтернатива должна сохранить те числа во временной таблице и использовать ее в соединении, чтобы сделать обновление. Если Вы можете выполниться, единственный оператор обновления определенно лучше, чем выполнение одного оператора на запись.
В Oracle существует предел значений, которые можно поместить в В пункте. Таким образом, Вы лучше используете a ИЛИ, x=1 или x=2... они не ограничены, насколько я знаю.
Как Вы генерируете В пункте?
, Если существует там другой оператор SELECT, который генерирует те значения, Вы могли просто включить это в ОБНОВЛЕНИЕ как так:
UPDATE TARGET_TABLE T
SET
SOME_VALUE = 'Whatever'
WHERE T.ID_NUMBER IN(
SELECT ID_NUMBER --this SELECT generates your ID #s.
FROM SOURCE_TABLE
WHERE SOME_CONDITIONS
)
В некотором RDBMses, Вы доберетесь, лучшая производительность при помощи СУЩЕСТВУЕТ синтаксис, который был бы похож на это:
UPDATE TARGET_TABLE T
SET
SOME_VALUE = 'Whatever'
WHERE EXISTS (
SELECT ID_NUMBER --this SELECT generates your ID #s.
FROM SOURCE_TABLE S
WHERE SOME_CONDITIONS
AND S.ID_NUMBER = T.ID_NUMBER
)
Я использовал бы табличную переменную / поддающийся соблазну; вставьте значения в это и соедините с ним. Затем можно использовать тот же набор многократно. Это работает особенно хорошо, если Вы (например), передаете CSV идентификаторов как varchar. Как пример SQL Server:
DECLARE @ids TABLE (id int NOT NULL)
INSERT @ids
SELECT value
FROM dbo.SplitCsv(@arg) // need to define separately
UPDATE t
SET t. // etc
FROM [TABLE] t
INNER JOIN @ids #i ON #i.id = t.id
Если бы Вы были на Oracle, то я рекомендовал бы использовать функции таблицы, подобные сообщению Marc Gravell.
-- first create a user-defined collection type, a table of numbers
create or replace type tbl_foo as table of number;
declare
temp_foo tbl_foo;
begin
-- this could be passed in as a parameter, for simplicity I am hardcoding it
temp_foo := tbl_foo(7369, 7788);
-- here I use a table function to treat my temp_foo variable as a table,
-- and I join it to the emp table as an alternative to a massive "IN" clause
select e.*
from emp e,
table(temp_foo) foo
where e.empno = foo.column_value;
end;
Не зная, каково "очень большое" количество идентификатора могло бы быть, я буду рисковать предположением. ;-)
, Так как Вы используете Доступ в качестве базы данных, количество идентификатора не может быть тот высоко. Принятие, о котором мы говорим меньше, чем, говорят 10 000 чисел, и мы должны знать, что ограничения контейнеров содержат идентификатор (какой язык используется для фронтэнда?), я придерживался бы одного UPDATE
оператор; если это является самым читаемым и самым легким выполнить обслуживание на позже. Иначе я разделил их на несколько операторов с помощью некоторой умной логики. Чему-то нравится, разделяет оператор на несколько операторов с в один, десять, сотня, тысяча... Идентификатор на оператор.
Затем я предоставил бы оптимизатору DB право выполнять оператор (операторы), максимально эффективный. Я, вероятно, сделал бы 'объяснение' на запросе / запросы, чтобы удостовериться, что ничто глупое не продолжается все же.
, Но по моему опыту, нормально довольно часто оставлять этот вид оптимизации к самому менеджеру базы данных. Одной вещью, которая занимает большую часть времени, обычно является фактическое соединение к базе данных, поэтому если можно выполнить все запросы в рамках того же соединения, это обычно не проблемы. Удостоверьтесь, что Вы отсылаете весь UPDATE
операторы, прежде чем Вы начнете изучать и ожидать любого возвращения наборов результатов все же. :-)
Я не знаю тип значений в Вашем В списке. Если они - большинство значений от 1 до 10 000, Вы смогли обрабатывать их для получения чего-то как:
WHERE MyID BETWEEN 1 AND 10000 AND MyID NOT IN (3,7,4656,987)
Или, если бы НЕ В списке все еще было бы длинно, обработав список и генерировав набор операторов BETWEEN:
WHERE MyID BETWEEN 1 AND 343 AND MyID BETWEEN 344 AND 400 ...
И т.д.
В последний раз всех, Вы не должны волноваться о том, как Струя обработает В пункте при использовании запроса к внешнему источнику данных. Вы не можете сделать этого в коде, но у Вас мог быть сохраненный QueryDef, который определяется как передача, и измените оператор Where в коде во времени выполнения для использования Вашего В списке. Затем это все выдано к SQL Server, и SQL Server решит лучше всего, как обработать его.
В целом существует несколько вещей рассмотреть.
Мы недавно изменили нашу систему, чтобы ограничить размер в пунктах и всегда использовать связанные переменные, потому что это сократило количество различных SQL-операторов и таким образом улучшило производительность. В основном мы генерируем наши SQL-операторы и выполняем несколько операторов, если в пункте превышает определенный размер. Мы не делаем этого для обновлений, таким образом, мы не должны были волноваться о блокировке. Вы будете.
Используя временную таблицу может не улучшить производительность, потому что необходимо заполнить временную таблицу с идентификаторами. Экспериментирование и тесты производительности могут сказать Вам ответ здесь.
А, единственный В пункте, очень легко понять и поддержать. Это, вероятно, о чем необходимо волноваться сначала. Если Вы находите, что производительность запросов плоха, Вы могли бы хотеть попробовать другую стратегию и видеть, помогает ли она, но не оптимизируйте преждевременно. В ПУНКТЕ семантически корректен, так оставьте его в покое, если это не повреждается.