更新时找不到数据错误。如果该 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
有两个值(0和1只)
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有索引,那么它们都应该重新创建;如果其他用户有权限,也应该重新授予。
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
有两个值(0和1只)
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有索引,那么它们都应该重新创建;如果其他用户有权限,也应该重新授予。