动态地用PL-SQL中的双引号替换单引号

问题描述 投票:0回答:1

我有以下查询:

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 = bblRecistKal,

v_Columns = 'average_eps,COMPANY_ID,rec_code,rec_date'

V_value ='1.3220 c,20,'或','to-mar-to-1','

所以查询变成:

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;

但是查询仍然没有成功执行。

我怎样才能实现这一目标?

编辑:

正如Alex Poole所述,变量声明如下:

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;
oracle plsql
1个回答
3
投票

您还没有展示当前如何将一个语句转换为另一个语句 - 我怀疑使用您不需要的动态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()

© www.soinside.com 2019 - 2024. All rights reserved.