我试图通过构建动态查询并存储在变量中并执行变量来编写一个简单的SP。
我目前收到以下错误:
Msg 206,Level 16,State 2,Line 16
不兼容
操作数类型冲突:datetime2与float
以下代码:
DECLARE
@table_Num
@1 varchar(100) = 'boo',
@2 int =2,
@3 varchar(100) ='default',
@4 varchar(50) = NULL,
@5 int =NULL,
@6 float =12,
@7 datetime2(0) ='1970-01-01 00:00:00',
@8 datetime2(0)='1970-01-01 00:00:00',
@9 varchar(50)='',
@10 varchar(50)=NULL,
@11 decimal(18,0)=0000000000000,
@12 int =999999
DECLARE @SQLString NVARCHAR(MAX)
SET @SQLString = 'INSERT INTO abc_'+@table_Num+'(col1, col2, col3, col4, col5, col6, col7, col8, col9, col10, col11, col12)
VALUES ('+@1+',2,'+@3+','+@4+','+@5+','+@6+','+@7+','+@8+','+@9+','+@10+','+@11+','+@12+')'
EXEC (@SQLString)
据我所知,变量与表格类型的类型相同。有什么想法吗?
答案 0 :(得分:3)
我猜这与你使用引号有关,但是很难遵循。我建议使用EXEC sp_executesql
并将参数作为实际参数传递。对于这样的声明来说,这样做更容易一些,而且更加安全。
(根据TimLehner的评论编辑)
DECLARE @SQLString NVARCHAR(MAX), @ParamString NVARCHAR(MAX), @TableName sysname;
SET @TableName = N'abc_' + REPLACE(@table_num, '''', ''''''); --Escape apostrophes
IF OBJECT_ID(@TableName) IS NOT NULL
BEGIN
SET @SQLString =
N'INSERT INTO ' + QUOTENAME(@TableName) +
N' (col1, col2, col3, col4, col5, col6, col7, col8, col9, col10, col11, col12)
VALUES (@1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @11, @12)';
SET @ParamString = N'@1 varchar(100), @2 int, @3 varchar(100), ... , @12 int)';
EXEC sp_executesql @SQLString, @ParamString, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @11, @12
END
答案 1 :(得分:3)
要动态创建正确的insert语句,您至少需要:
cast(@2 as varchar(11))
replace(@1, '''', '''''')
'''' + replace(@1, '''', '''''') + ''''
coalesce(cast(@5 as varchar(11)), 'null')
这看起来不是很糟糕吗?
正如其他人所说,这是运行动态SQL的最糟糕方式,并打开了一个名为 SQL Injection 的主要安全漏洞。如果这需要是动态的,请使用带有类型参数的sp_executesql
(谢谢,@ JeffRosenberg)。但是,这个简单的插入也是一个简单的例子,根本不需要动态SQL(谢谢@AaronBertrand)。只需按原样运行命令:
INSERT INTO table_1 (col1, col2, /* ... */ col12)
VALUES (@1, @2, /* ... */ @12)
答案 2 :(得分:0)
您的字符串连接中存在转换问题。您需要将参数转换为varchar以构建字符串。
cast(@ 7 as varchar(50))。
FWIW,我认为您应该重新考虑如何构建查询。如果可能,请避免使用EXEC()。您将遇到此解决方案的各种问题。您可能还会遇到SQL注入问题。如果黑客设法发送int SQL代码,则可以重写您的插入查询。参数@ 1