Укороченный запрос - PullRequest
       3

Укороченный запрос

2 голосов
/ 09 января 2012

В исходной и целевой таблицах около 40 столбцов. Число строк, подлежащих обновлению, составляет около 20. Количество строк в таблице «Назначение» составляет около 30 тыс.

Есть ли лучший (более короткий запрос) подход к описанному ниже?

UPDATE destination_table t1
SET 
field1 = (select field1 from src_table t2 where t2.pk = t1.pk),
field2 = (select field2 from src_table t2 where t2.pk = t1.pk),
... 
field40 = (select field40 from src_table t2 where t2.pk = t1.pk),
WHERE EXISTS (select 1 from src_table t2 where t2.pk = t1.pk)

Ответы [ 3 ]

5 голосов
/ 09 января 2012

Вы можете использовать что-то вроде этого:

UPDATE      dest
SET         dest.Field1 = src.Field1,
            dest.Field2 = src.Field2,
            dest.Field3 = src.Field3,
            dest.Field4 = src.Field4,
            dest.Field5 = src.Field5,
            dest.Field6 = src.Field6
FROM        destination_table dest
INNER JOIN  src_table src
ON          src.pk = dest.pk

Вам просто нужно добавить дополнительные поля для обновления.

3 голосов
/ 09 января 2012
update t1 set
    field1 = t2.field1,
    field2 = t2.field2,
    ... 
    field40 = t2.field40,
from destination_table t1
join src_table t2 on t2.pk = t1.pk

Добавлено (после комментария):

По моему мнению, лучше избегать динамических запросов, но если вы действительно хотите, вы можете сделать это так, как показано ниже.Запрос сгенерирован и нет необходимости записывать все столбцы, но все столбцы будут обновлены.

declare @sql as nvarchar(max)
set @sql = ''

select @sql = @sql + ', ' + column_name + ' = t2.' + column_name
from information_schema.columns
where table_name = 'destination_table'

set @sql =
    'update t1 set ' + 
    stuff(@sql, 1, 2, '') +
    ' from destination_table t1 join src_table t2 on t2.pk = t1.pk'

exec sp_executesql @sql
1 голос
/ 10 января 2012

Ваш исходный запрос - это стандартный скалярный подзапрос SQL-92 **. Одна из причин, по которой он предпочтет (кроме понятий переносимости), заключается в том, что собственный синтаксис UPDATE..FROM..JOIN в SQL Server дает потенциально неоднозначные и неожиданные результаты.

Однако подход «скалярный подзапрос», безусловно, многословен (хотя умный оптимизатор обнаружит повторяющийся код). В качестве стандарта в SQL-99 был введен оператор MERGE, который был реализован (с полезными расширениями) в SQL Server 2008, например.

MERGE INTO destination_table
   USING src_table t2
      ON t2.pk = destination_table.pk
WHEN MATCHED THEN
   UPDATE 
      SET field1 = T2.field1, 
          field2 = T2.field2, 
          field2 = T2.field3, 
          ...
          field40 = T2.field40;

Поскольку вы не поддерживаете унаследованный (до 2008 года) код и предполагаете, что у вас нет непосредственных планов портировать на продукт SQL, который не поддерживает MERGE (отмечая, что Oracle и postgreSQL поддерживают, а mySQL нет), я не вижу причин для этого. использовать любую конструкцию, отличную от MERGE, для такого рода обновлений.


** ну почти. Ваше обновление предназначено для таблицы с именем корреляции 't1`. В SQL-92 имя корреляции должно иметь эффект материализации таблицы, которая выходит из области видимости в конце оператора SQL. Другими словами, хотя синтаксис действителен, результатом должно быть то, что данные в базовой базовой таблице остаются неизменными. Тем не менее, кажется очевидным, что это не является целью вашего обновления, и в действительности SQL Server действительно влияет на базовые таблицы, что является технически несовместимым поведением!

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