Memisahkan string menjadi beberapa baris di Oracle

104

Saya tahu ini telah dijawab sampai tingkat tertentu dengan PHP dan MYSQL, tetapi saya bertanya-tanya apakah seseorang dapat mengajari saya pendekatan paling sederhana untuk membagi string (dipisahkan koma) menjadi beberapa baris di Oracle 10g (lebih disukai) dan 11g.

Tabelnya adalah sebagai berikut:

Name | Project | Error 
108    test      Err1, Err2, Err3
109    test2     Err1

Saya ingin membuat yang berikut ini:

Name | Project | Error
108    Test      Err1
108    Test      Err2 
108    Test      Err3 
109    Test2     Err1

Saya telah melihat beberapa solusi potensial di sekitar tumpukan, namun mereka hanya menyumbang satu kolom (menjadi string yang dipisahkan koma). Bantuan apa pun akan sangat dihargai.

marshalllaw
sumber
2
Untuk contoh penggunaan REGEXP, XMLTABLEdan MODELklausa, lihat Memisahkan string yang dipisahkan koma dalam tabel menggunakan Oracle SQL
Lalit Kumar B

Jawaban:

121

Ini mungkin cara yang lebih baik (juga dengan regexp dan terhubung dengan):

with temp as
(
    select 108 Name, 'test' Project, 'Err1, Err2, Err3' Error  from dual
    union all
    select 109, 'test2', 'Err1' from dual
)
select distinct
  t.name, t.project,
  trim(regexp_substr(t.error, '[^,]+', 1, levels.column_value))  as error
from 
  temp t,
  table(cast(multiset(select level from dual connect by  level <= length (regexp_replace(t.error, '[^,]+'))  + 1) as sys.OdciNumberList)) levels
order by name

EDIT : Berikut adalah penjelasan sederhana (seperti, "tidak mendalam") dari kueri.

  1. length (regexp_replace(t.error, '[^,]+')) + 1digunakan regexp_replaceuntuk menghapus apa pun yang bukan pembatas (dalam hal ini koma) dan length +1untuk mendapatkan berapa banyak elemen (kesalahan) yang ada.
  2. The select level from dual connect by level <= (...)menggunakan permintaan hirarkis untuk membuat kolom dengan peningkatan jumlah pertandingan yang ditemukan, dari 1 sampai jumlah total kesalahan.

    Pratinjau:

    select level, length (regexp_replace('Err1, Err2, Err3', '[^,]+'))  + 1 as max 
    from dual connect by level <= length (regexp_replace('Err1, Err2, Err3', '[^,]+'))  + 1
  3. table(cast(multiset(.....) as sys.OdciNumberList)) melakukan beberapa casting jenis oracle.
    • The cast(multiset(.....)) as sys.OdciNumberListtransformasi beberapa koleksi (satu koleksi untuk setiap baris dalam kumpulan data asli) menjadi koleksi tunggal nomor, OdciNumberList.
    • The table()fungsi mengubah koleksi ke resultset.
  4. FROMtanpa gabungan membuat gabungan silang antara dataset Anda dan multiset. Akibatnya, baris dalam kumpulan data dengan 4 kecocokan akan berulang 4 kali (dengan peningkatan angka di kolom bernama "nilai_kolom").

    Pratinjau:

    select * from 
    temp t,
    table(cast(multiset(select level from dual connect by  level <= length (regexp_replace(t.error, '[^,]+'))  + 1) as sys.OdciNumberList)) levels
  5. trim(regexp_substr(t.error, '[^,]+', 1, levels.column_value))menggunakan column_valuesebagai parameter nth_appearance / ocurrence untuk regexp_substr.
  6. Anda dapat menambahkan beberapa kolom lain dari kumpulan data Anda ( t.name, t.projectsebagai contoh) untuk memudahkan visualisasi.

Beberapa referensi ke dokumen Oracle:

Nefreo
sumber
7
Awas! Regex dari format '[^,]+'untuk mengurai string tidak mengembalikan item yang benar jika ada elemen null dalam daftar. Lihat di sini untuk info lebih lanjut: stackoverflow.com/questions/31464275/…
Gary_W
13
karena 11g dapat Anda gunakan regexp_count(t.error, ',')alih-alih length (regexp_replace(t.error, '[^,]+')), yang dapat membawa peningkatan kinerja lain
Štefan Oravec
1
485 detik dengan "normal" CONNECT BY. 0,296 detik seperti ini. Kamu keren! Sekarang yang harus saya lakukan adalah memahami cara kerjanya. :-)
Bob Jarvis - Kembalikan Monica
@BobJarvis menambahkan suntingan untuk menjelaskan apa yang dilakukannya. Koreksi ejaan / tata bahasa dipersilakan.
Nefreo
"Jawaban yang diterima memiliki kinerja yang buruk" - apa jawaban yang diterima dalam topik ini? Silakan gunakan tautan untuk mereferensikan posting lain.
0xdb
28

ekspresi reguler adalah hal yang luar biasa :)

with temp as  (
       select 108 Name, 'test' Project, 'Err1, Err2, Err3' Error  from dual
       union all
       select 109, 'test2', 'Err1' from dual
     )

SELECT distinct Name, Project, trim(regexp_substr(str, '[^,]+', 1, level)) str
  FROM (SELECT Name, Project, Error str FROM temp) t
CONNECT BY instr(str, ',', 1, level - 1) > 0
order by Name
Andrey Khmelev
sumber
1
hai dapatkah Anda menjelaskan mengapa kueri di atas memberikan baris duplikat jika saya tidak menggunakan kata kunci yang berbeda dalam kueri
Jagadeesh G
2
Kueri itu tidak dapat digunakan karena @JagadeeshG, terutama pada tabel yang sangat besar.
Michael-O
3
Sangat lambat, ada jawaban yang lebih baik di bawah
MoreCoffee
Alasan kelambatan adalah karena setiap kombinasi Names terhubung, yang dapat dilihat jika Anda menghapus distinct. Sayangnya menambahkan and Name = prior Nameke connect bypenyebab klausa ORA-01436: CONNECT BY loop in user data.
mik
Anda dapat menghindari ORA-01436kesalahan dengan menambahkan AND name = PRIOR name(atau apa pun kunci utama) dan AND PRIOR SYS_GUID() IS NOT NULL
David Faber
28

Ada perbedaan besar antara keduanya:

  • memisahkan satu string yang dipisahkan
  • memisahkan string yang dipisahkan untuk beberapa baris dalam tabel.

Jika Anda tidak membatasi baris, klausa CONNECT BY akan menghasilkan beberapa baris dan tidak akan memberikan keluaran yang diinginkan.

Selain Ekspresi Reguler , beberapa alternatif lain menggunakan:

  • XMLTable
  • Klausa MODEL

Mempersiapkan

SQL> CREATE TABLE t (
  2    ID          NUMBER GENERATED ALWAYS AS IDENTITY,
  3    text        VARCHAR2(100)
  4  );

Table created.

SQL>
SQL> INSERT INTO t (text) VALUES ('word1, word2, word3');

1 row created.

SQL> INSERT INTO t (text) VALUES ('word4, word5, word6');

1 row created.

SQL> INSERT INTO t (text) VALUES ('word7, word8, word9');

1 row created.

SQL> COMMIT;

Commit complete.

SQL>
SQL> SELECT * FROM t;

        ID TEXT
---------- ----------------------------------------------
         1 word1, word2, word3
         2 word4, word5, word6
         3 word7, word8, word9

SQL>

Menggunakan XMLTABLE :

SQL> SELECT id,
  2         trim(COLUMN_VALUE) text
  3  FROM t,
  4    xmltable(('"'
  5    || REPLACE(text, ',', '","')
  6    || '"'))
  7  /

        ID TEXT
---------- ------------------------
         1 word1
         1 word2
         1 word3
         2 word4
         2 word5
         2 word6
         3 word7
         3 word8
         3 word9

9 rows selected.

SQL>

Menggunakan klausa MODEL :

SQL> WITH
  2  model_param AS
  3     (
  4            SELECT id,
  5                      text AS orig_str ,
  6                   ','
  7                          || text
  8                          || ','                                 AS mod_str ,
  9                   1                                             AS start_pos ,
 10                   Length(text)                                   AS end_pos ,
 11                   (Length(text) - Length(Replace(text, ','))) + 1 AS element_count ,
 12                   0                                             AS element_no ,
 13                   ROWNUM                                        AS rn
 14            FROM   t )
 15     SELECT   id,
 16              trim(Substr(mod_str, start_pos, end_pos-start_pos)) text
 17     FROM     (
 18                     SELECT *
 19                     FROM   model_param MODEL PARTITION BY (id, rn, orig_str, mod_str)
 20                     DIMENSION BY (element_no)
 21                     MEASURES (start_pos, end_pos, element_count)
 22                     RULES ITERATE (2000)
 23                     UNTIL (ITERATION_NUMBER+1 = element_count[0])
 24                     ( start_pos[ITERATION_NUMBER+1] = instr(cv(mod_str), ',', 1, cv(element_no)) + 1,
 25                     end_pos[iteration_number+1] = instr(cv(mod_str), ',', 1, cv(element_no) + 1) )
 26                 )
 27     WHERE    element_no != 0
 28     ORDER BY mod_str ,
 29           element_no
 30  /

        ID TEXT
---------- --------------------------------------------------
         1 word1
         1 word2
         1 word3
         2 word4
         2 word5
         2 word6
         3 word7
         3 word8
         3 word9

9 rows selected.

SQL>
Lalit Kumar B
sumber
1
Bisakah Anda menjelaskan lebih lanjut, mengapa harus ada ('"' || REPLACE(text, ',', '","') || '"')dan tanda kurung tidak bisa dihilangkan? Dokumen Oracle ([ docs.oracle.com/database/121/SQLRF/functions268.htm ) tidak jelas bagi saya. Apakah itu XQuery_string?
Betlista
@ Betlista itu adalah ekspresi XQuery.
Lalit Kumar B
Solusi XMLTABLE untuk beberapa alasan terus-menerus gagal mengeluarkan entri terakhir untuk baris panjang campuran. Misalnya. baris1: 3 kata; baris2: 2 kata, baris3: 1 kata; baris4: 2 kata, baris5: 1 kata - tidak akan menampilkan kata terakhir. Pengurutan baris tidak masalah.
Gnudiff
7

Beberapa contoh lagi yang sama:

SELECT trim(regexp_substr('Err1, Err2, Err3', '[^,]+', 1, LEVEL)) str_2_tab
  FROM dual
CONNECT BY LEVEL <= regexp_count('Err1, Err2, Err3', ',')+1
/

SELECT trim(regexp_substr('Err1, Err2, Err3', '[^,]+', 1, LEVEL)) str_2_tab
  FROM dual
CONNECT BY LEVEL <= length('Err1, Err2, Err3') - length(REPLACE('Err1, Err2, Err3', ',', ''))+1
/

Juga, dapat menggunakan DBMS_UTILITY.comma_to_table & table_to_comma: http://www.oracle-base.com/articles/9i/useful-procedures-and-functions-9i.php#DBMS_UTILITY.comma_to_table

Seni
sumber
Ketahuilah bahwa comma_to_table()hanya berfungsi dengan token yang sesuai dengan konvensi penamaan objek database Oracle. Ini akan terlempar pada string seperti '123,456,789'misalnya.
APC
7

Saya ingin mengusulkan pendekatan yang berbeda menggunakan fungsi tabel PIPELINED. Ini agak mirip dengan teknik XMLTABLE, kecuali Anda menyediakan fungsi kustom Anda sendiri untuk memisahkan string karakter:

-- Create a collection type to hold the results
CREATE OR REPLACE TYPE typ_str2tbl_nst AS TABLE OF VARCHAR2(30);
/

-- Split the string according to the specified delimiter
CREATE OR REPLACE FUNCTION str2tbl (
  p_string    VARCHAR2,
  p_delimiter CHAR DEFAULT ',' 
)
RETURN typ_str2tbl_nst PIPELINED
AS
  l_tmp VARCHAR2(32000) := p_string || p_delimiter;
  l_pos NUMBER;
BEGIN
  LOOP
    l_pos := INSTR( l_tmp, p_delimiter );
    EXIT WHEN NVL( l_pos, 0 ) = 0;
    PIPE ROW ( RTRIM( LTRIM( SUBSTR( l_tmp, 1, l_pos-1) ) ) );
    l_tmp := SUBSTR( l_tmp, l_pos+1 );
  END LOOP;
END str2tbl;
/

-- The problem solution
SELECT name, 
       project, 
       TRIM(COLUMN_VALUE) error
  FROM t, TABLE(str2tbl(error));

Hasil:

      NAME PROJECT    ERROR
---------- ---------- --------------------
       108 test       Err1
       108 test       Err2
       108 test       Err3
       109 test2      Err1

Masalah dengan jenis pendekatan ini adalah sering kali pengoptimal tidak mengetahui kardinalitas fungsi tabel dan harus membuat perkiraan. Ini bisa berpotensi membahayakan rencana eksekusi Anda, jadi solusi ini dapat diperpanjang untuk menyediakan statistik eksekusi untuk pengoptimal.

Anda dapat melihat estimasi pengoptimal ini dengan menjalankan EXPLAIN PLAN pada kueri di atas:

Execution Plan
----------------------------------------------------------
Plan hash value: 2402555806

----------------------------------------------------------------------------------------------
| Id  | Operation                          | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                   |         | 16336 |   366K|    59   (0)| 00:00:01 |
|   1 |  NESTED LOOPS                      |         | 16336 |   366K|    59   (0)| 00:00:01 |
|   2 |   TABLE ACCESS FULL                | T       |     2 |    42 |     3   (0)| 00:00:01 |
|   3 |   COLLECTION ITERATOR PICKLER FETCH| STR2TBL |  8168 | 16336 |    28   (0)| 00:00:01 |
----------------------------------------------------------------------------------------------

Meskipun koleksi hanya memiliki 3 nilai, pengoptimal memperkirakan 8168 baris untuknya (nilai default). Ini mungkin tampak tidak relevan pada awalnya, tetapi mungkin cukup bagi pengoptimal untuk memutuskan rencana yang kurang optimal.

Solusinya adalah dengan menggunakan ekstensi pengoptimal untuk memberikan statistik pengumpulan:

-- Create the optimizer interface to the str2tbl function
CREATE OR REPLACE TYPE typ_str2tbl_stats AS OBJECT (
  dummy NUMBER,

  STATIC FUNCTION ODCIGetInterfaces ( p_interfaces OUT SYS.ODCIObjectList )
  RETURN NUMBER,

  STATIC FUNCTION ODCIStatsTableFunction ( p_function  IN  SYS.ODCIFuncInfo,
                                           p_stats     OUT SYS.ODCITabFuncStats,
                                           p_args      IN  SYS.ODCIArgDescList,
                                           p_string    IN  VARCHAR2,
                                           p_delimiter IN  CHAR DEFAULT ',' )
  RETURN NUMBER
);
/

-- Optimizer interface implementation
CREATE OR REPLACE TYPE BODY typ_str2tbl_stats
AS
  STATIC FUNCTION ODCIGetInterfaces ( p_interfaces OUT SYS.ODCIObjectList )
  RETURN NUMBER
  AS
  BEGIN
    p_interfaces := SYS.ODCIObjectList ( SYS.ODCIObject ('SYS', 'ODCISTATS2') );
    RETURN ODCIConst.SUCCESS;
  END ODCIGetInterfaces;

  -- This function is responsible for returning the cardinality estimate
  STATIC FUNCTION ODCIStatsTableFunction ( p_function  IN  SYS.ODCIFuncInfo,
                                           p_stats     OUT SYS.ODCITabFuncStats,
                                           p_args      IN  SYS.ODCIArgDescList,
                                           p_string    IN  VARCHAR2,
                                           p_delimiter IN  CHAR DEFAULT ',' )
  RETURN NUMBER
  AS
  BEGIN
    -- I'm using basically half the string lenght as an estimator for its cardinality
    p_stats := SYS.ODCITabFuncStats( CEIL( LENGTH( p_string ) / 2 ) );
    RETURN ODCIConst.SUCCESS;
  END ODCIStatsTableFunction;

END;
/

-- Associate our optimizer extension with the PIPELINED function   
ASSOCIATE STATISTICS WITH FUNCTIONS str2tbl USING typ_str2tbl_stats;

Menguji rencana eksekusi yang dihasilkan:

Execution Plan
----------------------------------------------------------
Plan hash value: 2402555806

----------------------------------------------------------------------------------------------
| Id  | Operation                          | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                   |         |     1 |    23 |    59   (0)| 00:00:01 |
|   1 |  NESTED LOOPS                      |         |     1 |    23 |    59   (0)| 00:00:01 |
|   2 |   TABLE ACCESS FULL                | T       |     2 |    42 |     3   (0)| 00:00:01 |
|   3 |   COLLECTION ITERATOR PICKLER FETCH| STR2TBL |     1 |     2 |    28   (0)| 00:00:01 |
----------------------------------------------------------------------------------------------

Seperti yang Anda lihat, kardinalitas pada denah di atas bukanlah nilai tebakan 8196 lagi. Itu masih tidak benar karena kita mengirimkan kolom alih-alih string literal ke fungsi.

Beberapa penyesuaian pada kode fungsi akan diperlukan untuk memberikan perkiraan yang lebih dekat dalam kasus khusus ini, tetapi saya pikir konsep keseluruhan cukup banyak dijelaskan di sini.

Fungsi str2tbl yang digunakan dalam jawaban ini pada awalnya dikembangkan oleh Tom Kyte: https://asktom.oracle.com/pls/asktom/f?p=100:11 WindowsFAQ.ru::::P11_QUESTION_ID:110612348061

Konsep mengaitkan statistik dengan jenis objek dapat dieksplorasi lebih lanjut dengan membaca artikel ini: http://www.oracle-developer.net/display.php?id=427

Teknik yang dijelaskan di sini bekerja dalam 10g +.

Daniela Petruzalek
sumber
4

REGEXP_COUNT tidak ditambahkan hingga Oracle 11i. Berikut adalah solusi Oracle 10g, yang diadopsi dari solusi Art.

SELECT trim(regexp_substr('Err1, Err2, Err3', '[^,]+', 1, LEVEL)) str_2_tab
  FROM dual
CONNECT BY LEVEL <=
  LENGTH('Err1, Err2, Err3')
    - LENGTH(REPLACE('Err1, Err2, Err3', ',', ''))
    + 1;
durette
sumber
Bagaimana saya bisa menambahkan filter untuk ini katakanlah saya ingin memfilter hanya dengan name = '108'. Saya mencoba menambahkan tempat setelah klausa from tetapi berakhir dengan duplikat.
DRTauli
4

Mulai dari Oracle 12c, Anda dapat menggunakan JSON_TABLEdan JSON_ARRAY:

CREATE TABLE tab(Name, Project, Error) AS
SELECT 108,'test' ,'Err1, Err2, Err3' FROM dual UNION 
SELECT 109,'test2','Err1'             FROM dual;

Dan kueri:

SELECT *
FROM tab t
OUTER APPLY (SELECT TRIM(p) AS p
            FROM JSON_TABLE(REPLACE(JSON_ARRAY(t.Error), ',', '","'),
           '$[*]' COLUMNS (p VARCHAR2(4000) PATH '$'))) s;

Keluaran:

┌──────┬─────────┬──────────────────┬──────┐
 Name  Project       Error         P   
├──────┼─────────┼──────────────────┼──────┤
  108  test     Err1, Err2, Err3  Err1 
  108  test     Err1, Err2, Err3  Err2 
  108  test     Err1, Err2, Err3  Err3 
  109  test2    Err1              Err1 
└──────┴─────────┴──────────────────┴──────┘

db <> demo biola

Lukasz Szozda
sumber
1
Saya akui ini adalah trik yang cerdas tapi terus terang itu akan membingungkan saya jika saya menemukannya di basis kode.
APC
@APC Ini hanya menunjukkan apa yang mungkin dilakukan dengan SQL. Jika saya harus menggunakan kode seperti itu dalam basis kode saya, saya pasti akan membungkusnya dengan sebuah fungsi atau meninggalkan komentar tambahan :)
Lukasz Szozda
Tentu saja. Hanya saja utas ini adalah salah satu hit yang lebih populer untuk tokenisasi string dengan Oracle jadi saya pikir kita harus menyertakan peringatan pada solusi yang lebih eksotis, untuk melindungi yang tidak bersalah dari diri mereka sendiri :)
APC
3

Berikut adalah implementasi alternatif menggunakan XMLTABLE yang memungkinkan transmisi ke tipe data berbeda:

select 
  xmltab.txt
from xmltable(
  'for $text in tokenize("a,b,c", ",") return $text'
  columns 
    txt varchar2(4000) path '.'
) xmltab
;

... atau jika string yang dipisahkan disimpan dalam satu atau beberapa baris tabel:

select 
  xmltab.txt
from (
  select 'a;b;c' inpt from dual union all
  select 'd;e;f' from dual
) base
inner join xmltable(
  'for $text in tokenize($input, ";") return $text'
  passing base.inpt as "input"
  columns 
    txt varchar2(4000) path '.'
) xmltab
  on 1=1
;
peredam suara
sumber
Saya pikir solusi ini berfungsi untuk Oracle 11.2.0.3 dan versi yang lebih baru.
APC
2

Saya ingin menambahkan metode lain. Yang ini menggunakan querys rekursif, sesuatu yang belum pernah saya lihat di jawaban lain. Ini didukung oleh Oracle sejak 11gR2.

with cte0 as (
    select phone_number x
    from hr.employees
), cte1(xstr,xrest,xremoved) as (
        select x, x, null
        from cte0
    union all        
        select xstr,
            case when instr(xrest,'.') = 0 then null else substr(xrest,instr(xrest,'.')+1) end,
            case when instr(xrest,'.') = 0 then xrest else substr(xrest,1,instr(xrest,'.') - 1) end
        from cte1
        where xrest is not null
)
select xstr, xremoved from cte1  
where xremoved is not null
order by xstr

Cukup fleksibel dengan karakter yang membelah. Cukup ubah dalam INSTRpanggilan.

Thomas Tschernich
sumber
2

Tanpa menggunakan connect by atau regexp :

    with mytable as (
      select 108 name, 'test' project, 'Err1,Err2,Err3' error from dual
      union all
      select 109, 'test2', 'Err1' from dual
    )
    ,x as (
      select name
      ,project
      ,','||error||',' error
      from mytable
    )
    ,iter as (SELECT rownum AS pos
        FROM all_objects
    )
    select x.name,x.project
    ,SUBSTR(x.error
      ,INSTR(x.error, ',', 1, iter.pos) + 1
      ,INSTR(x.error, ',', 1, iter.pos + 1)-INSTR(x.error, ',', 1, iter.pos)-1
    ) error
    from x, iter
    where iter.pos < = (LENGTH(x.error) - LENGTH(REPLACE(x.error, ','))) - 1;
Ilya Kharlamov
sumber
1

Saya memiliki masalah yang sama, dan xmltable membantu saya:

PILIH id, potong (COLUMN_VALUE) teks DARI t, xmltable (('"' || REPLACE (teks, ',', '", "') || '"'))

Volkov Maxim
sumber
0

Di Oracle 11g dan yang lebih baru, Anda dapat menggunakan sub-kueri rekursif dan fungsi string sederhana (yang mungkin lebih cepat daripada ekspresi reguler dan sub-kueri hierarki terkait):

Pengaturan Oracle :

CREATE TABLE table_name ( name, project, error ) as
 select 108, 'test',  'Err1, Err2, Err3' from dual union all
 select 109, 'test2', 'Err1'             from dual;

Pertanyaan :

WITH table_name_error_bounds ( name, project, error, start_pos, end_pos ) AS (
  SELECT name,
         project,
         error,
         1,
         INSTR( error, ', ', 1 )
  FROM   table_name
UNION ALL
  SELECT name,
         project,
         error,
         end_pos + 2,
         INSTR( error, ', ', end_pos + 2 )
  FROM   table_name_error_bounds
  WHERE  end_pos > 0
)
SELECT name,
       project,
       CASE end_pos
       WHEN 0
       THEN SUBSTR( error, start_pos )
       ELSE SUBSTR( error, start_pos, end_pos - start_pos )
       END AS error
FROM   table_name_error_bounds

Keluaran :

NAMA | PROYEK | KESALAHAN
---: | : ------ | : ----
 108 | tes | Err1
 109 | test2 | Err1
 108 | tes | Err2
 108 | tes | Err3

db <> biola di sini

MT0
sumber
-1

Saya telah menggunakan fungsi DBMS_UTILITY.comma_to _table sebenarnya yang bekerja dengan kode sebagai berikut

declare
l_tablen  BINARY_INTEGER;
l_tab     DBMS_UTILITY.uncl_array;
cursor cur is select * from qwer;
rec cur%rowtype;
begin
open cur;
loop
fetch cur into rec;
exit when cur%notfound;
DBMS_UTILITY.comma_to_table (
     list   => rec.val,
     tablen => l_tablen,
     tab    => l_tab);
FOR i IN 1 .. l_tablen LOOP
    DBMS_OUTPUT.put_line(i || ' : ' || l_tab(i));
END LOOP;
end loop;
close cur;
end; 

saya telah menggunakan nama tabel dan kolom saya sendiri

Smart003
sumber
5
Ketahuilah bahwa comma_to_table()hanya berfungsi dengan token yang sesuai dengan konvensi penamaan objek database Oracle. Ini akan terlempar pada string seperti '123,456,789'misalnya.
APC
dapatkah kita menerapkan menggunakan tabel sementara?
Smart003
1
Umm, mengingat semua solusi lain yang bisa diterapkan mengapa kita ingin menggunakan tabel sementara yang datang dengan overhead besar dalam mewujudkan data?
APC