@@ -30,6 +30,7 @@ Technology Innovation Group真野です。
3030
3131- 新規構築なら連番の自動採番はSERIAL/BIGSERIALの代わりに ` GENERATED ALWAYS AS IDENTITY ` の利用がベター
3232- DEFAULTキーワードは利用せず、省略する
33+ - 暗黙的に作成されるシーケンスは、テーブル名やカラム名のリネームに追随しないので、合わせてリネームする運用にする
3334- 気になった部分の調査事項と結果は下表
3435
3536| 調査項目 | 結果 |
@@ -39,6 +40,10 @@ Technology Innovation Group真野です。
3940| パーティションテーブルでの利用 | 利用できる |
4041| 作成されたシーケンスの名称 | {テーブル名}_ {カラム名}_ seq |
4142| 作成されたシーケンスを削除したらどうなるか | 削除不可 |
43+ | シーケンス名の上限63文字を超過したテーブル、カラム名の場合 | それぞれ29文字上限でオミットされて生成 |
44+ | テーブル名を変更した時シーケンス名はどうなるか | 変化なし |
45+ | カラム名をを変更した時シーケンス名はどうなるか | 変化なし |
46+ | 独自に作成したシーケンスとの紐づけ方法 | できない |
4247| 文字列型とGENERATED AS IDENTITYの組み合わせ| 設定不可 |
4348| SERIAL型とGENERATED AS IDENTITYの組み合わせ | 設定不可 |
4449
@@ -53,6 +58,19 @@ CREATE TABLE color (
5358);
5459```
5560
61+ テーブルの状態は以下です。` GENERATED AS IDENTITY ` を付けると暗黙的にNOT NULL制約がつくことも分かります。
62+
63+ ``` sql
64+ postgres- # \d color;
65+ Table " public.color"
66+ Column | Type | Collation | Nullable | Default
67+ -- ----------+-------------------+-----------+----------+----------------------------------
68+ color_id | bigint | | not null | generated by default as identity
69+ color_name | character varying | | not null |
70+ Indexes:
71+ " color_pkey" PRIMARY KEY , btree (color_id)
72+ ```
73+
5674このテーブルで` color_id ` を未指定にして、2件データを登録します。
5775
5876``` sql
@@ -358,6 +376,23 @@ WHERE
358376(1 row)
359377```
360378
379+ 上記のSQLは少し長いので、 ` pg_get_serial_sequence(table text, column text) ` というシステムカタログ情報関数も用意されています。
380+
381+ - https://www.postgresql.jp/document/16/html/functions-info.html#FUNCTIONS-INFO-CATALOG
382+
383+ ``` sql
384+ SELECT pg_get_serial_sequence(' color' , ' color_id' ) AS sequence_name;
385+ ```
386+
387+ 結果です。
388+
389+ ``` sql
390+ sequence_name
391+ -- -------------------------
392+ public .color_color_id_seq
393+ (1 row)
394+ ```
395+
361396### 5. 作成されたシーケンスを削除したらどうなるか
362397
363398誤ってIDENTITY列が内部的に使用するシーケンスオブジェクトを削除したら、不正な状態にならないかテストです。当然、失敗します。
@@ -370,7 +405,126 @@ HINT: You can drop column color_id of table color instead.
370405
371406もし、このシーケンスを削除したい場合は、colorテーブルのcolor_id列を削除する必要があるとあります。妥当なメッセージです。
372407
373- ### 6. 文字列型とGENERATED BY DEFAULT AS IDENTITYの組み合わせ
408+ ### 6. シーケンス名の上限63文字を超過したテーブル、カラム名の場合
409+
410+ PostgreSQLではシーケンスに限らず、識別子の最長は63文字です。
411+
412+ - https://www.postgresql.jp/document/16/html/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS
413+
414+ そのため、IDENTITYで自動で生成されるシーケンス名の体系が、{テーブル名}_ {カラム名}_ seq だとすると、超過した場合にどう命名されるか気になりました。
415+
416+ 試してみます。テーブル名が36文字、カラム名が39文字です。
417+
418+ ``` sql
419+ CREATE TABLE looooooooooooooooooooooooooooooooong (
420+ looooooooooooooooooooooooooooooooong_id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY ,
421+ color_name VARCHAR NOT NULL
422+ );
423+ ```
424+
425+ シーケンス名を確認すると、次の結果となりました。
426+
427+ ``` sql
428+ postgres= # SELECT pg_get_serial_sequence('looooooooooooooooooooooooooooooooong', 'looooooooooooooooooooooooooooooooong_id') AS sequence_name;
429+ sequence_name
430+ -- ----------------------------------------------------------------------
431+ public .loooooooooooooooooooooooooooo_loooooooooooooooooooooooooooo_seq
432+ ```
433+
434+ テーブル名、カラム名が長いと最長で29文字で前方からオミットされて生成されるようです。
435+
436+ 直接シーケンス名を指定して ` setval() ` するときに困ることが多いかなと思いますので、注意が必要です。
437+
438+ ### 7. テーブル名を変更した時シーケンス名はどうなるか
439+
440+ シーケンス名は自動生成されますが、ALTERでテーブル名を変えた場合にどうなるか確かめます。
441+
442+ ``` sql
443+ ALTER TABLE looooooooooooooooooooooooooooooooong RENAME TO color;
444+ ```
445+
446+ 結果は以下の通り、変化無しです。
447+
448+ ``` sql
449+ postgres= # SELECT pg_get_serial_sequence('color', 'looooooooooooooooooooooooooooooooong_id') AS sequence_name;
450+ sequence_name
451+ -- ----------------------------------------------------------------------
452+ public .loooooooooooooooooooooooooooo_loooooooooooooooooooooooooooo_seq
453+ (1 row)
454+ ```
455+
456+ そのため、テーブル名を変更した場合は、シーケンス名もリネームするような運用を行った方が良いでしょう。
457+
458+ ### 8. カラム名をを変更した時シーケンス名はどうなるか
459+
460+ 7と同様に、カラム名を変更した場合にシーケンス名がどうなるか確認します。
461+
462+ ``` sql
463+ ALTER TABLE color RENAME COLUMN looooooooooooooooooooooooooooooooong_id TO color_id;
464+ ```
465+
466+ 結果は以下の通り、テーブル名と同様、カラム名の変更も変化ありません。
467+
468+ ``` sql
469+ postgres= # SELECT pg_get_serial_sequence('color', 'color_id') AS sequence_name;
470+ sequence_name
471+ -- ----------------------------------------------------------------------
472+ public .loooooooooooooooooooooooooooo_loooooooooooooooooooooooooooo_seq
473+ (1 row)
474+ ```
475+
476+ 結論も7と同様、テーブル名/カラム名が変更した場合は、シーケンス名もリネームする運用を行うとベターでしょう。
477+
478+ ``` sql シーケンスのリネーム
479+ ALTER SEQUENCE loooooooooooooooooooooooooooo_loooooooooooooooooooooooooooo_seq RENAME TO color_color_id_seq;
480+ ```
481+
482+ ### 9. 独自に作成したシーケンスとの紐づけ方法
483+
484+ SERIAL型であれば、以下のように指定すると独自のシーケンスと紐づけることができました。
485+
486+ ``` sql
487+ -- 独自シーケンス
488+ CREATE SEQUENCE custom_color_seq ;
489+
490+ -- DEAULTでシーケンスと紐づける
491+ CREATE TABLE color (
492+ color_id BIGINT NOT NULL DEFAULT nextval(' custom_color_seq' ) PRIMARY KEY ,
493+ color_name VARCHAR NOT NULL
494+ );
495+ ALTER SEQUENCE custom_color_seq OWNED BY color .color_id ;
496+ ```
497+
498+ BIGINTを指定していて、BIGSERIALを使っていないじゃない?と思うかもしれません。しかし[ ドキュメント] ( https://www.postgresql.jp/docs/16/datatype-numeric.html#DATATYPE-SERIAL ) にも記載通り、以下の2つの構文は同義ですので、これが言えます。
499+
500+ ``` sql
501+ CREATE TABLE tablename (
502+ colname SERIAL
503+ );
504+ ```
505+
506+ ``` sql SERIAL型の裏側
507+ CREATE SEQUENCE tablename_colname_seq AS integer ;
508+ CREATE TABLE tablename (
509+ colname integer NOT NULL DEFAULT nextval(' tablename_colname_seq' )
510+ );
511+ ALTER SEQUENCE tablename_colname_seq OWNED BY tablename .colname ;
512+ ```
513+
514+ IDENTITY列に関しては、手動で作成したシーケンスとIDENTITY列を紐づける構文は、ドキュメントを探した時点では存在しませんでした。
515+
516+ そのため、独自の名称のシーケンスにしたければ ` ALTER SEQUENCE RENAME ` で変更する運用になるかと思います。
517+
518+ また、次のようにシーケンスオプションも作成時に指定できます(ALTERで変更も可能)です。おそらく、困ることは無いかなと思います。
519+
520+ ``` sql
521+ CREATE TABLE color (
522+ color_id INT GENERATED ALWAYS AS IDENTITY (START WITH 10 INCREMENT BY 1 CACHE 100 ),
523+ color_name VARCHAR NOT NULL
524+ );
525+ ```
526+
527+ ### 10. 文字列型とGENERATED BY DEFAULT AS IDENTITYの組み合わせ
374528
375529文字列型(text型)にGENERATED ALWAYS AS IDENTITYを指定すると、いい感じの型変換により '1'、'2'、...といった採番がされないかと思いついたので試しました。
376530
@@ -384,7 +538,7 @@ ERROR: identity column type must be smallint, integer, or bigint
384538
385539無事エラーで、これは対応していないようです。型としては、` smallint ` ` integer ` ` bigint ` のみ対応。
386540
387- ### 7 . SERIAL型とGENERATED BY DEFAULT AS IDENTITYの組み合わせ
541+ ### 11 . SERIAL型とGENERATED BY DEFAULT AS IDENTITYの組み合わせ
388542
389543SERIAL型であれば、型としては ` integer ` 型なので、いけるのではと一応チャレンジしました。結果は以下のエラーです。
390544
0 commit comments