錯誤:序列“rss_sub_source_id_seq”的currval 尚未在此會話中定義
當我使用此查詢查看 PostgreSQL 13 表的目前主鍵種子時:
select CURRVAL(pg_get_serial_sequence('rss_sub_source', 'id'))
它告訴我:
SQL Error [55000]: ERROR: currval of sequence "rss_sub_source_id_seq" is not yet defined in this session
該
id
列定義如下:ALTER TABLE rss_sub_source ALTER id SET NOT NULL, -- optional ALTER id ADD GENERATED ALWAYS AS IDENTITY (START WITH 1233);
表定義:
CREATE TABLE public.rss_sub_source ( id int8 NOT NULL GENERATED ALWAYS AS IDENTITY, sub_url varchar NOT NULL, created_time int8 NOT NULL DEFAULT date_part('epoch'::text, now()), -- ... many more columns CONSTRAINT rss_sub_source_pkey PRIMARY KEY (id), CONSTRAINT unique_sub_url UNIQUE (sub_url) );
如何查看目前主鍵的自增種子?
這些功能只有在同一個會話
currval(regclass)
中使用lastval()
後才 有意義nextval()
(不是事務!)。PostgreSQL 中的並發控制是這種行為背後的原因。如果您只是對序列的目前狀態(不是會話中實際使用的最後一個序列號)感到好奇,您可以隨時呼叫
nextval()
:SELECT nextval(pg_get_serial_sequence('foo', 'id'));
返回下一個尚未使用的序列號。這帶來了實際使用返回的 ID 的缺陷(這在適當的關係設計中應該無關緊要)。但是這種副作用是可以避免的。在 Postgres 中,
serial
列IDENTITY
是使用SEQUENCE
內部實現的,它恰好是一個類似表格的對象,可以像表格一樣被查詢。如果您對 a 的目前狀態感到好奇SEQUENCE
,只需使用SELECT
:SELECT * FROM public.rss_sub_source_id_seq;
(需要序列的
SELECT
權限,而上面提到的序列函式需要USAGE
權限。)您需要知道序列的名稱,並且您已經知道如何獲取它:
pg_get_serial_sequence('rss_sub_source', 'id')
. 這也很容易猜到。看:對於臨時使用,只需手動編譯查詢。或者你可以
\gexec
在 psql 中使用:SELECT 'SELECT last_value - CASE WHEN is_called THEN 0 ELSE 1 END FROM ' || pg_get_serial_sequence('b2', 'big_id')\gexec
看:
對於自動(或正常)使用,您需要動態 SQL 以將函式返回的文本值用作 SQL 標識符。這是一個簡單的自定義函式來做到這一點。還考慮到
is_called
:CREATE OR REPLACE FUNCTION sequence_currval(_tbl text, _col text, OUT currval bigint) LANGUAGE plpgsql AS $func$ BEGIN EXECUTE 'SELECT last_value - CASE WHEN is_called THEN 0 ELSE 1 END FROM ' || pg_get_serial_sequence(_tbl, _col) INTO currval; END $func$;
稱呼:
SELECT sequence_currval('foo', 'id');
這對 SQLi 是安全的,因為
pg_get_serial_sequence()
根據需要返回安全雙引號的標識符。該函式返回從此序列中消耗的最後一個值。(並不意味著它進入了表格。)下一個會更大。(假設預設序列為
INCREMENT
1!)它不使用序列號,也不需要
nextval()
在同一會話中呼叫過的序列號。考慮這個展示:
db<>fiddle here