2017-01-17 185 views
0

我不明白爲什麼我不斷收到此錯誤。任何人都可以幫助我理解爲什麼這個錯誤即將到來,將不勝感激。我正在嘗試更新大型數據庫,並試圖用'D:'替換所有附件的默認位置字符串。我覺得我很接近,但我不明白這個錯誤。這個查詢成功地遍歷了我所有保存在@Tables中的表名,但是在每個表中我都會得到這個錯誤。這裏是我的代碼... 錯誤:必須聲明標量變量「@oldPath」必須聲明標量變量

DECLARE @newPath VARCHAR(500); 
SET @newPath = 'D:\temp'; 

DECLARE @oldPath VARCHAR(500); 
SET @oldPath = (SELECT Value FROM Settings WHERE Name = 'AttachmentDirectoryPath'); 



DECLARE @Tables TABLE 
(
    myTableName VARCHAR(500) 
) 

insert into @Tables(myTableName) values ('WorkOrderMasterAttachments'); 
insert into @Tables(myTableName) values ('BillOfMaterialAttachments'); 
insert into @Tables(myTableName) values ('CustomerAttachments'); 
insert into @Tables(myTableName) values ('ToolAttachments'); 
insert into @Tables(myTableName) values ('FacilityAttachments'); 
insert into @Tables(myTableName) values ('LocationAttachments'); 
insert into @Tables(myTableName) values ('AssetAttachments'); 
insert into @Tables(myTableName) values ('ContractorAttachments'); 
insert into @Tables(myTableName) values ('VendorAttachments'); 
insert into @Tables(myTableName) values ('WorkOrderAttachments'); 
insert into @Tables(myTableName) values ('ClosedWorkOrderAttachments'); 
insert into @Tables(myTableName) values ('EmployeeAttachments'); 
insert into @Tables(myTableName) values ('PurchaseOrderAttachments'); 
insert into @Tables(myTableName) values ('PurchaseOrderHistoryAttachments'); 
insert into @Tables(myTableName) values ('PartAttachments'); 
insert into @Tables(myTableName) values ('AssetSystemAttachments'); 

DECLARE cursor_tables cursor 
FOR SELECT myTableName from @Tables 

OPEN cursor_tables 

DECLARE @loopTableName VARCHAR(100) 

fetch next from cursor_tables 
into @loopTableName 

DECLARE @updateSql VARCHAR(2000); 

WHILE @@FETCH_STATUS = 0 
BEGIN 

    SET @updateSql = ' UPDATE ' + @loopTableName + 
       ' SET Path = REPLACE(Path,@oldPath,@newPath)' 

    --print @updateSql 
    EXEC(@updatesql) 

    fetch next from cursor_tables 
    into @loopTableName 
END 

CLOSE cursor_tables 
DEALLOCATE cursor_tables 
+0

難道這不是一個很簡單的只寫你的15-16更新語句,而不是在循環中這樣做嗎?這會花費很少的打字,而且會更簡單。 –

+0

是的,但我將加載帶有名稱LIKE'%Attachments%'而不是所有插入語句的所有表的@Tables。 – techkris

+0

即使你正在使用動態sql,我也不會使用循環。使用動態sql來構建sql語句並一次執行它。 –

回答

2

使用SP_EXECUTESQL將值傳遞給變量的動態查詢裏面

DECLARE @updateSql NVARCHAR(2000) -- important 

SET @updateSql = ' UPDATE ' + QUOTENAME(@loopTableName) + 
      ' SET Path = REPLACE(Path,@oldPath,@newPath)' 

--print @updateSql 
EXEC sp_executesql @updatesql, 
    N'@oldPath VARCHAR(500),@newPath VARCHAR(500)', 
     @oldPath = @oldPath, @newPath = @newPath 

sp_executesql需要@stmt參數是的NVARCHAR類型,因此將@updateSql的數據類型從VARCHAR更改爲NVARCHAR

1

字符串不會自動kn它們包含變量。因此,忘記EXEC()作爲執行動態SQL的一般方法。記住:sp_executesql反而讓內環路:

SET @updateSql = ' UPDATE ' + @loopTableName + 
      ' SET Path = REPLACE(Path, @oldPath, @newPath)' 

exec sp_executesql @updatesql, 
    N'@oldPath varchar(500), @newPath varchar(500)', 
    @oldPath = @oldPath, @newPath = @newPath; 

這將執行SQL和分配變量。注意:您無法將表名稱作爲參數傳入查詢,因此您仍然需要直接在字符串中提供該名稱。

1

這是一個比使用循環更簡單的方法,它可能不是您需要頻繁運行的東西。

DECLARE @newPath VARCHAR(500) = 'D:\temp'; 

DECLARE @oldPath VARCHAR(500); 
SELECT @oldPath = Value 
FROM Settings 
WHERE Name = 'AttachmentDirectoryPath' 

update WorkOrderMasterAttachments SET Path = REPLACE(Path, @oldPath, @newPath) 
update BillOfMaterialAttachments SET Path = REPLACE(Path, @oldPath, @newPath) 
update CustomerAttachments SET Path = REPLACE(Path, @oldPath, @newPath) 
update ToolAttachments SET Path = REPLACE(Path, @oldPath, @newPath) 
update FacilityAttachments SET Path = REPLACE(Path, @oldPath, @newPath) 
update LocationAttachments SET Path = REPLACE(Path, @oldPath, @newPath) 
update AssetAttachments SET Path = REPLACE(Path, @oldPath, @newPath) 
update ContractorAttachments SET Path = REPLACE(Path, @oldPath, @newPath) 
update VendorAttachments SET Path = REPLACE(Path, @oldPath, @newPath) 
update WorkOrderAttachments SET Path = REPLACE(Path, @oldPath, @newPath) 
update ClosedWorkOrderAttachments SET Path = REPLACE(Path, @oldPath, @newPath) 
update EmployeeAttachments SET Path = REPLACE(Path, @oldPath, @newPath) 
update PurchaseOrderAttachments SET Path = REPLACE(Path, @oldPath, @newPath) 
update PurchaseOrderHistoryAttachments SET Path = REPLACE(Path, @oldPath, @newPath) 
update PartAttachments SET Path = REPLACE(Path, @oldPath, @newPath) 
update AssetSystemAttachments SET Path = REPLACE(Path, @oldPath, @newPath) 

- 編輯 -

既然你說你真的想用一個表來獲取所有的表名在這裏更新是使用動態SQL不需要循環的方法。它建立了一串很長的sql語句來更新每個表,但不使用循環。我意識到15-16次迭代的表現並不是很多,但這個例子是避免循環的一種方式,在我看來,更容易調試的代碼。這也是我對這種類型的東西的概念化,而不是使用循環。

DECLARE @Tables TABLE 
(
    myTableName VARCHAR(500) 
) 

insert into @Tables(myTableName) values ('WorkOrderMasterAttachments'); 
insert into @Tables(myTableName) values ('BillOfMaterialAttachments'); 
insert into @Tables(myTableName) values ('CustomerAttachments'); 
insert into @Tables(myTableName) values ('ToolAttachments'); 
insert into @Tables(myTableName) values ('FacilityAttachments'); 
insert into @Tables(myTableName) values ('LocationAttachments'); 
insert into @Tables(myTableName) values ('AssetAttachments'); 
insert into @Tables(myTableName) values ('ContractorAttachments'); 
insert into @Tables(myTableName) values ('VendorAttachments'); 
insert into @Tables(myTableName) values ('WorkOrderAttachments'); 
insert into @Tables(myTableName) values ('ClosedWorkOrderAttachments'); 
insert into @Tables(myTableName) values ('EmployeeAttachments'); 
insert into @Tables(myTableName) values ('PurchaseOrderAttachments'); 
insert into @Tables(myTableName) values ('PurchaseOrderHistoryAttachments'); 
insert into @Tables(myTableName) values ('PartAttachments'); 
insert into @Tables(myTableName) values ('AssetSystemAttachments'); 

declare @SQL nvarchar(max) = '' 

select @SQL = @SQL + 'Update ' + myTableName + ' set Path = REPLACE(Path,@oldPath,@newPath);' 
from @Tables 

select @SQL 

exec sp_executesql @SQL, N'@oldPath varchar(500), @newPath varchar(500)', @oldPath = @oldPath, @newPath = @newPath 
+0

這很有趣。我喜歡這個,可能會用這個而不是循環。我結束了裝載@Tables本: INSERT INTO @Tables(myTableName) \t SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES \t WHERE TABLE_NAME LIKE '%附件%' – techkris

+0

你可以完全跳過表變量,只是使用SYS.TABLES。我希望你在代碼中包含模式。如果是這樣,你不應該使用INFORMATION_SCHEMA.TABLES來確定模式。 https://msdn.microsoft.com/en-us/library/ms186224.aspx –