Oracle
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Oracle

XUẤT NHƯ THỐNG KÊ CHÈN:Nhưng trong SQL Plus, dòng ghi đè lên 2500 ký tự!

Wow, những ràng buộc đó khá hạn chế nhưng tôi nghĩ có thể có một cách để giải quyết nó. Tôi nghĩ rằng bạn có thể phải viết một kịch bản nhỏ của riêng mình cho việc này.

Bản thân tôi sẽ sử dụng Java với JDBC (nhưng bất kỳ ngôn ngữ nào có thể kết nối và đọc cơ sở dữ liệu cũng như kết xuất chuỗi sẽ làm được), viết một chương trình nhỏ truy xuất tập hợp bản ghi của mọi hàng trong cơ sở dữ liệu. Sau đó, đối với mỗi hàng trong số các hàng đó:

  • Xây dựng một câu lệnh chèn với đầy đủ dữ liệu. Nếu con số này nhỏ hơn 2.000 byte, thì chỉ cần xuất nó ra tệp và chuyển sang hàng tiếp theo.

  • Nếu không, hãy tạo một câu lệnh chèn cho mọi trường, nhưng để lại c13 trường dưới dạng '' (trống).

  • Sau đó, miễn là c13input của bạn chuỗi lớn hơn 2000 ký tự, xuất ra một câu lệnh cập nhật có dạng "update tbl set c13 = c13 || '" + c13input.substring (0,2000) + "' where ..." (nối 2000 ký tự tiếp theo) rồi thực hiện c13input = c13input.substring(2000) để loại bỏ các ký tự đó khỏi chuỗi của bạn.

  • Một lần c13input có độ dài nhỏ hơn hoặc bằng 2000 ký tự, chỉ cần xuất một bản cập nhật cuối cùng để cập nhật nó vào cuối.

Điều này cho phép bạn giữ các câu lệnh SQL riêng lẻ của mình xung quanh dấu 2000 ký tự và thực thi SQL chính xác một cách hiệu quả để tạo lại bảng cơ sở dữ liệu khác.

Đây là kiểu mà tôi đang nói đến (đối với một bảng chỉ chứa khóa chính c1 và một honkin 'varchar c13 lớn ):

rowset r = db.exec ("select * from oldtable");
while r.next != NO_MORE_ROWS:
    string s = "insert into newtable (c1,c13) values ('" +
        r.get("c1") + "','" + r.get("c13") + "')"
    if s.len() < 2000:
        print s
    else:
        s = "insert into newtable (c1,c13) values ('" + r.get("c1") + "','')"
        print s
        f = r.get("c13")
        while f.len() > 2000:
            s = "update newtable set c13 = c13 || '" + f.substring(0,2000) + ')"
            f = f.substring(2000)
            print s
        endwhile
        s = "update newtable set c13 = c13 || '" + f + ')"
        print s
    endif
endwhile

Rõ ràng, bạn có thể cần phải biến đổi các chuỗi để cho phép chèn các ký tự đặc biệt - Tôi không chắc Oracle mong đợi những ký tự này ở định dạng nào, nhưng hy vọng sẽ là một vấn đề đơn giản khi chuyển các chuỗi (r.get("c13") nếu độ dài của toàn bộ chèn nhỏ hơn 2000, f.substring(0,2000)f nếu bạn cũng đang xây dựng các bản cập nhật) cho một chức năng trợ giúp để thực hiện việc này.

Nếu sự biến đổi đó có khả năng làm tăng kích thước của dòng được in, bạn có thể muốn giảm ngưỡng trở lại 1000 để an toàn, để đảm bảo chuỗi được biến đổi không dẫn đến một dòng lớn hơn giới hạn PL / SQL.

Xin lỗi nếu điều đó có vẻ phức tạp nhưng những hạn chế mà bạn đã nêu sẽ làm chúng tôi khó chịu một chút. Có thể có một cách tốt hơn nhưng tôi không thể nghĩ ra một cách đáp ứng tất cả tiêu chí của bạn.

Cập nhật: Có vẻ như bạn thậm chí còn hơn thế nữa hamstrung hơn suy nghĩ ban đầu:nếu bạn phải giới hạn bản thân với SQL để tạo kịch bản cũng như chạy nó, có một cách, mặc dù nó là cực hình.

Bạn có thể sử dụng SQL để tạo SQL. Sử dụng bảng đã đề cập ở trên của tôi với c1c13 , bạn có thể làm:

select
    'insert into newtable (c1,c13) values ("' ||
    c1 ||
    '","");'
from oldtable;
# Xlates to: insert into newtable (c1,c13) values ("[c1]","");

Điều đó sẽ cung cấp cho bạn tất cả đường cơ sở của bạn insert các câu lệnh để sao chép mọi thứ ngoại trừ c13 cột.

Những gì bạn cần làm sau đó là tạo thêm các câu lệnh để thiết lập c13 . Để cập nhật c13 cho tất cả các giá trị có độ dài từ 1000 trở xuống (tập hợp đơn giản):

select
    'update newtable set c13 = "' ||
    c13 ||
    '" where c1 = "' ||
    c1 ||
    '";'
from oldtable where length(c13) <= 1000;
# Xlates to: update newtable set c13 = "[c13]" where c1 = "[c1]";
#   but only for rows where length([c13]) <= 1000

Sau đó, để update c13 cho tất cả các giá trị từ 1001 đến 2000 ký tự (đặt rồi thêm vào):

select
    'update newtable set c13 = "' ||
    substring(c13,1,1000) ||
    '" where c1 = "' ||
    c1 ||
    '";'
from oldtable where length(c13) > 1000 and length(c13) <= 2000;
select
    'update newtable set c13 = c13 || "' ||
    substring(c13,1001,1000) ||
    '" where c1 = "' ||
    c1 ||
    '";'
from oldtable where length(c13) > 1000 and length(c13) <= 2000;
# Xlates to: update newtable set c13 =        "[c13a]" where c1 = "[c1]";
#            update newtable set c13 = c13 || "[c13b]" where c1 = "[c1]";
#   but only for rows where length([c13]) > 1000 and <= 2000
#   and [c13a]/[c13b] are the first/second thousand chars of c13.

Và tiếp tục như vậy đối với những cái có độ dài từ 2001 đến 3000 và 3001 đến 4000.

Có thể sẽ cần phải thực hiện một số điều chỉnh. Tôi rất vui được cung cấp cho bạn một cách giải quyết nó nhưng mong muốn của tôi để làm việc với sự kỳ lạ như vậy cho đến khi hoàn thành là tối thiểu :-)

Nó sẽ hoàn thành công việc chứ? Đúng. Nó có đẹp không? Tôi muốn nói rằng đó là một tiếng "KHÔNG!" nhưng, với những ràng buộc của bạn, đó có thể là điều tốt nhất bạn có thể hy vọng.

Như một bằng chứng về khái niệm, đây là một tập lệnh SQL trong DB2 (mặc dù không có tính năng đặc biệt nào, nó sẽ hoạt động tốt trong bất kỳ DBMS nào có lengthsubstr tương đương):

# Create table and populate.

DROP TABLE XYZ;
COMMIT;
CREATE TABLE XYZ (F1 VARCHAR(1),F2 VARCHAR(20));
COMMIT;
INSERT INTO XYZ VALUES ('1','PAX');
INSERT INTO XYZ VALUES ('2','GEORGE');
INSERT INTO XYZ VALUES ('3','VLADIMIR');
INSERT INTO XYZ VALUES ('4','ALEXANDRETTA');
SELECT * FROM XYZ ORDER BY F1;

# Create initial insert statem,ents.

SELECT 'INSERT INTO XYZ (F1,F2) VALUES (' || F1 ','''');' 
    FROM XYZ;

# Updates for 1-5 character F2 fields.

SELECT 'UPDATE XYZ SET F2 = ''' || F2 ||
    ''' WHERE F1 = ''' || F1 || ''';'
    FROM XYZ WHERE LENGTH(F2) <= 5;

# Updates for 6-10 character F2 fields.

SELECT 'UPDATE XYZ SET F2 = ''' || SUBSTR(F2,1,5) ||
    ''' WHERE F1 = ''' || F1 || ''';'
    FROM XYZ WHERE LENGTH(F2) > 5 AND LENGTH(F2) <= 10;

SELECT 'UPDATE XYZ SET F2 = F2 || ''' || SUBSTR(F2,6) ||
    ''' WHERE F1 = ''' || F1 || ''';'
    FROM XYZ WHERE LENGTH(F2) > 5 AND LENGTH(F2) <= 10;

# Updates for 11-15 character F2 fields.

SELECT 'UPDATE XYZ SET F2 = ''' || SUBSTR(F2,1,5) ||
    ''' WHERE F1 = ''' || F1 || ''';'
    FROM XYZ WHERE LENGTH(F2) > 10 AND LENGTH(F2) <= 15;

SELECT 'UPDATE XYZ SET F2 = F2 || ''' || SUBSTR(F2,6,5) ||
    ''' WHERE F1 = ''' || F1 || ''';'
  FROM XYZ WHERE LENGTH(F2) > 10 AND LENGTH(F2) <= 15;

SELECT 'UPDATE XYZ SET F2 = F2 || ''' || SUBSTR(F2,11) || 
    ''' WHERE F1 = ''' || F1 || ''';'
    FROM XYZ WHERE LENGTH(F2) > 10 AND LENGTH(F2) <= 15;

và điều này tạo ra các dòng sau:

> DROP TABLE XYZ;
> COMMIT;
> CREATE TABLE XYZ (F1 VARCHAR(1),F2 VARCHAR(20));
> COMMIT;
> INSERT INTO XYZ VALUES ('1','PAX');
> INSERT INTO XYZ VALUES ('2','GEORGE');
> INSERT INTO XYZ VALUES ('3','VLADIMIR');
> INSERT INTO XYZ VALUES ('4','ALEXANDRETTA');
> SELECT * FROM XYZ;
    F1  F2
    --  ------------
    1   PAX
    2   GEORGE
    3   VLADIMIR
    4   ALEXANDRETTA

> SELECT 'INSERT INTO XYZ (F1,F2) VALUES (' || F1 || ','''');'
> FROM XYZ;
    INSERT INTO XYZ (F1,F2) VALUES (1,'');
    INSERT INTO XYZ (F1,F2) VALUES (2,'');
    INSERT INTO XYZ (F1,F2) VALUES (3,'');
    INSERT INTO XYZ (F1,F2) VALUES (4,'');

> SELECT 'UPDATE XYZ SET F2 = ''' || F2 ||
> ''' WHERE F1 = ''' || F1 || ''';'
> FROM XYZ WHERE LENGTH(F2) <= 5;
    UPDATE XYZ SET F2 = 'PAX' WHERE F1 = '1';

> SELECT 'UPDATE XYZ SET F2 = ''' || SUBSTR(F2,1,5) ||
> ''' WHERE F1 = ''' || F1 || ''';'
> FROM XYZ WHERE LENGTH(F2) > 5 AND LENGTH(F2) <= 10;
    UPDATE XYZ SET F2 = 'GEORG' WHERE F1 = '2';
    UPDATE XYZ SET F2 = 'VLADI' WHERE F1 = '3';

> SELECT 'UPDATE XYZ SET F2 = F2 || ''' || SUBSTR(F2,6) ||
> ''' WHERE F1 = ''' || F1 || ''';'
> FROM XYZ WHERE LENGTH(F2) > 5 AND LENGTH(F2) <= 10;
    UPDATE XYZ SET F2 = F2 || 'E' WHERE F1 = '2';
    UPDATE XYZ SET F2 = F2 || 'MIR' WHERE F1 = '3';

> SELECT 'UPDATE XYZ SET F2 = ''' || SUBSTR(F2,1,5) ||
> ''' WHERE F1 = ''' || F1 || ''';'
> FROM XYZ WHERE LENGTH(F2) > 10 AND LENGTH(F2) <= 15;
    UPDATE XYZ SET F2 = 'ALEXA' WHERE F1 = '4';

> SELECT 'UPDATE XYZ SET F2 = F2 || ''' || SUBSTR(F2,6,5) ||
> ''' WHERE F1 = ''' || F1 || ''';'
> FROM XYZ WHERE LENGTH(F2) > 10 AND LENGTH(F2) <= 15;
    UPDATE XYZ SET F2 = F2 || 'NDRET' WHERE F1 = '4';

> SELECT 'UPDATE XYZ SET F2 = F2 || ''' || SUBSTR(F2,11) ||
> ''' WHERE F1 = ''' || F1 || ''';'
> FROM XYZ WHERE LENGTH(F2) > 10 AND LENGTH(F2) <= 15;
    UPDATE XYZ SET F2 = F2 || 'TA' WHERE F1 = '4';

Chia nhỏ các dòng đầu ra, chúng tôi nhận được:

INSERT INTO XYZ (F1,F2) VALUES (1,'');
INSERT INTO XYZ (F1,F2) VALUES (2,'');
INSERT INTO XYZ (F1,F2) VALUES (3,'');
INSERT INTO XYZ (F1,F2) VALUES (4,'');
UPDATE XYZ SET F2 = 'PAX' WHERE F1 = '1';
UPDATE XYZ SET F2 = 'GEORG' WHERE F1 = '2';
UPDATE XYZ SET F2 = 'VLADI' WHERE F1 = '3';
UPDATE XYZ SET F2 = F2 || 'E' WHERE F1 = '2';
UPDATE XYZ SET F2 = F2 || 'MIR' WHERE F1 = '3';
UPDATE XYZ SET F2 = 'ALEXA' WHERE F1 = '4';
UPDATE XYZ SET F2 = F2 || 'NDRET' WHERE F1 = '4';
UPDATE XYZ SET F2 = F2 || 'TA' WHERE F1 = '4';

sẽ cung cấp cho bạn các hàng ban đầu, mặc dù theo đường vòng.

Và đó là nỗ lực tối đa mà tôi có thể đặt ra cho bất kỳ câu hỏi nào mà không phải lo lắng về bộ não của mình, vì vậy tôi sẽ trả giá cho bạn trừ khi có bất kỳ lỗi nghiêm trọng nào được chỉ ra cho tôi.

Chúc bạn may mắn với dự án và những lời chúc tốt đẹp nhất.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. sự cố khi sử dụng các tham số Oracle trong SELECT IN

  2. không thể nhận tham số từ thủ tục oracle được thực thi bởi mybatis

  3. Các hàm chuỗi của Oracle (Danh sách đầy đủ)

  4. Có Oracle tương đương với OUTPUT INSERTED của SQL Server. * Không?

  5. Tìm hiểu ký hiệu tiền tệ mà phiên của bạn sử dụng trong Oracle