在DB2数据库,LOAD既可以从数据文件中将数据LOAD进目标表,也可以将一张表或一个结果集LOAD到另一张表。
将结果集LOAD进一张表时,有两种方法。
一种是将LOAD 。。。 CURSOR命令拼接成一个字段串,然后调用系统过程CALL SYSPROC.ADMIN_CMD来执行。经过实际测试,这种方法在LOAD 。。。 CURSOR命令命令中的SELECT语句比较复杂(SQL语句本身没有问题)时,实际LOAD 。。。 CURSOR命令没有执行成功,也就是说,数据没有真正的进入目标表,但SYSPROC.ADMIN_CMD返回成功,导致的安全隐患。
另一种方法是调用系统过程CALL SYSPROC.DB2LOAD。这个系统过程需要的参数比较多,虽然功能比较强大,可很多时候使用起来并不需要。它有一个比较大的优点,就是对于上面LOAD 。。。 CURSOR命令的安全隐患,它可以执行成功。没有任何问题。
虽然解决了LOAD 。。。 CURSOR命令这一隐患,但后面在实际使用的过程中,发现CALL SYSPROC.DB2LOAD本身也存在另一个安全隐患:SELECT结果集中的字段类型与目标表字段类型不一致,如SELECT结果集中某一个字段为INT类型,而目标表中对应的字段类型为VARCHAR,这时CALL SYSPROC.DB2LOAD会抛出下面这个WARNING,但SELECT结果集中的数据并没有被导入目标表。
SQL0462W Command or routine "SYSPROC.DB2LOAD" (specific name "DB2LOAD") has returned a warning SQLSTATE, with diagnostic text "LOAD ERROR". SQLSTATE=01H00
我们都知道,当使用INSERT语句时,如果SELECT结果集中值的数据与目标表对应字段的数据类型不一致时,数据库会自动进行类型转换,于是INSERT语句可以成功执行,并且数据也会被正确的插入目标表。
但在CALL SYSPROC.DB2LOAD系统过程中,只是会抛出一个WARING,而且直接返回,并不实际执行数据的LOAD操作。导致如果在调用的过程中,只检测了ERROR错误,而忽略WARING的话,就会导致数据错误。
经分析,CALL SYSPROC.DB2LOAD系统过程报这个错的原因是因为SELECT结果集的字段数据类型与目标表对应字段的数据类型不一致引起的。显式转换SELECT结果集中的字段类型后,CALL SYSPROC.DB2LOAD成功执行,且数据被正确的LOAD进目标表。
PS. 2018年12月27日:调用SYSPROC.DB2LOAD时,再次报标题的错误,原因为要LOAD的目标表被加锁,导致死锁。将锁定目标表的进程force掉,就运行成功了。之前一直找不到原因,结果查看SYSPROC.DB2LOAD的出参SQLCODE=911,就找到原因了。