1. 程式人生 > 其它 >SQL Server與ORACLE資料庫儲存過程編寫的幾個不同之處

SQL Server與ORACLE資料庫儲存過程編寫的幾個不同之處

一直在使用SQLServer數庫的儲存過程進行業務資料處理,現在ORACLE上進行儲存過程應用,感覺沒有MSSQL的方便靈活,總結了以下幾點區別:

1、入引數據型別不要書寫長度。比如:userName VARCHAR2(100)是不正確的。

2、過程內變數宣告必須在關鍵字IS/AS後,過程的開始BEGIN之間,且無需DECLARE關鍵字,變數名也無需@符號開頭。而MSSQL是可以在過程體內任意位置通過Declare宣告的。

3、浮點型別的變數一定要宣告成NUMBER型別,DECIMAL會有精度問題導致取值不是所期望的值。

4、遊標的使用如果是動態遊標(並不是一開始就固定建立的,而是根據不同條件的生成的),必須先宣告動態遊標的型別和變數名。比如下例程式碼中的:

TYPE ref_cur IS REF CURSOR;

cur_stock REF_CUR; --庫存處理遊標

5、SELECT語句對變數賦值語法:SELECTcol1,col2 INTO var1,var2 FROM table1 WHERE ROWNUM=1,而MSSQL的語法是:SELECT @var1=col1,@var2=col2 FROMtable1 WHERE id=1。

6、如果上4中所說的變數賦值沒有檢索到記錄還會觸發NO_DATA_FOUND THEN異常,可以用EXCEPTION對異常進行捕獲處理。而MSSQL沒檢索到資料變數會被賦值為NULL值。

7、ORACLE的UPDATE語句內不能對變數進行更新操作,這一點真的是太不爽啦!!!。MSSQL是可以,例:DELCARE @NUM=0; UPDATE table1 SET @NUM=@NUM+1,col1=@NUM

CREATE OR REPLACE PROCEDURE JUNAN.P_OPD_QUOTN_INS (
--門診醫囑簽名過程 liuyc 20210902
writeId IN INT, --待簽名醫囑記錄id
operateId IN INT, --操作員id
exprdate IN INT, --減少庫存時批次:0不控制效期,1控制效期
upstatus IN INT, --是否更新醫囑狀態為已簽名
amount OUT NUMBER, --出庫銷售金額
mess OUT VARCHAR2 --OK為執行成功
)
IS
--本組變數儲存醫囑資訊
ow_drugId VARCHAR2(30); --
藥品id ow_drugTypeId VARCHAR2(30); --藥品類別id ow_unitName VARCHAR2(30); --藥品單位名稱 ow_unitId NUMBER(12,0); --藥品包裝單位id ow_count NUMBER(12,4); --藥品數量 ow_baseCount NUMBER(12,4); --按基本單位算的藥品數量 ow_status VARCHAR2(4); --醫囑狀態 ow_patientId NUMBER(12,0); --患者id ow_deptId NUMBER(12,0); --藥房id ow_hosId NUMBER(12,0); --醫院id ow_relation NUMBER(12,6); --藥品包裝單位換算比 --本組變數儲存臨時庫存批次資訊 st_rowid ROWID; --庫存批次錶行系統rowid st_id INT; --庫存遊標儲存變數 庫存記錄id st_unitId INT; --庫存包裝單位id st_relation NUMBER(22,6); --換算比 st_count NUMBER(22,4); --庫存數量 st_price NUMBER(22,6); --藥房包裝單位的零售價格 --其他變數 per_quantity NUMBER(22,4) :=0; --每次庫存迴圈處理數量 per_amount NUMBER(22,2) :=0; --每次庫存迴圈處理金額 total_quantity NUMBER(22,4) :=0; --累計數量 total_amount NUMBER(22,2) :=0; --累計金額 operateName VARCHAR2(60); --操作員姓名 TYPE ref_cur IS REF CURSOR; cur_stock REF_CUR; --庫存處理遊標 BEGIN mess:=''; --取得醫囑資訊 BEGIN SELECT DOCTOR_ORDER_ID,DRUG_COUNT,DRUG_COUNT_UNIT,DRUG_UNIT_ID,ORDER_STATUS_ID,PATIENT_ID,EXECUTIVE_SECTION_ID,HOSPITAL_ID INTO ow_drugId,ow_count,ow_unitName,ow_unitId,ow_status,ow_patientId,ow_deptId,ow_hosId FROM T_OPD_DOCTOR_ORDER_WRITE WHERE DOCTOR_ORDER_TYPE_ID='drug' AND id=writeId FOR UPDATE NOWAIT; EXCEPTION WHEN NO_DATA_FOUND THEN mess:='醫囑記錄不存在!'; RETURN; END; --只有醫囑狀態0未簽名、10稽核駁回時可以做簽名操作 IF NVL(ow_status,'0') NOT IN ('0','10') THEN mess:=CONCAT('醫囑記錄簽名狀態無效,值:',NVL(ow_status,'')); RETURN; END IF; --取得門診處方藥品包裝單位換算比,藥品類別id BEGIN SELECT a.RELATION,b.DRUG_TYPE_ID INTO ow_relation,ow_drugTypeId from T_PHARMACY_DRUG_PACKAGE a INNER JOIN T_PHARMACY_DRUG b ON b.ID=A.DRUG_ID WHERE ROWNUM=1 and a.STATUS='1' and a.ID=ow_unitId; EXCEPTION WHEN NO_DATA_FOUND THEN mess:='查詢藥品包裝單位換算比無資料!'; RETURN; END; IF ow_relation IS NULL THEN mess:='藥品包裝單位換算比為null!'; RETURN; END IF; --取操作員資訊 BEGIN SELECT name INTO operateName FROM T_SYS_OPERATOR WHERE id=operateId; EXCEPTION WHEN NO_DATA_FOUND THEN mess:='操作員記錄不存在!'; RETURN; END; IF NVL(ow_status,'')!=0 THEN mess:=CONCAT('醫囑記錄簽名狀態無效,值:',NVL(ow_status,'')); RETURN; END IF; --換算醫囑藥品數量為基本單位數量 ow_baseCount:=ROUND(ow_count*ow_relation,4); --開啟動態遊標,將臨時庫存中本藥品有效批次庫存的行id儲存用於後續扣減處理 open cur_stock FOR SELECT ROWID FROM T_DRUGSTORE_DRUG_STOCK_TEMP T WHERE T.STATUS = '1' AND T.BATCH_INVALID = '1' AND (CASE WHEN exprdate=1 THEN T.EXPIRATION_DATE ELSE TO_DATE('9999-12-31','YYYY-MM-dd') END) >= trunc(sysdate) AND T.QUANTITY > 0 AND T.DEPT_ID=ow_deptId AND T.DRUG_ID =ow_drugId order by EXPIRATION_DATE; LOOP --遍歷庫存記錄進行庫存處理 FETCH CUR_STOCK INTO st_rowid; exit when cur_stock%NOTFOUND; --取得當前id批次庫存資訊並鎖定 BEGIN SELECT ID,NEW_MAX_PACKAGE_UNIT_ID,RELATION,QUANTITY,DRUGSTORE_RETAIL_PRICE INTO st_id,st_unitId,st_relation,st_count,st_price FROM T_DRUGSTORE_DRUG_STOCK_TEMP WHERE QUANTITY > 0 AND ROWID=ST_ROWID FOR UPDATE; EXCEPTION WHEN NO_DATA_FOUND THEN CONTINUE; END; --計算本批次扣減庫存數量:批次庫存小於等於待出庫數量時取本批結餘數,否則用待出庫數 PER_QUANTITY:=(CASE WHEN st_count<=ow_baseCount THEN st_count ELSE ow_baseCount END); --計算銷售金額 PER_AMOUNT:=ROUND(PER_QUANTITY/ST_RELATION*ST_PRICE,2); --更新本批次結存數量 UPDATE T_DRUGSTORE_DRUG_STOCK_TEMP SET QUANTITY=QUANTITY-PER_QUANTITY,UPDATE_OPER=operateId,UPDATE_DATE=SYSDATE WHERE QUANTITY>=PER_QUANTITY AND ROWID=st_rowid; IF SQL%ROWCOUNT<1 THEN mess:='扣減臨時庫存更新了0行,庫存數量有變化請重試!'; RETURN; END IF; --寫入藥品劃價記錄 INSERT INTO T_OPD_QUOTN (ID, HOSPITAL_ID, DEPT_ID, ORDER_WRITE_ID, STOCK_ID, DRUG_ID, UNIT_NAME, QUANTITY, PRICE, AMOUNT, RETURN_QUANTITY, CREATE_TIME,CREATE_OPER) VALUES (SEQ_OPD_QUOTN.NEXTVAL,OW_HOSID,OW_DEPTID,writeId,ST_ID,OW_DRUGID,OW_UNITNAME, ROUND(PER_QUANTITY/ow_relation,4),ROUND(PER_AMOUNT*ow_relation/PER_QUANTITY,4),PER_AMOUNT,0,SYSDATE,operateName); --更新累計出庫數量和金額,待出庫基本單位數量 TOTAL_QUANTITY:=TOTAL_QUANTITY+PER_QUANTITY; TOTAL_AMOUNT:=TOTAL_AMOUNT+PER_AMOUNT; ow_baseCount:=ow_baseCount-PER_QUANTITY; IF ow_baseCount=0 THEN EXIT; --庫存數量足額扣減退出迴圈 END IF; END LOOP; CLOSE CUR_STOCK; --迴圈結束判斷待出庫數量如果為非零,則說明不足出庫 IF ow_baseCount!=0 THEN mess:=CONCAT('臨時庫存不足,待扣減基本單位數量:',TO_CHAR(ow_baseCount)); RETURN; END IF; --庫存扣減正常,更新門診患者費用表金額資訊,醫囑金額返回呼叫由程式碼修改 UPDATE T_OPD_DOCTOR_COST SET TOTAL_SUM=TOTAL_AMOUNT,PRICE=ROUND(TOTAL_AMOUNT/ORDER_COUNT,4),UPDATE_OPER=operateId,UPDATE_DATE=SYSDATE WHERE TOTAL_SUM!=TOTAL_AMOUNT AND HOSPITAL_ID=OW_HOSID AND ORDER_WRITE_ID=writeId; --更新醫囑藥品費用金額 UPDATE T_OPD_DOCTOR_ORDER_WRITE SET SUM_PRICE=TOTAL_AMOUNT, PRICE=(CASE WHEN DRUG_COUNT=0 THEN 0 ELSE ROUND(TOTAL_AMOUNT/DRUG_COUNT,4) END), ORDER_STATUS_ID=(CASE WHEN upstatus=1 THEN '1' ELSE ORDER_STATUS_ID END),UPDATE_DATE=SYSDATE WHERE id=writeId; amount:=TOTAL_AMOUNT; mess:='OK'; EXCEPTION WHEN NO_DATA_FOUND THEN mess:='查詢記錄資料為空!'; WHEN OTHERS THEN mess := SUBSTR(SQLERRM,1,2000); END P_OPD_QUOTN_INS; /
凡哥,別他媽吹牛逼了