2017-09-19 7 views
0

非常に多くの行数(数百万)を持つデータベーステーブル(db2)があります。私は列の1つのデータ型を変更する必要があります。バッチをSQLを使用して更新する

DB2 LUWでは、列のデータ型を直接変更する方法はありません(ALTER TABLE ALTER COLUMN SET DATA TYPEは機能しません)。だから私は新しい列を作成して、それにデータをコピーし、古い列を削除します。

テーブルで直接更新するのは良い考えではないので、一度に10000行を更新してコミットするプロシージャを作成しています。

はこのことを考えると、私は次の質問を持っている:

  • ここアップデートを実施するための最良の方法は何ですか? - 私が知る限り、カーソルは一度に1行以上の反復を許します。 10000行を1つずつ更新してからコミットし、テーブルが正しい方法で更新されるまで繰り返しますか?
  • 簡単な方法で列のデータ型を変更するという最初の問題を処理するには、より良い方法がありますか?
+0

不要の​​ため、以下の

CURSORからのこの使用LOADの一例ですその時点で10000行を更新する代わりにpk条件を持っています。 – jarlh

+0

@jarlhループして、ある時点で停止する必要はありませんか?どのように私は手続きなしでそれを行うのですか? – BX21

+0

どのようなDb2のバージョンとプラットフォームですか?どのようなデータ型ですか?いくつかのデータ型を変更することができます。また、互換性のない型を変更するADMIN_MOVE_TABLEがあります。 https://www.ibm.com/support/knowledgecenter/SSEPGG_11.1.0/com.ibm.db2.luw.sql.rtn.doc/doc/r0055069.html –

答えて

0

DB2には、データの高速マイグレーションを可能にするLOAD FROM CURSORという機能があります。

-- this is the original table 
CREATE TABLE TEST (
    ID INT NOT NULL GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, 
    TEXT VARCHAR(50) 
)@ 

CREATE TABLE TEST_NEW (
    ID INT NOT NULL GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, 
    TEXT CLOB(5000000) 
)@ 

DECLARE C1 CURSOR FOR SELECT ID, TEXT FROM [email protected] 

LOAD FROM C1 OF CURSOR INSERT INTO TEST_NEW (ID,TEXT)@ 

DROP TABLE [email protected] 
RENAME TABLE TEST_NEW TO [email protected] 

加えて、以下の手順を使用することもできる(すべて10000のレコードの後に​​コミット):

-- this is the original table 
CREATE TABLE TEST (
    ID INT NOT NULL GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, 
    TEXT VARCHAR(50) 
)@ 

CREATE OR REPLACE PROCEDURE MIGRATE_TEST() 
LANGUAGE SQL 
BEGIN 

    DECLARE EOF INT DEFAULT 0; 

    DECLARE CUR_COUNT INT DEFAULT 0; 
    DECLARE CUR_ID INT DEFAULT 0; 

    DECLARE C CURSOR WITH HOLD FOR 
     SELECT ID FROM TEST WHERE TEXT_NEW IS NULL; 

    DECLARE CONTINUE HANDLER FOR NOT FOUND 
     SET EOF = 1; 

    OPEN C; 

    FETCH_LOOP: LOOP 
     FETCH FROM C INTO CUR_ID; 
     IF EOF <> 0 THEN 
       LEAVE FETCH_LOOP; 
     END IF; 

     UPDATE TEST 
     SET TEXT_NEW = TEXT 
     WHERE ID = CUR_ID ; 

     SET CUR_COUNT = CUR_COUNT + 1; 

     IF CUR_COUNT >= 10000 THEN 
      CALL DBMS_OUTPUT.PUT_LINE('COMMITTING'); 
      COMMIT WORK; 
      SET CUR_COUNT = 0; 
     END IF; 

    END LOOP FETCH_LOOP; 

    COMMIT WORK; 

    CLOSE C; 
[email protected] 
関連する問題