Microsoft查询正确显示数据,但不会将数据返回到Excel-错误SQ20448



早上好,

我有一个半功能SQL查询,可以将数据从IBM AS/400拉入Microsoft Excel。数据在Microsoft Query中正确显示,但当我单击"返回数据"将数据返回到Excel时,我收到以下错误消息:

[IBM][System i Access ODBC Driver][DB2 for i5/OS]SQ20448 - Expression not 
valid using format string specified for TIMESTAMP_FORMAT.

从本质上讲,我的代码是连接几个文件,为我提供项目信息,并使用日期删除重复项,这样我就可以获得最近的交易。

我对其他正常工作的文件使用了几乎相同的代码,因此我怀疑我的原始数据中可能存在格式错误的日期,这会在使用to_date函数将IBM日期转换为与Microsoft兼容的日期时导致错误我知道我的日期转换工作正常,因为IBM日期是实际日期

我的问题是,我如何在异常中进行编码以忽略格式不正确的数据,或者如何返回格式错误的数据,以便在代码中写入异常

这是我的代码(希望评论有帮助):

SELECT xh.ITNBR, yh.VNDNR, zh.VN35VM, yh.BUYNO, xh.Create_Date -- Item #, Vendor #, Vendor Name, Buyer, Create_Date
FROM
(SELECT PO_IH.ITNBR, -- Item #
max(TO_DATE((CONCAT(
CONCAT(
(CONCAT(SUBSTRING(PO_MH.ACTDT,4,2), '/')),
(CONCAT(SUBSTRING(PO_MH.ACTDT,6,2), '/'))),
SUBSTRING(PO_MH.ACTDT,2,2))), 'MM/DD/YY')) as Create_Date -- Converts IBM date format to work with Microsoft Query
FROM POHISTI as PO_IH, POHSTM as PO_MH 
WHERE PO_IH.ORDNO = PO_MH.ORDNO AND
(TO_DATE((CONCAT(
CONCAT(
(CONCAT(SUBSTRING(PO_MH.ACTDT,4,2), '/')),
(CONCAT(SUBSTRING(PO_MH.ACTDT,6,2), '/'))),
SUBSTRING(PO_MH.ACTDT,2,2))), 'MM/DD/YY')) = 
(SELECT MIN((TO_DATE((CONCAT(
CONCAT(
(CONCAT(SUBSTRING(PO_MH.ACTDT,4,2), '/')),
(CONCAT(SUBSTRING(PO_MH.ACTDT,6,2), '/'))),
SUBSTRING(PO_MH.ACTDT,2,2))), 'MM/DD/YY'))) -- All of this chaos basically removes duplicate information and converts IBM date
FROM POHSTM as PO_MH2
WHERE PO_MH.ORDNO = PO_MH2.ORDNO AND
PO_MH.ACTDT NOT LIKE '0%' AND -- Removes dates that start with 0 (i.e. IBM's way of saying "no date")
PO_MH.ACTDT NOT LIKE '9%') -- Removes dates from 20th century
GROUP BY PO_IH.ITNBR) xh
LEFT JOIN 
(SELECT PO_IH2.ITNBR, -- Item #
PO_IH2.BUYNO, -- Buyer
PO_IH2.VNDNR, -- Vendor
(TO_DATE((CONCAT(
CONCAT(
(CONCAT(SUBSTRING(PO_MH2.ACTDT,4,2), '/')),
(CONCAT(SUBSTRING(PO_MH2.ACTDT,6,2), '/'))),
SUBSTRING(PO_MH2.ACTDT,2,2))), 'MM/DD/YY')) as Create_Date
FROM POHISTI as PO_IH2, POHSTM as PO_MH2
WHERE PO_IH2.ORDNO = PO_MH2.ORDNO AND
PO_MH2.ACTDT NOT LIKE '0%' AND -- Removes dates that start with 0 (i.e. IBM's way of saying "no date")
PO_MH2.ACTDT NOT LIKE '9%') yh -- Removes dates from 20th century
ON xh.ITNBR = yh.ITNBR AND xh.Create_Date = yh.Create_Date
LEFT JOIN VENNAML0 zh -- Vendor Name
ON yh.VNDNR = zh.VNDRVM

以下是Microsoft Query中的输出:

ITNBR           VNDNR   VN35VM          BUYNO   CREATE_DATE
A-FUL           76      HOLLAND COMP    SUSY    2016-12-06 00:00:00.000000
A-MINI          76      HOLLAND COMP    SUSY    2016-11-28 00:00:00.000000
A-SHIMBOX       76      HOLLAND COMP    SUSY    2014-10-16 00:00:00.000000
A-001           76      HOLLAND COMP    SUSY    2016-12-19 00:00:00.000000
A-002           76      HOLLAND COMP    SUSY    2016-12-19 00:00:00.000000
....

正如我所说,信息在Microsoft Query中显示得很好,但当我将其返回到Excel时,我会出现上述错误。我尝试使用上面的"NOT LIKE"语句来处理两个最常见的错误,但我不知道如何找到其他错误。

我真的不在乎我是否得到了坏数据,只要它能转储到Excel中。到那时,我可以纠正它。但我怀疑,如果Microsoft Query不能转换日期,它就不会将数据返回到Excel。

谢谢。

您有一个格式类似CYYMMDD的数字字段。这是IBMi世界中常见的日期格式,其中C是世纪代码(0=>19,1=>20,2=>21,…,9=>28)。之所以会出现这种情况,是因为在Y2K修复之前,大多数十进制日期都是以2位数年份的压缩十进制格式存储的。由于格式的配置,压缩小数总是有奇数位数的空间,但大多数日期被定义为(6,0)(长度,小数位数)。这在磁盘上为日期左侧多留了一位数字,人们可以将日期定义为(7,0),而无需更改记录中数据的格式。因此7位数字的日期是Y2K的结果。据我所知,Syno是第一家在2E代码生成器中这样做的公司。它很受欢迎,而且格式无处不在。它甚至进入了IBM操作系统。

因此,当SQL将其强制转换为CHAR时,像0951107这样的日期将看起来像951107,而当SQL将1171107强制转换为查尔斯时,它将看起来像1171107。不幸的是,NOT LIKE '9%'在某个时刻将是不可靠的,因为前导9可能是1990年代日期的第一个非零数字,也可能是2800年代日期。更糟糕的是,1900年CHAR的日期可以从1-9开始。例如,日期1985/12/05在CYYMMDD数字格式中看起来像0851205。这将被铸造为851205。因此,在处理日期时,需要使用DIGITS将数字强制转换为CHAR,这样就不会丢失开头的0字符。你需要测试你的日期字段0,它实际上是0000000(而不是00/00/00,尽管这是用EDITC(Y)格式化时的样子)。

下面是正在发生的事情的一个例子:

create table datetest
(decdt       decimal(7,0));
insert into datetest
values (0), (941107), (1170304), (1000101);
select substr(decdt,4,2) || '/' || 
substr(decdt,6,2) || '/' || 
substr(decdt,2,2), 
decdt 
from datetest;

结果在:

/  /      0
10/7 /41    941,107
03/04/17    1,170,304
01/01/00    1,000,101

我敢打赌,你的程序TO_DATE()没有正确处理无效日期,因为它们几乎肯定会被通过。如果你在substr函数中使用digits,你会得到更理智的东西。

select substr(digits(decdt),4,2) || '/' || 
substr(digits(decdt),6,2) || '/' || 
substr(digits(decdt),2,2), 
decdt
from datetest

结果在:

00/00/00    0
11/07/94    941,107
03/04/17    1,170,304
01/01/00    1,000,101

请注意,月份、日期和年份部分现在都在正确的位置,您只需要为0日期编码,这意味着没有日期。在任何情况下,函数to_date()都需要检测一个无效日期,然后忽略它,或者将它设置为类似0001-01-01null的可用日期。

相关内容

  • 没有找到相关文章

最新更新