必须声明标量变量

时间:2017-01-17 15:40:11

标签: sql sql-server

我不明白为什么我一直收到这个错误。任何人都可以帮助我理解为什么会出现这个错误,非常感谢。我正在尝试更新大型数据库并尝试使用“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

3 个答案:

答案 0 :(得分:2)

使用\b\w*(cei|\bie|(?!c)\w(?=ie))\w*\b 将值传递给动态查询

中的变量
SP_EXECUTESQL

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 参数为@stmt类型,因此将NVARCHAR的数据类型从@updateSql更改为VARCHAR

答案 1 :(得分:1)

字符串不会自动知道它们包含变量。因此,忘记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并分配变量。注意:您不能将表名作为参数传入查询,因此您仍需要直接在字符串中提供。

答案 2 :(得分:1)

这是一种比使用循环更简单的方法,可能不需要经常运行。

$http

- 编辑 -

由于您声明您确实想要使用表来获取要更新的所有表名,这是一种使用不需要循环的动态SQL的方法。它构建了一长串sql语句来更新每个表,但不使用循环。我意识到15-16迭代的性能并不多,但这个例子是一种避免循环的方法,在我看来是更容易调试的代码。我也可以将这类事物概念化,而不是使用循环。

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)