Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ Technology Innovation Group真野です。

- 新規構築なら連番の自動採番はSERIAL/BIGSERIALの代わりに `GENERATED ALWAYS AS IDENTITY` の利用がベター
- DEFAULTキーワードは利用せず、省略する
- 暗黙的に作成されるシーケンスは、テーブル名やカラム名のリネームに追随しないので、合わせてリネームする運用にする
- 気になった部分の調査事項と結果は下表

| 調査項目 | 結果 |
Expand All @@ -39,6 +40,10 @@ Technology Innovation Group真野です。
| パーティションテーブルでの利用 | 利用できる |
| 作成されたシーケンスの名称 | {テーブル名}_{カラム名}_seq |
| 作成されたシーケンスを削除したらどうなるか | 削除不可 |
| シーケンス名の上限63文字を超過したテーブル、カラム名の場合 | それぞれ29文字上限でオミットされて生成 |
| テーブル名を変更した時シーケンス名はどうなるか | 変化なし |
| カラム名をを変更した時シーケンス名はどうなるか | 変化なし |
Copy link
Contributor

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)

| 独自に作成したシーケンスとの紐づけ方法 | できない |
| 文字列型とGENERATED AS IDENTITYの組み合わせ| 設定不可 |
| SERIAL型とGENERATED AS IDENTITYの組み合わせ | 設定不可 |

Expand All @@ -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
Expand Down Expand Up @@ -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列が内部的に使用するシーケンスオブジェクトを削除したら、不正な状態にならないかテストです。当然、失敗します。
Expand All @@ -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 だとすると、超過した場合にどう命名されるか気になりました。
Copy link
Contributor

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/no-doubled-joshi> reported by reviewdog 🐶
一文に二回以上利用されている助詞 "で" がみつかりました。

次の助詞が連続しているため、文を読みにくくしています。

  • "で"
  • "で"

同じ助詞を連続して利用しない、文の中で順番を入れ替える、文を分割するなどを検討してください。
(ja-technical-writing/no-doubled-joshi)


試してみます。テーブル名が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文字で前方からオミットされて生成されるようです。
Copy link
Contributor

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/no-doubled-joshi> reported by reviewdog 🐶
一文に二回以上利用されている助詞 "で" がみつかりました。

次の助詞が連続しているため、文を読みにくくしています。

  • "で"
  • "で"

同じ助詞を連続して利用しない、文の中で順番を入れ替える、文を分割するなどを検討してください。
(ja-technical-writing/no-doubled-joshi)


直接シーケンス名を指定して `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. カラム名をを変更した時シーケンス名はどうなるか
Copy link
Contributor

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)


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つの構文は同義ですので、これが言えます。
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[textlint-fix] reported by reviewdog 🐶

Suggested change
BIGINTを指定していて、BIGSERIALを使っていないじゃない?と思うかもしれません。しかし[ドキュメント](https://www.postgresql.jp/docs/16/datatype-numeric.html#DATATYPE-SERIAL)にも記載通り、以下の2つの構文は同義ですので、これが言えます。
BIGINTを指定していて、BIGSERIALを使っていないじゃない? と思うかもしれません。しかし[ドキュメント](https://www.postgresql.jp/docs/16/datatype-numeric.html#DATATYPE-SERIAL)にも記載通り、以下の2つの構文は同義ですので、これが言えます。


```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'、...といった採番がされないかと思いついたので試しました。

Expand All @@ -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` 型なので、いけるのではと一応チャレンジしました。結果は以下のエラーです。

Expand Down