什么是错误数据类型varchar和datetime2在add运算符中不兼容

时间:2014-09-24 05:54:48

标签: sql sql-server database

DECLARE @State VARCHAR(32) =NULL,
        @Industry varchar(128)= NULL,
        @ListSource varchar(128) = NULL,
        @TimeZone VARCHAR(30) =NULL
DECLARE @Today DATETIME
SET     @Today = GETDATE() 
DECLARE @sSQL NVARCHAR(3000)
SET @State=1
SET @Industry=1
SET @ListSource=1
SET @TimeZone=5
SET @sSQL = 
'SELECT top 20 p.ID'+ 
CHAR(10) +'from dbo.Prospects P WITH (NOLOCK)'+ CHAR(10) +
'where p.State=ISNULL('+ CHAR(39)+@State +CHAR(39)+','+'p.State)'+ CHAR(10) +
'AND p.Industry ='+@Industry + CHAR(10) +'AND p.ListSource='+@ListSource+ CHAR(10) +'
AND p.StatusID not in(-1,2,4,5,6,7,8,9,12,13,14)'+ CHAR(10) +'
AND isnull(p.PushDate,'+CHAR(39)+'1/1/1900'+CHAR(39)+')<='+CHAR(39)+@Today+CHAR(39)+
CHAR(10) +'AND p.TimeZone ='+@TimeZone+ CHAR(10) +'
order by isnull(p.LastActivityDate,'+CHAR(39)+'1/1/1900'+CHAR(39)+')'

2 个答案:

答案 0 :(得分:6)

这是当前的问题:

')<='+CHAR(39)+@Today+CHAR(39)

您尝试在字符串连接中使用DATETIME。日期不是文本 - 它是一个日期。因此,如果要在字符串连接中使用它,则需要先将其转换为文本,例如

')<=' + CHAR(39) + CONVERT(VARCHAR(23), @Today, 126) + CHAR(39)

(有关可用样式,请参阅CAST and CONVERT documentation。根据我的估算,样式126需要23个字符。)

下一个问题是,像这样构建SQL是非常不安全的 - 即使客户端做了正确的事情并使用参数调用了您,您也很容易受到SQL注入攻击。您还没有向我们展示您使用sSQL 的内容,但您应该尽可能努力地尝试构建动态SQL。几乎当然是一个更好的解决方案。通过避免使用动态SQL,您最终会得到:

  • 很多更易读的代码(每个CHAR(39)都会跟着字符串连接)
  • 针对SQL注入攻击的安全性
  • 非文本值与文本之间的转换次数减少,从而减少了出错的机会

答案 1 :(得分:0)

连接@Today时,必须先将其转换为VARCHAR以防止出错。

CONVERT(VARCHAR(10), @Today, 101)