【发布时间】:2019-05-17 19:11:26
【问题描述】:
我之前多次运行过这种类型的代码,但在另一个组织的另一个环境中运行,并且 SQL Server 上的版本不完全相同。下面的示例代码已简化,但它可以作为我的问题的示例。
在此示例中,我尝试在几年内进行循环(“ar”变量),并为每年在另一个数据库中创建一个新表,而不是原始表的保存位置。原始表包括所有年份。原表中的“ar”变量是一个int。
我的代码如下所示:
declare @Ar int = 2007
declare @ArVC varchar(4)=''
declare @CreateTable varchar(MAX)=''
declare @DB varchar(MAX)='MIRK3utv'
while @Ar <= 2015
begin
set @ArVC = cast(@Ar as varchar)
set @CreateTable = '
select *
into ' + @DB + 'dbo.Tab_' + @ArVC + '
from DBorg.dbo.OrgTab
where ar = ' + @ArVC
exec @CreateTable
set @Ar = @Ar + 1
end
这给了我一个错误,上面写着:
消息 203,第 16 级,状态 2,第 34 行 名字 ' 选择 * 进入 MIRK3utv.dbo.Tab_2007 来自 DBorg.dbo.OrgTab 其中 ar = 2007' 不是有效标识符。
我在这里缺少什么?我已经在网上和这个论坛上搜索了答案,但在这种情况下我似乎找不到适合我的解决方案。
【问题讨论】:
-
你应该使用
QUOTENAME(@DB)和QUOTENAME('Tab'+@ArVC)来避免SQL注入。 -
而
@CreateTable应该是NVARCHAR(MAX)以支持Unicode 命名对象 -
而且
@DB也应该是Unicode,最好是sysname类型,因为它确实代表系统对象(数据库名称) -
最后,将
@ArVC作为参数传递给sp_executesql以避免在执行SQL 中嵌入值的问题:set @CreateTable = N'select * from ... where ar = @ArVC和exec sp_executesql @createSQL, N'@ArVC varchar(4)', @ArVC
标签: sql sql-server sql-server-2014 declare scalar