Как передать таблицу в качестве параметра и заполнить эту таблицу с помощью процедуры pl sql - PullRequest
1 голос
/ 25 января 2020

Я хочу заполнить таблицу, используя pl sql. Он получит имя таблицы в качестве параметра и вставит записи, которые уже существуют в таблице. Проблема в том, что когда в таблице есть первичный ключ, не может быть повторяющихся записей. Я не знаю, как решить эту проблему. Этот код генерирует 20 строк и вставляет их в таблицу c. Поскольку employee_id является первичным ключом, я сгенерировал последовательность для этого. Но моя проблема в том, когда я хочу вставить записи для любой таблицы. Чтобы сделать его коротким, я хочу выполнить Dynami c insert в операторе.

Этот код прекрасно работает для вставки записей для таблицы сотрудников.

create or replace procedure proc ( number_of_records IN number )
IS
BEGIN
INSERT INTO employees (EMPLOYEE_ID,FIRST_NAME,LAST_NAME,EMAIL,PHONE_NUMBER,HIRE_DATE,JOB_ID,SALARY,COMMISSION_PCT,MANAGER_ID,DEPARTMENT_ID)
SELECT generate.nextval,FIRST_NAME,LAST_NAME,DBMS_RANDOM.STRING('A', 20),PHONE_NUMBER,HIRE_DATE,JOB_ID,SALARY,COMMISSION_PCT,MANAGER_ID,DEPARTMENT_ID
FROM employees where rownum<=number_of_records;
end proc;

execute proc(20);

Ответы [ 5 ]

1 голос
/ 25 января 2020

Хотя вам может и не нравиться это, я предлагаю вам отказаться от этой идеи, но это очень плохая идея. Во-первых, поскольку вы хотите передать имя таблицы в качестве параметра, вы не можете написать оператор SQL; вам нужна Dynami c sql, либо через EXECUTE IMMEDIATE, либо через DBMS_ SQL, что само по себе никогда не бывает простым. Во-вторых, чтобы полностью реализовать должным образом, это становится сложным, меняется быстро. Заранее вам нужно подумать, что если:

  1. PK не генерируется автоматически.
  2. Для ПК 12 c и выше используется IDENTITY, но оно определено как ON DEFAULT.
  3. PK - это несколько столбцов.
  4. Существуют ли УНИКАЛЬНЫЕ ограничения, кроме PK (или вместо PK).
  5. Существуют ли уникальные индексы, которые не определены как ограничения.
  6. Другие?

В-третьих, Dynami c SQL имеет тенденцию быть перетащить или производительность.

Есть альтернатива, но не очень хорошая. Создайте процедуру для каждой таблицы, затем ваша процедура PRO C просматривает имя таблицы и вызывает соответствующую процедуру более низкого уровня. Но это очень быстро становится головной болью при обслуживании. Удачи!

1 голос
/ 25 января 2020

Я бы посоветовал вам создать динамический c запрос в вашей процедуре, используя следующие запросы:

Ниже запроса даст вам имя таблицы и столбцы для входного параметра (V_TABLE_NAME)

    select  aa.table_name, 
            aa.column_name  
    from    all_tab_columns aa
    where   (instr(aa.table_name, '$') = 0 
    and     aa.owner = 'V_SCHEMA_NAME')
    and     aa.table_name = 'V_TABLE_NAME'; 

используя запрос ниже, вы можете определить первичный ключ, доступный для этого имени входной таблицы

    select  aa.table_name, 
            aa.column_name ,
            ac.constraint_type
    from   all_tab_columns aa,
           ALL_CONSTRAINTS ac
    where  aa.table_name = ac.table_name
    and    (instr(aa.table_name, '$') = 0 
    and    aa.owner = 'V_SCHEMA_NAME')
    and    aa.table_name = 'V_TABLE_NAME'
    and    ac.constraint_type = 'P'; 

Убедитесь, что это решение работает для вас. Если у вас есть еще вопросы по этому вопросу, пожалуйста, дайте мне знать. Я постараюсь решить это.

спасибо.

1 голос
/ 25 января 2020

Oracle 12 C или более поздней версии теперь разрешено использовать столбец Identity. Таким образом, вы можете вставить несколько строк, не используя последовательности больше. Но до 12 C, я думаю, вам нужно использовать CURSOR для достижения этого -

CREATE OR REPLACE PROCEDURE PROC ( number_of_records IN NUMBER)
IS
BEGIN
    FOR REC IN (SELECT FIRST_NAME
                      ,LAST_NAME
                      ,DBMS_RANDOM.STRING('A',20) EMAIL
                      ,PHONE_NUMBER
                      ,HIRE_DATE
                      ,JOB_ID
                      ,SALARY
                      ,COMMISSION_PCT
                      ,MANAGER_ID
                      ,DEPARTMENT_ID
                FROM employees
                WHERE ROWNUM <= number_of_records)
        LOOP
             INSERT INTO employees(EMPLOYEE_ID
                                  ,FIRST_NAME
                                  ,LAST_NAME
                                  ,EMAIL
                                  ,PHONE_NUMBER
                                  ,HIRE_DATE
                                  ,JOB_ID
                                  ,SALARY
                                  ,COMMISSION_PCT
                                  ,MANAGER_ID
                                  ,DEPARTMENT_ID)
             VALUES(generate.nextval
                   ,REC.FIRST_NAME
                   ,REC.LAST_NAME
                   ,REC.EMAIL
                   ,REC.PHONE_NUMBER
                   ,REC.HIRE_DATE
                   ,REC.JOB_ID
                   ,REC.SALARY
                   ,REC.COMMISSION_PCT
                   ,REC.MANAGER_ID
                   ,REC.DEPARTMENT_ID);
        END LOOP;
END PROC;
/
execute proc(20);
1 голос
/ 25 января 2020

Поскольку вопрос помечен как Oracle, предполагается, что вы используете Oracle базу данных. Исходя из этого, вы можете исследовать представления all_tables и all_tab_columns, чтобы получить информацию о таблице и соответствующую информацию столбца о таблице, имя которой передается в качестве параметра.

Вы можете дополнительно изучить Oracle документация для соответствующего представления об ограничениях, которая может использоваться для определения первичных ключей таблицы.

0 голосов
/ 26 января 2020

Пожалуйста, проверьте мой другой подход, я думаю, этот подход будет работать для вас.

  1. Создать процедуру с двумя параметрами

    CREATE OR REPLACE PROCEDURE PROC ( P_TABLE_NAME IN VARCHAR2(100),P_number_of_records 
    IN NUMBER) 
    
  2. создать две динамические c SQL

    i , Первая динамика c SQL для курсора

    REC_STATE_STATEMENT := SELECT 'FOR REC IN (SELECT ' || RTRIM (xmlagg (xmlelement 
    (e, COLUMN_NAME || ',')).extract ('//text()'),',') || ' FROM '||P_TABLE_NAME || ' 
    WHERE ROWNUM <= ' ||P_number_of_records||' )' COLUMN_NAMES
    FROM ALL_TAB_COLS 
    WHERE TABLE_NAME='P_TABLE_NAME' 
    GROUP BY
    TABLE_NAME;   
    

    ii. Secon Dynami c Sql для вставки в (Выполните эту инструкцию в l oop)

    INSERT_INTO_STATEMENT:SELECT 'INSERT INTO ' ||P_TABLE_NAME||' (' 
    || RTRIM (xmlagg (xmlelement (e, COLUMN_NAME || ',')).extract ('//text()'),',') 
    ||' )' ||' VALUES (' 
    || RTRIM (xmlagg (xmlelement (e, COLUMN_NAME || ',REC.')).extract 
    ('//text()'),',REC.')||' )' COLUMN_NAMES
    FROM ALL_TAB_COLS 
    WHERE TABLE_NAME='P_TABLE_NAME'
    GROUP BY
    TABLE_NAME;
    

Пожалуйста, дайте мне знать, если это поможет вам.

С уважением, Четан

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...