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
NameDescriptionLanguageServer?ICU?Bytes/CharAliases
BIG5Big FiveTraditional ChineseNoNo1-2WIN950Windows950
EUC_CNExtended UNIX Code-CNSimplified ChineseYesYes1-3
EUC_JPExtended UNIX Code-JPJapaneseYesYes1-3
EUC_JIS_2004Extended UNIX Code-JP, JIS X 0213JapaneseYesNo1-3
EUC_KRExtended UNIX Code-KRKoreanYesYes1-3
EUC_TWExtended UNIX Code-TWTraditional Chinese, TaiwaneseYesYes1-3
GB18030National StandardChineseNoNo1-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 就沒有這麼多問題了吧?

    Blogger Comment

0 意見: