PostgreSQL報跨庫異常及解決一例

今天羣裏一個哥們發了個錯誤信息:
ERROR:  cross-database references are not implemented: "public.test.id"

********** 錯誤 **********

ERROR: cross-database references are not implemented: "public.test.id"
SQL 狀態: 0A000
看到貼出的SQL語句時就發現他的錯誤了
comment on table public.test is '測試表';
comment on table public.test.id is '測試ID';
..
給字段加備註的時候應該是column,而不是table。修改完備註SQL就不會報錯。
報這種錯誤,得須要提醒一下,postgresql的體系結構認爲不一樣的數據庫是獨立的,因此並不支持跨庫查詢。並且執行一個查詢時,postgresql首先會檢查自身的dbname(通常鏈接的當前DB名,可不寫),而後是schema(由於一個DB裏可包含多個schema,默認鏈接是public),再最後纔是數據庫對象(table,view,function...)。
因此當出現cross-database錯誤時咱們就能夠認爲postgres認爲用戶作了一次非規範的跨庫操做了。

回過頭來想想,什麼狀況下會報這種錯誤呢,我整理了一下,有如下這麼幾種狀況:

測試環境:
postgresql 9.1.2
postgres=# \l
                                資料庫列表
   名稱    |  擁有者  | 字元編碼 | Collate | Ctype |       存取權限
-----------+----------+----------+---------+-------+-----------------------
 d_kenyon  | postgres | UTF8     | C       | C     |
 postgres  | postgres | UTF8     | C       | C     |
 template0 | postgres | UTF8     | C       | C     | =c/postgres          +
           |          |          |         |       | postgres=CTc/postgres
 template1 | postgres | UTF8     | C       | C     | =c/postgres          +
           |          |          |         |       | postgres=CTc/postgres
(4 行記錄)

postgres=# \d
                   關聯列表
 架構模式 |      名稱      |  型別  |  擁有者
----------+----------------+--------+----------
 public   | pgweb          | 資料表 | postgres
 public   | t_kenyon       | 資料表 | postgres
 public   | tbl_order_item | 資料表 | postgres
 public   | tbl_orders     | 資料表 | postgres
 public   | tbl_product    | 資料表 | postgres
(5 行記錄)

postgres=# select current_user;
 current_user
--------------
 postgres
(1 行記錄)

postgres=# \c d_kenyon
You are now connected to database "d_kenyon" as user "postgres".
d_kenyon=# \d
               關聯列表
 架構模式 | 名稱  |  型別  |  擁有者
----------+-------+--------+----------
 public   | test  | 資料表 | postgres
 public   | test2 | 資料表 | postgres
(2 行記錄)
1.真正地作了一次跨庫查詢
d_kenyon=# select *from postgres.public.t_kenyon limit 1;
ERROR:  cross-database references are not implemented: "postgres.public.t_kenyon
"
第1行select *from postgres.public.t_kenyon limit 1;
                  ^
d_kenyon=#
2.沒有作跨庫查詢,可是pg誤認爲你作了一次跨庫操做
postgres=# \d
                   關聯列表
 架構模式 |      名稱      |  型別  |  擁有者
----------+----------------+--------+----------
 public   | pgweb          | 資料表 | postgres
 public   | t_kenyon       | 資料表 | postgres
 public   | tbl_order_item | 資料表 | postgres
 public   | tbl_orders     | 資料表 | postgres
 public   | tbl_product    | 資料表 | postgres
(5 行記錄)

postgres=# \d t_kenyon
 資料表 "public.t_kenyon"
  欄位  |  型別   | 修飾詞
--------+---------+--------
 id     | integer |
 t_name | text    |

postgres=# select * from public.t_kenyon limit 1;
 id | t_name
----+--------
  1 | kenyon
(1 行記錄)

postgres=# select * from public.t_kenyon.id limit 1;
ERROR:  cross-database references are not implemented: "public.t_kenyon.id"
第1行select * from public.t_kenyon.id limit 1;

postgres=# select * from public.t_kenyon.22 limit 1;
ERROR:  syntax error at or near ".22"
第1行select * from public.t_kenyon.22 limit 1;
                                  ^
postgres=# select * from public.t_kenyon.x22 limit 1;
ERROR:  cross-database references are not implemented: "public.t_kenyon.x22"
第1行select * from public.t_kenyon.x22 limit 1;
第二種場景裏面還有多種方式會觸發,好比最開始提到的comment,insert...select...也有可能,第二種場景裏有一個頗有意思的發現,當最後一個實心點後面跟的是數字時並不報跨庫錯誤,而是語法錯誤。

擴展: 1.schema是 postgresql裏一個相對特別的數據庫對象,能夠簡單將理解成是一個容器,相似oracle的一個namespace,可是更靈活,可對schema授相應的用戶權限來控制; 2.除此以外,能夠將DB中的數據按相應的功能作水平切分,存放到不一樣的schema裏面; 3.不一樣的用戶能夠設置不一樣的默認schema,可參考search_path這個變量; 4.目前版本JDBC鏈接postgresql時須要先鏈接上來,而後執行set search_path to xxx,否則可能取不到特定schema下的數據。
相關文章
相關標籤/搜索