好的,继续尝试学习动态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还是仅制作或全部七个输入;相应删除记录。
答案 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;
/