SQL Server直接查询正常,EXEC动态SQL遇int溢出错误求助
问题原因与解决方案
你这是踩了动态SQL拼接的常见坑——没给字符串参数加单引号,触发了不必要的类型转换。
为什么会报错?
直接拼接@document到SQL语句时,生成的动态SQL会变成这样:
SELECT * FROM a inner join b ON a.OpId = b.OpId ... WHERE f.document = 52147896
注意这里的52147896没有单引号,SQL Server会把它当作int类型处理。而你的f.document是varchar类型,里面存在像'99101500728'这种远大于int最大值(2,147,483,647)的值,当SQL尝试把这些varchar值转换成int做比较时,就触发了溢出错误。
解决方法
优先推荐参数化动态SQL,这是既安全又能避免类型问题的最佳实践:
declare @document varchar(20) = '52147896' DECLARE @SELECT2 nvarchar(max) = N'SELECT * FROM a inner join b ON a.OpId = b.OpId INNER JOIN c ON b.AdId = c.AdId INNER JOIN d ON c.AdId = d.AdId INNER JOIN e ON a.CId = e.CId INNER JOIN f ON b.OpId = f.OpId INNER JOIN g ON a.AdRId = g.AdRId INNER JOIN s ON c.AdSId = s.AdSId WHERE f.document = @doc' EXEC sp_executesql @SELECT2, N'@doc varchar(20)', @doc = @document
用sp_executesql传递参数,既保证了@document和f.document的类型匹配,又能防止SQL注入风险,还能避免手动拼接字符串的各种问题。
如果非要用字符串拼接的方式(不推荐,有安全隐患),需要给参数加上单引号(注意转义单引号,如果参数里包含单引号的话):
declare @document varchar(20) = '52147896' DECLARE @SELECT2 nvarchar(max) = N'SELECT * FROM a inner join b ON a.OpId = b.OpId INNER JOIN c ON b.AdId = c.AdId INNER JOIN d ON c.AdId = d.AdId INNER JOIN e ON a.CId = e.CId INNER JOIN f ON b.OpId = f.OpId INNER JOIN g ON a.AdRId = g.AdRId INNER JOIN s ON c.AdSId = s.AdSId WHERE f.document = ''' + @document + '''' EXEC(@SELECT2)
这种方式的缺点是,如果@document里包含单引号,会直接导致SQL语法错误,还存在SQL注入风险,所以尽量不用。
另外提醒一句:动态SQL的字符串尽量用nvarchar类型,并且给字符串常量加上N前缀(比如N'SELECT ...'),避免字符编码转换问题。
内容的提问来源于stack exchange,提问作者Lightning Snake
相关产品推荐
相关产品推荐

