插入、更新或删除的 CASE 语句

Posted

技术标签:

【中文标题】插入、更新或删除的 CASE 语句【英文标题】:CASE statement for insert, update or delete 【发布时间】:2018-07-02 07:43:24 【问题描述】:

我已经创建了存储过程。在那个存储过程中,我想要插入、更新或删除的 case 语句。

If v_var='I' then insert into main_tbl
If v_var='D' then delete from main_tbl where  <condition>
If v_var='U' then update main_tbl set <condition>.

为此我创建了存储过程

create or replace procedure sp_cs as
    v_var txt.col1%type;
    type record is ref cursor return txt%rowtype;  --Staging table
    v_rc record;
    cursor c1 is select * from txt;
begin
    open c1;
    loop 
        fetch c1 into v_rc;
        for i in 1 .. v_rc.count
        loop
         select v_rc(i).col1 into v_var from txt;
            case when v_var ='I' then
                 insert into main_tbl values (v_rc(i).col1, .....);
            when v_var ='D' then
                 delete from main_tbl m where m.col2=v_rc(i).col2;
            when v_var ='U' then
                 update main_tbl m set m.col2=v_rc(i).col2;
            end case;
        end loop;
    end loop;
    close c1;
end;

执行此操作后,数据无法加载到 ma​​in_tbl。你能帮我解决我的问题吗? 谢谢

【问题讨论】:

when 关键字丢失了两次。还有一个end @jarlh 我已经完成了,但仍然遇到同样的问题。 create or replace sp_cs 实际上是 create or replace procedure sp_cs as 在你的真实代码中吗? 循环永远不会退出,因为没有exit when c1%notfound 来检查光标状态(尽管普通的Cursor FOR loop 会使这变得简单得多)。此外,v_var 永远不会设置为任何值。另外,v_rc 是记录而不是数组,所以不能有任何v_rc.countv_rc(i) 您没有为 v_var 设置任何值。在这种情况下,默认情况下它将为空。所以 case 语句永远不会满足。 【参考方案1】:

嗯,OPEN..FETCH..LOOP 已经过时了。您应该根据参数简单地使用单个插入/更新/删除语句。这将比您的循环构造更有效。

CREATE OR replace PROCEDURE sp_cs (p_var txt.col1%TYPE) 
IS 
BEGIN 
    CASE p_var 
      WHEN 'I' THEN 
        INSERT INTO main_tbl 
        SELECT * 
        FROM   txt; 
      WHEN 'D' THEN 
        DELETE FROM main_tbl m 
        WHERE  EXISTS (SELECT 1 
                       FROM   txt t 
                       WHERE  m.col2 = t.col2); 
      WHEN 'U' THEN 
        UPDATE main_tbl m 
        SET    m.col2 = (SELECT v_rc.col2 
                         FROM   txt 
                         WHERE  m.somecol = t.somecol); -- the column you want to compare while updating
    END CASE; 
END; 

/ 

虽然从您的更新查询中不清楚您想要实现什么,但我假设您在从 main_tbl 更新 col2 时在 txt 中有一个公共列。此外,我已将您的参数用作过程参数p_var。如果您不想传递它,可以将其用作局部变量。

【讨论】:

【参考方案2】:

您需要按原样声明您的过程,因此您在第一行缺少一个关键字:

create or replace PROCEDURE sp_cs

您缺少 WHEN 关键字和 END CASE

 case when v_var = 'I'
      then insert into main_tbl values (v_rc(i).col1, .....);
      when v_var = 'D'
      then delete from main_tbl m where m.col2=v_rc.col2;
      when v_var = 'U'
      then update main_tbl m set m.col2=v_rc.col2;
 end case;

【讨论】:

【参考方案3】:

创建过程有几个语法错误,试试下面的。 另外,看看Oracle MERGE

MERGE 可以在一个语句中执行 INSERT、UPDATE 和 DELETE。

CREATE OR REPLACE PROCEDURE sp_cs
IS
   v_var   txt.col1%TYPE;

   TYPE record IS REF CURSOR
      RETURN txt%ROWTYPE;                                      --Staging table

   v_rc    record;

   CURSOR c1
   IS
      SELECT * FROM txt;
BEGIN
   OPEN c1;

   LOOP
      FETCH c1 INTO v_rc;

      FOR i IN 1 .. v_rc.COUNT
      LOOP
         CASE
            WHEN v_var = 'I'
            THEN
               INSERT INTO main_tbl
                    VALUES (v_rc (i).col1);
            WHEN v_var = 'D'
            THEN
               DELETE FROM main_tbl m
                     WHERE m.col2 = v_rc.col2;
            WHEN v_var = 'U'
            THEN
               UPDATE main_tbl m
                  SET m.col2 = v_rc.col2;
         END CASE;
      END LOOP;
   END LOOP;

   CLOSE c1;
END;

【讨论】:

【参考方案4】:

这里需要 ref cur 吗?如果没有,那么试试这个

create or replace procedure sp_cs 
as
    cursor c1 is select * from txt;
    rc c1%rowtype;
begin
    For c in rc Loop
        case c.col1 
            When 'I' Then
                insert into main_tbl values (c.col1, .....);
            When 'U' Then
                update main_tbl m set m.col2=c.col2;
            When 'D'
                delete from main_tbl m where m.col2=c.col2;
        End Case;
    End Loop;
end;

【讨论】:

以上是关于插入、更新或删除的 CASE 语句的主要内容,如果未能解决你的问题,请参考以下文章

存储更新、插入或删除语句影响了意外数量的行

我收到存储更新、插入或删除语句影响了意外的行数 (0) 错误

[Asp.net mvc]实体更新异常:存储区更新插入或删除语句影响到了意外的行数。实体在加载后可能被修改或删除。

将 MERGE 语句的更新列审计为不同表中的行

使用 Case 语句更新程序

Oracle触发器使用case语句创建