未使用存储过程创建索引 - Oracle
Posted
技术标签:
【中文标题】未使用存储过程创建索引 - Oracle【英文标题】:Index not getting created using stored procedure - Oracle 【发布时间】:2019-05-27 17:16:22 【问题描述】:我有这个存储过程来在表上创建索引:
CREATE OR REPLACE PROCEDURE create_index (
in_tb VARCHAR2,
in_index VARCHAR2,
in_columns VARCHAR2,
lc_status OUT NUMBER
) AS
lc_affected NUMBER;
lc_stmt VARCHAR2(1500);
BEGIN
lc_stmt := 'BEGIN EXECUTE IMMEDIATE ''CREATE INDEX '
|| in_index
|| ' ON '
|| in_tb
|| ' ('
|| in_columns
|| ')''; END;';
dbms_output.put_line(lc_stmt);
dbms_utility.exec_ddl_statement(lc_stmt);
lc_affected := SQL%rowcount;
dbms_output.put_line('AFFECTED -->' || lc_affected);
IF ( lc_affected > 0 ) THEN
lc_status := 1;
ELSE
lc_status := 1;
END IF;
END create_index;
/
我使用以下方法执行存储过程:
SET SERVEROUTPUT ON;
DECLARE
lc_status NUMBER;
BEGIN
create_index('TABLE_1_LOAD', 'ON_RUN_INDEX', 'MY_ID', lc_status);
END;
但是,索引没有在表 TABLE_1_LOAD
中创建。
输出是:
BEGIN EXECUTE IMMEDIATE 'CREATE INDEX ON_RUN_INDEX ON TABLE_1_LOAD (MY_ID)'; END;
AFFECTED -->
PL/SQL procedure successfully completed.
我无法理解为什么存储过程不创建索引。你能帮忙吗?
【问题讨论】:
【参考方案1】:您尝试通过exec_ddl_statement
运行的动态语句不是 DDL。它包含 DDL,但嵌入在匿名 PL/SQL 块中,这不是一回事。看起来dbms_utility
过程只是出于这个原因默默地忽略它。
如果您简化语句以删除不必要的块,那么它将起作用:
...
BEGIN
lc_stmt := 'CREATE INDEX '
|| in_index
|| ' ON '
|| in_tb
|| ' ('
|| in_columns
|| ')';
...
演示:
create table table_1_load (my_id number);
Table TABLE_1_LOAD created.
CREATE OR REPLACE PROCEDURE create_index (
in_tb VARCHAR2,
in_index VARCHAR2,
in_columns VARCHAR2,
lc_status OUT NUMBER
) AS
lc_affected NUMBER;
lc_stmt VARCHAR2(1500);
BEGIN
lc_stmt := 'CREATE INDEX '
|| in_index
|| ' ON '
|| in_tb
|| ' ('
|| in_columns
|| ')';
dbms_output.put_line(lc_stmt);
dbms_utility.exec_ddl_statement(lc_stmt);
lc_affected := SQL%rowcount;
dbms_output.put_line('AFFECTED -->' || lc_affected);
IF ( lc_affected > 0 ) THEN
lc_status := 1;
ELSE
lc_status := 1;
END IF;
END create_index;
/
Procedure CREATE_INDEX compiled
SET SERVEROUTPUT ON;
DECLARE
lc_status NUMBER;
BEGIN
create_index('TABLE_1_LOAD', 'ON_RUN_INDEX', 'MY_ID', lc_status);
END;
/
CREATE INDEX ON_RUN_INDEX ON TABLE_1_LOAD (MY_ID)
AFFECTED -->
PL/SQL procedure successfully completed.
“受影响”的数字仍然为空,因为execute_ddl_statement
不会导致设置SQL%rowcount
,所以你不能依赖它来告诉你任何事情。但是索引已经创建:
select object_type, object_name from user_objects where created > trunc(sysdate);
OBJECT_TYPE OBJECT_NAME
------------------- ------------------------------
TABLE TABLE_1_LOAD
PROCEDURE CREATE_INDEX
INDEX ON_RUN_INDEX
您可以使用execute immediate
运行您的原始语句,这实际上会设置SQL%rowcount
,但由于您还没有运行任何DML,它真的毫无意义。为了证明这一点,使用(仍然不必要的)匿名块你得到 1;没有块,使用与上面相同的简化语句,你得到 0。
【讨论】:
以上是关于未使用存储过程创建索引 - Oracle的主要内容,如果未能解决你的问题,请参考以下文章