如何将列的值提取到CLOB变量中?

时间:2020-10-30 03:05:30

标签: oracle plsql

我试图在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.

2 个答案:

答案 0 :(得分:2)

您的idNUMBER。您的all_idsCLOB,基本上是一个很大的字符串字段。查询中的IN子句适用于离散值的显式列表。这不是字符串搜索之类的东西。您可能想要的是一个收藏夹。

IN的工作方式如下:

WHERE id IN (1, 2, 3)

列表的长度必须固定。它也可以像这样工作:

WHERE id IN ( SELECT id FROM table2 )

我不太清楚你要做什么。您的第二个查询会将表中的行更新为newID,这几乎肯定不是您想要的。如果表中不存在fnamelname,如何识别要更新的行?

答案 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;
/

谢谢