greenplum(postgresql)之數據字典

本文轉自:http://blog.csdn.net/scutshuxue/article/details/6371803

 greenplum是基於postgresql開發的分佈式數據庫,裏面大部分的數據字典是一樣的。我們在維護gp的時候對gp的數據字典比較熟悉,特此分享給大家。在這裏不會詳細介紹每個字典的內容,只會介紹常見的應用以及一些已經封裝好了的函數。具體的介紹大家可以去看postgresql的中文文檔(附件),裏面有詳細的解釋。

    1.postgresql中,所有數據庫的對象都是用oid連接在一起的。

        這樣子會造成我們在理解數據字典的時候有一些不知所云。下面介紹幾個函數,可以簡化很多的操作。

名字

引用

描述

regproc

pg_proc

函數名字

regprocedure

pg_proc

帶參數類型的函數

regoper

pg_operator

操作符名

regoperator

pg_operator

帶參數類型的操作符

regclass

pg_class

關係名

 

      最常用的是regclass,關聯數據字典的oid,使用方法如下:

 

  1. aligputf8=# select 1259::regclass;  
  2.  regclass   
  3. ----------  
  4.  pg_class  
  5. (1 row)  
  6. aligputf8=# select oid,relname from pg_class where oid='pg_class'::regclass;  
  7.  oid  | relname    
  8. ------+----------  
  9.  1259 | pg_class  
  10. (1 row)  


         這樣子就可以通過regclass尋找一個表的信息,就不用去關聯 pg_class跟pg_namespace(記錄schema信息)了。比較方便。

        同樣的,其他幾個類型也是一樣的用法,如regproc(regprocedure)是跟pg_proc(保存普通函數的命令)關聯的。regoper(regoperator)是跟pg_operator(操作符)的oid關聯的。

Eg:

  1. aligputf8=# select oid::regoper,oid::regoperator,oid,oprname from pg_operator limit 1;  
  2.      oid      |        oid        | oid | oprname   
  3. --------------+-------------------+-----+---------  
  4.  pg_catalog.= | =(integer,bigint) |  15 | =  
  5. (1 row)  
  6.   
  7. aligputf8=# select oid::regproc,oid::regprocedure,oid,proname from pg_proc limit 1;  
  8.   oid   |       oid       | oid  | proname   
  9. --------+-----------------+------+---------  
  10.  boolin | boolin(cstring) | 1242 | boolin  
  11. (1 row)  

        下面給給出如何使用regclass的例子。

 

  2.獲取表的字段信息。

         表名是放在pg_class,schema名是放在pg_namespace裏面的,字段信息是放在pg_attribute裏面的。一般是關聯這三張表:

         eg:        

  1. SELECT a.attname,pg_catalog.format_type(a.atttypid, a.atttypmod) AS data_type   
  2.  FROM    pg_catalog.pg_attribute a,  
  3.         (  
  4.          SELECT  c.oid   
  5.            FROM    pg_catalog.pg_class c    
  6.            LEFT JOIN pg_catalog.pg_namespace n      
  7.              ON n.oid = c.relnamespace    
  8.           WHERE c.relname = 'pg_class'  
  9.             AND n.nspname = 'pg_catalog'   
  10.          )b   
  11.  WHERE a.attrelid = b.oid   
  12.  AND a.attnum > 0   
  13.  AND NOT a.attisdropped ORDER BY a.attnum;  
  14.   
  15.   
  16.    

          如果使用regclass就會簡化很多:                                  

  1. SELECT a.attname,pg_catalog.format_type(a.atttypid, a.atttypmod) AS data_type   
  2.  FROM    pg_catalog.pg_attribute a  
  3. WHERE a.attrelid ='pg_catalog.pg_class'::regclass  
  4.  AND a.attnum > 0   
  5.  AND NOT a.attisdropped ORDER BY a.attnum;  

          其實regclass就是一個類型,oid或text到regclass有一個類型轉換,跟多表關聯不一樣,多數據字典表關聯的話,如果表不存在,會返回空記錄,不會報錯,而如果採用regclass則會報錯,所以在不確定表是否存在的情況下,慎用regclass。

 

3.獲取表的分佈鍵:

gp_distribution_policy記錄這表的數據字典,localoid跟pg_class的oid關聯。attrnums是一個數組,記錄字段的attnum,跟pg_attribute裏面的attnum關聯的。

 

  1. aligputf8=# create table cxfa2 ( a int ,b int ,c int ,d int ) distributed by (c,a);   
  2.   
  3.   
  4.   
  5. ligputf8=# select * from gp_distribution_policy where localoid='cxfa2'::regclass     ;  
  6. localoid | attrnums   
  7. ---------+----------  
  8.   334868 | {3,1}  
  9. 1 row)  
  10.   
  11.  select a.attrnums[i.i],b.attname,a.localoid::regclass   
  12.    from gp_distribution_policy a,  
  13.         (select generate_series(1,10))i(i),  
  14.         pg_attribute b   
  15.   where a.attrnums[i.i] is not null   
  16.     and a.localoid=b.attrelid   
  17.     and a.attrnums[i.i]=b.attnum   
  18.     and a.localoid='public.cxfa2'::regclass   
  19.       order by i.i;  


 

結果如下:

  1.  attrnums | attname | localoid   
  2. ----------+---------+----------  
  3.         3 | c       | cxfa2  
  4.         1 | a       | cxfa2  
  5. (2 rows)  


 

4.獲取一個視圖的定義。

  1. aligputf8=# \df pg_get_viewdef  
  2.                           List of functions  
  3.    Schema   |      Name      | Result data type | Argument data types   
  4. ------------+----------------+------------------+---------------------  
  5.  pg_catalog | pg_get_viewdef | text             | oid  
  6.  pg_catalog | pg_get_viewdef | text             | oid, boolean  
  7.  pg_catalog | pg_get_viewdef | text             | text  
  8.  pg_catalog | pg_get_viewdef | text             | text, boolean  
  9. (4 rows)  

使用這個系統函數可以獲取視圖的定義,可以傳入oid或者是表名,第二個參數表示是否格式化輸出,默認不格式化輸出。

  1. aligputf8=# create table cxfa( a int) distributed by (a);  
  2. CREATE TABLE  
  3. aligputf8=# create view v_cxfa as select * from cxfa;  
  4. CREATE VIEW  
  5. aligputf8=# select pg_get_viewdef('v_cxfa',true);  
  6.  pg_get_viewdef   
  7. ----------------  
  8.   SELECT cxfa.a  
  9.     FROM cxfa;  
  10. (1 row)  


 

其實這個函數是去獲取數據字典pg_rewrite(存儲爲表和視圖定義的重寫規則),將規則重新算出sql展現給我們。可以通過下面sql去查詢數據庫保存的重寫規則。

aligputf8=# select ev_action from pg_rewrite where ev_class='v_cxfa'::regclass;

                                                                                               ev_action                                                                                                                             

------------------------------------------------------------------------------------------------------------------------------------------------------------

 ({QUERY :commandType 1 :querySource 0 :canSetTag true :utilityStmt <> :resultRelation 0 :into <> :intoOptions <> :intoOnCommit 0 :intoTableSpaceName <> :hasAggs false :hasWindFuncs false :hasSubLinks false :rtable ({RTE :alias {ALIAS :aliasname *OLD* :colnames <>} :eref {ALIAS :aliasname *OLD* :colnames ("a")} :rtekind 0 :relid 334939 :inh false :inFromCl false :requiredPerms 0 :checkAsUser 0 :forceDistRandom false :pseudocols <>} {RTE :alias {ALIAS :aliasname *NEW* :colnames <>} :eref {ALIAS :aliasname *NEW* :colnames ("a")} :rtekind 0 :relid 334939 :inh false :inFromCl false :requiredPerms 0 :checkAsUser 0 :forceDistRandom false :pseudocols <>} {RTE :alias <> :eref {ALIAS :aliasname cxfa :colnames ("a")} :rtekind 0 :relid 334930 :inh true :inFromCl true :requiredPerms 2 :checkAsUser 0 :forceDistRandom false :pseudocols <>}) :jointree {FROMEXPR :fromlist ({RANGETBLREF :rtindex 3}) :quals <>} :targetList ({TARGETENTRY :expr {VAR :varno 3 :varattno 1 :vartype 23 :vartypmod -1 :varlevelsup 0 :varnoold 3 :varoattno 1} :resno 1 :resname a :ressortgroupref 0 :resorigtbl 334930 :resorigcol 1 :resjunk false}) :returningList <> :groupClause <> :havingQual <> :windowClause <> :distinctClause <> :sortClause <> :limitOffset <> :limitCount <> :rowMarks <> :setOperations <> :resultRelations <> :result_partitions <> :result_aosegnos <> :returningLists <> :intoOidInfo.relOid 0 :intoOidInfo.comptypeOid 0 :intoOidInfo.toastOid 0 :intoOidInfo.toastIndexOid 0 :intoOidInfo.toastComptypeOid 0 :intoOidInfo.aosegOid 0 :intoOidInfo.aosegIndexOid 0 :intoOidInfo.aosegComptypeOid 0})

(1 row)

 

與pg_get_viewdef類似的函數還有如下,其原理都是差不多的,將數據字典的重寫規則翻譯爲sql:

  1. aligputf8=# \df pg_get_*def  
  2.                                  List of functions  
  3.    Schema   |           Name            | Result data type |  Argument data types   
  4. ------------+---------------------------+------------------+-----------------------  
  5.  pg_catalog | pg_get_constraintdef      | text             | oid  
  6.  pg_catalog | pg_get_constraintdef      | text             | oid, boolean  
  7.  pg_catalog | pg_get_indexdef           | text             | oid  
  8.  pg_catalog | pg_get_indexdef           | text             | oid, integer, boolean  
  9.  pg_catalog | pg_get_partition_def      | text             | oid  
  10.  pg_catalog | pg_get_partition_def      | text             | oid, boolean  
  11.  pg_catalog | pg_get_partition_rule_def | text             | oid  
  12.  pg_catalog | pg_get_partition_rule_def | text             | oid, boolean  
  13.  pg_catalog | pg_get_ruledef            | text             | oid  
  14.  pg_catalog | pg_get_ruledef            | text             | oid, boolean  
  15.  pg_catalog | pg_get_triggerdef         | text             | oid  

注:觸發器在greenplum裏面是不支持的。 

5.分區表相關操作

\d一個表是看不出一個表是否是分區表的,所以必須查詢數據字典才能知道。查分區表可以通過pg_partitions跟pg_partition_columns這兩個視圖來查詢,但是這兩個視圖的結構非常複雜,在線上gp上數據字典都非常大,沒有充分利用到索引,這個查詢起來效率太低了。我們直接通過數據字典的實體表來查詢的話,會快很多。

首先創建一個分區表:

  1. create table public.cxfa3(  
  2.       id               integer                  
  3.      ,name             character varying(20)    
  4.      ,birth            date                     
  5. )Distributed by (id)  
  6. PARTITION BY range(birth)  
  7. (  
  8.     PARTITION p19860801 START ('1986-08-01'::dateEND ('1986-08-02'::date) EVERY ('1 day'::interval),  
  9.     PARTITION p19860802 START ('1986-08-02'::dateEND ('1986-08-03'::date) EVERY ('1 day'::interval)  
  10. );  

 

    5.1 查詢一個表是否是分區表

表pg_partition:每一個分區表的父表有一行記錄。

parkind:    表示分區類型(range 或者 list)。

parnatts:  分區建個數。

paratts:       分區鍵,跟pg_attribute關聯,是一個列表。

 表pg_partition_rule:保存分區表每一個子分區的分區名以及分區規則等。

  1. aligputf8=# select count(*) from pg_partition where parrelid='public.cxfa3'::regclass;  
  2.  count   
  3. -------  
  4.      1  
  5. (1 row)  

只要count的結果是=1的,表示該表是分區表,否則該表不是分區表。每個分區表在裏面只有一行記錄。

     5.2 查詢一個表的分區鍵

  1. aligputf8=# select attname as columnname   
  2. aligputf8-#   from pg_attribute a,pg_partition b   
  3. aligputf8-#  where a.attnum = b.paratts[0]   
  4. aligputf8-#    and b.parrelid = a.attrelid   
  5. aligputf8-#    and a.attrelid='public.cxfa3'::regclass;  
  6.  columnname   
  7. ------------  
  8.  birth  
  9. (1 row)  

由於現在gp上面的分區鍵都是一個的,所以爲了效率,我們也只是獲取第一個分區鍵

      5.3 查詢分區表每個分區的具體信息

  1. aligputf8=# SELECT pp.parrelid::regclass,pr1.parchildrelid::regclass,pr1.parname,  
  2. aligputf8-#          CASE  
  3. aligputf8-#              WHEN pp.parkind = 'h'::"char" THEN 'hash'::text  
  4. aligputf8-#              WHEN pp.parkind = 'r'::"char" THEN 'range'::text  
  5. aligputf8-#              WHEN pp.parkind = 'l'::"char" THEN 'list'::text  
  6. aligputf8-#              ELSE NULL::text  
  7. aligputf8-#          END AS partitiontype,  
  8. aligputf8-#          pg_get_partition_rule_def(pr1.oid, trueAS partitionboundary  
  9. aligputf8-# FROM  pg_partition pp, pg_partition_rule pr1    
  10. aligputf8-# WHERE pp.paristemplate = false AND pp.parrelid = 'cxfa3'::regclass AND pr1.paroid = pp.oid  
  11. aligputf8-# order by pr1.parname;  
  12.         parrelid |     parchildrelid     |  parname  | partitiontype |                                         partitionboundary                                          
  13. ----------+-----------------------+-----------+---------------+---------------------------------------------------------------------------------------------------  
  14.  cxfa3    | cxfa3_1_prt_p19860801 | p19860801 | range         | PARTITION p19860801 START ('1986-08-01'::dateEND ('1986-08-02'::date) EVERY ('1 day'::interval)  
  15.  cxfa3    | cxfa3_1_prt_p19860802 | p19860802 | range         | PARTITION p19860802 START ('1986-08-02'::dateEND ('1986-08-03'::date) EVERY ('1 day'::interval)  
  16. (2 rows)  

6.查詢comment(備註信息)

comment信息是放在表pg_description中的。

名字

類型

引用

描述

objoid

oid

任意 oid 屬性

這條描述所描述的對象的 OID

classoid

oid

pg_class.oid

這個對象出現的系統表的 OID

objsubid

int4

 

對於一個表字段的註釋,它是字段號(objoid 和 classoid 指向表自身)。對於其它對象類型,它是零。

description

text

 

作爲對該對象的描述的任意文本

 

     查詢在表上的comment信息:

  1. aligputf8=# select  COALESCE(description,''as comment from pg_description where objoid='cxfa'::regclass and objsubid=0;  
  2.                comment                  
  3. --------------------------------------  
  4.  a table created by scutshuxue.chenxf  
  5. (1 row)  

    查詢表中字段的comment信息:

  1. aligputf8=# select b.attname as columnname, COALESCE(a.description,'')  as comment  
  2. aligputf8-#   from pg_catalog.pg_description a,pg_catalog.pg_attribute b   
  3. aligputf8-#  where objoid='cxfa'::regclass   
  4. aligputf8-#    and a.objoid=b.attrelid   
  5. aligputf8-#    and a.objsubid=b.attnum;  
  6.  columnname |        comment           
  7. ------------+------------------------  
  8.  a          | column a of table cxfa  
  9. (1 row)  

7.查詢權限信息

對於表、視圖來說,在pg_class裏面有一個字段relacl,保存了權限信息,如下:

  1. aligputf8=# select relacl from pg_class where relname='cxfa3';  
  2.                          relacl                           
  3. --------------------------------------------------------  
  4.  {gpadmin1=arwdxt/gpadmin1,role_aquery=arwdxt/gpadmin1}  
  5. (1 row)  

具體解釋如下:

              =xxxx -- 賦予 PUBLIC 的權限
         uname=xxxx -- 賦予一個用戶的權限
   group gname=xxxx -- 賦予一個組的權限

r -- SELECT ("讀")
                  w -- UPDATE ("寫")
                  a -- INSERT ("追加")
                  d -- DELETE
                  x -- REFERENCES
                  t -- TRIGGER
                  X -- EXECUTE
                  U -- USAGE
                  C -- CREATE
                  c -- CONNECT
                  T -- TEMPORARY
             arwdxt -- ALL PRIVILEGES (用於表)
                  * -- 給前面權限的授權選項

/yyyy -- 授出這個權限的用戶

對於函數,在pg_proc裏面也有一個對應的字段proacl。對於schema,pg_namespace裏面也有對應的字段nspacl。

但是查這些字段有點不是很方便,在數據庫裏面有很多函數可以方便一些查詢。如下:

  1. aligputf8=# \df *privilege*  
  2.                                List of functions  
  3.    Schema   |           Name           | Result data type | Argument data types  
  4. ------------+--------------------------+------------------+---------------------  
  5.  pg_catalog | has_database_privilege   | boolean          | name, oid, text  
  6.  pg_catalog | has_database_privilege   | boolean          | name, text, text  
  7.  pg_catalog | has_database_privilege   | boolean          | oid, oid, text  
  8.  pg_catalog | has_database_privilege   | boolean          | oid, text  
  9.  pg_catalog | has_database_privilege   | boolean          | oid, text, text  
  10.  pg_catalog | has_database_privilege   | boolean          | text, text  
  11.  pg_catalog | has_function_privilege   | boolean          | name, oid, text  
  12.  pg_catalog | has_function_privilege   | boolean          | name, text, text  
  13.  pg_catalog | has_function_privilege   | boolean          | oid, oid, text  
  14.  pg_catalog | has_function_privilege   | boolean          | oid, text  
  15.  pg_catalog | has_function_privilege   | boolean          | oid, text, text  
  16.  pg_catalog | has_function_privilege   | boolean          | text, text  
  17.  pg_catalog | has_language_privilege   | boolean          | name, oid, text  
  18.  pg_catalog | has_language_privilege   | boolean          | name, text, text  
  19.  pg_catalog | has_language_privilege   | boolean          | oid, oid, text  
  20.  pg_catalog | has_language_privilege   | boolean          | oid, text  
  21.  pg_catalog | has_language_privilege   | boolean          | oid, text, text  
  22.  pg_catalog | has_language_privilege   | boolean          | text, text  
  23.  pg_catalog | has_schema_privilege     | boolean          | name, oid, text  
  24.  pg_catalog | has_schema_privilege     | boolean          | name, text, text  
  25.  pg_catalog | has_schema_privilege     | boolean          | oid, oid, text  
  26.  pg_catalog | has_schema_privilege     | boolean          | oid, text  
  27.  pg_catalog | has_schema_privilege     | boolean          | oid, text, text  
  28.  pg_catalog | has_schema_privilege     | boolean          | text, text  
  29.  pg_catalog | has_table_privilege      | boolean          | name, oid, text  
  30.  pg_catalog | has_table_privilege      | boolean          | name, text, text  
  31.  pg_catalog | has_table_privilege      | boolean          | oid, oid, text  
  32.  pg_catalog | has_table_privilege      | boolean          | oid, text  
  33.  pg_catalog | has_table_privilege      | boolean          | oid, text, text  
  34.  pg_catalog | has_table_privilege      | boolean          | text, text  
  35.  pg_catalog | has_tablespace_privilege | boolean          | name, oid, text  
  36.  pg_catalog | has_tablespace_privilege | boolean          | name, text, text  
  37.  pg_catalog | has_tablespace_privilege | boolean          | oid, oid, text  
  38.  pg_catalog | has_tablespace_privilege | boolean          | oid, text  
  39.  pg_catalog | has_tablespace_privilege | boolean          | oid, text, text  
  40.  pg_catalog | has_tablespace_privilege | boolean          | text, text  
  41. (36 rows)  

示例:

查詢role_aquery用戶是否有訪問public.cxfa3這個表的select權限。如果結果爲't'則表示有這個權限,如果爲'f'則沒有權限。

  1. aligputf8=# select has_table_privilege('role_aquery','public.cxfa3','select');  
  2.  has_table_privilege   
  3. ---------------------  
  4.  t  
  5. (1 row)  
  6. aligputf8=# select has_table_privilege('role_dhw','public.cxfa3','select');  
  7.  has_table_privilege   
  8. ---------------------  
  9.  f  
  10. (1 row)  

8.查詢表的依賴關係

          我們在drop一個表的時候,經常被提醒上面有視圖,不能drop。例如:

  1. aligputf8=# drop table cxfa;  
  2. NOTICE:  rule _RETURN on view v_cxfa depends on table cxfa  
  3. NOTICE:  view v_cxfa depends on rule _RETURN on view v_cxfa  
  4. ERROR:  cannot drop table cxfa because other objects depend on it  
  5. HINT:  Use DROP ... CASCADE to drop the dependent objects too.  

         那麼數據庫裏面是怎麼保存這些依賴關係的呢?答案就在pg_depend數據字典。下面就以視圖

                  create  view v_cxfa as select * from cxfa;

         爲例,介紹依賴關係是如何工作的。

         pg_depend的官方文檔:http://www.pgsqldb.org/pgsqldoc-8.1c/catalog-pg-depend.html#AEN56970

  1. aligputf8=# select * from pg_depend where refobjid='cxfa'::regclass;  
  2.  classid | objid  | objsubid | refclassid | refobjid | refobjsubid | deptype   
  3. ---------+--------+----------+------------+----------+-------------+---------  
  4.     1247 | 334931 |        0 |       1259 |   334930 |           0 | i  
  5.     2618 | 334941 |        0 |       1259 |   334930 |           1 | n  
  6. (2 rows)  
  7.    
  8. aligputf8=# select relname from pg_class where oid in (1247,2618);  
  9.   relname     
  10. ------------  
  11.  pg_type  
  12.  pg_rewrite  
  13. (2 rows)  
  14.    
  15. aligputf8=# select typname from pg_type where oid=334931;  
  16.  typname   
  17. ---------  
  18.  cxfa  
  19. (1 row)  
  20.    
  21. aligputf8=# select rulename,ev_class::regclass,ev_class from pg_rewrite where oid=334941;  
  22.  rulename | ev_class | ev_class   
  23. ----------+----------+----------  
  24.  _RETURN  | v_cxfa   |   334939  
  25. (1 row)  

上面說明了複合類型(每創建一個表,都會在pg_type裏面創建一個複合類型,drop表的時候會默認drop掉的)cxfa是依賴於表cxfa的,還有pg_rewrite這個表裏面oid=334941的記錄是依賴於表cxfa的,這個記錄是表示視圖v_cxfa的重寫規則的,所以我們可以通過這個找到依賴於表cxfa的視圖。

我們可以下面的sql來查詢依賴於表上面的視圖,過濾掉複合類型及其他函數等。

由於pg_depend是沒有記錄數據字典的依賴關係的,所以我們如果要查詢數據字典上面的視圖,我們可以這麼做:

  1. aligputf8=# select ev_class::regclass from pg_rewrite where oid in (  
  2. aligputf8(#    select b.objid   
  3. aligputf8(#      from pg_depend a,pg_depend b   
  4. aligputf8(#     where a.refclassid=1259         
  5. aligputf8(#       and b.deptype='i'   
  6. aligputf8(#       and a.classid=2618  
  7. aligputf8(#       and a.objid=b.objid   
  8. aligputf8(#       and a.classid=b.classid   
  9. aligputf8(#       and a.refclassid=b.refclassid   
  10. aligputf8(#       and a.refobjid<>b.refobjid  
  11. aligputf8(#       and a.refobjid='cxfa'::regclass   
  12. aligputf8(#    );  
  13.  ev_class   
  14. ----------  
  15.  v_cxfa  
  16. (1 row)  


 

查出pg_attribute的oid:

  1. aligputf8=# select oid from pg_class where relname='pg_attribute';  
  2.  oid    
  3. ------  
  4.  1249  
  5. (1 row)  

加入一個視圖,驗證能否找到新加入的表:

aligputf8=# create view v_cxf_attribute as select * from pg_attribute;

CREATE VIEW

 

然後用下面的sql查找出視圖:

  1. aligputf8=# SELECT ev_class::regclass FROM pg_catalog.pg_rewrite WHERE ev_action like '%relid 1249%';  
  2.                   ev_class                    
  3. --------------------------------------------  
  4.  pg_stats  
  5.  pg_partition_columns  
  6.  information_schema.attributes  
  7.  information_schema.check_constraints  
  8.  information_schema.column_domain_usage  
  9.  information_schema.column_privileges  
  10.  information_schema.column_udt_usage  
  11.  information_schema.columns  
  12.  information_schema.constraint_column_usage  
  13.  information_schema.key_column_usage  
  14.  information_schema.role_column_grants  
  15.  information_schema.table_constraints  
  16.  information_schema.view_column_usage  
  17.  information_schema.element_types  
  18.  v_cxf_attribute  
  19. (15 rows)  

9.類型轉換

        在gp中,我們經常使用 cast函數,或者是::type進行類型轉換,究竟哪兩種類型之間是可以轉換的,哪兩種類型之間不能轉換,轉換的規則是什麼。其實這些都在pg_cast裏面中定義了。

 

名字

類型

引用

描述

castsource

oid

pg_type.oid

源數據類型的 OID

casttarget

oid

pg_type.oid

目標數據類型的 OID

castfunc

oid

pg_proc.oid

用於執行這個轉換的函數的 OID 。如果該數據類型是二進制兼容的,那麼爲零(也就是說,不需要運行時的操作來執行轉換)。

castcontext

char

 

標識這個轉換可以在什麼環境裏調用。e 表示只能進行明確的轉換(使用 CAST 或 :: 語法)。a 表示在賦值給目標字段的時候隱含調用,也可以明確調用。i 表示在表達式中隱含,當然也包括其它情況。

 

        我們想知道,text類型到date類型的轉換是用了那個函數可以這麼查:

  1. aligputf8=# select castfunc::regprocedure from pg_cast where castsource='text'::regtype and casttarget='date'::regtype;  
  2.   castfunc    
  3. ------------  
  4.  date(text)  
  5. (1 row)  
  6.   
  7. aligputf8=# select '20110302'::date;  
  8.     date      
  9. ------------  
  10.  2011-03-02  
  11. (1 row)  
  12.   
  13. aligputf8=# select date('20110302');  
  14.     date      
  15. ------------  
  16.  2011-03-02  
  17. (1 row)  

可以看出,cast('20110302' as date)跟'20110302'::date其實都是調用了date('20110302')函數進行類型轉換了。

我們是否可以自定義類型轉換呢?答案是肯定的。

比方說,上面的regclass類型是沒有到text類型的轉換的:

  1. aligputf8=# select 1259::regclass::text;  
  2. ERROR:  cannot cast type regclass to text  
  3. LINE 1: select 1259::regclass::text;  

           我們先創建一個類型轉換函數:

  1. CREATE or replace FUNCTION regclass2text(a regclass)  
  2.   RETURNS text  
  3. AS $    
  4.   return a;  
  5. $ LANGUAGE plpythonu;  

          然後定義一個cast類型轉換規則。

  1. aligputf8=# create cast(regclass as text) with function regclass2text(a regclass);  
  2. CREATE CAST  

         這樣子我們就定義好了一個類型轉換,驗證:

  1. aligputf8=# select 1259::regclass::text;  
  2.    text     
  3. ----------  
  4.  pg_class  
  5. (1 row)  
  6.   
  7. aligputf8=# select cast(1259::regclass as text);  
  8.    text     
  9. ----------  
  10.  pg_class  
  11. (1 row)  

發佈了35 篇原創文章 · 獲贊 4 · 訪問量 30萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章