在 DML 过程中使用立即执行并在参数中传递字符值

Use execute immediate in procedure for DML and passing character value in parameter

我有一个删除过程,它使用 table 名称和一些值来从 table 中删除记录,因此我创建了一个立即执行的过程,它通过采用参数并删除。

但是,每当我在参数中传递 char 值时,它都会出错:

invalid identifier 

作为字符值不带单引号的查询。请告诉我如何在过程中传递 char 值以正确形成字符串。

程序如下:

CREATE OR replace PROCEDURE Prd_delete(p_tbl_name IN VARCHAR2,
                                       p_sys      VARCHAR2,
                                       p_b_id     VARCHAR2,
                                       p_c_date   NUMBER)
IS
  dlt_query VARCHAR2(200);
BEGIN
    dlt_query := 'delete from '
                 ||p_tbl_name
                 ||' where system='
                 ||p_sys
                 || ' And batch_id='
                 ||p_b_id
                 || ' And cobdate='
                 ||p_c_date;

    --dbms_output.put_line(dlt_query);
    EXECUTE IMMEDIATE dlt_query;
END;

/ 

运行命令如下:

exec prd_delete ('TBL_HIST_DATA','M','N1',20141205);

错误如下:

ORA-00904:"N1" invalid identifier.

如何正确传递这个值?请建议。

您在连接过程中丢失了 N1 周围的引号

您可以通过在 前后添加引号来修复,例如。

dlt_query := 'delete from '||P_TBL_NAME||' where system='||P_SYS||
' And batch_id='||''''||P_B_ID|| '''' ||
' And cobdate='||P_C_DATE;
  • 首先,为什么DELETE需要PL/SQL。你可以用简单的 SQL.
  • 为什么P_C_DATENUMBERcobdateCOLUMN是什么数据类型。日期应始终为 DATE。如果列数据类型是DATE,那么你会运行陷入更多的错误。始终注意声明正确的数据类型。

对于dynamic SQL,在直接执行之前,最好使用DBMS_OUTPUT查看查询是否正确形成。我还建议使用 quoting string literal technique 使它更容易。

DBMS_OUTPUT.PUT_LINE(dlt_query);

查询的问题是您缺少 VARCHAR2 类型周围的 single-quotation 标记。

修改查询为-

dlt_query := 'delete from '||P_TBL_NAME||' where system='||P_SYS||
             ' And batch_id='||''''||P_B_ID|| '''' ||
             ' And cobdate='||P_C_DATE;

如果必须使用 EXECUTE IMMEDIATE 语句,则应使用绑定变量:

    CREATE OR REPLACE PROCEDURE prd_delete (P_TBL_NAME IN VARCHAR2,
                                                P_SYS VARCHAR2,
                                                P_B_ID VARCHAR2,
                                                P_C_DATE NUMBER) IS
          dlt_query   VARCHAR2 (200);
    BEGIN
      dlt_query := 'delete from ' || P_TBL_NAME || ' where system=:1 and batch_id=:2 and cobdate=:3';
      BEGIN
        EXECUTE IMMEDIATE dlt_query USING P_SYS, P_B_ID, P_C_DATE;
      EXCEPTION
        WHEN OTHERS THEN
          -- catch exception !!
      END;
    END;
   /