Создание операторов SQL UPDATE на лету - PullRequest
1 голос
/ 09 сентября 2009

Я нахожусь в процессе обновления данных в нескольких таблицах. В настоящее время у меня есть таблица, которая имеет одно поле «sources», то есть просто список всех таблиц, которые включают поле «itemid» У меня также есть таблица, которая имеет 2 поля, "itemid" и "olditemid". В TSQL я хотел бы перебирать источники и создавать операторы обновления на лету. Вот что я пытался сделать, но я получаю некоторые ошибки в операторе обновления, что моя переменная не объявлена. Я не уверен, что это даже близко к тому, как я должен это делать. Идеи?

DECLARE @tblName varchar(50)

DECLARE process_cursor CURSOR FOR 
    SELECT source 
    FROM tmpTableNames

OPEN process_cursor

FETCH NEXT FROM processcursor 
INTO @tblName

WHILE @@FETCH_STATUS = 0

    UPDATE @tblName 
        SET itemid = r.itemid 
        FROM @tblName v, itemref r
        WHERE r.olditemid = v.itemid

    FETCH NEXT FROM process_cursor
    INTO @tblName

END
CLOSE processcursor
DEALLOCATE processcursor

Ответы [ 5 ]

4 голосов
/ 09 сентября 2009

То, что вы пытаетесь сделать, называется «динамический SQL». Пока вы на правильном пути, вы не можете просто вставить переменную вместо имени объекта и выполнить запрос. Я оставлю ловушки динамического SQL кому-то еще. То, что вы ищете, это:

DECLARE @tblName varchar(50)

DECLARE process_cursor CURSOR FOR 
    SELECT source 
    FROM tmpTableNames

OPEN process_cursor

FETCH NEXT FROM processcursor 
INTO @tblName

WHILE @@FETCH_STATUS = 0
BEGIN
    DECLARE @sql NVARCHAR(500)

    SELECT @sql = 'UPDATE [' + @tbleName + '] SET itemid = r.itemid FROM [' + @tbleName + '] v, itemref r WHERE r.ilditemid = v.itemid'

    EXEC sp_executesql @sql
    FETCH NEXT FROM process_cursor
    INTO @tblName

END
CLOSE processcursor
DEALLOCATE processcursor

Это превращает ваш запрос на обновление в строку, а затем передает SQL, содержащийся в этой строке, в хранимую процедуру sp_executesql (это рекомендуемый способ выполнения динамического sql, а не EXEC('foo')).

3 голосов
/ 09 сентября 2009

Я не думаю, что вы можете сделать это с помощью такой переменной. Вы можете использовать динамический SQL для обновления:

DECLARE @sql VARCHAR(1000)

SET @sql = 'UPDATE' + @tableName + etc..

EXEC ( @sql )

И просто сделайте это внутри вашего курсора.

1 голос
/ 09 сентября 2009

Вы не можете выполнить sql динамически, как это - вам нужно передать динамически сгенерированную строку в функцию exec следующим образом:

DECLARE @tblName varchar(50)

DECLARE process_cursor CURSOR FOR 
    SELECT source 
    FROM tmpTableNames

OPEN process_cursor

FETCH NEXT FROM processcursor 
INTO @tblName

WHILE @@FETCH_STATUS = 0

    Declare @sql varchar(5000)
    Select @sql = 'UPDATE ' + @tblName +  
        'SET itemid = r.itemid 
        FROM ' + @tblName + ' v, itemref r
        WHERE r.olditemid = v.itemid'

    Exec @sql
    FETCH NEXT FROM process_cursor
    INTO @tblName

END
CLOSE processcursor
DEALLOCATE processcursor
0 голосов
/ 09 сентября 2009

Мне никогда не удавалось работать с операторами UPDATE на основе переменных (т. Е. UPDATE @tblName), если я не собрал их в строку и не выполнил их динамически, как в:

EXEC 'UPDATE ' + @tblName + '
SET ItemId = (SELECT r.ItemId FROM itemref r WHERE r.OldItemId = ' + @tblName + '.itemId)'

Для таблицы TheTable это должно расшириться до:

EXEC 'UPDATE TheTable
      SET ItemId = (SELECT r.ItemId FROM itemref r WHERE r.OldItemId = TheTable.ItemId)'
0 голосов
/ 09 сентября 2009

ты пробовал ОБЪЯВИТЬ @tblName varchar (50)? Я бы подумал, что это сделает.

...