Создание операторов SQL UPDATE на лету
Я нахожусь в процессе обновления данных в нескольких таблицах. В настоящее время у меня есть таблица, которая имеет одно поле "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 ответов
То, что вы пытаетесь сделать, называется "динамический 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')
).
Я не думаю, что вы можете сделать это с помощью такой переменной. Вы можете использовать динамический SQL для обновления:
DECLARE @sql VARCHAR(1000)
SET @sql = 'UPDATE' + @tableName + etc..
EXEC ( @sql )
И просто сделай это внутри своего курсора.
Вы не можете выполнить 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
Вы пробовали объявить @tblName varchar(50)? Я думаю, что это сделало бы это.
Я никогда не был успешным с основанными на переменных операторами 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)'