我正在尝试使用 informix 数据库中的过程来获取所有表的计数。 但是,我在使用 Dynamic 的 SELECT INTO 语句获取计数时遇到错误 SQL。
错误 - “变量 (v_count) 具有未定义的值。”
***请告诉我如何使用动态 SQL 为“INFORMIX”中的变量赋值(SELECT count() INTO ****
CREATE PROCEDURE all_table_count_proc()
DEFINE v_table_name VARCHAR(70);
DEFINE v_count INT8;
DEFINE x VARCHAR(100);
DEFINE y VARCHAR(100);
DEFINE z VARCHAR(100);
LET x = 'SELECT count(*) INTO v_count ' ;
LET y = ' FROM ';
SELECT
tabname
INTO
v_table_name
FROM
systables
WHERE
tabtype = 'T'
and tabid = 508;
LET z = x || y || v_table_name;
EXECUTE IMMEDIATE z;
INSERT INTO table_count_details_tbl values(v_table_name,v_count);
END PROCEDURE;
AFAIK,您不能将 INTO 子句与 EXECUTE IMMEDIATE 一起使用。 EXECUTE IMMEDIATE 不接受输入或输出参数。您必须准备一条语句,声明一个游标,打开、获取、关闭游标,然后释放游标和语句。 AFAIK,您也不能使用 FOREACH 来封装 OPEN、FETCH、CLOSE 序列。
请参阅 SQL 参考手册中的有效语句的限制(与 EXECUTE IMMEDIATE 一起使用)。
此版本的代码可以处理任意表名。它没有错误检查 - 因此在同一个表名上运行该过程两次将生成错误,就像给出不存在的表名等一样。您可能希望使用
WHENEVER ERROR
子句来控制错误处理。 MERGE 语句可用于在 table_count_details_tbl
中插入或更新行。
CREATE PROCEDURE table_count_proc(tabname VARCHAR(128))
DEFINE tabrows BIGINT;
DEFINE stmt VARCHAR(255);
LET stmt = 'SELECT COUNT(*) FROM ' || TRIM(tabname);
PREPARE p FROM stmt;
DECLARE c CURSOR FOR p;
OPEN c;
FETCH c INTO tabrows;
INSERT INTO table_count_details_tbl VALUES(tabname, tabrows);
CLOSE c;
FREE c;
FREE p;
END PROCEDURE;
此代码“知道”准备好的 SELECT 语句只会选择一行,因此单个 FETCH 就足够了。一般来说,您需要一个循环来获取所有要返回的行。
请注意,我使用
BIGINT
而不是 INT8
。由于特殊的历史原因,INT8
类型(以及匹配的SERIAL8
类型)在磁盘上占用 10 个字节(而不是 8 个字节)。当然,浪费的空间并不大,但不要使用 INT8
和 SERIAL8
类型。 BIGINT
和 BIGSERIAL
类型在磁盘上占用 8 个字节 — 始终使用它们。