助け合いフォーラム

OSS-DB

OSS-DB Silver(Ver3.0)
問題ID : 35022
問題を開く
シーケンスについて正しいものはどれか。(2つ選択)

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

上に戻る

シーケンスのcurrvalについて

投稿日 2024/03/17

『 初期値の取得は、シーケンスを作成した直後にcurrval()関数で行う』が間違いであり、その説明として『nextval()関数を呼び出す前にcurrval()関数を呼び出すとエラーとなります。 』と記載されています。
つまり、setvalの直後に(nextvalを行わずに)currvalを呼び出すとエラーになるという意味だと思いますが、問題35306では、setvalの直後に(nextvalを行わずに)currvalを呼び出すと値が取れると書いてあります。
どちらの答えが正しいのでしょうか?
問題35306では実行結果画面が掲載されているので、当問題の解答が間違っていると想像しています。

2024/03/17 22:25

つまり、setvalの直後に(nextvalを行わずに)currvalを呼び出すとエラーになるという意味だと思いますが、問題35306では、setvalの直後に(nextvalを行わずに)currvalを呼び出すと値が取れると書いてあります。

これは条件を正しく一致させてないですね。シーケンス作成直後の状態とsetval()直後の状態は同じではありません。

前者(問題ID:35022)だとこういう話ですよね。

$ docker run --name postgres13 -e POSTGRES_PASSWORD=mysecretpassword -d postgres:13
5eae36f2d752bd9e7de8f351e4f80e8ed7e0cdf6c73c0a71516b2014641ba52a
$ docker exec -it postgres13 psql -U postgres
psql (13.14 (Debian 13.14-1.pgdg120+2))
Type "help" for help.

postgres=# CREATE SEQUENCE q35022;
CREATE SEQUENCE
postgres=# select currval('q35022');
ERROR:  currval of sequence "q35022" is not yet defined in this session

作成直後のシーケンスは(START句で指定していない限り)初期値が存在しないので、そのままだと「何を返せばいいかがわからないので現在値を取得しようとするとエラーになる」ものです。なお、その場合でも「nextval()」をすることで初期値(デフォルトの最小値)が定義されるので、その後はcurrval()が利用可能になります。

postgres=# select nextval('q35022');
 nextval
---------
       1
(1 row)

postgres=# select currval('q35022');
 currval
---------
       1
(1 row)

問題ID:35306の場合はこうですね。最初にsetval()で値をセットしているのでnextval()しなくても値がすでに存在するので、そのままcurrval()で値が取れます。

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)

setval()が初期値をセットしているので、setval()する前だと問題ID:35022と同じことが起きます。

postgres=# CREATE SEQUENCE sample_seq_2 CACHE 5 NO CYCLE;
CREATE SEQUENCE
postgres=# SELECT currval('sample_seq_2');
ERROR:  currval of sequence "sample_seq_2" is not yet defined in this session
postgres=# SELECT setval('sample_seq_2', 200);
 setval
--------
    200
(1 row)

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


コメント

g gorogorosan

2024/03/20 11:40

①シーケンス作成⇒②setval⇒③currvalということですね。①②を同一視してしまっていました。ご解説ありがとうございました。

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

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