Đây là một giải pháp sử dụng truy vấn con có tính toán đệ quy (Oracle 11.2 trở lên):
with inputs ( str ) as (
select to_clob('ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0')
from dual
),
prep ( s, n, token, st_pos, end_pos ) as (
select ',' || str || ',', -1, null, null, 1
from inputs
union all
select s, n+1, substr(s, st_pos, end_pos - st_pos),
end_pos + 1, instr(s, ',', 1, n+3)
from prep
where end_pos != 0
)
select n as idx, token as column_name
from prep
where n > 0;
IDX COLUMN_NAME
------ ----------------------------
1 ABCDEF:PmId12345RmLn1VlId0
2 ABCDEF:PmId12345RmLn1VlId0
3 ABCDEF:PmId12345RmLn1VlId0
4 ABCDEF:PmId12345RmLn1VlId0
5 ABCDEF:PmId12345RmLn1VlId0
Ghi chú :
Bạn đã nói CLOB nhưng trong ví dụ của bạn, bạn đã trích xuất từ một chuỗi varchar2. Tôi đã thêm to_clob()
để xem liệu điều này có hoạt động trên CLOB hay không.
Tôi đã sử dụng instr
và substr
, vì chúng thường (thường là?) hoạt động từ tốt hơn đến tốt hơn nhiều so với regexp
của chúng tương đương.
Tôi đã lưu "chỉ mục" của mỗi chuỗi con trong chuỗi đầu vào; trong một số trường hợp, thứ tự của các mã thông báo trong chuỗi đầu vào là quan trọng. (Tuy nhiên, không phải trong ví dụ của bạn, bạn chỉ có cùng một mã thông báo lặp lại năm lần.)
Nếu bạn cần hiệu suất tốt hơn, đặc biệt nếu CLOB của bạn rất lớn, bạn có thể tốt hơn nên sử dụng dbms_lob.substr
và dbms_lob.instr
- xem Hiệu suất của SUBSTR trên CLOB
, đặc biệt là câu trả lời của Alex Poole và tài liệu tại đây: http ://docs.oracle.com/cd/B28359_01/appdev.111/b28419/d_lob.htm#BABEAJAD
. Lưu ý sự khác biệt về cú pháp so với substr
thông thường / instr
.