与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的表

场景:您有一个遗留数据库,并希望检查哪些表(如果有)仍然启用了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 OIDS

DO LANGUAGE plpgsql $$
DECLARE
  rec_table RECORD;
BEGIN
  FOR rec_table IN
    SELECT 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.relname;
     EXECUTE FORMAT ('ALTER TABLE %I SET WITHOUT OIDS', rec_table.relname);
   END LOOP;
END
$$;
获取当前数据库的OID

由于没有 regdatabase 修饰符,因此执行此操作的唯一方法是将识别当前会话的查询与可以将该识别与特定数据库相关联的系统目录表结合起来,例如

SELECT oid FROM pg_database WHERE datname = current_database()

SELECT datid FROM pg_stat_activity WHERE pid = pg_backend_pid()