2017-01-17 2 views
0

Oracle 12 데이터베이스가 있습니다.pl/sql에서 테이블을 순환하고 값을 업데이트하는 방법

테이블을 순환하여 이전 행을 기반으로 값을 업데이트해야합니다. 아래처럼 행 1에서 값을 가져와 행 2에서 6으로 업데이트해야합니다. 그런 다음 행 7에서 새 값을 가져 와서 테이블 끝까지 계속합니다.

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 내가 돈 '다음, 컬럼은 ... 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 

입니다 pl/sql에 많은 경험이 있습니다. 루프를 사용하는 동안 pl/sql을 사용하려고했지만 작동하지 않았습니다.

누군가가 올바른 방향으로 나를 걷어차 주면 감사 할 것입니다.

+0

몇 가지 빠른 쿼리. 행은 항상 6 개 그룹으로되어 있으며, 또는 가변적 일 수 있으며 첫 번째 행은 항상 같은 길이입니까? – MightyRearranger

+0

행이 24 행에서부터 더 다양 할 수는 없습니다. 첫 번째 줄은 항상 길이가 같고 처음 세 줄은 동일합니다. – snow

답변

1

당신은 이것에 대한 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 
0

이와 비슷한 내용은 원하는대로 수행해야합니다. 그것은 '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; 
0

이 경우 PL/SQL이 필요하지 않지만 단일 MERGE 문에서 수행 할 수 있습니다.

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 

그런 다음에 그것을 사용할 수 있습니다 : 당신이 그렇게처럼 'LAST_VALUE() 분석 함수를 사용하여이 작업을 수행 할 수 있습니다 -

첫째로, 당신은 뒤에있는 결과를 얻는 방법 운동 소위 같이 업데이트를 할 MERGE 문 : 당신이 값이 CSV 값이있는 컬럼 1 행의 2 열을 업데이트하지 않는 경우

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; 

는 (I 현재 세미콜론이있을 것으로 가정 한 값이 csv 값인 경우) and driving_column1 = 'N'을 포함하도록 ON 절을 업데이트하거나 driving_column1을 필터링하는 외부 쿼리에 원본 하위 쿼리를 래핑 할 수 있습니다 (불행히도 같은 쿼리 내에서 분석 함수를 필터링 할 수 없음). 또는 merge 문의 업데이트 섹션에 where 절을 추가 할 수 있습니다.

+0

약간의 조정만으로이 코드를 사용할 수있었습니다. 마지막 병합 부분에 'src'및 'set'명령이 없지만 모든 항목을 추가 한 후에 정상적으로 작동했습니다. – snow

+0

@snow 네, 사과드립니다. 나는 포스트 버튼을 치는 데 너무 지나치게 흥분했을 것입니다. 그리고 내가 쓴 것을 자세히 확인하지 않았습니다. D' oh! – Boneist

관련 문제