1

我正在尝试通过构建动态查询并将其存储在变量中并执行该变量来编写一个简单的 SP。

我目前收到以下错误:

消息 206,级别 16,状态 2,第 16 行
操作数类型冲突:datetime2 与浮点数不兼容

对于以下代码:

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)

据我所见,变量的类型与表列类型相同。有任何想法吗?

4

3 回答 3

3

I'm guessing it has something to do with your use of quotation marks, but it's quite hard to follow. I'd recommend using EXEC sp_executesql and passing your parameters as actual parameters. It's a little easier to do for a statement like this, and much more secure.

(Edited based on comment from 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

Read about sp_execultesql on MSDN here.

于 2013-04-15T14:29:30.610 回答
3

要动态创建正确的插入语句,您至少必须:

  1. 将变量转换为字符串:cast(@2 as varchar(11))
  2. 字符串中的双撇号:replace(@1, '''', '''''')
  3. 用撇号包装字符串(包括日期作为字符串):'''' + replace(@1, '''', '''''') + ''''
  4. 处理空值,因为连接空值会产生空值: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)
于 2013-04-15T15:11:42.260 回答
0

您的字符串连接中有一个转换问题。您需要将参数转换为 varchar 以构建字符串。

演员(@7 作为 varchar(50))。

FWIW,我认为您应该重新考虑如何构建查询。如果可能,请避免使用 EXEC()。您将遇到此解决方案的各种问题。您可能还会遇到 SQL 注入问题。如果黑客设法在参数@1 中发送 int SQL 代码,您的插入查询可能会被重写

于 2013-04-15T14:45:33.710 回答