Индекс не создается с использованием хранимой процедуры - Oracle

У меня есть эта хранимая процедура для создания индекса в таблице:

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.

Я не могу понять, почему хранимая процедура не создает индексы. Не могли бы вы помочь?

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
121
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 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.

Другие вопросы по теме