Postgresql

錯誤:序列“rss_sub_source_id_seq”的currval 尚未在此會話中定義

  • May 24, 2021

當我使用此查詢查看 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 中,serialIDENTITY使用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()根據需要返回安全雙引號的標識符。

該函式返回從此序列中消耗的最後一個值。(並不意味著它進入了表格。)下一個會更大。(假設預設序列為INCREMENT1!)

它不使用序列號,也不需要nextval()在同一會話中呼叫過的序列號。

考慮這個展示:

db<>fiddle here

引用自:https://dba.stackexchange.com/questions/292058