Динамическая замена одинарных кавычек на двойные в PL-SQL - PullRequest
0 голосов
/ 27 марта 2019

У меня есть запрос ниже:

select ''|| CHR(10) || CHR(10)  
         || 'INSERT into ' || v_TableName || '(' || v_Columns || ')' || CHR(10) 
         || 'VALUES (' || SUBSTR(v_Values,1, LENGTH(RTRIM(v_Values))-1) || ')' from dual;

где после выполнения я получаю:

v_TableName = 'tblRecHistCalc',

v_Columns = 'average_eps, company_id, rec_code, rec_date'

v_Values ​​= '3.3887524216711,25597,' В ' '20-Mar-2019','

Таким образом, запрос становится:

select ''|| CHR(10) || CHR(10)  
         || 'INSERT into ' || 'tblRecHistCalc' || '(' || 'average_eps,company_id,rec_code,rec_date' || ')' || CHR(10) 
         || 'VALUES (' || SUBSTR('3.3887524216711,25597,'B','20-Mar-2019',',1, LENGTH(RTRIM('3.3887524216711,25597,'B','20-Mar-2019','))-1) || ')' from dual;

Но я не могу выполнить вышеупомянутый запрос, поскольку в 'B' и '20 -Mar-2019 'есть одинарные кавычки, что останавливает запрос для успешного выполнения.

Я попытался изменить это ниже:

select ''|| CHR(10) || CHR(10)  
         || 'INSERT into ' || 'tblRecHistCalc' || '(' ||'average_eps,company_id,rec_code,rec_date' || ')' || CHR(10) 
         || 'VALUES (' || SUBSTR(Replace('3.3887524216711,25597,'B','20-Mar-2019',',''','''''),1, LENGTH(RTRIM('3.3887524216711,25597,'B','20-Mar-2019','))-1) || ')' from dual;

Но все равно запрос не выполняется успешно.

Как мне этого добиться?

EDIT:

По просьбе Алекс Пул , Переменные объявляются следующим образом:

v_TableName NVARCHAR2 (50);

v_Columns Nvarchar2 (4000);

v_Values ​​Nvarchar2 (4000);

v_Count NUMBER (10);

v_SQL Nvarchar2 (4000): = '';

А ниже показано, как заполняются три переменные:

WHILE (v_Count > 0) 
LOOP 
v_Columns := ''; 
v_Values := ''; 

-- Gets 1 table name at a time 
SELECT TableName INTO v_TableName  
FROM ( 
        SELECT ROW_NUMBER() OVER (PARTITION BY 1 ORDER BY TableName) as Rowcnt, TableName  
        FROM 
        --#tmp_Templates_Load_InsertSQL STARTS
        (

            SELECT D.TableName, D.ColumnName, D.Val
            FROM 

            --#tmp_Templates_Load_Destinations STARTS
            (         
                SELECT ID, TableName, ColumnName, Val  
                FROM tblTemplates_Load_OtherObjects_Raw OO  
                JOIN tblTemplates_Fields F ON OO.OtherObjectsField = F.FieldName 
                WHERE TemplateType IN ('All','ALL', v_TemplateType) 
                AND OO.Val IS NOT NULL 
                AND  (TemplateVersion = p_TemplateVersion or (TemplateVersion is null and p_TemplateVersion <> 'V8')) 

                UNION 

                SELECT FieldID, TableName, ColumnName, Val 
                FROM tblTemplates_Fields_OtherDestinations OD 
                JOIN  
                ( 
                    SELECT ID, Val 
                    FROM tblTemplates_Load_OtherObjects_Raw OO  
                    JOIN tblTemplates_Fields F ON OO.OtherObjectsField = F.FieldName 
                    WHERE TemplateType IN ('All','ALL', v_TemplateType) 
                    AND OO.Val IS NOT NULL 
                    AND    (TemplateVersion = p_TemplateVersion or (TemplateVersion is null and p_TemplateVersion <> 'V8')) 

                ) UsedIDs 
                ON OD.FieldID = UsedIDs.ID


            ) D
            --#tmp_Templates_Load_Destinations ENDS

            JOIN USER_TAB_COLS C  ON upper(D.TableName) = upper(C.TABLE_NAME) AND upper(D.ColumnName) = upper(C.COLUMN_NAME)
            WHERE (v_UpdateComp = 0 OR D.TableName <> 'tblComp') 
            AND (v_UpdateCompInd = 0 OR D.TableName <> 'tblCompInd') 
            ORDER BY D.TableName, D.ColumnName
        )

        --#tmp_Templates_Load_InsertSQL ENDS
         GROUP BY TableName 
    ) DistinctTableNames 
WHERE Rowcnt = v_Count; 



-- Get lists of all columns  for current table 
 Select  LISTAGG( ColumnName, ',' ) WITHIN GROUP ( ORDER BY ROWNUM ) 
          into v_Columns
 FROM 
 --#tmp_Templates_Load_InsertSQL STARTS
  (

        SELECT D.TableName, D.ColumnName, D.Val
        FROM 

        --#tmp_Templates_Load_Destinations STARTS
        (         
            SELECT ID, TableName, ColumnName, Val  
            FROM tblTemplates_Load_OtherObjects_Raw OO  
            JOIN tblTemplates_Fields F ON OO.OtherObjectsField = F.FieldName 
            WHERE TemplateType IN ('All','ALL', v_TemplateType) 
            AND OO.Val IS NOT NULL 
            AND  (TemplateVersion = p_TemplateVersion or (TemplateVersion is null and p_TemplateVersion <> 'V8')) 

            UNION 

            SELECT FieldID, TableName, ColumnName, Val 
            FROM tblTemplates_Fields_OtherDestinations OD 
            JOIN  
            ( 
                SELECT ID, Val 
                FROM tblTemplates_Load_OtherObjects_Raw OO  
                JOIN tblTemplates_Fields F ON OO.OtherObjectsField = F.FieldName 
                WHERE TemplateType IN ('All','ALL', v_TemplateType) 
                AND OO.Val IS NOT NULL 
                AND    (TemplateVersion = p_TemplateVersion or (TemplateVersion is null and p_TemplateVersion <> 'V8')) 

            ) UsedIDs 
            ON OD.FieldID = UsedIDs.ID


        ) D
        --#tmp_Templates_Load_Destinations ENDS

        JOIN USER_TAB_COLS C  ON upper(D.TableName) = upper(C.TABLE_NAME) AND upper(D.ColumnName) = upper(C.COLUMN_NAME)
        WHERE (v_UpdateComp = 0 OR D.TableName <> 'tblComp') 
        AND (v_UpdateCompInd = 0 OR D.TableName <> 'tblCompInd') 
        ORDER BY D.TableName, D.ColumnName
   )

   --#tmp_Templates_Load_InsertSQL ENDS

WHERE TableName = v_TableName ;

-- Get lists of all  values for current table 

Select   LISTAGG(
            CASE ISNUMERIC(Val) 
                WHEN 1 THEN Val 
                WHEN 0 THEN '''' || REPLACE(LTRIM(RTRIM(Val)), '''','''''') || '''' 
            END
            || ',' ) WITHIN GROUP ( ORDER BY ROWNUM ) 
            into v_Values
 FROM 
 --#tmp_Templates_Load_InsertSQL STARTS
  (

        SELECT D.TableName, D.ColumnName, D.Val
        FROM 

        --#tmp_Templates_Load_Destinations STARTS
        (         
            SELECT ID, TableName, ColumnName, Val  
            FROM tblTemplates_Load_OtherObjects_Raw OO  
            JOIN tblTemplates_Fields F ON OO.OtherObjectsField = F.FieldName 
            WHERE TemplateType IN ('All','ALL', v_TemplateType) 
            AND OO.Val IS NOT NULL 
            AND  (TemplateVersion = p_TemplateVersion or (TemplateVersion is null and p_TemplateVersion <> 'V8')) 

            UNION 

            SELECT FieldID, TableName, ColumnName, Val 
            FROM tblTemplates_Fields_OtherDestinations OD 
            JOIN  
            ( 
                SELECT ID, Val 
                FROM tblTemplates_Load_OtherObjects_Raw OO  
                JOIN tblTemplates_Fields F ON OO.OtherObjectsField = F.FieldName 
                WHERE TemplateType IN ('All','ALL', v_TemplateType) 
                AND OO.Val IS NOT NULL 
                AND    (TemplateVersion = p_TemplateVersion or (TemplateVersion is null and p_TemplateVersion <> 'V8')) 

            ) UsedIDs 
            ON OD.FieldID = UsedIDs.ID


        ) D
        --#tmp_Templates_Load_Destinations ENDS

        JOIN USER_TAB_COLS C  ON upper(D.TableName) = upper(C.TABLE_NAME) AND upper(D.ColumnName) = upper(C.COLUMN_NAME)
        WHERE (v_UpdateComp = 0 OR D.TableName <> 'tblComp') 
        AND (v_UpdateCompInd = 0 OR D.TableName <> 'tblCompInd') 
        ORDER BY D.TableName, D.ColumnName
   )

   --#tmp_Templates_Load_InsertSQL ENDS

WHERE TableName = v_TableName ;



-- Build Insert and append to v_SQL variable 
v_SQL:= v_SQL || CHR(10) || CHR(10)  
        || 'INSERT into ' || v_TableName || '(' || SUBSTR(v_Columns, 1, LENGTH(RTRIM(v_Columns))) || ')' || CHR(10) 
        || 'VALUES (' || SUBSTR(v_Values, 1, LENGTH(RTRIM(v_Values))-1) || ')' ;

v_Count := v_Count -1; 
   EXECUTE IMMEDIATE  v_SQL;
end loop;

1 Ответ

3 голосов
/ 27 марта 2019

Вы еще не показали, как вы в настоящее время преобразовываете один оператор в другой - я подозреваю, что вы используете динамический SQL, который вам не нужен, - но вы можете сделать это так:

declare
  v_TableName varchar2(30) := 'tblRecHistCalc';
  v_Columns varchar2(80) := 'average_eps,company_id,rec_code,rec_date';
  v_Values varchar2(80) := q'[3.3887524216711,25597,'B','20-Mar-2019',]';

  v_sql varchar2(4000);
begin
  select ''|| CHR(10) || CHR(10)  
           || 'INSERT into ' || v_TableName || '(' || v_Columns || ')' || CHR(10) 
           || 'VALUES (' || SUBSTR(v_Values,1, LENGTH(RTRIM(v_Values))-1) || ')'
  into v_sql
  from dual;

  dbms_output.put_line(v_query);

end;
/

или с помощьюприсваивание вместо выбора по двойной таблице:

  v_sql := CHR(10) || CHR(10)  
           || 'INSERT into ' || v_TableName || '(' || v_Columns || ')' || CHR(10) 
           || 'VALUES (' || SUBSTR(v_Values,1, LENGTH(RTRIM(v_Values))-1) || ')';

, любой из которых генерирует:

INSERT into tblRecHistCalc(average_eps,company_id,rec_code,rec_date)
VALUES (3.3887524216711,25597,'B','20-Mar-2019')


PL/SQL procedure successfully completed.

'20-Mar-2019' по-прежнему является строкой, поэтому вы полагаетесь на неявное преобразованиеи настройки NLS - если вы выполняете эту вставку немедленно, то они, по крайней мере, будут совпадать, но вы потеряете часть времени любых значений (с этой моделью; возможны худшие эффекты), и было бы лучше использовать явные преобразования дляи из строкового значения.

Мне также неясно из вашего кода - не то, чтобы я изучил его слишком подробно - как v_Values заканчивается запятой;но вы могли бы trim() это тоже отключить вместо использования substr().

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