-
Notifications
You must be signed in to change notification settings - Fork 18
追記: PostgreSQLで連番を自動生成してくれるIDENTITY列 #1427
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -30,6 +30,7 @@ Technology Innovation Group真野です。 | |||||
|
|
||||||
| - 新規構築なら連番の自動採番はSERIAL/BIGSERIALの代わりに `GENERATED ALWAYS AS IDENTITY` の利用がベター | ||||||
| - DEFAULTキーワードは利用せず、省略する | ||||||
| - 暗黙的に作成されるシーケンスは、テーブル名やカラム名のリネームに追随しないので、合わせてリネームする運用にする | ||||||
| - 気になった部分の調査事項と結果は下表 | ||||||
|
|
||||||
| | 調査項目 | 結果 | | ||||||
|
|
@@ -39,6 +40,10 @@ Technology Innovation Group真野です。 | |||||
| | パーティションテーブルでの利用 | 利用できる | | ||||||
| | 作成されたシーケンスの名称 | {テーブル名}_{カラム名}_seq | | ||||||
| | 作成されたシーケンスを削除したらどうなるか | 削除不可 | | ||||||
| | シーケンス名の上限63文字を超過したテーブル、カラム名の場合 | それぞれ29文字上限でオミットされて生成 | | ||||||
| | テーブル名を変更した時シーケンス名はどうなるか | 変化なし | | ||||||
| | カラム名をを変更した時シーケンス名はどうなるか | 変化なし | | ||||||
| | 独自に作成したシーケンスとの紐づけ方法 | できない | | ||||||
| | 文字列型とGENERATED AS IDENTITYの組み合わせ| 設定不可 | | ||||||
| | SERIAL型とGENERATED AS IDENTITYの組み合わせ | 設定不可 | | ||||||
|
|
||||||
|
|
@@ -53,6 +58,19 @@ CREATE TABLE color ( | |||||
| ); | ||||||
| ``` | ||||||
|
|
||||||
| テーブルの状態は以下です。`GENERATED AS IDENTITY` を付けると暗黙的にNOT NULL制約がつくことも分かります。 | ||||||
|
|
||||||
| ```sql | ||||||
| postgres-# \d color; | ||||||
| Table "public.color" | ||||||
| Column | Type | Collation | Nullable | Default | ||||||
| ------------+-------------------+-----------+----------+---------------------------------- | ||||||
| color_id | bigint | | not null | generated by default as identity | ||||||
| color_name | character varying | | not null | | ||||||
| Indexes: | ||||||
| "color_pkey" PRIMARY KEY, btree (color_id) | ||||||
| ``` | ||||||
|
|
||||||
| このテーブルで`color_id` を未指定にして、2件データを登録します。 | ||||||
|
|
||||||
| ```sql | ||||||
|
|
@@ -358,6 +376,23 @@ WHERE | |||||
| (1 row) | ||||||
| ``` | ||||||
|
|
||||||
| 上記のSQLは少し長いので、 `pg_get_serial_sequence(table text, column text)` というシステムカタログ情報関数も用意されています。 | ||||||
|
|
||||||
| - https://www.postgresql.jp/document/16/html/functions-info.html#FUNCTIONS-INFO-CATALOG | ||||||
|
|
||||||
| ```sql | ||||||
| SELECT pg_get_serial_sequence('color', 'color_id') AS sequence_name; | ||||||
| ``` | ||||||
|
|
||||||
| 結果です。 | ||||||
|
|
||||||
| ```sql | ||||||
| sequence_name | ||||||
| --------------------------- | ||||||
| public.color_color_id_seq | ||||||
| (1 row) | ||||||
| ``` | ||||||
|
|
||||||
| ### 5. 作成されたシーケンスを削除したらどうなるか | ||||||
|
|
||||||
| 誤ってIDENTITY列が内部的に使用するシーケンスオブジェクトを削除したら、不正な状態にならないかテストです。当然、失敗します。 | ||||||
|
|
@@ -370,7 +405,126 @@ HINT: You can drop column color_id of table color instead. | |||||
|
|
||||||
| もし、このシーケンスを削除したい場合は、colorテーブルのcolor_id列を削除する必要があるとあります。妥当なメッセージです。 | ||||||
|
|
||||||
| ### 6. 文字列型とGENERATED BY DEFAULT AS IDENTITYの組み合わせ | ||||||
| ### 6. シーケンス名の上限63文字を超過したテーブル、カラム名の場合 | ||||||
|
|
||||||
| PostgreSQLではシーケンスに限らず、識別子の最長は63文字です。 | ||||||
|
|
||||||
| - https://www.postgresql.jp/document/16/html/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS | ||||||
|
|
||||||
| そのため、IDENTITYで自動で生成されるシーケンス名の体系が、{テーブル名}_{カラム名}_seq だとすると、超過した場合にどう命名されるか気になりました。 | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚫 [textlint] <eslint.rules.ja-technical-writing/no-doubled-joshi> reported by reviewdog 🐶 次の助詞が連続しているため、文を読みにくくしています。
同じ助詞を連続して利用しない、文の中で順番を入れ替える、文を分割するなどを検討してください。 |
||||||
|
|
||||||
| 試してみます。テーブル名が36文字、カラム名が39文字です。 | ||||||
|
|
||||||
| ```sql | ||||||
| CREATE TABLE looooooooooooooooooooooooooooooooong ( | ||||||
| looooooooooooooooooooooooooooooooong_id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, | ||||||
| color_name VARCHAR NOT NULL | ||||||
| ); | ||||||
| ``` | ||||||
|
|
||||||
| シーケンス名を確認すると、次の結果となりました。 | ||||||
|
|
||||||
| ```sql | ||||||
| postgres=# SELECT pg_get_serial_sequence('looooooooooooooooooooooooooooooooong', 'looooooooooooooooooooooooooooooooong_id') AS sequence_name; | ||||||
| sequence_name | ||||||
| ------------------------------------------------------------------------ | ||||||
| public.loooooooooooooooooooooooooooo_loooooooooooooooooooooooooooo_seq | ||||||
| ``` | ||||||
|
|
||||||
| テーブル名、カラム名が長いと最長で29文字で前方からオミットされて生成されるようです。 | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚫 [textlint] <eslint.rules.ja-technical-writing/no-doubled-joshi> reported by reviewdog 🐶 次の助詞が連続しているため、文を読みにくくしています。
同じ助詞を連続して利用しない、文の中で順番を入れ替える、文を分割するなどを検討してください。 |
||||||
|
|
||||||
| 直接シーケンス名を指定して `setval()` するときに困ることが多いかなと思いますので、注意が必要です。 | ||||||
|
|
||||||
| ### 7. テーブル名を変更した時シーケンス名はどうなるか | ||||||
|
|
||||||
| シーケンス名は自動生成されますが、ALTERでテーブル名を変えた場合にどうなるか確かめます。 | ||||||
|
|
||||||
| ```sql | ||||||
| ALTER TABLE looooooooooooooooooooooooooooooooong RENAME TO color; | ||||||
| ``` | ||||||
|
|
||||||
| 結果は以下の通り、変化無しです。 | ||||||
|
|
||||||
| ```sql | ||||||
| postgres=# SELECT pg_get_serial_sequence('color', 'looooooooooooooooooooooooooooooooong_id') AS sequence_name; | ||||||
| sequence_name | ||||||
| ------------------------------------------------------------------------ | ||||||
| public.loooooooooooooooooooooooooooo_loooooooooooooooooooooooooooo_seq | ||||||
| (1 row) | ||||||
| ``` | ||||||
|
|
||||||
| そのため、テーブル名を変更した場合は、シーケンス名もリネームするような運用を行った方が良いでしょう。 | ||||||
|
|
||||||
| ### 8. カラム名をを変更した時シーケンス名はどうなるか | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚫 [textlint] <eslint.rules.ja-technical-writing/ja-no-successive-word> reported by reviewdog 🐶 |
||||||
|
|
||||||
| 7と同様に、カラム名を変更した場合にシーケンス名がどうなるか確認します。 | ||||||
|
|
||||||
| ```sql | ||||||
| ALTER TABLE color RENAME COLUMN looooooooooooooooooooooooooooooooong_id TO color_id; | ||||||
| ``` | ||||||
|
|
||||||
| 結果は以下の通り、テーブル名と同様、カラム名の変更も変化ありません。 | ||||||
|
|
||||||
| ```sql | ||||||
| postgres=# SELECT pg_get_serial_sequence('color', 'color_id') AS sequence_name; | ||||||
| sequence_name | ||||||
| ------------------------------------------------------------------------ | ||||||
| public.loooooooooooooooooooooooooooo_loooooooooooooooooooooooooooo_seq | ||||||
| (1 row) | ||||||
| ``` | ||||||
|
|
||||||
| 結論も7と同様、テーブル名/カラム名が変更した場合は、シーケンス名もリネームする運用を行うとベターでしょう。 | ||||||
|
|
||||||
| ```sql シーケンスのリネーム | ||||||
| ALTER SEQUENCE loooooooooooooooooooooooooooo_loooooooooooooooooooooooooooo_seq RENAME TO color_color_id_seq; | ||||||
| ``` | ||||||
|
|
||||||
| ### 9. 独自に作成したシーケンスとの紐づけ方法 | ||||||
|
|
||||||
| SERIAL型であれば、以下のように指定すると独自のシーケンスと紐づけることができました。 | ||||||
|
|
||||||
| ```sql | ||||||
| -- 独自シーケンス | ||||||
| CREATE SEQUENCE custom_color_seq; | ||||||
|
|
||||||
| -- DEAULTでシーケンスと紐づける | ||||||
| CREATE TABLE color ( | ||||||
| color_id BIGINT NOT NULL DEFAULT nextval('custom_color_seq') PRIMARY KEY, | ||||||
| color_name VARCHAR NOT NULL | ||||||
| ); | ||||||
| ALTER SEQUENCE custom_color_seq OWNED BY color.color_id; | ||||||
| ``` | ||||||
|
|
||||||
| BIGINTを指定していて、BIGSERIALを使っていないじゃない?と思うかもしれません。しかし[ドキュメント](https://www.postgresql.jp/docs/16/datatype-numeric.html#DATATYPE-SERIAL)にも記載通り、以下の2つの構文は同義ですので、これが言えます。 | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [textlint-fix] reported by reviewdog 🐶
Suggested change
|
||||||
|
|
||||||
| ```sql | ||||||
| CREATE TABLE tablename ( | ||||||
| colname SERIAL | ||||||
| ); | ||||||
| ``` | ||||||
|
|
||||||
| ```sql SERIAL型の裏側 | ||||||
| CREATE SEQUENCE tablename_colname_seq AS integer; | ||||||
| CREATE TABLE tablename ( | ||||||
| colname integer NOT NULL DEFAULT nextval('tablename_colname_seq') | ||||||
| ); | ||||||
| ALTER SEQUENCE tablename_colname_seq OWNED BY tablename.colname; | ||||||
| ``` | ||||||
|
|
||||||
| IDENTITY列に関しては、手動で作成したシーケンスとIDENTITY列を紐づける構文は、ドキュメントを探した時点では存在しませんでした。 | ||||||
|
|
||||||
| そのため、独自の名称のシーケンスにしたければ `ALTER SEQUENCE RENAME` で変更する運用になるかと思います。 | ||||||
|
|
||||||
| また、次のようにシーケンスオプションも作成時に指定できます(ALTERで変更も可能)です。おそらく、困ることは無いかなと思います。 | ||||||
|
|
||||||
| ```sql | ||||||
| CREATE TABLE color ( | ||||||
| color_id INT GENERATED ALWAYS AS IDENTITY (START WITH 10 INCREMENT BY 1 CACHE 100), | ||||||
| color_name VARCHAR NOT NULL | ||||||
| ); | ||||||
| ``` | ||||||
|
|
||||||
| ### 10. 文字列型とGENERATED BY DEFAULT AS IDENTITYの組み合わせ | ||||||
|
|
||||||
| 文字列型(text型)にGENERATED ALWAYS AS IDENTITYを指定すると、いい感じの型変換により '1'、'2'、...といった採番がされないかと思いついたので試しました。 | ||||||
|
|
||||||
|
|
@@ -384,7 +538,7 @@ ERROR: identity column type must be smallint, integer, or bigint | |||||
|
|
||||||
| 無事エラーで、これは対応していないようです。型としては、`smallint` `integer` `bigint` のみ対応。 | ||||||
|
|
||||||
| ### 7. SERIAL型とGENERATED BY DEFAULT AS IDENTITYの組み合わせ | ||||||
| ### 11. SERIAL型とGENERATED BY DEFAULT AS IDENTITYの組み合わせ | ||||||
|
|
||||||
| SERIAL型であれば、型としては `integer` 型なので、いけるのではと一応チャレンジしました。結果は以下のエラーです。 | ||||||
|
|
||||||
|
|
||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🚫 [textlint] <eslint.rules.ja-technical-writing/ja-no-successive-word> reported by reviewdog 🐶
"を" が連続して2回使われています。 (ja-technical-writing/ja-no-successive-word)