[英]How to loop through table and update values in pl/sql
我們有Oracle 12數據庫。
我需要遍歷表並根據上一行更新值。 像下面一樣,我需要從第1行獲取值並將其更新為第2至6行。然后從第7行獲取新值並繼續進行到表末尾。 column1是csv格式的文本,因此我需要從那里提取數字值。
id column1 column2
1 xxx;yyy;zzz;123456;
2 aaa
3 bbb
4 ccc
5 ddd
6 eee
7 xxx;yyy;zzz;789123;
8 aaa
更新后的表應如下所示:
id column1 column2
1 xxx;yyy;zzz;123456;
2 aaa 123456
3 bbb 123456
4 ccc 123456
5 ddd 123456
6 eee 123456
7 xxx;yyy;zzz;789123;
8 aaa 789123
Tbh我對pl / sql沒有太多經驗。 我試圖在循環中使用pl / sql,但是沒有用。
如果有人可以將我踢向正確的方向,將不勝感激。
您不需要PL / SQL,可以使用MERGE
, LAG( ... ) IGNORE NULLS ...
分析函數和REGEXP_SUBSTR
的組合完全通過SQL來完成(提取子字符串):
MERGE INTO table_name dst
USING (
SELECT id,
CASE WHEN val IS NULL
THEN LAG( val ) IGNORE NULLS OVER ( ORDER BY id )
END AS val
FROM (
SELECT id,
REGEXP_SUBSTR( column1, ';(\d{6});$', 1, 1, NULL, 1 ) AS val
FROM table_name
)
) src
ON ( dst.id = src.id )
WHEN MATCHED THEN
UPDATE SET column2 = src.val;
更新后的表格:
id column1 column2
-- ------------------- -------
1 xxx;yyy;zzz;123456;
2 aaa 123456
3 bbb 123456
4 ccc 123456
5 ddd 123456
6 eee 123456
7 xxx;yyy;zzz;789123;
8 aaa 789123
這樣的事情應該做你想要的。 它遍歷該表,每次以“ xxx”開頭時,將第一條記錄的最后一位傳遞給變量,如果沒有則更新第2列。
DECLARE
L_UpdateVal VARCHAR2(10) := '';
BEGIN
FOR REC IN (SELECT Column1, column2, ROWNUM From table) LOOP
IF SUBSTR(REC.column1, 1, 3) = 'xxx' THEN
L_UpdateVal := SUBSTR(column1, 13, 6);
ELSE
UPDATE Table SET Column2 = L_UpdateVal
WHERE ROWNUM := REC.ROWNUM
END IF;
END LOOP;
END;
您不需要PL / SQL,可以在一個MERGE語句中完成。
首先,找出如何獲得所需的結果-您可以使用LAST_VALUE()分析函數來完成此操作,如下所示:
WITH your_table AS (SELECT 1 id, 'xxx;yyy;zzz;123456;' column1, NULL column2 FROM dual UNION ALL
SELECT 2 id, 'aaa' column1, NULL column2 FROM dual UNION ALL
SELECT 3 id, 'bbb' column1, NULL column2 FROM dual UNION ALL
SELECT 4 id, 'ccc' column1, NULL column2 FROM dual UNION ALL
SELECT 5 id, 'ddd' column1, NULL column2 FROM dual UNION ALL
SELECT 6 id, 'eee' column1, NULL column2 FROM dual UNION ALL
SELECT 7 id, 'xxx;yyy;zzz;789123;' column1, NULL column2 FROM dual UNION ALL
SELECT 8 id, 'aaa' column1, NULL column2 FROM dual)
select id,
column1,
last_value(CASE WHEN substr(column1, -1) = ';' THEN
regexp_substr(column1, ';*([[:digit:]]*)(;$)', 1, 1, NULL, 1)
END IGNORE NULLS) OVER (ORDER BY ID) column2
from your_table;
ID COLUMN1 COLUMN2
---------- ------------------- -------------------
1 xxx;yyy;zzz;123456; 123456
2 aaa 123456
3 bbb 123456
4 ccc 123456
5 ddd 123456
6 eee 123456
7 xxx;yyy;zzz;789123; 789123
8 aaa 789123
然后,您可以在MERGE語句中使用它進行更新,如下所示:
MERGE INTO your_table tgt
USING (select id,
column1,
CASE WHEN substr(column1, -1) = ';' THEN 'Y' ELSE 'N' END driving_column1,
last_value(CASE WHEN substr(column1, -1) = ';' THEN
regexp_substr(column1, ';*([[:digit:]]*)(;$)', 1, 1, NULL, 1)
END IGNORE NULLS) OVER (ORDER BY ID) column2 -- assuming id drives the correct order to use here
from your_table) src
ON (tgt.id = src.id) -- assuming id is the primary key of your_table
WHEN MATCHED THEN
UPDATE SET tgt.column2 = src.column2;
如果您不想更新其中的值是csv值的column1行的column2(我假設如果它們是csv值,則會出現分號),那么您可以更新ON子句以包括and driving_column1 = 'N'
或者您可以將源子查詢包裝在過濾對Driving_column1的外部查詢中(不幸的是,您不能對同一查詢中的分析函數進行過濾),也可以在where子句中添加where子句合並語句。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.