移除AS400连接字符串库列表触发iDB2SQLErrorException的原因与解决
AS400 Mapics表INSERT报错问题:原因分析与解决
问题背景
我在更新一个向AS400(IBM DB2中型机)上的Mapics数据库表写入数据的应用,移除连接字符串中的库列表后,执行INSERT操作时抛出iDB2SQLErrorException。明明SQL语句已经指定了库名(AMFLIBT.SHIPVF),为什么无库列表的连接字符串会导致报错?更重要的是,有没有办法在不修改连接字符串的前提下解决这个问题?
复现代码
try { var connectionString = "DataSource=as400.myCompany.com" + "; UserID=" + ConfigurationManager.AppSettings["UserName"] + "; Password=" + ConfigurationManager.AppSettings["Password"] + "; InitialCatalog=PRODTEST" + //"; LibraryList=*USRLIBL, AMALIBT" + //Works... WHY? //"; LibraryList=AMALIB" + //Doesn't work. //"; LibraryList=*USRLIBL" +//Doesn't work. "; DataCompression=True; CheckConnectionOnOpen=True; Naming = System;"; const string sql = "insert into AMFLIBT.SHIPVF(VIACD, VIADS, MDATE) values(?, ?, ?) with NC"; var parameters = new List<IBM.Data.DB2.iSeries.iDB2Parameter> { new IBM.Data.DB2.iSeries.iDB2Parameter("NameDoesNotMatter","AAA"), new IBM.Data.DB2.iSeries.iDB2Parameter("NameDoesNotMatter","TEST555"), new IBM.Data.DB2.iSeries.iDB2Parameter("NameDoesNotMatter", 1240129), }; var conn = new IBM.Data.DB2.iSeries.iDB2Connection(connectionString); conn.Open(); var transaction = conn.BeginTransaction(); var command = new IBM.Data.DB2.iSeries.iDB2Command(sql, conn, transaction); command.SetParameters(parameters); var rc = command.ExecuteNonQuery(); command.Dispose(); } catch (IBM.Data.DB2.iSeries.iDB2SQLErrorException e) { //e.ToString() returns "SQL0901 SQL system error.". Console.WriteLine(e); throw; }
作业日志信息
SQL system error. Trigger error. 153 - CALL PGM(QMHSNDPM) /* The CALL command contains paramsters */ Error found on CALL command. Program AMZTRG3R in library %LIBL not found. 122 - CALL PGM(AMZTRGRR) /* The CALL command contains paramsters */ 112 - CHDTAARA DTAARA(ZTRIGCOMM (1 10)) VALUE('*ALL ') Data area ZTRIGCOMM created in library QTEMP. 110 CRTDTAARA DTAARA(QTEMP/ZTRIGCOMM) TYPE (*CHAR) LEN(1024) Data area ZTRIGCOMM created in *LIBL not found. 108 - RTVDTAARA DTAARA(ZTRIGCOMM (1 10)) RTNVAR(&TRGSRC) 107 - RTVDTAARA DTAARA(*LDA *ALL) RTNVAR(&LDA)
问题原因
虽然SQL语句明确指定了表的库名,但INSERT操作触发的RPG程序AMZTRG3R是通过%LIBL(当前会话的库列表)来查找的。当连接字符串中不设置LibraryList时,当前会话的库列表不包含该程序所在的库,导致触发器调用程序失败,最终抛出SQL0901系统错误。
不修改连接字符串的解决办法
- 动态添加库到会话库列表:在数据库连接打开后,执行AS400命令把触发器程序所在的库添加到当前会话的库列表中。比如如果
AMZTRG3R在AMALIBT库,可执行以下代码:// 在conn.Open()之后、开启事务之前添加 using (var cmd = new IBM.Data.DB2.iSeries.iDB2Command("CALL QSYS.QCMDEXC('ADD LIBLE AMALIBT')", conn)) { cmd.ExecuteNonQuery(); } - 修改触发器的程序调用方式:如果有权限修改触发器,把触发器中调用
AMZTRG3R的语句改为指定库名,比如CALL PGM(AMALIBT/AMZTRG3R),这样就不再依赖库列表查找程序。 - 配置用户默认库列表:让AS400管理员修改连接所用用户ID的配置文件,把触发器程序所在的库添加到用户的默认库列表中。这样即使连接字符串不指定
LibraryList,会话也会继承用户的库列表设置。
内容的提问来源于stack exchange,提问作者Sarov
相关产品推荐
相关产品推荐

