在 db2 中使用动态 table 名称

Using dynamic table name in db2

目前在我的项目开发中需要根据某些标准生成记录计数,其中 table 名称存储在单独的 table.For 实例中,例如 xx table 存储 table 列名称下的名称是 tableInfo.

我以这样的方式编写了存储过程

DECLARE FGCURSOR CURSOR FOR SELECT tableInfo FROM xx WHERE col1='PO';

OPEN FGCURSOR;

FETCH FROM FGCURSOR INTO FILEGROUPMEM;

WHILE SQLCODE <> 100
DO

SET COUNTVal =   'SELECT COUNT(*)  FROM  ' ||  FILEGROUPMEM || '  WHERE ICLS=  '  || CLASS  || '  AND  IVEN=  ' || VENDOR  || ' AND ISTY=  ' || STYLE || '  AND ICLR= ' || COLOR || ' AND ISIZ=  ' || SIZE   ; 


IF(COUNTVal  >= 1) THEN 
RETURN 1;
END IF;

FETCH FROM FGCURSOR INTO FILEGROUPMEM;

END WHILE;

CLOSE FGCURSOR;

在执行过程时获取异常说明

Message: [SQL0420] Character in CAST argument not valid. Cause . . . . . : A character in the argument for the CAST function was not correct. Recovery . . . : Change the result data type to one that recognizes the characters in the CAST argument, or change the argument to contain a valid representation of a value for the result data type. Try the request again.

这行不正确:

SET COUNTVal =   'SELECT COUNT(*)  FROM  ' ||  FILEGROUPMEM || '  WHERE ICLS=  '  || CLASS  || '  AND  IVEN=  ' || VENDOR  || ' AND ISTY=  ' || STYLE || '  AND ICLR= ' || COLOR || ' AND ISIZ=  ' || SIZE   ; 

要按照您尝试的方式使用它,您必须使用像这样的静态 SQL 语句

exec sql SELECT COUNT(*) INTO :COUNTVal  
  FROM  MYTBL 
 WHERE ICLS=  :CLASS  AND  IVEN=  :VENDOR  AND ISTY=  :STYLE 
       AND ICLR= :COLOR  AND ISIZ=  :SIZE;

然而,虽然静态语句可以使用变量,但 FROM 子句中的 table 名称不能是变量。

因此您必须准备和使用动态语句。不幸的是,SELECT INTO 不能用在动态语句中。 VALUES INTO可以动态使用。

set wSqlStmt = 'VALUES ( SELECT COUNT(*)  FROM  ' ||  FILEGROUPMEM 
                || '  WHERE ICLS=  '  || CLASS  || '  AND  IVEN=  ' 
                || VENDOR  || ' AND ISTY=  ' || STYLE || '  AND ICLR= ' 
                || COLOR || ' AND ISIZ=  ' || SIZE ||') INTO ?';

exec sql PREPARE S1 FROM :wSqlStmt;

exec sql EXECUTE S1 USING COUNTVal;

警告 上述代码可能会受到 SQL 注入攻击。为了防止 SQL 注入,动态 SQL 应该使用参数标记而不是将输入直接连接到语句。虽然您不能为 table 名称使用参数标记,但您可以像这样为其余变量使用参数标记:

set wSqlStmt = 'VALUES ( SELECT COUNT(*)  FROM  ' ||  FILEGROUPMEM 
                || '  WHERE ICLS=  ?  AND  IVEN=  ? ' 
                || '  AND ISTY= ? AND ICLR= ?' 
                || '  AND ISIZ= ?) INTO ?';

exec SQL PREPARE S1 FROM :wSqlStmt;

exec SQL EXECUTE S1 USING :CLASS, :VENDOR, :STYLE, :COLOR, :SIZE, :COUNTVal;