我试图在CLOB变量中传递单个INTEGER列的值,以便可以执行IN操作(列输出的大小未知),但是出现错误,现在卡住了。首先,我试图在IN之后使用SELECT语句,但是我发现它在PL / SQL中不起作用。因此,简而言之,我希望能够检查表中的主键,如果不存在该主键,请使用新值更新现有记录,但是如果已经存在,则无法执行该操作。
DoGood Donor应用程序包含一个页面,该页面允许 管理员在DD_DONOR中更改分配给捐赠者的ID 表。创建一个PL / SQL块来处理此任务。包括 异常处理代码,以解决尝试通过 输入重复的捐赠者ID。如果发生此错误,则显示消息 “此ID已被分配。”通过更改供体ID 305来测试代码。
这是我使用的桌子。 DD_DONOR
Name Null? Type
--------- -------- ------------
IDDONOR NOT NULL NUMBER(4)
FIRSTNAME VARCHAR2(15)
LASTNAME VARCHAR2(30)
TYPECODE CHAR(1)
STREET VARCHAR2(40)
CITY VARCHAR2(20)
STATE CHAR(2)
ZIP VARCHAR2(9)
PHONE VARCHAR2(10)
FAX VARCHAR2(10)
EMAIL VARCHAR2(25)
NEWS CHAR(1)
DTENTERED DATE
这是我的代码:
DECLARE
all_ids clob;
newID DD_DONOR.IDDONOR%TYPE;
fname DD_DONOR.FIRSTNAME%TYPE;
lname DD_DONOR.LASTNAME%TYPE;
CURSOR id IS
SELECT IDDONOR FROM DD_DONOR;
BEGIN
newID := 305;
fname := 'Thomas';
lname := 'Sheer';
OPEN id;
FETCH id BULK COLLECT INTO all_ids;
IF id%NOTFOUND THEN
UPDATE DD_DONOR
SET IDDONOR = newID
WHERE FIRSTNAME = fname AND LASTNAME = lname;
DBMS_OUTPUT.PUT_LINE(fname || ' ' || lname || ' ' || 'New ID: ' || newID);
ELSIF id%FOUND THEN
DBMS_OUTPUT.PUT_LINE('This ID is already assigned.');
END IF;
CLOSE id;
END;
这是错误:
Error report -
ORA-06550: line 14, column 32:
PLS-00497: cannot mix between single row and multi-row (BULK) in INTO list
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
我在开始时创建的这段代码可以编译,但是对表没有任何作用,所以我放弃了它:
DECLARE
newID DD_DONOR.IDDONOR%TYPE;
fname DD_DONOR.FIRSTNAME%TYPE;
lname DD_DONOR.LASTNAME%TYPE;
BEGIN
newID := 305;
fname := 'Thomas';
lname := 'Sheer';
UPDATE DD_DONOR
SET IDDONOR = newID
WHERE NOT EXISTS (SELECT IDDONOR
FROM DD_DONOR
WHERE FIRSTNAME = fname AND LASTNAME = lname);
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('This ID is already assigned.');
END;
输出:
PL/SQL procedure successfully completed.
另一个无效的版本:
DECLARE
newID DD_DONOR.IDDONOR%TYPE;
fname DD_DONOR.FIRSTNAME%TYPE;
lname DD_DONOR.LASTNAME%TYPE;
BEGIN
newID := 305;
fname := 'Thomas';
lname := 'Sheer';
IF (SELECT IDDONOR FROM DD_DONOR
WHERE FIRSTNAME = fname AND LASTNAME = lname) = newID
THEN
DBMS_OUTPUT.PUT_LINE('This ID is already assigned.');
ELSE
UPDATE DD_DONOR
SET IDDONOR = newID
WHERE FIRSTNAME = fname AND LASTNAME = lname;
END IF;
END;
这种方法有效,但同样不会输出错误的ID信息:
SET SERVEROUTPUT ON SIZE 100000
DECLARE
newID DD_DONOR.IDDONOR%TYPE;
fname DD_DONOR.FIRSTNAME%TYPE;
lname DD_DONOR.LASTNAME%TYPE;
CURSOR id IS
SELECT IDDONOR FROM DD_DONOR
WHERE FIRSTNAME = fname AND LASTNAME = lname;
BEGIN
newID := 305;
fname := 'Thomas';
lname := 'Sheer';
OPEN id;
IF SQL%NOTFOUND THEN
UPDATE DD_DONOR
SET IDDONOR = newID
WHERE FIRSTNAME = fname AND LASTNAME = lname;
DBMS_OUTPUT.PUT_LINE(fname || ' ' || lname || ' ' || 'New ID: ' || newID);
ELSIF SQL%FOUND THEN
DBMS_OUTPUT.PUT_LINE('This ID is already assigned.');
END IF;
CLOSE id;
END;
这是行不通的,但是我喜欢。看起来应该可以。
SET SERVEROUTPUT ON SIZE 100000
DECLARE
newID DD_DONOR.IDDONOR%TYPE;
fname DD_DONOR.FIRSTNAME%TYPE;
lname DD_DONOR.LASTNAME%TYPE;
CURSOR id IS
SELECT IDDONOR FROM DD_DONOR
WHERE FIRSTNAME = fname AND LASTNAME = lname;
all_IDs DD_DONOR%rowtype;
BEGIN
newID := 305;
fname := 'Thomas';
lname := 'Sheer';
OPEN id;
LOOP
FETCH id into all_IDs;
UPDATE DD_DONOR
SET IDDONOR = newID
WHERE FIRSTNAME = fname AND LASTNAME = lname;
DBMS_OUTPUT.PUT_LINE(fname || ' ' || lname || ' ' || 'New ID: ' || newID);
EXIT WHEN id%FOUND;
DBMS_OUTPUT.PUT_LINE('This ID is already assigned.');
END LOOP;
CLOSE id;
END;
Error report -
ORA-06550: line 15, column 9:
PLS-00394: wrong number of values in the INTO list of a FETCH statement
ORA-06550: line 15, column 9:
PL/SQL: SQL Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
答案 0 :(得分:2)
您的id
是NUMBER
。您的all_ids
是CLOB
,基本上是一个很大的字符串字段。查询中的IN
子句适用于离散值的显式列表。这不是字符串搜索之类的东西。您可能想要的是一个收藏夹。
IN
的工作方式如下:
WHERE id IN (1, 2, 3)
列表的长度必须固定。它也可以像这样工作:
WHERE id IN ( SELECT id FROM table2 )
我不太清楚你要做什么。您的第二个查询会将表中的每行更新为newID
,这几乎肯定不是您想要的。如果表中不存在fname
和lname
,如何识别要更新的行?
答案 1 :(得分:1)
请尝试这段代码:
DECLARE
newID DD_DONOR.IDDONOR%TYPE;
oldID DD_DONOR.IDDONOR%TYPE;
fname DD_DONOR.FIRSTNAME%TYPE;
lname DD_DONOR.LASTNAME%TYPE;
BEGIN
newID := 305;
fname := 'Thomas';
lname := 'Sheer';
select
iddonor
into
oldId
from
dd_donor
WHERE iddonor = newId;
dbms_output.put_line('This ID is already assigned');
exception
when NO_DATA_FOUND then
UPDATE DD_DONOR
SET IDDONOR = newID
WHERE FIRSTNAME = fname AND LASTNAME = lname;
DBMS_OUTPUT.PUT_LINE(fname || ' ' || lname || ' ' || 'New ID: ' || newID);
END;
/
如果您要坚持使用光标的方法,请在此处更改初始脚本:
已在更改:
all_ids DD_DONOR.IDDONOR%TYPE-不需要CLOB,因为您期望只有一个具有此ID的记录。
游标的声明和调用-添加了参数,因此您可以搜索特定的ID
DECLARE
all_ids DD_DONOR.IDDONOR%TYPE;
newID DD_DONOR.IDDONOR%TYPE;
fname DD_DONOR.FIRSTNAME%TYPE;
lname DD_DONOR.LASTNAME%TYPE;
CURSOR id(newID in DD_DONOR.IDDONOR%TYPE) IS
SELECT IDDONOR FROM DD_DONOR where iddonor = newID;
BEGIN
newID := 305;
fname := 'Thomas';
lname := 'Sheer';
OPEN id(newId);
FETCH id INTO all_ids;
IF id%NOTFOUND THEN
UPDATE DD_DONOR
SET IDDONOR = newID
WHERE FIRSTNAME = fname AND LASTNAME = lname;
DBMS_OUTPUT.PUT_LINE(fname || ' ' || lname || ' ' || 'New ID: ' || newID);
ELSIF id%FOUND THEN
DBMS_OUTPUT.PUT_LINE('This ID is already assigned.');
END IF;
CLOSE id;
END;
/
谢谢