sql >> データベース >  >> RDS >> Oracle

EXPORT AS INSERT STATEMENTS:しかし、SQL Plusでは、行は2500文字を上書きします!

    うわー、それらの制約はかなり制限されていますが、私はそれを回避する方法があるかもしれないと思います。このために、独自の小さなスクリプトを作成する必要があると思います。

    私は自分でJDBCでJavaを使用し(ただし、データベースに接続して読み取り、文字列を出力できる任意の言語で実行できます)、データベース内のすべての行のレコードセットを取得する小さなプログラムを作成します。次に、それらの行のすべてについて:

    • 完全なデータを使用して挿入ステートメントを作成します。これが2,000バイト未満の場合は、ファイルに出力して次の行に移動します。

    • それ以外の場合は、すべてのフィールドに挿入ステートメントを作成しますが、c13はそのままにしておきます ''としてのフィールド (空)。

    • 次に、c13inputである限り 文字列が2000文字を超える場合は、"update tbl set c13 = c13 || '" + c13input.substring (0,2000) + "' where ..."の形式の更新ステートメントを出力します。 (次の2000文字を追加)次に、c13input = c13input.substring(2000)を実行します。 文字列からそれらの文字を削除します。

    • 一度c13input 長さが2000文字以下の場合は、最終更新を1つ出力するだけで、最後に追加できます。

    これにより、個々のSQLステートメントを2000文字前後に保ち、正しいSQLを効率的に実行して、別のデータベーステーブルを再作成できます。

    これは私が話しているタイプのことです(主キーc1だけを含むテーブルの場合 と大きなhonkin'varcharc13 ):

    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
    

    明らかに、特殊文字の挿入を可能にするために文字列をモーフィングする必要があるかもしれません-Oracleがこれらをどの形式で期待するかはわかりませんが、文字列を渡すだけの簡単な問題であることが望まれます(r.get("c13") 完全な挿入の長さが2000未満の場合、f.substring(0,2000) およびf これを行うためのヘルパー関数の更新も作成している場合。

    そのモーフィングによって印刷される行のサイズが大きくなる可能性がある場合は、安全のためにしきい値を1000に戻し、モーフィングされた文字列がPL/SQLの制限を超える行にならないようにすることができます。

    それが複雑に思える場合は申し訳ありませんが、あなたが述べた制限は私たちを少し困惑させます。もっと良い方法があるかもしれませんが、すべてを満たす方法は考えられません。 あなたの基準。

    更新: あなたはさらに 当初考えていたよりも困惑している:生成のためにSQLに制限する必要がある場合 スクリプトを実行するだけでなく、それでも厄介な方法があります。

    SQLを使用してSQLを生成できます。前述のテーブルをc1で使用する およびc13 、次のことができます:

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

    これにより、すべてのベースラインinsertが得られます c13以外のすべてを複製するためのステートメント 列。

    次に行う必要があるのは、c13を設定するためのステートメントをさらに生成することです。 。 c13を更新するには 長さが1000以下のすべての値の場合(単純なセット):

    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
    

    次に、update 1001〜2000文字のすべての値の場合はc13(設定してから追加):

    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.
    

    2001から3000および3001から4000の長さのものについても同様です。

    微調整が必​​要になる可能性があります。私はあなたにそれを解決する方法を与えてうれしいですが、そのような怪物に完全に取り組むという私の願望はせいぜい最小限です:-)

    それは仕事を成し遂げますか?はい。きれいですか?それは「NO!」と響き渡ったと思います。しかし、あなたの制約を考えると、それはあなたが望むことができる最高のものかもしれません。

    概念実証として、DB2のSQLスクリプトを次に示します(ただし、特別な機能はありませんが、lengthを持つすべてのDBMSで正常に機能するはずです。 およびsubstr 同等):

    # 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;
    

    これにより、次の行が生成されます。

    > 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';
    

    出力行を分割すると、次のようになります。

    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';
    

    ラウンドアバウトの方法ではありますが、元の行が表示されるはずです。

    そして、それは私が頭を悩ませることなく1つの質問に答えることができるのと同じくらいの努力です。したがって、重大なエラーが指摘されない限り、私はあなたにadieuを入札します。

    プロジェクトを頑張ってください。そして、よろしくお願いします。



    1. SQLテーブルから(複数の列の値に基づいて)重複する行を削除する

    2. クエリ内でDML操作を実行できない解決策はありますか?

    3. データベースからdjangoモデルを生成することは可能ですか?

    4. ステップバイステップR12.2.6VirtualBoxへのEBSのインストール