【问题标题】:CURRENT_TIMESTAMP not always populatingCURRENT_TIMESTAMP 并不总是填充
【发布时间】:2018-04-18 22:53:57
【问题描述】:

这是运行于 7.3 版的 DB2 for i。

我目前正在评估如何将 DDS 定义的物理和逻辑文件转换为 DDL 定义的表和视图。作为我测试的一部分,我遇到了一个不寻常的发现。给定一个表,其列定义为TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,有时当从 RPGLE 程序写入新行时,该值会正确填充 - 但大多数情况下不会。 SQL INSERTs 似乎一直运行良好。

来源:

QDDLSRC/SOT

CREATE OR REPLACE TABLE SOT (                                               
  ID   BIGINT        GENERATED ALWAYS AS IDENTITY (START WITH 1),           
  DESC CHAR(20)      NOT NULL DEFAULT '',                                   
  CTS  TIMESTAMP     NOT NULL DEFAULT CURRENT_TIMESTAMP,                    
  UTS  TIMESTAMP     NOT NULL FOR EACH ROW ON UPDATE AS ROW CHANGE TIMESTAMP,
  PRIMARY KEY(ID)                                                            
) RCDFMT SOTR;                                                              

然后编译它:

RUNSQLSTM SRCFILE(MYLIB/QDDLSRC) SRCMBR(SOT) DFTRDBCOL(MYLIB)

这是一个简单的旧 RPGLE 程序的源代码,它执行 WRITE

QRPGLESRC/SOT1(普通的旧 RPGLE 代码)

  CTL-OPT Optimize(*full);
  CTL-OPT Option(*nodebugio : *noshowcpy : *nounref : *srcstmt);
  CTL-OPT Dftactgrp(*no) Actgrp('QILE');
  CTL-OPT Bnddir('QC2LE');
  CTL-OPT Alwnull(*USRCTL);
//-----------------------------
  DCL-F sot disk(*ext) usage(*input : *output : *update) keyed;
//-----------------------------
  DCL-PR sot1 EXTPGM;
  END-PR sot1;

  DCL-PI sot1;
  END-PI;
//-----------------------------
  *INLR = *ON;

  desc = 'RPGLE I 1';
  WRITE sotr;

  CHAIN (1) sot;
  IF %FOUND(sot);
    desc = 'RPGLE U 1';
    UPDATE sotr;
  ENDIF;

  desc = 'RPGLE I 2';
  WRITE sotr;
//-----------------------------

这是执行 INSERT 的 SQLRPGLE 程序的源代码 - 这似乎工作得很好。

QRPGLESRC/SOT2(SQLRPGLE 代码)

  CTL-OPT Optimize(*full);
  CTL-OPT Option(*nodebugio : *noshowcpy : *nounref : *srcstmt);
  CTL-OPT Dftactgrp(*no) Actgrp('QILE');
  CTL-OPT Alwnull(*USRCTL);
//-----------------------------
  DCL-PR sot2 EXTPGM;
  END-PR sot2;

  DCL-PI sot2;
  END-PI;
//-----------------------------
  EXEC SQL
    INSERT INTO sot (desc)
    VALUES('SQLRPGLE I 1');

  EXEC SQL
    INSERT INTO sot (desc)
    VALUES('SQLRPGLE I 2');

  EXEC SQL
    UPDATE sot
    SET desc = 'SQLRPGLE U 1'
    WHERE id=5;

  *INLR = *ON;
//-----------------------------

最后,这是我的测试方式。首先我通过STRSQLINSERT 记录了几条记录:

INSERT INTO sot        
(desc) VALUES('SQL I 1')

INSERT INTO sot        
(desc) VALUES('SQL I 2')

然后执行 SOT1(普通的旧 RPGLE 程序):CALL SOT1

然后执行 SOT2(SQLRPGLE 程序):CALL SOT2

然后查看结果(这是来自 WRKQRY):

Line   ....+....1....+....2....+....3....+....4....+....5....+....6....+....7....+....8....+....9....+...10..

                            ID   DESC                  CTS                         UTS                      

000001                       1   RPGLE U 1             2018-04-18-16.05.13.520198  2018-04-18-16.05.26.275153

000002                       2   SQL I 2               2018-04-18-16.05.19.670653  2018-04-18-16.05.19.670653

000003                       3   RPGLE I 1             0001-01-01-00.00.00.000000  2018-04-18-16.05.26.274977

000004                       4   RPGLE I 2             2018-04-18-16.05.13.520198  2018-04-18-16.05.26.275196

000005                       5   SQLRPGLE U 1          2018-04-18-16.05.29.244307  2018-04-18-16.05.29.253463

000006                       6   SQLRPGLE I 2          2018-04-18-16.05.29.248723  2018-04-18-16.05.29.248723

****** ********  End of report  ********

请注意,第 3 行在 CTS 列中的时间戳值不正确。然而,第 4 行在CTS 中具有预期的时间戳值。

关于为什么这种情况不一致发生的任何想法?

【问题讨论】:

    标签: ibm-midrange db2-400 rpgle


    【解决方案1】:

    这完全符合预期。您从 RPG 中的 WRITE 正在从表 SOT 中写入整个记录。这包括在 RPG 中默认为空白的 CTS 字段。 SQL 表不需要生成时间戳,因为您从 RPG 传递了一个时间戳,即时间“0001-01-01 00:00:00.0000”。换句话说,您的 RPG 正在将以下值写入 SQL 表:

    DESC: RPGLE U 1
    CTS: '0001-01-01 00:00:00.0000'
    UTS: '0001-01-01 00:00:00.0000'
    

    每次表格更新时,UTS 都会更新,因此它随后会更新为当前时间,因此它看起来是正确的。 CTS 仅在未传递任何内容时才会更新,但实际上在这种情况下传递了 0。

    另一方面,您的 SQL 插入只插入 DESC 字段,因此表必须根据 SQL 规则生成默认时间。这将按您的预期生成时间戳。 RPG 正在执行的操作的等效语句如下所示:

    Exec SQL
      Insert Into SOL (DESC, CTS)
      Values ('SQL I 1', Timestamp('00010101000000'));
    

    【讨论】:

    • 它不是“时间 0”或时间戳 (0)...它是 '0001-01-01 00:00:00.0000' 又名 0001 年 1 月 1 日午夜,也就是时间戳字段的 *LOVAL。
    • 谢谢查尔斯。我回去并将其更正为工作值。我是从头顶开始的,其他一些 SQL 数据库允许使用 0。
    【解决方案2】:

    在 SOT1 写入的第一条记录中(描述为“RPGLE I 1”),CTS 时间戳字段从未被程序初始化(或者您可能会说它被初始化为“0001-01-01-00.00.00.000000 "。在它的第二次写入(“RPGLE I 2”)中,时间戳与第一条记录完全相同,因为时间戳是由 CHAIN 操作初始化为第一条记录的(然后从未清除或更改过)。

    DDL 中的“DEFAULT CURRENT_TIMESTAMP”仅适用于 SQL 插入。至少,RPG 的行为与其遗产一致。

    【讨论】:

      【解决方案3】:

      按设计工作....

      DEFAULT 在 a 未传递时发挥作用,但正如 @Playerfirst 所提到的,RPG 将始终传递一个值。

      执行以下操作之一
      - 使用 %timestamp() BIF 从 RPG 加载值
      - 通过没有字段的视图/LF 从 RPG 写入

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-06-21
        • 2017-05-01
        • 2014-03-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多