OID 相关技巧

显示下一个 OID

场景:您想知道下一个将使用哪个 OID

解决方案:执行 SELECT next_oid FROM pg_control_checkpoint() 来显示下一个 OID 的近似值(截至最近一次 检查点

postgres=# SELECT next_oid FROM pg_control_checkpoint();
 next_oid
----------
    95549
(1 row)

对于 PostgreSQL 9.6 之前的版本,请使用 pg_controldata 来提取 NextOID 字段

postgres $ pg_controldata /path/to/pgdata | grep OID
Latest checkpoint's NextOID:          2254511
获取当前数据库的 OID

PostgreSQL 18 及更早版本中,没有 regdatabase 修饰符,唯一的方法是结合一个识别当前会话的查询和 系统目录 表,该表可以将该标识与特定数据库关联起来,例如:

SELECT oid FROM pg_database WHERE datname = current_database()

SELECT datid FROM pg_stat_activity WHERE pid = pg_backend_pid()

PostgreSQL 19 及更高版本中,可以像这样使用 regdatabase

postgres=# select current_database()::regdatabase;
 current_database 
------------------
 postgres
(1 row)
显示带有 OID 的表

场景:您有一个旧版数据库(PostgreSQL 11 或更早版本),并想检查哪些表(如果有的话)仍然启用了 OID。

解决方案:执行以下查询

testdb=> SELECT n.nspname, c.relname, c.relhasoids
           FROM pg_class c
           JOIN pg_namespace n ON (c.relnamespace=n.oid)
          WHERE n.nspname !~ '^pg_'
            AND c.relkind='r'
            AND c.relhasoids IS TRUE;
 nspname |         relname         | relhasoids
---------+-------------------------+------------
 appdb   | entry                   | t
 appdb   | form_session            | t
 appdb   | action                  | t
 appdb   | language                | t
 appdb   | markup_language_variant | t
(5 rows)
从所有仍带有 OID 的表中移除 OID

以下匿名代码块查找所有带有 OID 的表,并动态执行 ALTER TABLE ... SET WITHOUT OIDSPostgreSQL 11 及更早版本)

DO LANGUAGE plpgsql $$
DECLARE
  rec_table RECORD;
BEGIN
  FOR rec_table IN
    SELECT n.nspname, c.relname
      FROM pg_namespace n
INNER JOIN pg_class c
        ON n.oid=c.relnamespace
     WHERE n.nspname !~ '^pg_'
       AND c.relkind='r'
       AND c.relhasoids IS TRUE
  ORDER BY 1
   LOOP
     RAISE NOTICE 'Removing OIDs from table %.%', rec_table.nspname, rec_table.relname;
     EXECUTE FORMAT ('ALTER TABLE %I.%I SET WITHOUT OIDS', rec_table.nspname, rec_table.relname);
   END LOOP;
END
$$;