web-dev-qa-db-ja.com

自動インクリメント列の次に生成された値を見つける方法は?

IBM DB2の自動インクリメントカラムで問題が発生しました。最初、すべての列はGENERATED ALWAYSとして定義されていましたが、「db2 import ...」コマンドを使用するときにこれに問題があったため、それらをGENERATED BY DEFAULTに変更しました。他のテーブルがIDを参照するため、IDの一貫性が必要なので、これは必要です。したがって、「db2 import ... identityignore ...によって変更された」の使用はオプションではありません。

データをインポートすると、IDは正しく挿入されますが、これを行うたびに、最大のId + 1を取得して自動インクリメント列の新しい開始を設定し、次のように列を変更することを忘れないでください。

SELECT MAX(mycolumn)+ 1 FROM mytable;
ALTER TABLE mytable ALTER COLUMN mycolumn RESTART WITH <above_result>;

これを忘れた場合、自動インクリメント列が主キーであるため、Insert-Statementは重複PKエラーで失敗します。

だから私の質問は:自動インクリメント列の次の値を見つける方法はありますか?この値がSELECT MAXより小さく、設定する必要があるかどうかをチェックするステートメントを書くことができますか?

または:この全体が私には思えるほど複雑ではありませんか?どういうわけか、IDを保持したままデータをインポートして、自動インクリメント列を期待どおりに機能させることはできますか?

6
Tim Büthe

ティム、私はアイデンティティを次の値に再起動する必要がある同じ問題に直面していました。私はdb2v9.1を使用していました。

残念ながら、次の値を自動的に指定する方法はありません。 DB2のドキュメントに従って、値は「数値定数」である必要があります。したがって、select max(id)を実行し、値を取得して、alter..restart stmtで手動で置き換える必要がありました。

私がこれを試したかどうか覚えていませんが、変数にmax(id)が設定されているspを記述して、alter ... restart stmtで変数を割り当てることができます。 (私はもうdb2データベースにアクセスできないので、試すことができません)。私はそれがうまくいくとは思いません。 (動作する場合はお知らせください:))

DB2リファレンス:

RESTARTまたはRESTART WITH numeric-constant

ID列に関連付けられたシーケンスの状態をリセットします。 WITH数値定数が指定されていない場合、ID列のシーケンスは、ID列が最初に作成されたときの開始値として、暗黙的または明示的に指定された値から再開されます。列は指定されたテーブルに存在している必要があり(SQLSTATE 42703)、IDENTITY属性ですでに定義されている必要があります(SQLSTATE 42837)。 RESTARTは、元のSTART WITH値を変更しません。

Numeric-constantは、この列に割り当てることができる任意の正または負の値である正確な数値定数であり(SQLSTATE 42815)、小数点の右側にゼロ以外の数字はありません(SQLSTATE 428FA)。数値定数は、列の次の値として使用されます。

4
Rashmi Pandit

DB2でシーケンス番号を使用してから、シーケンスを使用することはできません。 nextval()?

DB2でのシーケンス値の自動生成へのリンク: http://www.ibm.com/developerworks/data/library/techarticle/0302fielding/0302fielding.html

2
Crowie

あなたの問題は今では解決されているかもしれませんが、同じ問題を持つ他のすべての人のために:すべてのテーブルのmax_id +1を取得するためのソリューションを提供できます。唯一の制限は、ソース列は自動インクリメント列でなければならないことです(GENERATED = 'D')。結果セットは、clpまたは他のクエリツールを介して実行できます。

SELECT   'alter table ' || rtrim(TABSCHEMA) || '.' || TABNAME || ' alter column ' || COLNAME || ' restart with ' || 
cast((case when (trim ((replace ( HIGH2KEY, '+' , '' )))) = '' then 0 else integer(trim ((replace ( HIGH2KEY, '+' , '' ))))+2 end) as varchar(20)) 
|| ' ;'
FROM     SYSCAT.COLUMNS
WHERE    GENERATED = 'D'
1
antih
  1. その列のデータを手動でインポートする場合、なぜ自動インクリメントを使用することを考えるのですか?この自動インクリメントはまったく使用されていません。
  2. SP=-a。admin_cmdを呼び出す-ロードオプションb。max(id)を選択し、現在のタイムスタンプと一緒にログテーブルにロードします。ログテーブルをクエリし、bash/windowsスクリプトを使用して更新します。
0
Arun Srini