如何在 Oracle PL/SQL 中按分隔符拆分字符串并将空值处理为 NULL?

问题描述 投票:0回答:1

我在 Oracle PL/SQL 中有一个字符串,如下所示:

280,1,2,3,3 | 120,,0,2,3 | 280,1,2,3,3

每个部分由 | 分隔字符,并且在每个部分中,值以逗号分隔。我面临的挑战是正确提取值以及缺失值或空值

比如我期望的数据是:

  • 国家/地区 ID:280,EIN:1,SSN:2,ITIN:3,ATIN:3
  • 国家/地区 ID:120,EIN:NULL,SSN:0,ITIN:2,ATIN:3
  • 国家/地区 ID:280,EIN:1,SSN:2,ITIN:3,ATIN:3

这是我尝试过的:

DECLARE
    v_entry VARCHAR2(500); 
    v_countries VARCHAR2(500) := '280,1,2,3,3 | 120,,0,2,3 | 280,1,2,3,3';
    v_country_id VARCHAR2(50);
    v_ein VARCHAR2(50);
    v_ssn VARCHAR2(50);
    v_itin VARCHAR2(50);
    v_atin VARCHAR2(50);
BEGIN
    FOR i IN 1 .. REGEXP_COUNT(v_countries, '\|') + 1 LOOP
        v_entry := REGEXP_SUBSTR(v_countries, '[^|]+', 1, i);
    
        v_country_id := REGEXP_SUBSTR(v_entry, '([^,]*)', 1, 1);
        v_ein := REGEXP_SUBSTR(v_entry, '([^,]*)', 1, 2);
        v_ssn := REGEXP_SUBSTR(v_entry, '([^,]*)', 1, 3);
        v_itin := REGEXP_SUBSTR(v_entry, '([^,]*)', 1, 4);
        v_atin := REGEXP_SUBSTR(v_entry, '([^,]*)', 1, 5);

        v_country_id := CASE WHEN v_country_id IS NULL OR v_country_id = '' THEN 'NULL' ELSE v_country_id END;
        v_ein := CASE WHEN v_ein IS NULL OR v_ein = '' THEN 'NULL' ELSE v_ein END;
        v_ssn := CASE WHEN v_ssn IS NULL OR v_ssn = '' THEN 'NULL' ELSE v_ssn END;
        v_itin := CASE WHEN v_itin IS NULL OR v_itin = '' THEN 'NULL' ELSE v_itin END;
        v_atin := CASE WHEN v_atin IS NULL OR v_atin = '' THEN 'NULL' ELSE v_atin END;

        DBMS_OUTPUT.PUT_LINE('Country ID: ' || v_country_id);
        DBMS_OUTPUT.PUT_LINE('EIN: ' || v_ein);
        DBMS_OUTPUT.PUT_LINE('SSN: ' || v_ssn);
        DBMS_OUTPUT.PUT_LINE('ITIN: ' || v_itin);
        DBMS_OUTPUT.PUT_LINE('ATIN: ' || v_atin);
    END LOOP;
END;

问题: 我希望将逗号之间的空字段处理为 NULL,但输出没有正确反映这一点。

例如,对于第二部分120,,0,2,3,我期望:

  • 国家/地区 ID:120
  • EIN:空
  • 社会安全号码:0
  • ITIN:2
  • ATIN:3

但是,我得到了意想不到的行为,要么没有正确分配值,要么没有正确显示 NULL 值。

sql oracle plsql
1个回答
0
投票

您可以使用简单的字符串表达式:

DECLARE
  v_entry      VARCHAR2(500); 
  v_countries  VARCHAR2(500) := '280,1,2,3,3 | 120,,0,2,3 | 280,1,2,3,3';
  v_country_id VARCHAR2(50);
  v_ein        VARCHAR2(50);
  v_ssn        VARCHAR2(50);
  v_itin       VARCHAR2(50);
  v_atin       VARCHAR2(50);
  v_spos       PLS_INTEGER := 1;
  v_epos       PLS_INTEGER;
  v_entry_spos PLS_INTEGER;
  v_entry_epos PLS_INTEGER;
BEGIN
  LOOP
    v_epos  := INSTR(v_countries, '|', v_spos);
    v_entry := CASE v_epos
               WHEN -1
               THEN SUBSTR(v_countries, v_spos)
               ELSE SUBSTR(v_countries, v_spos, v_epos - v_spos)
               END;
    v_entry_spos := 1;
    v_entry_epos := INSTR(v_entry, ',', v_entry_spos);
    v_country_id := SUBSTR(v_entry, v_entry_spos, v_entry_epos - v_entry_spos);
    v_entry_spos := v_entry_epos + 1;
    v_entry_epos := INSTR(v_entry, ',', v_entry_spos);
    v_ein        := SUBSTR(v_entry, v_entry_spos, v_entry_epos - v_entry_spos);
    v_entry_spos := v_entry_epos + 1;
    v_entry_epos := INSTR(v_entry, ',', v_entry_spos);
    v_ssn        := SUBSTR(v_entry, v_entry_spos, v_entry_epos - v_entry_spos);
    v_entry_spos := v_entry_epos + 1;
    v_entry_epos := INSTR(v_entry, ',', v_entry_spos);
    v_itin       := SUBSTR(v_entry, v_entry_spos, v_entry_epos - v_entry_spos);
    v_entry_spos := v_entry_epos + 1;
    v_entry_epos := INSTR(v_entry, ',', v_entry_spos);
    v_atin       := SUBSTR(v_entry, v_entry_spos, v_entry_epos - v_entry_spos);
    
    DBMS_OUTPUT.PUT_LINE('Country ID: ' || COALESCE(v_country_id, 'NULL'));
    DBMS_OUTPUT.PUT_LINE('EIN: ' || COALESCE(v_ein, 'NULL'));
    DBMS_OUTPUT.PUT_LINE('SSN: ' || COALESCE(v_ssn, 'NULL'));
    DBMS_OUTPUT.PUT_LINE('ITIN: ' || COALESCE(v_itin, 'NULL'));
    DBMS_OUTPUT.PUT_LINE('ATIN: ' || COALESCE(v_atin, 'NULL'));
    EXIT WHEN v_epos = 0;
    v_spos := v_epos + 1;
  END LOOP;
END;
/

哪个输出:

Country ID: 280
EIN: 1
SSN: 2
ITIN: 3
ATIN: NULL
Country ID:  120
EIN: NULL
SSN: 0
ITIN: 2
ATIN: NULL
Country ID: NULL
EIN: NULL
SSN: NULL
ITIN: NULL
ATIN: NULL

小提琴

© www.soinside.com 2019 - 2024. All rights reserved.