助け合いフォーラム

OSS-DB

OSS-DB Silver(Ver3.0)
問題ID : 35306
問題を開く
以下のSQLが実行された場合の説明として、正しいものはどれか。 CREATE SEQUENCE sample_seq CACHE 5 NO CYCLE; SELECT setval('sample_seq', 100);

この問題はプレミアムコンテンツです。

上に戻る

シーケンス操作関数について

投稿日 2025/01/04

【質問】
同一セッション内で該当のシーケンスに対してnextvalが一度も呼ばれていなければ、currval関数はエラーを返すと認識しています。
その為、回答としては④も正しいですが、②も正しいと思います。
しかし、【解説】ではcurrval関数は、この問題の条件ではエラーにはならず、「100を返す」と説明しています。
勉強中の身で解説の正しいor間違いを判断できないのと、調べても出てこないのでここで質問させて頂きます。
どうぞよろしくお願いいたします。

___________________________________________________
【問題文】
以下のSQLが実行された場合の説明として、正しいものはどれか。
CREATE SEQUENCE sample_seq CACHE 5 NO CYCLE;
SELECT setval('sample_seq', 100);

【選択肢】
①「SELECT nextval('sample_seq');」を実行すると105が返される
②「SELECT currval('sample_seq');」を実行するとエラーとなる
③「SELECT currval('sample_seq');」を実行すると5が返される
④「SELECT nextval('sample_seq');」を実行すると101が返される (正解はコレ)
⑤「SELECT nextval('sample_seq');」を実行すると100が返される

【解説】
1行ずつ確認していきます。

CREATE SEQUENCE sample_seq CACHE 5 NO CYCLE;
「sample_seq」シーケンスを作成しています。
オプションにより、メモリに格納できるシーケンス番号の量が5、シーケンスが限界値に達した時はエラーになるように設定されています。増減値は指定がないため、1ずつ増加します。

SELECT setval('sample_seq', 100);
シーケンスの現在の値を100に設定しています。

この場合、「SELECT currval('sample_seq');」を実行すると100が、「SELECT nextval('sample_seq');」を実行すると101が取得されます。

したがって正解は
・「SELECT nextval('sample_seq');」を実行すると101が返される
です。
_______________________________________________

2025/01/04 22:17

少なくとも解説の実行例の通りにはなるようですね。

$ docker run --rm --name postgres -e POSTGRES_PASSWORD=postgres -d postgres
720321aa6c7d2cefb46d37adecc3938d34ea2daaff4958b49b309a8186f1edf3

$ docker exec -it postgres psql -U postgres
psql (17.2 (Debian 17.2-1.pgdg120+1))
Type "help" for help.

postgres=# CREATE SEQUENCE sample_seq CACHE 5 NO CYCLE;
CREATE SEQUENCE
postgres=# SELECT setval('sample_seq', 100);
 setval
--------
    100
(1 row)

postgres=# SELECT currval('sample_seq');
 currval
---------
     100
(1 row)

postgres=#

この状態で setval() で再度シーケンスの「現在値」を変更したら同じように設定後の「現在値」を返してくれます。

postgres=# SELECT setval('sample_seq', 200);
 setval
--------
    200
(1 row)

postgres=# SELECT currval('sample_seq');
 currval
---------
     200
(1 row)

nextval() を呼ぶかどうかが問題なのではなく「シーケンスを作成後に現在値が未設定の場合」に currval() を呼ぶと「現在値がないのでエラーになる」ということです。現在値を設定するには、「nextval() により初期値を取得する」か「setval() により任意の現在値を設定する」かのいずれかだということですね。

■ nextval() で初期化
postgres=# CREATE SEQUENCE sample_seq2 CACHE 5 NO CYCLE;
CREATE SEQUENCE
postgres=# SELECT currval('sample_seq2');
ERROR:  currval of sequence "sample_seq2" is not yet defined in this session
postgres=# SELECT nextval('sample_seq2');
 nextval
---------
       1
(1 row)

postgres=# SELECT currval('sample_seq2');
 currval
---------
       1
(1 row)


■ setval() で任意の値を設定
postgres=# CREATE SEQUENCE sample_seq3 CACHE 5 NO CYCLE;
CREATE SEQUENCE
postgres=# SELECT currval('sample_seq3');
ERROR:  currval of sequence "sample_seq3" is not yet defined in this session
postgres=# SELECT setval('sample_seq3', 35306);
 setval
--------
  35306
(1 row)

postgres=# SELECT currval('sample_seq3');
 currval
---------
   35306
(1 row)


コメント

m mku2bull

2025/01/07 10:42

納得して理解できました!ご回答ありがとうございます!

この返信に対して
コメントを記入できます

スタッフからの返信

s staff_ishii

2025/01/06 21:02

mku2bull さん、arashi1977 さん ご指摘の点について、参考の加筆・修正をいたしました。 ご報告、誠にありがとうございました。

この投稿に対して返信しませんか?