1. 程式人生 > >oracle遷移到pg問題整理

oracle遷移到pg問題整理

這個帖子轉自http://bbs.pgsqldb.com,把兩個帖子合在一起了

很多內容是網上查的資料,我只是整理下,有遺漏的地方,歡迎補充
首先用工具(Ora2pg)自動轉換
由於這個專案後臺程式量很大,儲存過程+觸發器大約有15萬行程式碼。
用這個工具可以將一些oracle與pgsql的語法差異自動處理下,但不是全部,剩下的需要手工修改。

ORACLE語法 → PostgreSQL語法
1、VARCHAR2 → varchar
2、DATE → timestamp
3、SYSDATE → localtimestamp
4、Oracle中''和NULL是相同的,但pgsql是不同的,所以需要將''修改成NULL
5、字串連線符 ||
Oracle: 'a'||null 結果是'a'
pgsql: 'a'||null 結果是null
所以用concat()函式替代
6、trunc(時間) → date_trunc()
7、to_char, to_number, to_date pgsql都需要指定格式
8、DECODE → case
9、NVL → coalesce()
10、外連線(+) → left(right) join
11、GOTO語句 → pgsql不支援
12、pgsql不支援procedure和package,都需要改寫成function
當package有全域性變數的情況修改起來比較麻煩,我們是用臨時表傳遞的。
14、COMMIT,ROLLBACK;SAVEPOINT → pgsql不支援
15、Oracle的系統包,例如 DBMS_OUTPUT,DBMS_SQL,UTIL_FILE,UTIL_MAIL → pgsql不支援
16、異常處理方法不同
17、trigger的語法不同
18、日期的加減計算語法不同。

13、cursor的屬性
%FOUND → found
%NOTFOUND → not found
%ISOPEN → pgsql不支援
%ROWCOUNT → pgsql不支援
另外關於cursor還發現了其他差異,見下面:


13.1、pgsql中cursor名是全域性的

例如函式A和函式B有一個相同名字的cursor,當A開啟這個cursor,然後呼叫B,當B再開啟同名的cursor時,會丟擲異常。
這個問題在oracle中不會出現。
解決辦法:用隱式宣告定義cursor,或者保證所有的程式中cursor名唯一。

13.2、pgsql中使用for update 的cursor,loop迴圈次數很可能被改變

例如這樣一段程式碼

for rec in (select * from employee for update) loop
update employee set dep_no = 'test';
end loop;

按通常的理解,如果employee中有100條記錄,這個迴圈就會執行100次,
但pgsql只會執行1次,因為一個update語句會把所有的記錄都更新了,好像與鎖有關,
如果把 for update 去掉,就會執行100次。

這個和cursor的宣告及使用方式有關,見下面實踐:
測試了加上 " for update " 和不加的情況,測試的結果都是要更新遊標結果集的次數,

實驗如下:


--1 建立表和初始資料
skytf=> create table employee(id serial,emp_name varchar(32),dep_no int4);
NOTICE: CREATE TABLE will create implicit sequence "employee_id_seq" for serial column "employee.id"
CREATE TABLE

skytf=> insert into employee (emp_name,dep_no) select generate_series(1,3)||'a',1;
INSERT 0 3

skytf=> insert into employee (emp_name,dep_no) select generate_series(4,10)||'b',2;
INSERT 0 7

skytf=> select * From employee;
id | emp_name | dep_no
----+----------+--------
1 | 1a | 1
2 | 2a | 1
3 | 3a | 1
4 | 4b | 2
5 | 5b | 2
6 | 6b | 2
7 | 7b | 2
8 | 8b | 2
9 | 9b | 2
10 | 10b | 2
(10 rows)


--2 建立函式,不帶 for update 屬性
CREATE or replace FUNCTION fun_employee() RETURNS INTEGER AS $$
DECLARE
update_flag INTEGER ;
rec refcursor;
BEGIN

update_flag :=0;

for rec in (select * from employee ) loop
update employee set dep_no = 3;
update_flag:=update_flag+1;

RAISE NOTICE ' The update_flag is %', update_flag;
end loop;
return 0;
END;
$$ LANGUAGE 'plpgsql';


--3 建立函式,加上 for update 屬性
CREATE or replace FUNCTION fun_employee_for_update() RETURNS INTEGER AS $$
DECLARE
update_flag INTEGER ;
rec refcursor;
BEGIN

update_flag :=0;

for rec in (select * from employee for update ) loop
update employee set dep_no = 3;
update_flag:=update_flag+1;

RAISE NOTICE ' The update_flag is %', update_flag;
end loop;
return 0;
END;
$$ LANGUAGE 'plpgsql';


--4 測試 fun_employee()
skytf=> select fun_employee();
NOTICE: The update_flag is 1
NOTICE: The update_flag is 2
NOTICE: The update_flag is 3
NOTICE: The update_flag is 4
NOTICE: The update_flag is 5
NOTICE: The update_flag is 6
NOTICE: The update_flag is 7
NOTICE: The update_flag is 8
NOTICE: The update_flag is 9
NOTICE: The update_flag is 10
fun_employee
--------------
0
(1 row)


--5 測試 fun_employee_for_update()
skytf=> select fun_employee_for_update();
NOTICE: The update_flag is 1
NOTICE: The update_flag is 2
NOTICE: The update_flag is 3
NOTICE: The update_flag is 4
NOTICE: The update_flag is 5
NOTICE: The update_flag is 6
NOTICE: The update_flag is 7
NOTICE: The update_flag is 8
NOTICE: The update_flag is 9
NOTICE: The update_flag is 10
fun_employee_for_update
-------------------------
0
(1 row)

備註:根據測試結果輸出,兩個函式都執行了 10 次 update 語句。


--6
把什麼的函式改為如下宣告的cursor,只執行一次

CREATE or replace FUNCTION fun_employee_for_update() RETURNS INTEGER AS $$
DECLARE
update_flag INTEGER;
cur cursor is select * from employee for update;
rec employee%rowtype;
BEGIN

update_flag :=0;

for rec in cur loop
update employee set dep_no = 3;
update_flag:=update_flag+1;

RAISE NOTICE ' The update_flag is %', update_flag;
end loop;
return 0;
END;
$$ LANGUAGE 'plpgsql';


另外:
oracle中 %rowcount pg 可以用 GET DIAGNOSTICS integer_var = ROW_COUNT;
oracle 中我們除錯過程時常用 output.putline 去輸出一些變數的值 在pg 中 可以用 RAISE NOTICE 'i IS %', i; 去輸出你想輸出的變數。

相關推薦

oracle遷移pg問題整理

這個帖子轉自http://bbs.pgsqldb.com,把兩個帖子合在一起了 很多內容是網上查的資料,我只是整理下,有遺漏的地方,歡迎補充 首先用工具(Ora2pg)自動轉換 由於這個專案後臺程式量很大,儲存過程+觸發器大約有15萬行程式碼。 用這個工具可以將一些orac

Oracle遷移MySQL 注意事項三兩點(還不完整,繼續整理中)

大小寫問題,MySQL是區分大小寫的,而Oracle在執行SQL時會將欄位統一為大寫,所以在修改SQL和mapper檔案的時候需要將小寫的欄位修改為大寫 欄位別名問題 如果該欄位是通過MySQL

window2012 oracle 遷移 centos6 oracle

bit nec 語句 rdquo centos6 查點 emp over ans 本文目的:   oracle是大型數據庫旺旺年限和版本及環境都比較陳舊,性能影響了業務正常,近日公司需求從Windows2003 32bit的Oracle服務器上將數據遷移到Windows2

Oracle遷移到MySQL性能下降的註意點(轉)

class acl 技術 table 劃分 hash join 重要 發生 rst 背景:最近有較多的客戶系統由原來由Oracle改造到MySQL後出現了性能問題CPU 100%,或是後臺的CRM系統復雜SQL在業務高峰的時候出現堆積導致業務故障。在我的記憶裏面淘寶最初從O

Oracle遷移數據文件

ora- startup roo select one err tar 遷移 file 場景如下: [root@localhost ~]# df -h Filesystem 容量 已用 可用 已用% 掛載點 /dev/sda2

oracle遷移到mysql方案之——ogg(goldengate)

icp ger AR 問題 IT flush get gop extract source源端 oracle 11.2.0.4 ogg12cip:10.200.3.193 系統centos 7.1 1. 創建source表和一些初始化數據su - oraclesqlplu

oracle遷移到mysql分庫分表方案之——ogg(goldengate)

apply columns version alt ML -c testing name sam 之前文章主要介紹了oracle 遷移到mysql,主要是原表原結構遷移,但是實際運維中會發現,到mysql以後需要分庫和分表的拆分操作,這個時候,用ogg來做,也是很強大好用的

Oracle遷移到MySQL的各種坑及自救方案

ppi 行數據 服務器 內部 fin htm 分離 data 意思 當企業內部使用的數據庫種類繁雜時,或者有需求更換數據庫種類時,都可能會做很多數據遷移的工作。有些遷移很簡單,有些遷移可能就會很復雜,大家有沒有考慮過為了順利完成復雜的數據庫遷移任務,都需要考慮並解決哪些

Oracle遷移到Postgresql的方法

postgres oracle .html postgresq 參考資料 gre acl postgre nsh Oracle遷移到Postgresql的方法一:用Oracle_fdw參考資料:https://www.jianshu.com/p/e0d11f57ab75ht

Oracle 時間有關整理

檢視一個區間內的所有時間: select (to_date('20180708', ' yyyyMMdd ') + rownum - 1) as DATE_TIME   from all_objects where rownum <= (to_date('20190823', '

Oracle系統表整理+常用SQL語句收集(轉載)

原文:https://www.cnblogs.com/jiangxinnju/p/5840420.html-- DBA/ALL/USER/V_$/GV_$/SESSION/INDEX開頭的絕大部分都是檢視 -- DBA_TABLES意為DBA擁有的或可以訪問的所有的關係表。 -- ALL_TABLES意

Oracle常規操作整理(容易遺忘的)持續更新...

1、檢視自己建立的序列;            select * from user_sequences; 2、刪除表之後,表其實是被放進了回收站,這時  select * from tab;會看到以BIN$開頭的表,這些是d

專注於 Oracle & MSSQL & PG & Mysql 調優 & 優化(Tuning & Optimization)

1.PV常用相關命令 1)lsdev:列出ODM中的裝置。 2)chdev:修改一個AIX裝置的屬性。 3)mkdev:建立一個AIX裝置。 4)chpv:修改PV的狀態和屬性。 5)lspv:檢視AIX中PV的相關資訊。 6)migratepv:將一個PV中的P

Oracle學習手冊整理

PS:本部落格收錄自己工作中遇到學到的一些Oracle技能,有時間就更新整理一下 (1)Oracle正則匹配使用 PS:這條SQL可以通過正則匹對查詢一下,表A的欄位a是否有非數字的資料,有時候資料表的一些欄位是varchar型別的,如果sql裡用to_num

ORACLE遷移中的一些經驗(三)批量匯出index 建索引、使用者、許可權等語句

1、批量匯出INDEXES語句 SELECT DBMS_METADATA.GET_DDL(u.OBJECT_TYPE, u.object_name,u.OWNER) FROM DBA_OBJECTS u where u.OBJECT_TYPE='INDEX' AND u.o

Oracle資料庫知識點整理和複習

select 標識 選擇哪些列. from  標識從哪個表中選擇. as 列的別名可以省略,別名使用雙引號,可以在別名中包含空格或特殊字元並區分大小寫. || 把列與列,列與字元連線在起一起 select ename||'_'||job as "Employees" fro

資料遷移經驗整理

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px "PingFang SC"; color: #000000 } p.p2 { margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px "Helvetica Neue";

MAGASeek 利用 AWS DMS 從 Oracle 遷移到 Aurora

2016 年 3 月末,MAGASeek 的 AWS 雲遷移專案啟動。公司從應用程式入手,使用 AWS Database Migration Service (AWS DMS) 來遷移其資料庫基礎設施。MAGASeek 預計這一過程將需要多達四名工程師,但在 AWS DMS 的幫助下,

oracle 遷移至 mysql 部分語句的轉換

前幾天吧系統從oracle往mysql上遷移,很多的語句是比較簡單的,就是一些函式的修改如to-date等 但是也有幾個比較棘手的,這裡記錄下 第一、row_number() over(partition by    首先要了解下oracle中這個函式的用法,看個例子 s

Oracle 11G函式整理(轉換函式)

1、ASCIISTR(ch) 轉換ch為ASCII字串 SELECT ASCIISTR('AB?CDE張三') a1 FROM DUAL; 2、BIN_TO_NUM(ch)  轉換位向量為一個數字[ch為逗號隔開的0或1] SELECT BIN_TO_NUM(1,0,0