タイプを使用するときに取得するシーケンスではなくserial
、値1がすでに列に存在しない限り値2を挿入できないように、各値がシーケンス内にある必要があるようにPostgreSQLで列を定義するにはどうすればよいですか?
3 に答える
PL/PgSQL を使用したギャップレス シーケンスの実装の詳細な例をここに書きました。
一般的な考え方は、テーブルにシーケンス値を格納する必要があり、トランザクションがコミットまたはロールバックされるまで行をロックしながら、それにSELECT ... FOR UPDATE
続くUPDATE
- または省略形- を使用してテーブルから値を取得することです。UPDATE ... RETURNING
理論的には、このように機能する制約を使用できます。(しかし、実際には機能しません。)
- 行を数えます。
- 評価し
max(column) - min(column) + 1
ます。 - 結果を比較します。
CHECK 制約を作成する前に、おそらく 1 行挿入する必要があります。そうしないと、max(column) は NULL を返します。一行で、
- 行を数えます (1)。
- 評価し
max(column) - min(column) + 1
ます。(1 - 1 + 1 = 1) - 結果を比較します。(1 = 1)
10行で。.
- 行を数えます (10)。
- 評価し
max(column) - min(column) + 1
ます。(10 - 1 + 1 = 10) - 結果を比較します。(10 = 10)
シーケンスが 1 から始まるかどうかは問題ではありません。このチェック方法では、存在する場合は常にギャップが表示されます。ギャップレス シーケンスが 1 から始まることを保証する必要がある場合は、それを CHECK 制約に追加できます。
私の知る限り、現在の dbms でこれを宣言的に行う方法はありません。そのためには、 のサポートが必要ですCREATE ASSERTION
。(しかし、私は間違っている可能性があります。) PostgreSQL では、これに対するあなたの唯一のショットは、複数の AFTER トリガーの手続き型コードに関係していると思います。
ギャップレスにする必要があるテーブルは 1 つだけです。カレンダー表です。これらの計算を行うクエリを 1 晩に 1 回実行すると、ギャップがあるかどうかがわかります。
You write an on insert tigger
or a check constraint
. However, this will still allow to delete "1" afterwards and "2" stays in the table, you'll probably have to address this too.