【问题标题】:PL/SQL to TSQL conversionPL/SQL 到 TSQL 的转换
【发布时间】:2014-07-12 06:47:07
【问题描述】:

我使用了一个工具将 PL/SQL 转换为 TSQL,但在某些情况下我遇到了奇怪的错误。

CREATE PROC Dates
(
    @PeriodType varchar(15),
    @ReportStart varchar(15),
    @ReportEnd varchar(15)
)
AS
BEGIN
    SELECT CASE
               WHEN @PeriodType  = 'CUR_WEEK' THEN CONVERT(DATETIME, CONVERT(VARCHAR, GETDATE() + 1 - CONVERT(NUMERIC(8, 2), CONVERT(VARCHAR(23), GETDATE())), 112))
               WHEN @PeriodType  = 'NEXT_WEEK' THEN CONVERT(DATETIME, CONVERT(VARCHAR, GETDATE() + 8 - CONVERT(NUMERIC(8, 2), CONVERT(VARCHAR(23), GETDATE())), 112))
               WHEN @PeriodType  = 'PREV_DAY' THEN CONVERT(DATETIME, CONVERT(VARCHAR, GETDATE() - 1, 112))
               WHEN @PeriodType  = 'PREV_WEEK' THEN CONVERT(DATETIME, CONVERT(VARCHAR, GETDATE() - 6 - CONVERT(NUMERIC(8, 2), CONVERT(VARCHAR(23), GETDATE())), 112))
               WHEN @PeriodType  = 'PREV_2WEEK' THEN CONVERT(DATETIME, CONVERT(VARCHAR, GETDATE() - 13, 112))
               WHEN @PeriodType  = 'CUR_MONTH' THEN CONVERT(DATETIME, CAST(CONVERT(VARCHAR(23), GETDATE()) AS VARCHAR) + '01', 112)
               WHEN @PeriodType  = 'DATE_RANGE' THEN CONVERT(DATETIME, @ReportStart)
           END AS "StartDate",
           CASE
               WHEN @PeriodType  = 'CUR_WEEK' THEN CONVERT(DATETIME, CONVERT(VARCHAR, GETDATE() + 8 - CONVERT(NUMERIC(8, 2), CONVERT(VARCHAR(23), GETDATE())), 112)) - (1 / CONVERT(FLOAT, 86400))
               WHEN @PeriodType  = 'NEXT_WEEK' THEN CONVERT(DATETIME, CONVERT(VARCHAR, GETDATE() + 15 - CONVERT(NUMERIC(8, 2), CONVERT(VARCHAR(23), GETDATE())), 112)) - (1 / CONVERT(FLOAT, 86400))
               WHEN @PeriodType  = 'PREV_DAY' THEN CONVERT(DATETIME, CONVERT(VARCHAR, GETDATE(), 112)) - (1 / CONVERT(FLOAT, 86400))
               WHEN @PeriodType  = 'PREV_WEEK' THEN CONVERT(DATETIME, CONVERT(VARCHAR, GETDATE() - CONVERT(NUMERIC(8, 2), CONVERT(VARCHAR(23), GETDATE())), 112)) + 1 - (1 / CONVERT(FLOAT, 86400))
               WHEN @PeriodType  = 'PREV_2WEEK' THEN CONVERT(DATETIME, CONVERT(VARCHAR, GETDATE() + 1, 112)) - (1 / CONVERT(FLOAT, 86400))
               WHEN @PeriodType  = 'CUR_MONTH' THEN DATEADD(M, 1, CONVERT(DATETIME, CONVERT(VARCHAR, GETDATE(), 112)) - (CONVERT(NUMERIC(8, 2), DATEPART(DD, GETDATE())) - 1)) - 1
               WHEN @PeriodType  = 'DATE_RANGE' THEN CONVERT(DATETIME, @ReportEnd) + 1
           END AS "EndDate"
END

我的存储过程正在执行 PREV_DAY 和 PREV_2WEEK 剩余期间类型我收到转换错误。

exec proc Dates 'PREV_DAY','',''
exec proc Dates 'PREV_2WEEK','',''

我的 PL\SQL 代码是

 SELECT CASE 
            WHEN :PeriodType = 'CUR_WEEK'
                 THEN TRUNC(SYSDATE + 1 - TO_NUMBER(TO_CHAR(SYSDATE, 'D')))
            WHEN :PeriodType = 'NEXT_WEEK'
                 THEN TRUNC(SYSDATE + 8 - TO_NUMBER(TO_CHAR(SYSDATE, 'D')))
            WHEN :PeriodType = 'PREV_DAY'
                 THEN TRUNC(SYSDATE - 1)
            WHEN :PeriodType = 'PREV_WEEK'
                 THEN TRUNC(SYSDATE - 6 - TO_NUMBER(TO_CHAR(SYSDATE, 'D')))
            WHEN :PeriodType = 'PREV_2WEEK'
                 THEN TRUNC(SYSDATE - 13)
            WHEN :PeriodType = 'CUR_MONTH'
                 THEN to_date(to_char(sysdate,'YYYYMM') || '01','YYYYMMDD')
            WHEN :PeriodType = 'DATE_RANGE'
                 THEN TO_DATE(:ReportStart)
        END  AS "StartDate",
        CASE
            WHEN :PeriodType = 'CUR_WEEK'
                 THEN TRUNC(SYSDATE + 8 - TO_NUMBER(TO_CHAR(SYSDATE, 'D'))) - (1/86400)
            WHEN :PeriodType = 'NEXT_WEEK'
                 THEN TRUNC(SYSDATE + 15 - TO_NUMBER(TO_CHAR(SYSDATE, 'D'))) - (1/86400)
            WHEN :PeriodType = 'PREV_DAY'
                 THEN TRUNC(SYSDATE)-(1/86400)
            WHEN :PeriodType = 'PREV_WEEK'
                 THEN TRUNC(SYSDATE - TO_NUMBER(TO_CHAR(SYSDATE, 'D'))) + 1 - (1/86400)
            WHEN :PeriodType = 'PREV_2WEEK'
                 THEN TRUNC ( SYSDATE+1) - (1/86400)
            WHEN :PeriodType = 'CUR_MONTH'
                 THEN ADD_MONTHS(TRUNC(SYSDATE) - (TO_NUMBER(TO_CHAR(SYSDATE,'DD')) - 1), 1) -1
            WHEN :PeriodType = 'DATE_RANGE'
                 THEN TO_DATE(:ReportEnd)+1
        END AS "EndDate"
   FROM DUAL

【问题讨论】:

  • @Serpiton。编辑了我的帖子。

标签: sql-server sql-server-2008 tsql case data-conversion


【解决方案1】:

第一个then子句中的这个表达式至少有一个问题:

CONVERT(NUMERIC(8, 2), CONVERT(VARCHAR(23), GETDATE()))

这个表达式:

select CONVERT(VARCHAR(23), GETDATE())

刚回来:

May 23 2014 3:01AM

这不会转换为数字。

我认为您需要逐行查看代码以找出最佳的处理方式。此外,无论何时使用varcharchar,都应该有一个与它们关联的长度。默认值有时(但不总是)为 1,这可能会导致问题。

【讨论】:

    【解决方案2】:

    Oracle 和 SQLServer 以不同的方式处理日期时间。

    该工具可以像字符串解析器一样转换脚本,就像有人在两种语言之间逐字翻译引号一样。

    在 SQLServer 中,要使用该数据类型,您必须使用函数 DATEADDDATEDIFF 和其他可以在 MS 的 help page 上找到的函数。

    使用SQLServer的日期函数将原函数翻译成

    CREATE PROC Dates(
    @PeriodType varchar(15),
    @ReportStart varchar(15),
    @ReportEnd varchar(15)
    )
    AS
    BEGIN
      SELECT CASE WHEN @PeriodType = 'CUR_WEEK' THEN DATEADD(DAY, - DATEPART(dw, GETDATE()) + 1, cast(cast(GETDATE() AS date) AS datetime))
                  WHEN @PeriodType = 'NEXT_WEEK' THEN DATEADD(DAY, 8 - DATEPART(dw, GETDATE()), cast(cast(GETDATE() AS date) AS datetime))
                  WHEN @PeriodType = 'PREV_DAY' THEN DATEADD(DAY, -1, cast(cast(GETDATE() AS date) AS datetime))
                  WHEN @PeriodType = 'PREV_WEEK' THEN DATEADD(DAY, - DATEPART(dw, GETDATE()) - 6, cast(cast(GETDATE() AS date) AS datetime))
                  WHEN @PeriodType = 'PREV_2WEEK' THEN DATEADD(DAY, - 13, cast(cast(GETDATE() AS date) AS datetime))
                  WHEN @PeriodType = 'CUR_MONTH' THEN DATEADD(DAY, - DATEPART(DAY, GETDATE()) + 1, cast(cast(GETDATE() AS date) AS datetime))
                  WHEN @PeriodType = 'DATE_RANGE' THEN CONVERT(DATETIME, @ReportStart)
             END AS StartDate,
           , CASE WHEN @PeriodType = 'CUR_WEEK' THEN DATEADD(mi, -1, DATEADD(DAY, 8 - DATEPART(dw, GETDATE()), cast(cast(GETDATE() AS date) AS datetime)))
                  WHEN @PeriodType = 'NEXT_WEEK' THEN DATEADD(mi, -1, DATEADD(DAY, 15 - DATEPART(dw, GETDATE()), cast(cast(GETDATE() AS date) AS datetime)))
                  WHEN @PeriodType = 'PREV_DAY' THEN DATEADD(mi, -1,  DATEADD(DAY, - DATEPART(dw, GETDATE()) + 1, cast(cast(GETDATE() AS date) AS datetime)))
                  WHEN @PeriodType = 'PREV_WEEK' THEN DATEADD(mi, -1, DATEADD(DAY, 8 - DATEPART(dw, GETDATE()), cast(cast(GETDATE() AS date) AS datetime)))
                  WHEN @PeriodType = 'PREV_2WEEK' THEN DATEADD(mi, -1, cast(cast(dateadd(DAY, 1, GETDATE()) AS date) AS datetime))
                  WHEN @PeriodType = 'CUR_MONTH' THEN DATEADD(DAY, -1, DATEADD(mm, DATEDIFF(mm, 0, cast(cast(GETDATE() AS date) AS datetime))+1,0))
                  WHEN @PeriodType = 'DATE_RANGE' THEN CONVERT(DATETIME, @ReportEnd) + 1
             END AS EndDate
    END
    

    CAST(CAST(GETDATE() AS DATE) AS DATETIME) 中的双 CAST 是获取今天午夜的小技巧,因为 GETDATE() 是日期时间类型并返回当前日期和时间

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-08-24
      • 2018-11-18
      • 2011-03-09
      • 2018-09-16
      • 1970-01-01
      • 2013-11-08
      • 1970-01-01
      • 2010-10-22
      相关资源
      最近更新 更多