SQL将整数正确格式化为日期

本文关键字:格式化 日期 整数 SQL | 更新日期: 2023-09-27 18:09:25

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

示例

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

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

我用来提取日期的SQL代码

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

程序以以下格式返回日期

2003年10月

80/5<lt<lt;这就是的问题

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

SQL将整数正确格式化为日期

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

如果它们是整数,那么执行字符串函数似乎是个坏主意。我只想把整数拉回到"原样",并在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]

显然,您将整数存储为字符。因为您将无法在整数列上使用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()

在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

如何使坏数据可读。我使用这种技术主要是为了在输出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

考虑到像许多帖子一样,没有给出DDL,我可以提供:

不管ML2DDM的DDL是CHAR(4(、VARCHAR(4,以下表达式应足以在每个MMDD数据的MM和DD分量之间插入一个CCD_;如果数字被存储为字符串,那么它们必须左对齐存储,并且任何非数字数据都将被类似地编辑,尽管它们不是实际日期值的有效表示,但也不能确保数字值的编辑结果以这种方式有效:

   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,并且该TIMESTAMP可以强制转换为DATE;例如DATE( TO_DATE( expr, 'MMDD' ) )当然,这种附加强制转换的结果将要求绝对将数据值存储为合法的MMDD[或MDD]值。

2016年9月30日附录
如果ML2DDM的DDL是数字[非浮点],则IIRC从数字到字符的隐式强制转换效果将强制转换为VARCHAR,因此下面的表达式非常简单,既可以将MMDD转换为"MM/DD",也可以将MDD转换为"MM/DD":

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