由于ORA-01006无法动态删除记录:绑定变量不存在,如何动态删除记录?

时间:2013-12-11 21:13:22

标签: sql dynamic procedure delete-row

好的,继续尝试学习动态sql,我现在尝试根据用户输入动态删除行。所以这是基于我在网上找到的代码

SET SERVEROUTPUT ON ;

SET TERMOUT ON;
SET ECHO OFF;

CREATE OR REPLACE PROCEDURE deleteProspect 
    (
    v_cname IN CHAR DEFAULT NULL ,
    v_make IN CHAR DEFAULT NULL ,
    v_model IN CHAR DEFAULT NULL,
    v_cyear IN CHAR DEFAULT NULL,
    v_color IN CHAR DEFAULT NULL,
    v_trim IN CHAR DEFAULT NULL,
    v_ocode IN CHAR DEFAULT NULL
    )
    AS


    l_query VARCHAR2(512) DEFAULT 'DELETE FROM prospect ';




BEGIN



    IF(v_cname IS NOT NULL)
        THEN
        l_query := l_query||'where cname = :v_cname ';
        ELSE
        RAISE_APPLICATION_ERROR(-20000, 'Customer name cannot be empty ');
    END IF;

    IF(v_make IS NOT NULL)
        THEN
        l_query := l_query||'and make = :v_make ';
        ELSE
        RAISE_APPLICATION_ERROR(-20000, 'Car make name cannot be empty ');
    END IF;

    IF(v_model IS NOT NULL)
        THEN
        l_query := l_query||'and model = :v_model ';
        ELSE
        l_query :=l_query||'and model IS NULL ';
    END IF;

    IF(v_cyear IS NOT NULL)
        THEN
        l_query := l_query||'and cyear = :v_cyear ';
        ELSE
        l_query :=l_query||'and cyear IS NULL ';
    END IF;

    IF(v_color IS NOT NULL)
        THEN
        l_query := l_query||'and color = :v_color ';
        ELSE
        l_query :=l_query||'and color IS NULL ';
    END IF;

    IF(v_trim IS NOT NULL)
        THEN
        l_query := l_query||'and trim = :v_trim ';
        ELSE
        l_query :=l_query||'and trim IS NULL ';
    END IF;

    IF(v_ocode IS NOT NULL)
        THEN
        l_query := l_query||'and ocode = :v_ocode  ';
        ELSE
        l_query :=l_query||'and ocode IS NULL ';
    END IF;

    DBMS_OUTPUT.PUT_LINE(l_query);

        EXECUTE IMMEDIATE l_query 
        USING v_cname,v_make,v_model,v_cyear,v_color,v_trim,v_ocode;

        DBMS_OUTPUT.PUT_LINE(SQL%ROWCOUNT||' Rows Deleted');








        EXCEPTION
        WHEN NO_DATA_FOUND THEN
        DBMS_OUTPUT.PUT_LINE(' No data found in database');

        WHEN TOO_MANY_ROWS THEN
        DBMS_OUTPUT.PUT_LINE('Query returns too many rows of data');

        WHEN OTHERS THEN
        DBMS_OUTPUT.PUT_LINE('An error was encountered - '||SQLCODE||' -ERROR- '||SQLERRM);

END deleteProspect;
/

现在我拥有它,以便用户输入必须至少在删除查询中具有cname和make,然后将其从另一个脚本传递到此过程。

然而,当它运行时,发生的事情是它正在抛出一个错误说明 遇到错误 - -1006 -ERROR- ORA-01006:绑定变量不存在 当我测试这个时,我发现如果在这部分代码中

使用v_cname,v_make,v_model,v_cyear,v_color,v_trim,v_ocode;

我将其更改为

使用v_cname,v_make;

程序继续但它不会删除我表格中的任何记录。

所以我的问题是我在做什么,错了,如何修复以便基于动态用户输入,它会相应地删除该记录或记录。

对于前。

在我的表格中,我记录了以下内容:

Talk to me>desc prospect
Name Null? Type
CRAME NOT NULL CHAR(20)
MAKE NOT NULL CHAR(lO)
MODEL CHAR(8)
CYEAR CHAR (4)
COLOR CHAR(l2)
TRIM CHAR(l6)
OCODE CHAR(4) 

Talk to me>select * from prospect where cname='BROCK';
    more...

    CNAME                MAKE       MODEL    CYEA COLOR        TRIM             OCOD
    -------------------- ---------- -------- ---- ------------ ---------------- ----
    BROCK                MERCEDES   M10      2011 BLACK        BLACK            S23

但是当我运行我的代码时,会发生这种情况:

    Talk to me>@tdprospect
Enter a customer name: BROCK
Enter a car make: MERCEDES
Enter a model:
Enter a year:
Enter a color:
Enter trim:
Enter an option code:
old  15:        v_cname:= UPPER('&p_cname');
new  15:        v_cname:= UPPER('BROCK');
old  16:        v_make:= UPPER('&p_make');
new  16:        v_make:= UPPER('MERCEDES');
old  17:        v_model:= UPPER('&p_model');
new  17:        v_model:= UPPER('');
old  18:        v_cyear:= UPPER('&p_cyear');
new  18:        v_cyear:= UPPER('');
old  19:        v_color:= UPPER('&p_color');
new  19:        v_color:= UPPER('');
old  20:        v_trim:= UPPER('&p_trim');
new  20:        v_trim:= UPPER('');
old  21:        v_ocode:= UPPER('&p_ocode');
new  21:        v_ocode:= UPPER('');
DELETE FROM prospect where cname = :v_cname and make = :v_make and model IS NULL and cyear IS NULL and color IS NULL and trim IS NULL and
ocode IS NULL
An error was encountered - -1006 -ERROR- ORA-01006: bind variable does not exist

PL/SQL procedure successfully completed.

谢谢,

根据Glenn的建议,我将其修改为:

IF(v_cname IS NOT NULL)
        THEN
        l_query := l_query||'where cname = :v_cname ';
        ELSE
        RAISE_APPLICATION_ERROR(-20000, 'Customer name cannot be empty ');
    END IF;

IF(v_make IS NOT NULL)
    THEN
    l_query := l_query||'and make = :v_make ';
    ELSE
    RAISE_APPLICATION_ERROR(-20000, 'Car make name cannot be empty ');
END IF;


    l_query := l_query||'and model = NVL(:v_model,model) ';



    l_query := l_query||'and cyear = NVL(:v_cyear,cyear) ';


    l_query := l_query||'and color = NVL(:v_color,color) ';



    l_query := l_query||'and trim = NVL(:v_trim,trim) ';



    l_query := l_query||'and ocode = NVL(:v_ocode, ocode)  ';

然而它似乎没有完全正常工作,因为我得到以下内容:

Talk to me>@tdprospect
Enter a customer name: chris
Enter a car make: acura
Enter a model:
Enter a year:
Enter a color:
Enter trim:
Enter an option code:
old  15:        v_cname:= UPPER('&p_cname');
new  15:        v_cname:= UPPER('chris');
old  16:        v_make:= UPPER('&p_make');
new  16:        v_make:= UPPER('acura');
old  17:        v_model:= UPPER('&p_model');
new  17:        v_model:= UPPER('');
old  18:        v_cyear:= UPPER('&p_cyear');
new  18:        v_cyear:= UPPER('');
old  19:        v_color:= UPPER('&p_color');
new  19:        v_color:= UPPER('');
old  20:        v_trim:= UPPER('&p_trim');
new  20:        v_trim:= UPPER('');
old  21:        v_ocode:= UPPER('&p_ocode');
new  21:        v_ocode:= UPPER('');
DELETE FROM prospect where cname = NVL(:v_cname,cname) and make = NVL(:v_make,make) and model = NVL(:v_model,model) and cyear =
NVL(:v_cyear,cyear) and color = NVL(:v_color,color) and trim = NVL(:v_trim,trim) and ocode = NVL(:v_ocode, ocode)
0 Rows Deleted

PL/SQL procedure successfully completed.

Talk to me>
Talk to me>
Talk to me>
Talk to me>rollback;

Rollback complete.

Talk to me>@dprospect

Procedure created.

Talk to me>@tdprospect
Enter a customer name: brock
Enter a car make: mercedes
Enter a model:
Enter a year:
Enter a color:
Enter trim:
Enter an option code:
old  15:        v_cname:= UPPER('&p_cname');
new  15:        v_cname:= UPPER('brock');
old  16:        v_make:= UPPER('&p_make');
new  16:        v_make:= UPPER('mercedes');
old  17:        v_model:= UPPER('&p_model');
new  17:        v_model:= UPPER('');
old  18:        v_cyear:= UPPER('&p_cyear');
new  18:        v_cyear:= UPPER('');
old  19:        v_color:= UPPER('&p_color');
new  19:        v_color:= UPPER('');
old  20:        v_trim:= UPPER('&p_trim');
new  20:        v_trim:= UPPER('');
old  21:        v_ocode:= UPPER('&p_ocode');
new  21:        v_ocode:= UPPER('');
DELETE FROM prospect where cname = NVL(:v_cname,cname) and make = NVL(:v_make,make) and model = NVL(:v_model,model) and cyear =
NVL(:v_cyear,cyear) and color = NVL(:v_color,color) and trim = NVL(:v_trim,trim) and ocode = NVL(:v_ocode, ocode)
1 Rows Deleted

PL/SQL procedure successfully completed.

Talk to me>
Talk to me>
Talk to me>
Talk to me>rollback;

Rollback complete.

我知道克里斯记录存在

CNAME                MAKE       MODEL    CYEA COLOR        TRIM             OCOD
-------------------- ---------- -------- ---- ------------ ---------------- ----
CHRIS                ACURA
CHRIS                MERCEDES

此外,我不知道这是否有帮助,但潜在客户表有cname,make,model,cyear,color,trim和ocode。我的最终目标是根据用户输入,无论是cname还是仅制作或全部七个输入;相应删除记录。

1 个答案:

答案 0 :(得分:1)

我认为你传递的是动态sql中没有使用的绑定变量。可选项仍应具有绑定变量,因此请替换:

IF(v_model IS NOT NULL)
    THEN
    l_query := l_query||'and model = :v_model ';
    ELSE
    l_query :=l_query||'and model IS NULL ';
END IF;

使用:

l_query :=l_query||'and model = NVL(:v_model, model) ';

对于所有可选块,以便在表达式中始终有7个绑定变量(因为这是您传入的数量)。您也可以阅读sql注入。

更新

如果您不关心动态sql,可以像这样放一些东西。如果前景表在允许的列中不允许NULL,则可以删除一些NVL内容。

SET SERVEROUTPUT ON ;

SET TERMOUT ON;
SET ECHO OFF;

CREATE OR REPLACE PROCEDURE deleteProspect(
    v_cname IN CHAR DEFAULT NULL ,
    v_make  IN CHAR DEFAULT NULL ,
    v_model IN CHAR DEFAULT NULL,
    v_cyear IN CHAR DEFAULT NULL,
    v_color IN CHAR DEFAULT NULL,
    v_trim  IN CHAR DEFAULT NULL,
    v_ocode IN CHAR DEFAULT NULL
    )
AS

  K_NULL_MARKER VARCHAR2(32) DEFAULT '~!';

BEGIN

    IF(v_cname IS NULL)
    THEN
        RAISE_APPLICATION_ERROR(-20000, 'Customer name cannot be empty ');
    END IF;

    IF(v_make IS NULL)
    THEN
        RAISE_APPLICATION_ERROR(-20000, 'Car make name cannot be empty ');
    END IF;


    DELETE
      FROM prospect
      WHERE cname = v_cname
        AND make  = v_make
        AND NVL(model, K_NULL_MARKER) = NVL(v_model, NVL(model, K_NULL_MARKER))
        AND NVL(cyear, K_NULL_MARKER) = NVL(v_cyear, NVL(cyear, K_NULL_MARKER))
        AND NVL(color, K_NULL_MARKER) = NVL(v_color, NVL(color, K_NULL_MARKER))
        AND NVL(trim,  K_NULL_MARKER) = NVL(v_trim,  NVL(trim,  K_NULL_MARKER))
        AND NVL(ocode, K_NULL_MARKER) = NVL(v_ocode, NVL(ocode, K_NULL_MARKER))
    ;

END deleteProspect;
/