PostgreSQL:使用 oracle_fdw 需要注意的二三事
RojerChen.2019.09.23
近期手邊的系統要從 Oracle 轉換到 PostgreSQL,由於當初的資料庫有使用 dblink 連到其他台 Oracle,所以也想說那 PostgreSQL 也設定 dblink 好了,只是沒想到安裝繁瑣之外、設定也很麻煩。
PostgreSQL 如果要連到 Oracle 可以透過建立 oracle_fdw 來連線到 Oracle。
由於我的系統是跑在 Linux 上,我覺得整體的安裝與設定非常麻煩,我好幾次想說那乾脆不要設定 dblink 好了,直接讓程式可以跑兩個資料庫連線,分別連 Oracle 與 PostgreSQL ,這樣做當然可以,只是我們是使用 .NET Core 來開發,而這會遇到幾個問題:
- Oracle 版本太舊了 9.2
- nuget 上的 Oracle Data Provider for .NET (ODP.NET) 看來是沒辦法支援 Oracle 9.2,最低能夠支援的應該是 10.2 以上的版本
- Oracle 官網可以找的東西我都沒辦法連到現有的 Oracle 9.2
- 找不到很多年前用的 Oracle 光碟片,即使找到了,而且相關的檔案在 Windows 上用沒問題,但是可以用在 Linux 上嗎?
由於無法確定能否在 Linux 上執行,最後還是選擇了 oracle_fdw,在使用上我覺得有幾件事情是應該要留意的:
資料庫使用哪種編碼
在使用之前需要先留意的是 Oracle 與 PostgreSQL 使用哪種編碼?兩邊的資料庫盡可能使用一致的編碼。
- PostgreSQL 是不支援 BIG5的,
- PostgreSQL 使用 SQL_ASCII 編碼,預設是不會做編碼的轉換,查出來的資料可能顯示為亂碼或沒資料。
以下是 PostgreSQL 對於各種不同編碼格式的支援狀況,
https://www.postgresql.org/docs/11/multibyte.html
Name | Description | Language | Server? | ICU? | Bytes/Char | Aliases |
---|---|---|---|---|---|---|
BIG5 | Big Five | Traditional Chinese | No | No | 1-2 | WIN950 , Windows950 |
EUC_CN | Extended UNIX Code-CN | Simplified Chinese | Yes | Yes | 1-3 | |
EUC_JP | Extended UNIX Code-JP | Japanese | Yes | Yes | 1-3 | |
EUC_JIS_2004 | Extended UNIX Code-JP, JIS X 0213 | Japanese | Yes | No | 1-3 | |
EUC_KR | Extended UNIX Code-KR | Korean | Yes | Yes | 1-3 | |
EUC_TW | Extended UNIX Code-TW | Traditional Chinese, Taiwanese | Yes | Yes | 1-3 | |
GB18030 | National Standard | Chinese | No | No | 1-4 |
我自己的狀況
- Oracle 編碼為 ZHT16MSWIN950
- PostgreSQL 編碼為 UTF8
在建立 oracle_fdw 的時候我一開始有指定 BIG5 編碼,只是這樣設定後會導致有部分資料查詢上會出現以下的錯誤,原本我想說是 Oracle 資料上的問題,讓我一度放棄使用 oracle_fdw,直到後來兩條 DB 連線沒辦法用又回過頭來測試,結果發現到我根本不需要設定 BIG5編碼就可以了。
invalid byte sequence for encoding "UTF8": 0x00
Oracle 空字串的處理
在 Oracle 的世界裡 NULL 是 NULL、空字串是 NULL,但是 PostgreSQL 並不接受空字串是 NULL
當你 foreign table 建立好之後,在查詢的時候,如果有遇到這樣的問題,那有可能就是 Oracle 字串的問題
invalid byte sequence for encoding "UTF8": 0x00
作者是這樣說的
關於字串的處理在 Oracle 18 已經改了,如果使用的舊版的那你可能就會遇到上面的問題。
https://docs.oracle.com/en/database/oracle/oracle-database/18/sqlrf/Nulls.html#GUID-29B6554B-C948-4A8E-81C1-696A5128AAAD
Oracle Database treats a character value with a length of zero as null. However, do not use null to represent a numeric value of zero, because they are not equivalent.
Note:
Oracle Database currently treats a character value with a length of zero as null. However, this may not continue to be true in future releases, and Oracle recommends that you do not treat empty strings the same as nulls.
關於這種情況,你應該做的是回去改 Oracle 的資料,只是你有權限嗎?
有無異動 Oracle Table 資料的權限
如果你有權限修改,可以來參考以下連結,看看別人是怎樣處理的,或許會有一些幫助。
https://github.com/laurenz/oracle_fdw/issues/114
而我自己是沒有權限,所以連想都不用想。
建立 foreign table 的時候要全欄位對應
Oracle 的 table 有 30 個欄位,建立 foreign table 的時候就要設定 30 個欄位,欄位的型態與順序與 Oracle 一致。
不一致也沒關係,只是會造成我在查 PostgreSQL B 的時候,結果查出來的結果是 Oracle C 而已。
Oracle A <--> PostgreSQL A
Oracle B <--> PostgreSQL C
Oracle C <--> PostgreSQL B
※後記
原本因為編碼的問題搞不定,想要放棄 oracle_fdw,改使用 java 或是其他旁門左道來讀取 Oracle 的資料,沒想到後來還是終於給試出來了,如果這次寫的是 java,或許讀取 Oracle 就沒有這麼多問題了吧?
0 意見:
張貼留言