我正在尝试在SQL解释器中创建一个触发器,而且我遇到了一些令人头疼的问题。
CREATE TRIGGER log_permission_role_rel_update AFTER UPDATE ON permission_role_rel
REFERENCING NEW ROW as newrow OLD ROW as oldrow
FOR EACH ROW
BEGIN ATOMIC
/* delete old row */
FOR SELECT * FROM TABLE(MYSCHEMA.simulate_by_permission_role_rel(oldrow.id_role, oldrow.id_permission)) simulationA
DO
CALL MYSCHEMA.log_proc('DELETE', 'SECVAL', 'test', '{}');
END FOR;
/* insert new row */
FOR SELECT * FROM TABLE(MYSCHEMA.simulate_by_permission_role_rel(newrow.id_role, newrow.id_permission)) simulationB
DO
CALL MYSCHEMA.log_proc('INSERT', 'SECVAL', '{}', 'test');
END FOR;
END;
上述声明导致错误声称指令结束无效,并突出显示第二个CALL的结尾为罪魁祸首。
SQL State: 42601
Vendor Code: -104
Message: [SQL0104] Token <END-OF-INSTRUCTION> was not valid. Valid tokens: ;.
两个FOR循环都是独立工作的,而不是当它们在同一个触发器下一起工作时。我真的不知道还有什么要尝试的。我在这做错了什么?为什么单个FOR循环工作,但不是两个?
谢谢。
修改 (编辑了解更多信息)
我在iSeries,i5 / OS 7.1上的DB2下运行。我也通过iNavigator运行所有SQL语句。
编辑#2
所有触发器似乎都是使用以下属性创建的:
...
FOR EACH ROW
MODE DB2SQL
SET OPTION ALWBLK = *ALLREAD ,
ALWCPYDTA = *OPTIMIZE ,
COMMIT = *NONE ,
DECRESULT = (31, 31, 00) ,
DFTRDBCOL = MYSCHEMA,
DYNDFTCOL = *NO ,
DYNUSRPRF = *USER ,
SRTSEQ = *HEX
BEGIN
...
步骤:
CREATE PROCEDURE MYSCHEMA.LOG_PROC (
IN OP VARCHAR(6) ,
IN TABLENAME VARCHAR(128) ,
IN OLDVAL VARCHAR(255) ,
IN NEWVAL VARCHAR(255) )
LANGUAGE SQL
SPECIFIC MYSCHEMA.LOG_PROC
NOT DETERMINISTIC
MODIFIES SQL DATA
CALLED ON NULL INPUT
SET OPTION ALWBLK = *ALLREAD ,
ALWCPYDTA = *OPTIMIZE ,
COMMIT = *NONE ,
DECRESULT = (31, 31, 00) ,
DFTRDBCOL = MYSCHEMA ,
DYNDFTCOL = *NO ,
DYNUSRPRF = *USER ,
SRTSEQ = *HEX
BEGIN
INSERT INTO AA_LEGACYLOG ( OPERATION , TABLENAME , OLDVALUE , NEWVALUE ) VALUES ( OP , TABLENAME , OLDVAL , NEWVAL ) ;
END ;
功能:
CREATE FUNCTION MYSCHEMA.SIMULATE_BY_PERMISSION_ROLE_REL (
ARG_ID_ROLE INTEGER ,
ARG_ID_PERMISSION INTEGER )
RETURNS TABLE (
USRCODE VARCHAR(10) ,
SECURABLE VARCHAR(12) ,
LG_INDX VARCHAR(1) ,
LG_VALO VARCHAR(10) ,
LG_ATRB VARCHAR(6) )
LANGUAGE SQL
SPECIFIC MYSCHEMA.SIMULATE_BY_PERMISSION_ROLE_REL
NOT DETERMINISTIC
READS SQL DATA
CALLED ON NULL INPUT
SET OPTION ALWBLK = *ALLREAD ,
ALWCPYDTA = *OPTIMIZE ,
COMMIT = *NONE ,
DECRESULT = (31, 31, 00) ,
DFTRDBCOL = MYSCHEMA ,
DYNDFTCOL = *NO ,
DYNUSRPRF = *USER ,
SRTSEQ = *HEX
RETURN (
SELECT DISTINCT A . USER_REF , P . SECURABLE , P . LG_INDX , P . LG_VALO , P . LG_ATRB
FROM ROLE R , PERMISSION P , ACTOR A , ACTOR_ROLE_REL
WHERE R . ID = ARG_ID_ROLE
AND P . ID = ARG_ID_PERMISSION
AND ACTOR_ROLE_REL . ID_ACTOR = ACTOR . ID
AND ACTOR_ROLE_REL . ID_ROLE = R . ID
GROUP BY A . USER_REF , P . SECURABLE , P . LG_INDX , P . LG_VALO , P . LG_ATRB
) ;
答案 0 :(得分:1)
这可能是Error SQL0104 when creating a function in System i V7R1的副本;我给出的链接是该讨论中的具体答案,但最好是阅读整个讨论。该讨论得出了我在下面做出的类似结论,问题是缺少应用于OP使用的IBM i 7.1系统的PTF \维护,因为解决 FOR语句的问题<缺陷 { {3}}不包括可选的cursor-name CURSOR FOR
子句时;即可选子句实际上是必需 ,直到修复已应用。
以下脚本应该足够喜欢 OP给出的[省略每个SET OPTION中的DFTRDBCOL和UDTF上的硬编码返回],运行正常以创建触发器,的情况下,使用RUNSQLSTM服务器端工具\ SQL脚本处理器和iACS运行SQL,在IBM i 7.1上使用RUNSQLSTM服务器端工具\ SQL脚本处理器[我没有Win OS哪个加载并尝试iNav]客户端工具\ SQL脚本处理器。注意:脚本末尾的最后一个DROP只是一个失败的额外语句,放在那里强调触发器中BEGIN的END之后的多余分号不会造成任何困难,我甚至添加了另一个分号作为语句 - 分离器,这也没有困难。我认为自OP问题以来,要么纠正了一个缺陷,要么
drop table qtemp.AA_LEGACYLOG
;
create table qtemp.AA_LEGACYLOG
( OPERATION VARCHAR( 6)
, TABLENAME VARCHAR(128)
, OLDVALUE VARCHAR(255)
, NEWVALUE VARCHAR(255)
)
;
drop PROCEDURE LOG_PROC
;
CREATE PROCEDURE LOG_PROC
( IN OP VARCHAR(6)
, IN TABLENAME VARCHAR(128)
, IN OLDVAL VARCHAR(255)
, IN NEWVAL VARCHAR(255)
) LANGUAGE SQL
SPECIFIC LOG_PROC
NOT DETERMINISTIC
MODIFIES SQL DATA
CALLED ON NULL INPUT
SET OPTION ALWBLK = *ALLREAD
, ALWCPYDTA = *OPTIMIZE
, COMMIT = *NONE
, DECRESULT = (31, 31, 00)
, DYNDFTCOL = *NO
, DYNUSRPRF = *USER
, SRTSEQ = *HEX
BEGIN
INSERT INTO QTEMP.AA_LEGACYLOG
( OPERATION , TABLENAME , OLDVALUE , NEWVALUE ) VALUES
( OP , TABLENAME , OLDVAL , NEWVAL )
;
END
;
drop table permission_role_rel
;
create table permission_role_rel
( ID_ROLE INTEGER
, ID_PERMISSION INTEGER
)
;
drop FUNCTION SIMULATE_BY_PERMISSION_ROLE_REL
;
CREATE FUNCTION SIMULATE_BY_PERMISSION_ROLE_REL
( ARG_ID_ROLE INTEGER
, ARG_ID_PERMISSION INTEGER
) RETURNS TABLE
( USRCODE VARCHAR(10)
, SECURABLE VARCHAR(12)
, LG_INDX VARCHAR(1)
, LG_VALO VARCHAR(10)
, LG_ATRB VARCHAR(6)
) LANGUAGE SQL
SPECIFIC SIMULATE_BY_PERMISSION_ROLE_REL
NOT DETERMINISTIC
READS SQL DATA
CALLED ON NULL INPUT
SET OPTION ALWBLK = *ALLREAD
, ALWCPYDTA = *OPTIMIZE
, COMMIT = *NONE
, DECRESULT = (31, 31, 00)
, DYNDFTCOL = *NO
, DYNUSRPRF = *USER
, SRTSEQ = *HEX
RETURN
( select 'code', 'capable', 'I', 'VALO', 'ATTR'
from qsys2.qsqptabl
)
;
CREATE TRIGGER log_permission_role_rel_update
AFTER UPDATE ON permission_role_rel
REFERENCING NEW ROW as newrow
OLD ROW as oldrow
FOR EACH ROW
MODE DB2SQL
BEGIN ATOMIC
/* delete old row */
FOR SELECT *
FROM TABLE
( simulate_by_permission_role_rel(oldrow.id_role, oldrow.id_permission)
) simulationA
DO
CALL log_proc('DELETE', 'SECVAL', 'test', '{}') ;
END FOR;
/* insert new row */
FOR SELECT *
FROM TABLE
( simulate_by_permission_role_rel(newrow.id_role, newrow.id_permission)
) simulationB
DO
CALL log_proc('INSERT', 'SECVAL', '{}', 'test');
END FOR;
END;
;
drop table qtemp.permission_test
;
答案 1 :(得分:0)
我看到你的函数中有分号结尾行,以及结束你的函数声明的分号。用@符号结束你的函数声明:
CREATE FUNCTION MYSCHEMA.SIMULATE_BY_PERMISSION_ROLE_REL (
ARG_ID_ROLE INTEGER ,
ARG_ID_PERMISSION INTEGER )
RETURNS TABLE (
USRCODE VARCHAR(10) ,
SECURABLE VARCHAR(12) ,
LG_INDX VARCHAR(1) ,
LG_VALO VARCHAR(10) ,
LG_ATRB VARCHAR(6) )
LANGUAGE SQL
SPECIFIC MYSCHEMA.SIMULATE_BY_PERMISSION_ROLE_REL
NOT DETERMINISTIC
READS SQL DATA
CALLED ON NULL INPUT
SET OPTION ALWBLK = *ALLREAD ,
ALWCPYDTA = *OPTIMIZE ,
COMMIT = *NONE ,
DECRESULT = (31, 31, 00) ,
DFTRDBCOL = MYSCHEMA ,
DYNDFTCOL = *NO ,
DYNUSRPRF = *USER ,
SRTSEQ = *HEX
RETURN (
SELECT DISTINCT A . USER_REF , P . SECURABLE , P . LG_INDX , P . LG_VALO , P . LG_ATRB
FROM ROLE R , PERMISSION P , ACTOR A , ACTOR_ROLE_REL
WHERE R . ID = ARG_ID_ROLE
AND P . ID = ARG_ID_PERMISSION
AND ACTOR_ROLE_REL . ID_ACTOR = ACTOR . ID
AND ACTOR_ROLE_REL . ID_ROLE = R . ID
GROUP BY A . USER_REF , P . SECURABLE , P . LG_INDX , P . LG_VALO , P . LG_ATRB
) @
然后将其保存到文件c:\ db \ simulate_by_permission_role_rel.sql
然后使用以下命令执行:
db2 connect to mydb
db2 -td@ -f c:\db\simulate_by_permission_role_rel.sql
db2 connect reset
-td @告诉db2命令行界面将@符号解释为语句终止符。 -f告诉db2 cli要执行哪个文件。