Nếu bạn chưa bao giờ có các đường ống trong các trường kèm theo, bạn có thể thực hiện việc đó từ tệp điều khiển. Nếu bạn có thể có cả dấu ngoặc kép và dấu ngoặc kép trong một trường thì tôi nghĩ bạn không có lựa chọn nào khác ngoài việc xử lý trước các tệp.
Giải pháp của bạn [1], để thay thế dấu ngoặc kép với toán tử SQL , đang xảy ra quá muộn để có ích; các dấu phân cách và vùng bao đã được SQL * Loader thông dịch trước khi nó thực hiện bước SQL. Giải pháp [2] của bạn, để bỏ qua bao vây, sẽ hoạt động kết hợp với [1] - cho đến khi một trong các trường chứa ký tự ống dẫn. Và giải pháp [3] có cùng vấn đề khi sử dụng [1] và / hoặc [2] trên toàn cầu.
Tài liệu về chỉ định dấu phân cách đề cập rằng:
Nói cách khác, nếu bạn lặp lại dấu ngoặc kép bên trong các trường sau đó chúng sẽ được thoát và sẽ xuất hiện trong dữ liệu bảng. Vì bạn không thể kiểm soát việc tạo dữ liệu, bạn có thể xử lý trước các tệp bạn nhận được để thay thế tất cả các dấu ngoặc kép bằng dấu ngoặc kép thoát. Ngoại trừ bạn không muốn thay thế tất cả trong số chúng - những cái thực sự là hộp thật không nên được thoát ra ngoài.
Bạn có thể sử dụng một biểu thức chính quy để nhắm mục tiêu các ký tự có liên quan sẽ bỏ qua những ký tự khác. Không phải lĩnh vực mạnh của tôi, nhưng tôi nghĩ bạn có thể làm điều này với xác nhận lookahead và lookbehind .
Nếu bạn có một tệp có tên là orig.txt
chứa:
"1"|A|"B"|"C|D"
"2"|A|"B"|"C"D"
3|A|""B""|"C|D"
4|A|"B"|"C"D|E"F"G|H""
bạn có thể làm:
perl -pe 's/(?<!^)(?<!\|)"(?!\|)(?!$)/""/g' orig.txt > new.txt
Điều đó tìm kiếm một dấu ngoặc kép không đứng trước ký tự neo bắt đầu dòng hoặc ký tự ống dẫn; và không được theo sau bởi một ký tự ống hoặc ký tự neo cuối dòng; và chỉ thay thế những từ có dấu ngoặc kép thoát (nhân đôi). Điều này sẽ làm cho new.txt
chứa:
"1"|A|"B"|"C|D"
"2"|A|"B"|"C""D"
3|A|"""B"""|"C|D"
4|A|"B"|"C""D|E""F""G|H"""
Dấu ngoặc kép ở đầu và cuối trường không được sửa đổi, nhưng những dấu ở giữa bây giờ được thoát ra. Nếu sau đó bạn đã tải tệp đó bằng tệp điều khiển có hộp dấu ngoặc kép:
load data
truncate
into table t42
fields terminated by '|' optionally enclosed by '"'
(
col1,
col2,
col3,
col4
)
Sau đó, bạn sẽ kết thúc với:
select * from t42 order by col1;
COL1 COL2 COL3 COL4
---------- ---------- ---------- --------------------
1 A B C|D
2 A B C"D
3 A "B" C|D
3 A B C"D|E"F"G|H"
hy vọng phù hợp với dữ liệu ban đầu của bạn. Có thể có những trường hợp cạnh không hoạt động (chẳng hạn như dấu ngoặc kép theo sau là dấu ngoặc kép trong một trường) nhưng có một giới hạn đối với những gì bạn có thể làm để cố gắng diễn giải dữ liệu của người khác ... Tất nhiên, cũng có thể có (nhiều) mẫu biểu thức chính quy tốt hơn.
Bạn cũng có thể cân nhắc sử dụng bảng bên ngoài thay vì SQL * Loader, nếu tệp dữ liệu nằm (hoặc có thể) trong thư mục Oracle và bạn có quyền phù hợp. Bạn vẫn phải sửa đổi tệp, nhưng bạn có thể thực hiện tự động với preprocessor
chỉ thị, thay vì cần thực hiện điều đó một cách rõ ràng trước khi gọi SQL * Loader.