Codeigniter WebサイトにPostgreSQLを使用しています。追加、編集、削除の操作に食料品の塊を使用しています。編集または追加を行っている間、コンテンツのIDに基づいて、アップロードされたファイルの名前を動的に変更します。私は食料品のcrudの_callback_after_upload
_関数を使用してこれを行うことができます。
新しいコンテンツを追加するときに、コンテンツの次のIDが必要です。 nextval()
関数を使用しようとしましたが、シーケンスが増加します。 nextval()
関数を使用せずにシーケンスの最後の値を取得するにはどうすればよいですか?
または、これを行う簡単な方法はありますか?
RETURNING
現代のPostgreSQL(8.2以降)では、データベースに対して1回の往復でこれを行います。
_INSERT INTO tbl(filename)
VALUES ('my_filename')
RETURNING tbl_id;
_
_tbl_id
_は serial
列です。 マニュアルの詳細 。
filename
に_tbl_id
_(冗長)を含める必要がある場合でも、単一のクエリを使用できます。lastval()
またはより具体的な currval()
:
_INSERT INTO tbl (filename)
VALUES ('my_filename' || lastval()) -- or currval('tbl_tbl_id_seq')
RETURNING tbl_id;
_
この関数は、シーケンス名を引数として取る代わりに、現在のセッションで
currval
が使用する最後のシーケンスの値を取得することを除いて、nextval
と同じです。
テーブルにリンクされた複数のシーケンスがある場合(またはトリガーを持つ場合でも)、sureの方法はcurrval('tbl_tbl_id_seq')
を使用することです。
文字列リテラル _'tbl_tbl_id_seq'
_は、actualシーケンスの名前であると想定され、regclass
にキャストされ、例外が発生します現在の _search_path
_ でその名前のシーケンスが見つからない場合。
_tbl_tbl_id_seq
_は、シリアル列_tbl_id
_を持つテーブルtbl
に対して自動的に生成されるデフォルトです。しかし、保証はありません。列のデフォルトは、定義されている場合、anyシーケンスから値をフェッチできます。また、テーブルの作成時にデフォルト名が使用される場合、Postgresはハードコーディングされたアルゴリズムに従って次の空き名を選択します。
しない場合knowserial
列のシーケンスの名前は、専用関数 pg_get_serial_sequence()
オンザフライでも実行できます。
_INSERT INTO tbl (filename)
VALUES ('my_filename' || currval(pg_get_serial_sequence('tbl', 'tbl_id'))
RETURNING tbl_id;
_
以前に取得したシーケンスの値には、currval()
関数を使用してアクセスします。
しかし、それはnextval()
がbefore thatと呼ばれた場合のみ値を返します。
実際にシーケンスを取得しないと、シーケンスの次の値を「覗く」方法はまったくありません。
しかし、あなたの質問は不明です。挿入を行う前にnextval()
を呼び出すと、その値を挿入で使用できます。または、さらに良いことに、挿入ステートメントでcurrval()
を使用します。
select nextval('my_sequence') ...
... do some stuff with the obtained value
insert into my_table(id, filename)
values (currval('my_sequence'), 'some_valid_filename');
どうにかしてこれを行うことができたとしても、それは別のレコードで使用されるシーケンスを取得することができるため、ひどい考えです!
より良いアイデアは、レコードを保存し、その後シーケンスを取得することです。
セッションに参加していない場合は、nextval( 'you_sequence_name')を実行するだけで問題ありません。
私はこれを試してみましたが、完全に動作します
@Entity
public class Shipwreck {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seq")
@Basic(optional = false)
@SequenceGenerator(name = "seq", sequenceName = "shipwreck_seq", allocationSize = 1)
Long id;
....
CREATE SEQUENCE public.shipwreck_seq
INCREMENT 1
START 110
MINVALUE 1
MAXVALUE 9223372036854775807
CACHE 1;
あなたの質問に文字通り答えるために、シーケンスをインクリメントせずに次の値を取得する方法は次のとおりです。
SELECT
CASE WHEN is_called THEN
last_value + 1
ELSE
last_value
END
FROM sequence_name
明らかに、実際にこのコードを使用するのは得策ではありません。 次の行が実際にこのIDを持っているという保証はありません。ただし、デバッグのために、シーケンスの値をインクリメントせずに知ることは興味深いかもしれません。これがその方法です。