代码之家  ›  专栏  ›  技术社区  ›  lije

动态sql中的减法

  •  0
  • lije  · 技术社区  · 7 年前

    我正在更新一个存储过程,以将报告时间更改为客户端时区。存储过程由一个动态sql组成,它包含smallint数据类型的time@timeoffset参数。

      DECLARE @sql VARCHAR(MAX) = 
      N'SELECT DISTINCT cl.ClientId, 
      CASE WHEN DATEADD(HOUR,'+CONVERT(CHAR(2),@timeoffset)+', x.changedate) >= '''+ CONVERT(varchar, @start_date) +''' 
      AND DATEADD(HOUR,'+CONVERT(CHAR(2),@timeoffset)+', x.changedate) < '''+ CONVERT(varchar, @end_date_plus1) +''' 
      THEN DATEADD(HOUR,'+CONVERT(CHAR(2),@timeoffset)+',x.changedate)' 
    

    要将时间更改为客户端的时区,我需要减去@timeoffset。使其为负不会改变输出。 在转换之前尝试添加(-)将引发错误,因为减法运算符对varchar无效。写它 如果不进行转换,则会引发错误 '将nvarchar值转换为数据类型smallint时转换失败。

    有人能帮我吗?谢谢.

    2 回复  |  直到 7 年前
        1
  •  1
  •   parliamentowl    7 年前

    您可以尝试将负数作为另一个变量传递:

    DECLARE @neg INT = -1;
    DECLARE @sql VARCHAR(MAX) = 
    N'SELECT DISTINCT cl.ClientId, 
    CASE WHEN DATEADD(HOUR,'+CONVERT(CHAR(2),@timeoffset)*@neg+', x.changedate) >= '''+ 
    CONVERT(varchar, @start_date) +''' 
    AND DATEADD(HOUR,'+CONVERT(CHAR(2),@timeoffset)*@neg+', x.changedate) < '''+ 
    CONVERT(varchar, @end_date_plus1) +''' 
    THEN DATEADD(HOUR,'+CONVERT(CHAR(2),@timeoffset)*@neg+',x.changedate)' 
    
        2
  •  1
  •   Zohar Peled    7 年前

    我注意到你发布的代码中有几个问题:

    1. 你在申报 @Sql 作为 varchar(max) ,但您正在使用 N 在设置其值之前添加前缀。在处理unicode数据时只需要这样做( nchar , nvarcar )这很关键,但你应该意识到这一点。

    2. 你正在使用 convert 不指定 style 参数。将int转换为字符串并没有那么糟糕,但在处理日期时可能会导致意外行为。无论何时需要对日期/日期时间值使用字符串表示法,都应始终使用ISO8601标准,因为它保证SQL Server始终将其正确转换为日期,而不管本地设置如何。转换一个 datetime 值符合ISO8061标准,使用 转换 语句。

    3. 你正在使用 varchar 不指定长度。这是一个坏习惯,因为根据上下文的不同,sql server的长度有不同的默认值。当声明变量时是1,但是在 cast 转换 .

    我对你的代码做了一些修改,包括 char(2) 你已经习惯了 varchar(11) (因为11个字符甚至包含int数据类型的最小值,即-2147483648)。 @timeoffset 参数,并且不存在负的问题。

    这是我的测试:

    DECLARE @timeOffset int = -10, 
            @start_date datetime = getdate(), 
            @sql nvarchar(max)
    
    SET @sql = 
    N'SELECT '''+ convert(char(23), @start_date, 126) +''' As GetDate, 
           DATEADD(HOUR, '+ CAST(@timeOffset as varchar(11)) +', '''+ convert(char(23), @start_date, 126) +''') As DateAdd';
    
    SELECT @Sql
    
    EXEC(@sql)
    

    结果:

    SELECT '2018-11-08T20:33:31.670' As GetDate, 
           DATEADD(HOUR, -10, '2018-11-08T20:33:31.670') As DateAdd
    
    GetDate                     DateAdd
    2018-11-08T20:33:31.670     08.11.2018 10:33:3