CURRENT_TIMESTAMP 不总是填充
CURRENT_TIMESTAMP not always populating
这是 DB2 for i 运行 7.3 版。
我目前正在评估将 DDS 定义的物理和逻辑文件转换为 DDL 定义的 table 和视图需要做些什么。作为测试的一部分,我发现了一个不寻常的发现。给定一个 table 和一个定义为 TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
的列,有时当从 RPGLE 程序写入新行时该值会正确填充 - 但大多数时候它不会。 SQL INSERT
s 似乎一直工作正常。
来源如下:
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)
这是执行 WRITE
:
的普通老式 RPGLE 程序的源代码
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(SQL角色扮演游戏代码)
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;
//-----------------------------
最后,这是我的测试方式。首先,我 INSERT
通过 STRSQL
:
记录了几条记录
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
.
中具有预期的时间戳值
关于为什么这种情况不一致发生的任何想法?
这完全符合预期。您从 RPG 写入的内容是从 table SOT 写入整个记录。这包括在 RPG 中默认为空白的 CTS 字段。 SQL table 不需要生成时间戳,因为您从 RPG 传入时间戳,时间为 '0001-01-01 00:00:00.0000'。换句话说,您的 RPG 正在将以下值写入 SQL table:
DESC: RPGLE U 1
CTS: '0001-01-01 00:00:00.0000'
UTS: '0001-01-01 00:00:00.0000'
UTS 会在每次 table 更新时更新,因此它随后会更新到当前时间,因此它看起来是正确的。 CTS 仅在未传递任何内容时才会更新,但实际上,在这种情况下传递了 0。
另一方面,您的 SQL 插入除了 DESC 字段外不插入任何内容,因此 table 必须根据 SQL 规则生成默认时间。这将按照您的预期生成时间戳。与 RPG 正在执行的操作等效的语句如下所示:
Exec SQL
Insert Into SOL (DESC, CTS)
Values ('SQL I 1', Timestamp('00010101000000'));
按设计工作....
DEFAULT
在 a 未通过时发挥作用,但正如@Playerfirst 提到的那样,RPG 将始终传递一个值。
执行以下操作之一
- 使用 %timestamp()
BIF
从 RPG 加载值
- 通过没有字段
的 view/LF 从 RPG 写入
在SOT1写入的第一条记录中(描述为"RPGLE I 1"),CTS时间戳字段从未被程序初始化(或者你可以说它被初始化为“0001-01-01-00.00 .00.000000”。在它的第二次写入 ("RPGLE I 2") 中,时间戳与第一条记录完全相同,因为时间戳是由 CHAIN 操作初始化到第一条记录(然后从未被清除或更改)。
DDL 中的 "DEFAULT CURRENT_TIMESTAMP" 仅适用于 SQL 插入。角色扮演游戏的行为至少与它的传统是一致的。
这是 DB2 for i 运行 7.3 版。
我目前正在评估将 DDS 定义的物理和逻辑文件转换为 DDL 定义的 table 和视图需要做些什么。作为测试的一部分,我发现了一个不寻常的发现。给定一个 table 和一个定义为 TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
的列,有时当从 RPGLE 程序写入新行时该值会正确填充 - 但大多数时候它不会。 SQL INSERT
s 似乎一直工作正常。
来源如下:
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)
这是执行 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(SQL角色扮演游戏代码)
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;
//-----------------------------
最后,这是我的测试方式。首先,我 INSERT
通过 STRSQL
:
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
.
关于为什么这种情况不一致发生的任何想法?
这完全符合预期。您从 RPG 写入的内容是从 table SOT 写入整个记录。这包括在 RPG 中默认为空白的 CTS 字段。 SQL table 不需要生成时间戳,因为您从 RPG 传入时间戳,时间为 '0001-01-01 00:00:00.0000'。换句话说,您的 RPG 正在将以下值写入 SQL table:
DESC: RPGLE U 1
CTS: '0001-01-01 00:00:00.0000'
UTS: '0001-01-01 00:00:00.0000'
UTS 会在每次 table 更新时更新,因此它随后会更新到当前时间,因此它看起来是正确的。 CTS 仅在未传递任何内容时才会更新,但实际上,在这种情况下传递了 0。
另一方面,您的 SQL 插入除了 DESC 字段外不插入任何内容,因此 table 必须根据 SQL 规则生成默认时间。这将按照您的预期生成时间戳。与 RPG 正在执行的操作等效的语句如下所示:
Exec SQL
Insert Into SOL (DESC, CTS)
Values ('SQL I 1', Timestamp('00010101000000'));
按设计工作....
DEFAULT
在 a 未通过时发挥作用,但正如@Playerfirst 提到的那样,RPG 将始终传递一个值。
执行以下操作之一
- 使用 %timestamp()
BIF
从 RPG 加载值
- 通过没有字段
在SOT1写入的第一条记录中(描述为"RPGLE I 1"),CTS时间戳字段从未被程序初始化(或者你可以说它被初始化为“0001-01-01-00.00 .00.000000”。在它的第二次写入 ("RPGLE I 2") 中,时间戳与第一条记录完全相同,因为时间戳是由 CHAIN 操作初始化到第一条记录(然后从未被清除或更改)。
DDL 中的 "DEFAULT CURRENT_TIMESTAMP" 仅适用于 SQL 插入。角色扮演游戏的行为至少与它的传统是一致的。