更新时找不到数据错误。如果该 ID 的任何一行为 0,则需要将记录更新为 0

While updating getting no data found error. Need to update the record to 0 if any one the rows for that ID is 0

CREATE TABLE test_tab (
    s_id        NUMBER(10),
    e_id        NUMBER(10),
    active_flg  NUMBER(1)
);

INSERT INTO test_tab VALUES(1,11,1);
INSERT INTO test_tab VALUES(2,11,1);
INSERT INTO test_tab VALUES(3,11,0);
INSERT INTO test_tab VALUES(4,12,1);
INSERT INTO test_tab VALUES(5,12,1);

COMMIT;

Tool Used: SQL Developer(18c)

我想通过识别其中的值 0 来更新 active_flg 列。假设,对于 e_id 11 我们有 3 行,所以首先它应该检查 e_id 11 是否有任何 0 active_flg 如果特定 e_id 存在 0 那么它应该更新e_id 11 到 0 的整行。如果 active_flg 没有条目,则它不应更新任何内容。

我的尝试:

SET SERVEROUTPUT ON;
DECLARE
lv_row test_tab%ROWTYPE;
BEGIN
FOR i IN (SELECT * FROM test_tab)
LOOP
SELECT * INTO lv_row FROM test_tab WHERE e_id = i.e_id AND active_flg = 0;
UPDATE test_tab SET active_flg = 0 WHERE active_flg = 0;
END LOOP;
END;

但是我没有找到任何数据错误。

预期输出:

+------+------+------------+
| s_id | e_id | active_flg |
+------+------+------------+
|    1 |   11 |          0 |
|    2 |   11 |          0 |
|    3 |   11 |          0 |
|    4 |   12 |          1 |
|    5 |   12 |          1 |
+------+------+------------+

引发 no data found 的原因是 SELECT INTO 子句没有 i.e_id 的每个值的数据。有些记录有 active_flg = 1,因此它会引发未找到该记录的数据。

DECLARE
BEGIN
  -- select DISTINCT so there is only 1 row per e_id.
  -- add WHERE clause to only select e_id values that 
  --  have an active_flag = 0. since no action is to be take on the 
  --  others ignore those
  FOR i IN (SELECT DISTINCT e_id FROM test_tab WHERE active_flag = 0)
  LOOP
    -- no need for the select into. The resultset of the cursor for loop
    -- only contains the relevant records.
    UPDATE test_tab SET active_flg = 0 WHERE e_id = i.e_id;
  END LOOP;
END;

merge 怎么样(而不是 PL/SQL)?

之前:

SQL> select * From test_tab order by s_id;

      S_ID       E_ID ACTIVE_FLG
---------- ---------- ----------
         1         11          1
         2         11          1
         3         11          0
         4         12          1
         5         12          1

合并:

SQL> merge into test_tab a
  2    using (select e_id from test_Tab
  3           where active_flg = 0
  4          ) b
  5    on (a.e_id = b.e_id)
  6    when matched then update set
  7      a.active_flg = 0;

3 rows merged.

之后:

SQL> select * From test_tab order by s_id;

      S_ID       E_ID ACTIVE_FLG
---------- ---------- ----------
         1         11          0
         2         11          0
         3         11          0
         4         12          1
         5         12          1

SQL>

一个(实用且快速)选项是使用分析函数假设active_flg有两个值(01只)

SQL> CREATE TABLE test_tab2 AS

SQL> SELECT t.s_id, t.e_id, MIN(t.active_flg) OVER (PARTITION BY t.e_id) AS active_flg
       FROM test_tab t;

SQL> DROP TABLE test_tab;

SQL> ALTER TABLE test_tab2 RENAME TO test_tab;

但是如果table有索引,那么它们都应该重新创建;如果其他用户有权限,也应该重新授予。