DB2 v7R1触发器问题:无法将数据变更转为XML字符串存入表中
解决DB2 v7R1中创建XML变更记录触发器的问题
针对你在QS36F库下创建触发器,把数据变更以XML字符串存入WEBTEST2表遇到的问题,结合DB2 v7R1(也就是IBM i 7.1)的SQL特性限制,给你梳理下解决方案:
一、INSERT触发器的XML转换错误问题
DB2 v7R1对SQL/XML的支持比较基础,直接用CAST(XMLROW(...) AS VARCHAR)的写法不被支持,而且QS36F作为S/36兼容库,对XML类型字段的支持有限,咱们换用标准的XMLSERIALIZE函数来处理,同时避免不必要的嵌套查询:
修正后的INSERT触发器写法:
CREATE TRIGGER QS36F.WEBTEST1_I AFTER INSERT ON QS36F.WEBTEST1 REFERENCING NEW AS R FOR EACH ROW MODE DB2SQL INSERT INTO QS36F.WEBTEST2 (NEW_R, ENTRY_DATE) VALUES ( XMLSERIALIZE(XMLROW(R.ID AS "id", R.ITEMNUMBER AS "itemnumber") AS VARCHAR(16355) CCSID 1208), CURRENT_TIMESTAMP );
这里要注意几点:
- 用
XMLSERIALIZE替代CAST,这是v7R1里将XML值转为字符串的标准方法 - 给XMLROW的字段指定别名(比如
AS "id"),避免生成默认的列名(比如COL1),让XML结构更清晰 - 指定CCSID 1208(UTF-8)可以避免编码转换错误,如果你用的是EBCDIC编码,可以换成对应CCSID(比如37)
- 不需要嵌套SELECT,直接引用NEW行的字段即可,v7R1的触发器支持直接在VALUES里调用XML函数
二、UPDATE触发器的SQL0312(变量未定义)错误
你遇到的SQL0312错误,根源是table (values(...)) as tbl里的列没有明确命名,导致后续SELECT时找不到id和itemnumber。v7R1的行值构造器(VALUES)不会自动给列命名,必须在表别名后显式指定列名,不过更简单的是直接跳过嵌套查询,直接引用触发器的OLD/NEW行变量:
修正后的UPDATE触发器写法:
CREATE TRIGGER QS36F.WEBTEST1_U AFTER UPDATE ON QS36F.WEBTEST1 REFERENCING OLD AS O NEW AS R FOR EACH ROW MODE DB2SQL INSERT INTO QS36F.WEBTEST2 (NEW_R, PREVIOUS_R, ENTRY_DATE) VALUES ( XMLSERIALIZE(XMLROW(R.ID AS "id", R.ITEMNUMBER AS "itemnumber") AS VARCHAR(16355) CCSID 1208), XMLSERIALIZE(XMLROW(O.ID AS "id", O.ITEMNUMBER AS "itemnumber") AS VARCHAR(16355) CCSID 1208), CURRENT_TIMESTAMP );
这种写法完全避免了行值构造器的嵌套,直接引用触发器自带的OLD/NEW行变量,不会出现变量未定义的问题,同时逻辑更清晰。
额外注意事项
- QS36F库下的表如果是S/36风格的物理文件,建议先确认它支持SQL触发器(有些旧的S/36文件可能需要转换为SQL表),可以用
DSPFD FILE(QS36F/WEBTEST1)查看文件类型是否为*SQLTABLE - 如果WEBTEST2的NEW_R字段长度不够,可能会出现截断错误,确保VARCHAR长度足够容纳生成的XML字符串
内容的提问来源于stack exchange,提问作者Ya Wang
相关产品推荐
相关产品推荐

