gpt4 book ai didi

oracle - 在plsql中使用for循环更新

转载 作者:行者123 更新时间:2023-12-04 14:01:43 25 4
gpt4 key购买 nike

我在更新和插入下面的列时遇到问题。请对此提供建议。

这是输入

depnto   extra    comm
----------------------------
20 300 NULL
20 300 400
20 NULL NULL
20 500 NULL

这是预期的输出
depnto  Extra    comm
---------------------
20 300 300
20 300 400
20 NULL NULL
20 500 500

在以下情况下,我需要使用 comm列更新 extra列。
  • 如果comm为null,则多余的值将更新为comm。
  • 如果comm不为null,则无需更新
  • 如果两者都为空,则保留为空,
  • ,如果comm列具有值,则无需覆盖。

  • 我的程序在下面。甚至我都需要跟踪哪些行被更新以及另一个表中的值。
    PROCEDURE (dept_id )
    AS
    BEGIN
    FOR r IN (SELECT *
    FROM emp
    WHERE comm IS NULL AND extra IS NOT NULL AND deptno = dept_id)
    LOOP
    UPDATE emp
    SET comm = extra
    WHERE comm IS NULL AND extra IS NOT NULL AND deptno = dept_id;



    INSERT INTO changed_comm (deptno, oldval, newval)
    VALUES (dept_id, r.comm, r.extra);
    END LOOP;
    EXCEPTION
    WHEN NO_DATA_FOUND
    THEN
    NULL;
    END;

    请在上面提供一些意见。它没有正确插入。

    最佳答案

    您不需要FOR LOOP,只需一个UPDATE即可完成工作:

    UPDATE emp
    SET comm = extra
    WHERE comm IS NULL AND extra IS NOT NULL;

    这是一个演示: http://www.sqlfiddle.com/#!4/aacc3/1

    ---编辑----
    我没有注意到,在预期的输出中,将deptno 10更新为20,以更新 deptno,需要另一个查询:
    UPDATE emp
    SET deptno = 20
    WHERE deptno = 10;

    ----编辑-----
    如果要将更改的值插入到另一个表中,请尝试使用RETURNING..BULK COLLECT和FORALL进行以下过程:
    CREATE OR REPLACE PROCEDURE pro_cedure( p_dept_id number  ) 
    IS
    TYPE changed_table_type IS TABLE OF changed%ROWTYPE;
    changed_buff changed_table_type;
    BEGIN
    SELECT deptno, comm, extra BULK COLLECT INTO changed_buff
    FROM emp
    WHERE comm IS NULL AND extra IS NOT NULL AND deptno = p_dept_id
    FOR UPDATE;
    UPDATE emp
    SET comm = extra
    WHERE comm IS NULL AND extra IS NOT NULL AND deptno = p_dept_id;
    FORALL i IN 1 .. changed_buff.count
    INSERT INTO changed VALUES changed_buff( i );
    END;
    /

    如果您不打算在一个调用中处理大量记录(超过1000个记录,或者最多数千个记录),则该过程应该有效。如果一个 dept_id可以包含一万多行,那么此过程可能会很慢,因为它将消耗大量的PGA内存。在这种情况下,需要另一种以块为单位进行批量收集的方法。

    -编辑---如何存储序列值-------

    我假设表 changed有4列,如下所示:
      CREATE TABLE "TEST"."CHANGED" 
    ( "DEPTNO" NUMBER,
    "OLDVAL" NUMBER,
    "NEWVAL" NUMBER,
    "SEQ_NEXTVAL" NUMBER
    ) ;

    并将序列值存储在 seq_nextval列中。

    在这种情况下,过程可能如下所示:
    create or replace 
    PROCEDURE pro_cedure( p_dept_id number )
    IS
    TYPE changed_table_type IS TABLE OF changed%ROWTYPE;
    changed_buff changed_table_type;
    BEGIN
    SELECT deptno, comm, extra, sequence_name.nextval
    BULK COLLECT INTO changed_buff
    FROM emp
    WHERE comm IS NULL AND extra IS NOT NULL AND deptno = p_dept_id
    FOR UPDATE;
    UPDATE emp
    SET comm = extra
    WHERE comm IS NULL AND extra IS NOT NULL AND deptno = p_dept_id;
    FORALL i IN 1 .. changed_buff.count
    INSERT INTO changed VALUES changed_buff( i );
    END;

    ---编辑---带有光标的版本用于少量数据集-----

    是的,对于少量数据集,批量收集不会显着提高速度,在这种情况下,带有for..loop的普通游标就足够了。
    以下是tu如何将游标与更新一起使用的示例,请注意 FOR UPDATE子句,当我们计划使用 WHERE CURRENT OF子句更新从游标中获取的记录时,这是必需的。
    这次在INSERT语句中评估序列值。
    create or replace 
    PROCEDURE pro_cedure( p_dept_id number )
    IS
    CURSOR mycursor IS
    SELECT deptno, comm, extra
    FROM emp
    WHERE comm IS NULL AND extra IS NOT NULL
    AND deptno = p_dept_id
    FOR UPDATE;
    BEGIN
    FOR emp_rec IN mycursor
    LOOP
    UPDATE emp
    SET comm = extra
    WHERE CURRENT OF mycursor;
    INSERT INTO changed( deptno, oldval, newval, seq_nextval)
    VALUES( emp_rec.deptno, emp_rec.comm,
    emp_rec.extra, sequence_name.nextval );
    END LOOP;
    END;

    关于oracle - 在plsql中使用for循环更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18670392/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com