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

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

Проблема: ----- У меня есть запрос на выборку, который возвращает два значения:

    src_Columns contains:
        ID_ELEMENT
        ID_ELEMENT_SA

Теперь, когда я пытаюсь пройти по результату запроса select (один столбец), используя «For Loop», я не получаю значения столбца, а получаю только его имя.

FOR columnItem IN (SELECT src_Columns FROM ELEM90_LNK_ELEM_BOSE)
           LOOP
           dbms_output.put_line('src_Columns 3: ' || columnItem.src_Columns);
           query_test:=  'insert into ' || destination_Table || '(NAME,' || dest_Columns_Value || ') VALUES( ''' || src_name_Value || ''',''' || columnItem.dummyValue || ''')';
           dbms_output.put_line('query_test:' || query_test);
           execute immediate query_test;
           END LOOP;

Я имею в виду, что сгенерированный тестовый запрос выглядит следующим образом, когда я использую имя переменной (src_columns):

insert into ATT_WTPART(NAME,STRINGVALUE) VALUES( 'ID_ELEMENT_SA','ID_ELEMENT_SA')

тогда как если я использую ID_ELEMENT_SA вместо src_Columns в FOR LOOP

FOR columnItem IN (SELECT ID_ELEMENT FROM ELEM90_LNK_ELEM_BOSE)

то я получаю правильные значения, которые желательны, например

insert into ATT_WTPART(NAME,STRINGVALUE) VALUES( 'ID_ELEMENT_SA','ID05')

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

Ниже приведена полная процедура: --------------

 create or replace 
PROCEDURE ELEM90_Lnk_Elem_ATT_WTPART_MK
AS
CURSOR targ_dest_relation IS
    SELECT sourcecolumn  FROM mapping where destinationtable='ATT_WTPART';
    BEGIN
DECLARE 

dest_Columns varchar2(1000);
src_Columns varchar2(1000); 
src_Type varchar2(1000);
destination_Table varchar2(1000) := 'ATT_WTPART';
source_Table varchar2(1000) := 'ELEM90_LNK_ELEM_BOSE';
query_test varchar2(1000);
query_test2 varchar2(1000);
src_name varchar2(255);
src_Type_Value varchar2(255);
dest_Columns_Value varchar2(255);
src_name_Value varchar2(255);
for_query varchar2(1000);
for_query_data varchar2(1000);
dummyValue varchar2(1000); 

BEGIN

    FOR rec IN targ_dest_relation loop
           dbms_output.put_line('destination_Table: ' || destination_Table);
           dbms_output.put_line('source_Table: ' || source_Table);

           src_Columns :=  rec.sourcecolumn;
           dbms_output.put_line('src_Columns: ' || src_Columns);

           src_Type := 'select data_type from user_tab_columns where table_name ='''||source_Table||'''and column_name='''|| src_Columns ||'''';
           dbms_output.put_line('src_Type: ' || src_Type);

           execute immediate src_Type INTO src_Type_Value;
           dbms_output.put_line('src_Type_Value: ' || src_Type_Value);

           dest_Columns := 'select DEST_COLUMN from ATT_PART_MAPPING where SOURCETYPE='''|| src_Type_Value || '''';
           dbms_output.put_line('dest_Columns: '  || dest_Columns);

           execute immediate dest_Columns INTO dest_Columns_Value;
           dbms_output.put_line('dest_Columns_Value: ' || dest_Columns_Value);

           src_name := 'select column_name from user_tab_columns where table_name ='''|| source_Table ||'''  and column_name= ''' || src_Columns || '''';
           dbms_output.put_line('src_name: ' || src_name);

           execute immediate src_name INTO src_name_Value;
           dbms_output.put_line('src_name_Value: ' || src_name_Value);

           FOR columnItem IN (SELECT src_Columns FROM ELEM90_LNK_ELEM_BOSE)
           LOOP
           dbms_output.put_line('src_Columns 3: ' || columnItem.src_Columns);
           query_test:=  'insert into ' || destination_Table || '(NAME,' || dest_Columns_Value || ') VALUES( ''' || src_name_Value || ''',''' || columnItem.dummyValue || ''')';
           dbms_output.put_line('query_test:' || query_test);
           execute immediate query_test;
           END LOOP;

    END loop;  
END;
END;

person user3069865    schedule 05.12.2013    source источник


Ответы (2)


Проблема с линией

FOR columnItem IN (SELECT src_Columns FROM ELEM90_LNK_ELEM_BOSE)

заключается в том, что src_Columns является локальной переменной. В результате вы выбираете одно и то же значение для каждой строки в ELEM90_LNK_ELEM_BOSE.

Если вы хотите, чтобы значение локальной переменной использовалось в качестве имени столбца в запросе, вы должны вместо этого использовать динамический SQL. Попробуйте заменить FOR columnItem ... LOOP ... END LOOP на следующее:

           OPEN curs FOR 'SELECT ' || src_Columns || ' FROM ELEM90_LNK_ELEM_BOSE';
           LOOP
             FETCH curs INTO column_value;
             EXIT WHEN curs%NOTFOUND;
             dbms_output.put_line('src_Columns 3: ' || column_value);
             query_test:=  'insert into ' || destination_Table || '(NAME,' || dest_Columns_Value || ') VALUES( ''' || src_name_Value || ''',''' || column_value || ''')';
             dbms_output.put_line('query_test:' || query_test);
             execute immediate query_test;
           END LOOP;

           CLOSE curs;

Вам нужно будет объявить следующие дополнительные переменные:

curs         SYS_REFCURSOR;
column_value VARCHAR2(4000);  

Однако на самом деле, вероятно, было бы лучше полностью удалить петлю. Вместо этого вы можете заменить его оператором INSERT INTO ... SELECT ... FROM ..., например следующим:

       EXECUTE IMMEDIATE 'INSERT INTO ' || destination_Table || ' (NAME,' ||
           dest_Columns_Value || ') SELECT :name,' || src_Columns || 
           ' FROM ELEM90_LNK_ELEM_BOSE' USING src_name_Value;

Это также избавляет от необходимости использовать две локальные переменные curs и column_value, а также, вероятно, будет значительно быстрее, поскольку нет необходимости один раз анализировать динамический SQL для каждой строки в целевой таблице.

person Luke Woodward    schedule 05.12.2013
comment
Спасибо за ваше предложение ... Это сработало как ракета :) - person user3069865; 05.12.2013

Это работает лучше, если вы попробуете это:

query_test:=  'insert into ' || destination_Table || 
   '(NAME,'||dest_Columns_Value||') VALUES (:p1, :p2)';
execute immediate query_test USING src_name_Value, columnItem.dummyValue;

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

person Wernfried Domscheit    schedule 05.12.2013
comment
Он по-прежнему ведет себя как раньше. - person user3069865; 05.12.2013