系統表顯示的都是當前操作數據庫下的信息,對象都來自當前數據庫。因為不同的系統表都用不同名的字段來記錄不同對象的oid,這個表引用那個表,那個表又引用另一個表,所以這些字段名不太好記。
pg_class (系統表:對象)是一個對象表,表的每個字段都是‘rel’開頭,分明就是 ‘relation’這個單詞的縮寫,意思就是‘關系’。表中relkind字段決定對象類型:r = 普通表,i = 索引,S = 序列,v = 視圖, c = 復合類型,s = 特殊,t = TOAST表。對象所屬的relnamespace(模式名稱)和relowner(所有者)都是用其對應的oid顯示,所以要直觀看到實際本名要聯合pg_namespace(系統表:模式)和pg_roles(系統視圖:角色)一起查,這兩個表和視圖中都有oid字段。
以查詢對象所屬模式及其名稱為例:
select relname,relkind,relnamespace,nspname from pg_class c,pg_namespace n where n.oid=16424 and c.relnamespace=n.oid relname | relkind | relnamespace | nspname -------------------+---------+--------------+--------- website_pkey | i | 16424 | yun website | r | 16424 | yun board_pkey | i | 16424 | yun board | r | 16424 | yun spam_keyword_pkey | i | 16424 | yun spam_keyword | r | 16424 | yun
oid數據類型,查詢有無單引號都可以。pg_namespace中的oid字段是隱含的,用select * from不能直接查詢。
select oid,* from pg_namespace
oid | nspname | nspowner | nspacl
-------+--------------------+----------+-------------------------------------
99 | pg_toast | 10 |
11194 | pg_temp_1 | 10 |
11195 | pg_toast_temp_1 | 10 |
11 | pg_catalog | 10 | {postgres=UC/postgres,=U/postgres}
11469 | information_schema | 10 | {postgres=UC/postgres,=U/postgres}
2200 | public | 10 | {postgres=UC/postgres,=UC/postgres}
16424 | yun | 16392 |
16551 | audit | 16392 |
PS:逗號其實是一種起到連結若干列與若干列作用的符號,是一個對查詢結果直接產生作用的符號,不是因為查多個字段所以用來分隔為了易讀好看的。
pg_namespace有模式的oid,pg_roles有用戶的oid。
pg_attribute,竟然有這么一張表用來記錄所有表的字段,神奇。
一直有兩點疑惑,一是怎么查看視圖的定義,二是怎么看一個函數(過程)的定義,也就是對象的實際實現語句,而不是其他屬性,視圖和函數都是不同模式下的對象,但是在查詢它們的時候都沒有受模式的影響。
先看視圖,以測試建的視圖‘test_view1’為例,psql提供了3個視圖相關的元命令,但是沒有顯示具體定義語句的,之后查詢了pg_views視圖才看到有,這還算是方便的。
yun=> \d test_view1 視觀表 "yun.test_view1" 欄位 | 型別 | 修飾詞 ------------+--------------------------------+-------- kid | smallint | word | character varying(255) | styles | integer[] | cids | integer[] | filter_pos | smallint | tm_update | timestamp(0) without time zone | yun=> \dp test_view1 存取權限 架構模式 | 名稱 | 型別 | 存取權限 | 列訪問權限 ----------+------------+--------+----------+------------ yun | test_view1 | 視觀表 | | (1 行記錄) yun=> \dv test_view1 關聯列表 架構模式 | 名稱 | 型別 | 擁有者 ----------+------------+--------+--------- yun | test_view1 | 視觀表 | chen (1 行記錄) yun=> select * from pg_views where viewname='test_view1' schemaname | viewname | viewowner | definition ------------+------------+-----------+---------------- yun | test_view1 | chen | SELECT 定義略 ; (1 行記錄)
再看函數,我直接查了pg_proc表,由於結果都只顯示一行而結果第一行都是換行符所以psql在prosrc只顯示了\r。另外psql給的2個函數相關的元命令也有用:\df 和 \sf 。
yun=> select prosrc from pg_proc where proname='thaha'
prosrc -------------------------------------------------------- \r + declare\r + t2_row record;\r + BEGIN\r + select into t2_row gid from board where fid=52163;\r + -- RAISE EXCEPTION 'employee % not found', ooo.name;\r+ return ooo||ooo.url||t2_row.gid;\r + END;\r + (1 行記錄)
cyyun=> \df thaha 函數列表 架構模式 | 名稱 | 結果資料型別 | 參數資料型別 | 型別 ----------+-------+--------------+--------------+------ cyyun | thaha | text | ooo website | 常規 (1 行記錄) cyyun=> \sf thaha CREATE OR REPLACE FUNCTION cyyun.thaha(ooo website) RETURNS text LANGUAGE plpgsql AS $function$ 略 return ooo||ooo.url||t2_row.gid; END; $function$
thaha是之前隨便寫的一個測試函數,這里\sf命令不能顯示實際執行的SQL,沒法直接看到是怎么進行結果的。
另話,新建視圖v2后,把v2的select分配給public,然后drop view v2,再新建同名的view v2,不分配權限,雖然之前分配過同名的v2權限,但是其他用戶是無法select新的v2的,說明權限的分配至少和viewname是沒有關系的,可能也是跟隨oid吧。
