這個帖子轉自http://bbs.,把兩個帖子合在一起了 很多內容是網上查的資料,我只是整理下,有遺漏的地方,歡迎補充 首先用工具(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 ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() --3 創建函數,加上 for update 屬性 CREATE or replace FUNCTION fun_employee_for_update() RETURNS INTEGER AS ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() --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 另外: oracle中 %rowcount pg 可以用 GET DIAGNOSTICS integer_var = ROW_COUNT; oracle 中我們調試過程時常用 output.putline 去輸出一些變量的值 在pg 中 可以用 RAISE NOTICE 'i IS %', i; 去輸出你想輸出的變量。 |
|