【问题标题】:SQL correctly format integers as datesSQL 正确地将整数格式化为日期
【发布时间】:2016-09-29 14:41:21
【问题描述】:

我正在用 C# 编写一个程序,其中一部分是从 DB2 服务器获取日期。日期在服务器上存储为长度为 4 的整数值。日期只保留月份和日期我遇到的问题是它们的存储精度不同。 编辑: 数据类型是数字长度 4,没有精度(所以整数长度 4)但是当 Select 语句运行时,所有内容都作为字符串返回。这就是我使用 SubStr() 的原因。

示例

一个日期存储为 1003,表示日期 10/03

另一个日期存储为 805 代表 8/05

我用来提取日期的 SQL 代码

(SubStr(ML2DDM,0,3) ||'/'|| SubStr(ML2DDM,3,2))as Due__Date

程序以下列格式返回日期

10 月 3 日

80/5

有没有办法每次都正确格式化值?

【问题讨论】:

  • '(SubStr(ML2DDM,0,3) ||'/'|| SubStr(ML2DDM,3,2))as Due__Date' 看起来不像 Sql :)
  • @Dan Nor 喜欢 c# :)
  • 这是完全有效的 SQL,尽管使用“0”作为 SUBSTR() 的起始位置即使有效也是不寻常的。并且对 INTEGER 列使用 SUBSTR() 也是不明智的,尽管在某些情况下当值自动转换为 CHAR 时可能有意义。
  • ('{'||ML2DDM||'}') 在您的两个示例案例中给出了什么结果?
  • 请提供“存储为长度为4 的整数值” 所隐含的DDL,以消除歧义。最好的猜测是 4 位字符串,因此是 CHAR(4)。但是,即使该列的数据类型为 INTEGER [4-bytes],给定表达式的结果也与 CHAR(4) 相同。然而,这些类型都不会产生给定 SQL 表达式所显示的效果。相反,结果如下:10 /0580 /5

标签: c# db2 ibm-midrange db2-400


【解决方案1】:
 select left(right(repeat('0', 4) || trim(ML2DDM), 4), 2) || '/' ||  
 right(right(repeat('0', 4) || trim(ML2DDM), 4), 2)  as Due__Date          

【讨论】:

    【解决方案2】:

    如果它们是整数,那么执行字符串函数似乎是个坏主意。我会“按原样”将整数拉回,并在 C# 中处理它,然后你有:

    int month = val / 100;
    int day = val % 100;
    

    然后您可以随心所欲地使用。我期望您的RDBMS 具有内置的整数除法和模运算,因此您也可以在服务器上执行此操作。比如在 SQL Server 中(因为我不懂 DB2):

    declare @v int = 805; -- obviously in real code this would be a column
    select @v / 100 as [month], @v % 100 as [day]
    

    【讨论】:

      【解决方案3】:

      显然您将整数存储为字符。因为您无法在整数列上使用 SUBSTR()

      几个 SQL 解决方案

      转换为分区/压缩十进制,然后使用DIGITS() 转换回字符并包含前导零

      select 
        (SubStr(digits(dec(ML2DDM,4)),1,2) 
          ||'/'|| SubStr(digits(dec(ML2DDM,4)),3,2))as Due__Date
      

      添加一些前导零,然后取RIGHT() 大多数字符...

      select 
        (left(right(trim('0' || ML2DDM),4),2)
          ||'/'|| right(trim('0'|| ML2DDM),2) as Due__Date
      

      如果列是固定长度字符而不是 VARCHAR,则需要 TRIM()

      【讨论】:

      • SUBSTR() 在 INTEGER [或任何数字类型] 列上是可接受/支持的,因为字符和数字之间的 隐式转换 功能。当然,可能的问题是从数字转换为字符会使值左对齐;当然,这可以解释为什么在从左到右查看长度为 N 的数字的数字时,对于找到任何特定的 10**N 位置时,有效精度少于四位的数字的结果可能会出现问题-1.
      【解决方案4】:

      在 C# 中我会做这样的事情:

      var fullValue = ML2DDM;
      var formattedDate = fullValue.Substring(0, fullValue.Length - 2) + "/" + fullValue.Substring(fullValue.Length - 2, 2);
      

      我不知道任何 DB2,但也许同样的方法有效?比如:

      (SubStr(ML2DDM,0,length(ML2DDM)-2) ||'/'|| SubStr(ML2DDM,length(ML2DDM)-2,2))as Due__Date
      

      【讨论】:

        【解决方案5】:

        如何让不良数据可读。我主要使用这种技术来制作打开和关闭标签或在输出 html、xml、纯文本时添加换行符。各种方法。

        select 
        case when length(trim(ml2ddm)) = 4 
        then substring(ml2ddm,1,2) || '/' || substring(ml2ddm,3)
        when substring(trim(ml2ddm,4,1) = ' ' 
        then substring(ml2ddm,1,1) || '/' || substring(ml2ddm,2) 
        else substring(ml2ddm,2,1) || '/' || substring(ml2ddm,3)  
        end as somefunkydate
        from somereallyfunkydata
        

        【讨论】:

          【解决方案6】:

          鉴于与许多帖子一样,没有给出 DDL,我可以提供:

          不管 ML2DDM 的 DDL 是 CHAR(4)、VARCHAR(4)、SMALLINT、DECIMAL、NUMERIC、BIGINT 或 INTEGER [的数字类型,然后还确保任何实际值的精度不超过四位,虽然实际的列精度无关紧要,但前提是该列也被定义为零刻度;这当然是各种 INT 类型所暗示的],下面的表达式应该足以在每个 MMDD 数据的 MM 和 DD 组件之间插入一个 / 字符,该数据存储的值为三位数字### 或四位数字的值#### [其中# 表示从零到九的任何十进制数字];如果数字存储为字符串,则它们必须左对齐存储,并且任何非数字数据都将被类似地编辑,尽管它们不是实际日期值的有效表示,但数字的编辑结果也不会以这种方式确保值有效:

             insert ( case length(rtrim(ML2DDM))  
                       when 3 then '0' else '' end
                      concat ML2DDM               
                    , 3, 0, '/' ) as due__date_ins
          

          了解实际的 DDL 可以让表达更简洁。

          如果需要实际的 DATE 数据类型结果,则可以使用上面提供的表达式替换以下 TIMESTAMP_FORMAT 表达式变体中的 expr,以生成具有当前年份值 TO_DATE( expr, 'MMDD' ) 的 TIMESTAMP,并且可以转换为 DATE;例如DATE( TO_DATE( expr, 'MMDD' ) ) 当然,这种额外转换的结果将要求绝对将数据值存储为合法的 MMDD [或 MDD] 值。

          2016 年 9 月 30 日附录
          如果 ML2DDM 的 DDL 是数字 [非浮点],则 IIRC 从数字到字符的隐式转换效果正在转换为 VARCHAR,因此以下将是一个非常简单的表达式,可以将 MMDD 影响为“MM/DD”,并将 MDD 影响为“月/日”:

           insert ( LPAD( ML2DDM , 4, '0' ) , 3, 0, '/' ) as Due__Date 
          

          【讨论】:

            猜你喜欢
            • 2013-09-18
            • 1970-01-01
            • 2013-10-18
            • 1970-01-01
            • 2022-06-27
            • 2012-02-15
            • 2017-04-10
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多