引自:http://www.itpub.net/23129.html
1. ORACLE存儲過程的參數不能限定位數,參數類型定位為
CHAR(5)是非法的,只能定義為CHAR,具體位數限定有調用時的實參決定,這一點確實與SYBASE有很大不同;
2.游標在PL/SQL中作用極大,游標的概念滲透到整個PL/SQL的核心,連INSERT,UPDATE等語句都隱含了一個隱式游標SQL,類似SYBASE的@@ROWCOUNT等系統變量,在ORACLE中定義為游標屬性SQL%ROWCOUNT;
3.ORACLE中顯示一個變量的語句為SELECT V_VAR FROM DUAL;
與SYBASE不同的是必須加FROM DUAL;
4.SYBASE存儲過程可以通過類似SELECT * FROM T_TABLE來返回數據集,在ORACLE中似乎不能,所有不帶INTO的SELECT 語句在ORACLE存儲過程中是非法的。這一點變化帶來最大麻煩,應為POWERBUILDER調用SYBASE存儲過程很喜歡這種方式。
5、在存儲過程中聲明參數不用加 DECLARE
6、在每個塊中只有一個 DECLARE
7、參數名不用加 @ 后綴
8、每條語句后要加分號
9、變量附值不同:
myvalue:='abc';
select @myvalue='abc'
SELECT EMPNO into :emp from EMP WHERE ...;
SELECT @emp=EMPNO from emp WHERE...
10、在TRIGGER 中出現exception 不用加ROLLBACK命令
11、oracle 不使用 read locks ,無論是 read-consistent 還是 serializable 事務所以要注意SELECT FOR UPDATE的使用
移植方案
一.后臺存儲過程利用conv72從SYBASE轉換到ORACLE。
USAGE: conv72 [-P -F -M] <input_file_name>
-P指存儲過程,-F指函數
例如:conv72 -P filename.sql
轉換后,產生文件名字是filename.sql.sql
二.轉換后的調整。
(一)后臺存儲過程的調整
1、NULL
ORACLE對NULL 的條件判斷只能用: 變量 IS NULL 和變量 IS NOT NULL;
對NULL 的附值只能用:變量 := NULL;
因此需要對所有存儲過程中有關 NULL 的操作做上述相應調整。
2、StoO_error:=0;
所有存儲過程中,凡是對數據庫做有效操作之前,包括UPDATE,DELETE,INSERT以及
執行子存儲過程或函數,都有必要將ORACLE轉化過程中自動加上的變量StoO_error清
零,即在操作之前加上 StoO_error:=0; 。
3、WHEN NO_DATA_FOUND THEN StoO_error :=0;
所有存儲過程中,對數據庫做有效操作之后,通常會用IF StoO_error != 0 THEN來
檢驗操作成功與否。對于空操作,即WHERE 子句條件不滿足時,ORACLE會產生例外,
而SYBASE 不會出錯。因此為了一致,在 EXCEPTION 中 應加入
WHEN NO_DATA_FOUND THEN StoO_error :=0;
4、示例:
StoO_error :=0;/*操作之前加上 StoO_error:=0*/
BEGIN
DELETE BOAD
WHERE (EXCH_ID = i_exch_id) AND (SWT_ID = i_swt_id)
AND (FRAME_NBR = i_frame_nbr) AND (SHELF_NBR = i_shelf_nbr)
AND (BOAD_NBR = i_boad_nbr);
StoO_rowcnt := SQL%ROWCOUNT;
EXCEPTION
WHEN NO_DATA_FOUND THEN
StoO_error :=0;
WHEN OTHERS THEN
StoO_error := SQLCODE;
END;
IF StoO_error != 0 THEN
BEGIN
ROLLBACK TO SAVEPOINT aa;
i_status := -1 ;
RETURN /* */;
END;
END IF;
5、事務設計
ORACLE的存儲過程中,COMMIT 語句將會把此前未提交的所有事務都提交,且對于
已提交的事務,無論在后臺存儲過程中,還是在前臺 PB 的腳本中,都無法回滾。
這與SYBASE 不同,因此事務應該結合后臺存儲過程與前臺 PB 腳本設計。
6、事務的調整
在ORACLE中,沒有SYBASE中事務嵌套數的概念,在后臺的存儲過程中,遇到
COMMIT時,將把整個事務(包括前臺和后臺)全部提交。而在SYBASE中,只
有當事物數為最低級時(設計都在前臺)才能提交。
由于所有事務都在前臺提交,
因此把后臺存儲過程中所有的COMMIT全部注釋掉。
7、時間參數調整
如果該存儲過程的輸入參數為DATE型時,在POWERBUILDER中創建存儲過程
時,將引發錯誤。
為了解決此問題,
在后臺,將這種存儲過程的DATE型輸入參數
全部改為VARCHAR2型。
在存儲過程中,將VARCHAR2轉化為DATE,為了前后臺一致,
采用統一的轉化格式。
i_start_DATE:=TO_DATE(i_start_string,'YYYY/MM/DD HH24:MI:SS');
i_end_date :=TO_DATE(i_end_string, 'YYYY/MM/DD HH24:MI:SS');
在前臺POWERBUILDER中,將DATE或者DATETIME型變量轉化為STRING型,
也采用上述統一格式,再作為存儲過程的參數。
v_STRING=STRING(v_DATE, 'YYYY/MM/DD HH:MM:SS')
v_STRING=STRING(v_DATETIME,'YYYY/MM/DD HH:MM:SS')
(二)用于數據窗口的后臺存儲過程的修改
1、通過特定表返回時,WHERE子句的處理
TABLE: TEST
COLUMN: NAME VARCHAR2(20);
AGE NUMBER;
BIRTH DATE;
REMARKS VARCHAR2(30);
最后的返回語句如下,WHERE子句的處理中,對字符型和日期型進行轉義處理
PBDBMS.PUT_LINE('SELECT NAME,AGE,BIRTH,REMARKS ')
PBDBMS.PUT_LINE(' FROM TEST ');
str_where:=' WHERE NAME='|| ''''||VAR_NAME||''''
||'AND AGE =' || TO_CHAR(VAR_AGE)
||'AND BIRTH=' || ''''||TO_CHAR(VAR_BIRTH)||'''';
PBDBMS.PUT_LINE(str_where);
注意:
如果NUMBER型變量是該存儲過程的輸入參數,則要對他進行
單獨處理
IF VAR_AGE IS NULL THEN
CONV:=' AND AGE IS NULL ';
ELSE
CONV:=' AND AGE = ' || TO_CHAR(VAR_AGE);
END IF;
2、最后數據的返回通過表DUAL進行
有兩種方式:
(1)、用PBDBMS.PUT_LINE。無法處理返回值為空值的情況
使用方法見底下示例:
注意:對不同變量類型進行了不同處理。
(2)、用PBDBMS.PUT
該過程已經過修改,可對各種變量類型進行處理,不在需要在程序中對
不同類型進行不同處理,同時也可適應NULL值的情況。
使用方法見底下示例:
注意:直接使用該參數,多個變量返回時注意中間加PUT(',');
另外:PBDBMS包中行最大長度為255,而PUT函數不換行,因此估計
長度快到255時,使用PUT_LINE(',')來實現換行目的。
PROCEDURE AAA
(I_SO_NBR VARCHAR2)
IS
I_NUM INTEGER;
i_date date;
I_NAME VARCHAR2(50);
I_COV VARCHAR2(100);
I_COV2 VARCHAR2(100);
BEGIN
/* 第一種方式*/
I_COV:= ' SELECT '||''''||I_NAME||''''||','||TO_CHAR(I_NUM)||','||''''||TO_CHAR(I_DATE)||'''';
I_COV2:=' FROM DUAL';
PBDBMS.PUT_LINE(i_cov);
PBDBMS.PUT_LINE(I_cov2);
/*第二種方式*/
PBDBMS.PUT_LINE('SELECT ');
PBDBMS.PUT(I_NAME);
PBDBMS.PUT(',');/* 如長度將超過255,此處用PUT_LINE(',')進行換行*/
PBDBMS.PUT(I_NUM);PBDBMS.PUT(',');
PBDBMS.PUT(I_DATE);
PBDBMS.PUT_LINE(' FROM DUAL');
END;
(三)前臺腳本中嵌入式SQL語句的調整
1、ORACLE 存儲過程前臺腳本調用方式:
DECLARE sosp_cust_i PROCEDURE FOR sosp_cust_i
(:name,:reg_nbr,:li_cust_cat_id,
osition,
null,
arent_id) ;
execute sosp_cust_i;
SYBASE 存儲過程前臺腳本調用方式:
DECLARE sosp_cust_i PROCEDURE FOR sosp_cust_i
@name = :ls_name,
@reg_nbr = :ls_regnbr,
@cat_id = :ii_cust_cat,
@position = null,
@type_id = :ii_cust_type,
@parent_id = :ll_parent_id ;
execute sosp_cust_i;
2、前臺腳本中嵌入式的SQL語句中
(1)NULL
ORACLE對NULL 的條件判斷只能用: 字段名 IS NULL 和 字段名?IS NOT NULL;
而不能用:字段名 = NULL 和 字段名?<> NULL?
若有上述情況,應做相應調整。
如:select * from so_charge where receipt_nbr = null;
應改為:select * from so_charge where receipt_nbr is null;
(2)""->''
ORACLE對字符串使用單引號,而SYBASE單引號、雙引號均可
因此若有如select * from so where state="A";的語句
應改為select * from so where state='A';
(3)insert -> insert into
SYBASE允許使用insert tablename...,而ORACLE必須使用
insert into tablename...,若有上述情況,應做相應調整。
(4)+ --> ||
字符串連接,SYBASE使用'+',而ORACLE使用'||'。?
(5)getdate() --> sysdate
取系統時間,SYBASE使用getdate(),而ORACLE使用sysdate。