在基于 FOR 循环的 SQL 查询中使用 PLSQL 变量
Using PLSQL variables in SQL Query based on FOR LOOP
我正在尝试使用 PLSQL
执行一些 DML
查询。我已经声明了一个有 5 个 table 名称的数组,我想 运行 它在 FOR LOOP
下。此时我的代码如下所示:
DECLARE
c_exist NUMBER;
test_array dbms_sql.varchar2_table;
BEGIN
test_array(1) := 'TEST_1';
test_array(2) := 'TEST_2';
FOR i IN test_array.FIRST .. test_array.LAST
LOOP
SELECT count(*) INTO c_exist from user_tables WHERE table_name = test_array(i);
IF c_exist = 1 THEN
EXECUTE IMEDIATE 'ALTER TABLE ' || test_array(i) || 'COMPRESS';
END IF;
END LOOP;
END;
问题是脚本试图读取 SELECT
语句下的 test_array
变量。我收到 ORA-06512 ERROR
。在我看来,脚本语法很好。它在没有 SELECT
stamtent 的情况下通过了测试,但只需使用 dbms_output.put_line(test_array(i))
它就通过了测试。
整个错误堆栈:
ORA-06502:
ORA-06512:
06502. 00000 - "PL/SQL: numeric or value error%s"
*Cause: An arithmetic, numeric, string, conversion, or constraint error
occurred. For example, this error occurs if an attempt is made to
assign the value NULL to a variable declared NOT NULL, or if an
attempt is made to assign an integer larger than 99 to a variable
declared NUMBER(2).
*Action: Change the data, how it is manipulated, or how it is declared so
that values do not violate constraints.
此外,类似的东西工作得很好,dbms_output 打印正确:
DECLARE
c_exist NUMBER;
test_array dbms_sql.varchar2_table;
BEGIN
test_array(1) := 'TEST_1';
test_array(2) := 'TEST_2';
FOR i IN test_array.FIRST .. test_array.LAST
LOOP
dbms_output.put_line(test_array(i));
END LOOP;
END;
您在动态查询中的语法不正确。
在 COMPRESS
关键字之前缺少一个 space。
您的代码:
EXECUTE IMEDIATE 'ALTER TABLE ' || test_array(i) || 'COMPRESS';
应该是代码:
EXECUTE IMEDIATE 'ALTER TABLE ' || test_array(i) || ' COMPRESS';
您拼写错误 IMMEDIATE
,需要在 table 名称和 COMPRESS
之间添加一个 space。
DECLARE
c_exist NUMBER;
test_array dbms_sql.varchar2_table;
BEGIN
test_array(1) := 'TEST_1';
test_array(2) := 'TEST_2';
FOR i IN test_array.FIRST .. test_array.LAST LOOP
SELECT count(*)
INTO c_exist
from user_tables
WHERE table_name = test_array(i);
IF c_exist = 1 THEN
EXECUTE IMMEDIATE 'ALTER TABLE ' || test_array(i) || ' COMPRESS';
DBMS_OUTPUT.PUT_LINE( test_array(i) || ' compressed.' );
END IF;
END LOOP;
END;
/
此外,您不需要检查 table 是否存在;只需尝试压缩 table 并捕获异常:
DECLARE
table_not_exists EXCEPTION;
test_array dbms_sql.varchar2_table;
i BINARY_INTEGER;
PRAGMA EXCEPTION_INIT( table_not_exists, -942 );
BEGIN
test_array(1) := 'TEST_1';
test_array(3) := 'TEST_2';
i := test_array.FIRST;
WHILE i IS NOT NULL LOOP
BEGIN
EXECUTE IMMEDIATE 'ALTER TABLE ' || test_array(i) || ' COMPRESS';
DBMS_OUTPUT.PUT_LINE( test_array(i) || ' compressed.' );
EXCEPTION
WHEN table_not_exists THEN
DBMS_OUTPUT.PUT_LINE( test_array(i) || ' ' || SQLERRM );
END;
i := test_array.NEXT(i);
END LOOP;
END;
/
(此外,dbms_sql.varchar2_table
是一个关联数组,可能是稀疏的,因此您不应假设 FIRST
和 LAST
之间的每个索引都存在。)
那么,如果你有 table:
CREATE TABLE test_1 ( id NUMBER );
上面的 PL/SQL 块输出:
TEST_1 compressed.
TEST_2 ORA-00942: table or view does not exist
db<>fiddle here
我正在尝试使用 PLSQL
执行一些 DML
查询。我已经声明了一个有 5 个 table 名称的数组,我想 运行 它在 FOR LOOP
下。此时我的代码如下所示:
DECLARE
c_exist NUMBER;
test_array dbms_sql.varchar2_table;
BEGIN
test_array(1) := 'TEST_1';
test_array(2) := 'TEST_2';
FOR i IN test_array.FIRST .. test_array.LAST
LOOP
SELECT count(*) INTO c_exist from user_tables WHERE table_name = test_array(i);
IF c_exist = 1 THEN
EXECUTE IMEDIATE 'ALTER TABLE ' || test_array(i) || 'COMPRESS';
END IF;
END LOOP;
END;
问题是脚本试图读取 SELECT
语句下的 test_array
变量。我收到 ORA-06512 ERROR
。在我看来,脚本语法很好。它在没有 SELECT
stamtent 的情况下通过了测试,但只需使用 dbms_output.put_line(test_array(i))
它就通过了测试。
整个错误堆栈:
ORA-06502:
ORA-06512:
06502. 00000 - "PL/SQL: numeric or value error%s"
*Cause: An arithmetic, numeric, string, conversion, or constraint error
occurred. For example, this error occurs if an attempt is made to
assign the value NULL to a variable declared NOT NULL, or if an
attempt is made to assign an integer larger than 99 to a variable
declared NUMBER(2).
*Action: Change the data, how it is manipulated, or how it is declared so
that values do not violate constraints.
此外,类似的东西工作得很好,dbms_output 打印正确:
DECLARE
c_exist NUMBER;
test_array dbms_sql.varchar2_table;
BEGIN
test_array(1) := 'TEST_1';
test_array(2) := 'TEST_2';
FOR i IN test_array.FIRST .. test_array.LAST
LOOP
dbms_output.put_line(test_array(i));
END LOOP;
END;
您在动态查询中的语法不正确。
在 COMPRESS
关键字之前缺少一个 space。
您的代码:
EXECUTE IMEDIATE 'ALTER TABLE ' || test_array(i) || 'COMPRESS';
应该是代码:
EXECUTE IMEDIATE 'ALTER TABLE ' || test_array(i) || ' COMPRESS';
您拼写错误 IMMEDIATE
,需要在 table 名称和 COMPRESS
之间添加一个 space。
DECLARE
c_exist NUMBER;
test_array dbms_sql.varchar2_table;
BEGIN
test_array(1) := 'TEST_1';
test_array(2) := 'TEST_2';
FOR i IN test_array.FIRST .. test_array.LAST LOOP
SELECT count(*)
INTO c_exist
from user_tables
WHERE table_name = test_array(i);
IF c_exist = 1 THEN
EXECUTE IMMEDIATE 'ALTER TABLE ' || test_array(i) || ' COMPRESS';
DBMS_OUTPUT.PUT_LINE( test_array(i) || ' compressed.' );
END IF;
END LOOP;
END;
/
此外,您不需要检查 table 是否存在;只需尝试压缩 table 并捕获异常:
DECLARE
table_not_exists EXCEPTION;
test_array dbms_sql.varchar2_table;
i BINARY_INTEGER;
PRAGMA EXCEPTION_INIT( table_not_exists, -942 );
BEGIN
test_array(1) := 'TEST_1';
test_array(3) := 'TEST_2';
i := test_array.FIRST;
WHILE i IS NOT NULL LOOP
BEGIN
EXECUTE IMMEDIATE 'ALTER TABLE ' || test_array(i) || ' COMPRESS';
DBMS_OUTPUT.PUT_LINE( test_array(i) || ' compressed.' );
EXCEPTION
WHEN table_not_exists THEN
DBMS_OUTPUT.PUT_LINE( test_array(i) || ' ' || SQLERRM );
END;
i := test_array.NEXT(i);
END LOOP;
END;
/
(此外,dbms_sql.varchar2_table
是一个关联数组,可能是稀疏的,因此您不应假设 FIRST
和 LAST
之间的每个索引都存在。)
那么,如果你有 table:
CREATE TABLE test_1 ( id NUMBER );
上面的 PL/SQL 块输出:
TEST_1 compressed. TEST_2 ORA-00942: table or view does not exist
db<>fiddle here