CURRENT_TIMESTAMP并不总是填充

Ben*_*ill 0 rpgle db2-400 ibm-midrange

这是DB2 for i在7.3版本上运行.

我目前正在评估我们需要做什么才能将DDS定义的物理和逻辑文件转换为DDL定义的表和视图.作为我测试的一部分,我遇到了一个不同寻常的发现.给定一个列定义为a的表TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,有时当从RPGLE程序写入新行时,该值会正确填充 - 但大多数情况下它不会.SQL INSERT似乎一直很好.

这是来源:

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;                                                              
Run Code Online (Sandbox Code Playgroud)

并编译它:

RUNSQLSTM SRCFILE(MYLIB/QDDLSRC) SRCMBR(SOT) DFTRDBCOL(MYLIB)
Run Code Online (Sandbox Code Playgroud)

这是一个普通的旧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;
//-----------------------------
Run Code Online (Sandbox Code Playgroud)

这是执行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;
//-----------------------------
Run Code Online (Sandbox Code Playgroud)

最后,这是我正在测试的方式.首先我INSERT通过STRSQL以下几条记录:

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

INSERT INTO sot        
(desc) VALUES('SQL I 2')
Run Code Online (Sandbox Code Playgroud)

然后执行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  ********
Run Code Online (Sandbox Code Playgroud)

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

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

Pla*_*1st 5

这与预期完全一致.您从RPG写的WRITE正在写表SOT的整个记录​​.这包括CTS字段,默认情况下在RPG中为空.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'
Run Code Online (Sandbox Code Playgroud)

每次表更新时UTS都会更新,因此它会随后更新到当前时间,因此它看起来是正确的.如果没有传递任何内容,CTS只会更新,但实际上,在这种情况下传递了0.

另一方面,SQL插入不会插入除DESC字段之外的任何内容,因此表必须从SQL规则生成默认时间.这将生成您期望的时间戳.RPG正在做的等价声明将是这样的:

Exec SQL
  Insert Into SOL (DESC, CTS)
  Values ('SQL I 1', Timestamp('00010101000000'));
Run Code Online (Sandbox Code Playgroud)