Oracle 10g - 逃避单引号的最佳方式

时间:2010-03-22 20:14:16

标签: oracle10g

我必须根据数据库中的表生成一些更新语句。我创建了以下脚本,它生成了我需要的更新语句。但是当我尝试运行这些脚本时,我收到的错误与内容中未转义的单引号以及在oracle中具有特殊含义的& B,& T字符有关。我通过将SET DEFINE设置为OFF来处理& B和& T问题。什么是逃避内容中单引号的最佳方式?

DECLARE
    CURSOR C1 IS
        SELECT * FROM EMPLOYEES;

BEGIN
    FOR I IN C1
    LOOP
        DBMS_OUTPUT.PUT_LINE('UPDATE EMPLOYEES SET 
            FIRST_NAME= ''' || I.FIRST_NAME|| ''',
            LAST_NAME = ''' || I.LAST_NAME ''',
            DOB = ''' || I.DOB|| '''
            WHERE EMPLOYEE_ID = ''' ||  I.EMPLOYEE_ID || ''';');
    END LOOP;
END;                

如果first_name或last_name包含单引号,则生成的update语句会中断。什么是逃避first_name和last_name中单引号的最佳方法?

1 个答案:

答案 0 :(得分:1)

您可以使用REPLACE:

DECLARE
    CURSOR C1 IS
        SELECT * FROM EMPLOYEES;

BEGIN
    FOR I IN C1
    LOOP
        DBMS_OUTPUT.PUT_LINE('UPDATE EMPLOYEES SET 
            FIRST_NAME= ''' || REPLACE(I.FIRST_NAME,'''','''''') || ''',
            LAST_NAME = ''' || REPLACE(I.LAST_NAME,'''','''''') || ''',
            DOB = TO_DATE(''' || TO_CHAR(I.DOB,'DD/MM/YYYY') || '',''DD/MM/YYYY'')'
            WHERE EMPLOYEE_ID = ' ||  I.EMPLOYEE_ID || ';');
    END LOOP;
END;

注意:

  • 您在||后错过了I.LAST_NAME
  • 我认为I.EMPLOYEE_ID是一个数字 - 在这种情况下,我不会用引号括起来。
  • 我认为I.DOB是一个日期 - 在这种情况下,我建议您明确地将其投放到某个日期。

<强> ALTERNATIVE: 如果您使用的是Oracle 10g或更高版本,则可以使用这种更易于阅读的替代语法;并使用REPLACE让事情变得更加明显 - 这是我个人的偏好:

DECLARE
    CURSOR C1 IS
        SELECT * FROM EMPLOYEES;

BEGIN
    FOR I IN C1
    LOOP
        DBMS_OUTPUT.PUT_LINE(REPLACE(REPLACE(REPLACE(REPLACE(
         q'[UPDATE EMPLOYEES SET 
            FIRST_NAME= q'{#FIRST_NAME#}',
            LAST_NAME = q'{#LAST_NAME#}',
            DOB = DATE '#DOB#'
            WHERE EMPLOYEE_ID = #EMPLOYEE_ID#;
           ]'
           ,'#FIRST_NAME#', I.FIRST_NAME)
           ,'#LAST_NAME#', I.LAST_NAME)
           ,'#DOB#', TO_CHAR(I.DOB,'YYYY-MM-DD'))
           ,'#EMPLOYEE_ID#', I.EMPLOYEE_ID)
           );
    END LOOP;
END;

以上优点是很容易发现动态SQL中可能存在的错误,在编译时没有检查语法错误。