首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> Oracle 資料庫 >> Oracle 資料庫基礎

SQL Server 與 Oracle 存儲過程語法差異完整對照表與遷移實戰範例

     編輯:Oracle 資料庫基礎

核心語法差異速查表

特性SQL Server (T-SQL)Oracle (PL/SQL)
返回單值存儲過程 + OUTPUT / RETURN**函數 (FUNCTION)** 更適合
大量處理無返回存儲過程存儲過程 (PROCEDURE)
參數定義位置`CREATE PROC @p1 INT, @p2 INT AS` (無括號)`CREATE PROCEDURE (P1 IN INT, P2 OUT INT) AS` (**有括號**)
區域變數宣告`DECLARE @v INT` (**@ 前綴**)`V INT;` (**無 @、在 DECLARE 區或 BEGIN 前**)
DDL 在過程中直接執行**禁止**,需 `EXECUTE IMMEDIATE` 動態 SQL
臨時表`#temp` (連線級)、`##temp` (全域)**全域暫存表** (結構永久、資料會話隔離),建表需在過程外
IF EXISTS 用法`IF EXISTS (SELECT ...) BEGIN ... END``EXISTS` **只能用在 WHERE**,需 `SELECT COUNT(*) INTO v ... IF v>0 THEN`
IF 語法`IF @x=1 BEGIN ... END ELSE BEGIN ... END``IF x=1 THEN ... ELSIF x=2 THEN ... ELSE ... END IF;`
空字串 vs NULL`''` ≠ `NULL``''` **等同於** `NULL`
事務提交隱式自動提交 (可關閉)**預設需顯式 COMMIT**
調用過程`EXEC proc` / `EXECUTE proc`直接 `proc(...);` 或 `CALL proc(...);` (**無 EXEC**)
UPDATE/DELETE ... FROM支援 `UPDATE T SET ... FROM T JOIN ...`**不支援**,需子查詢或 MERGE
隱式日期轉換靈活受 `NLS_DATE_FORMAT` 參數控制,較嚴格

遷移實戰範例:跨系統對賬存儲過程

原 T-SQL (簡化)


CREATE PROCEDURE P_GLBalanceWithOtherSys
  @FEntityNo VARCHAR(12), @FYear INT, @FPeriod INT
AS
DECLARE @ret INT, @sret CHAR(1)
IF (SELECT FValue FROM T_SysParam WHERE FEntityNo=@FEntityNo AND FSysNo='Csh' AND FParamNo='CshStartFlag') = '1'
BEGIN
  CREATE TABLE #Temp1 (FAmount DECIMAL(18,2))
  INSERT INTO #Temp1
  SELECT ABS(SUM(A.FBeginAmountOrg)-SUM(B.FBeginAmount)) + ...
  FROM T_GLBal A, T_CshBal B
  WHERE A.FEntityNo=B.FEntityNo AND A.FYear=B.FYear AND A.FPeriod=B.FPeriod
    AND A.FAcctNo=B.FAcctNo AND A.FCurrency=B.FCurrency AND A.FStatus='0'
    AND A.FEntityNo=@FEntityNo
  GROUP BY A.FEntityNo, A.FYear, A.FPeriod, A.FAcctNo, A.FCurrency
  IF EXISTS (SELECT * FROM #Temp1 WHERE FAmount <> 0)
  BEGIN
    RAISERROR('對賬不平!',18,1)
    RETURN -1
  END
  DROP TABLE #Temp1
END

目標 PL/SQL (Oracle 10g+)


CREATE OR REPLACE PROCEDURE P_GLBalanceWithOtherSys (
  P_FENTITYNO IN VARCHAR2,
  P_FYEAR IN NUMBER,
  P_FPERIOD IN NUMBER
) AS
  V_FLAG CHAR(1);
  V_CNT NUMBER;
BEGIN
  -- 1. 參數查詢
  SELECT FVALUE INTO V_FLAG
  FROM T_SYSPARAM
  WHERE FENTITYNO = P_FENTITYNO AND FSYSNO = 'Csh' AND FPARAMNO = 'CshStartFlag';

  IF V_FLAG = '1' THEN
    -- 2. 全域暫存表 (需預先建立結構: CREATE GLOBAL TEMPORARY TABLE GTT_TEMP1 (FAMOUNT NUMBER) ON COMMIT DELETE ROWS;)
    INSERT INTO GTT_TEMP1
    SELECT ABS(SUM(A.FBEGINAMOUNTORG)-SUM(B.FBEGINAMOUNT)) + ...
    FROM T_GLBAL A, T_CSHBAL B
    WHERE A.FENTITYNO = B.FENTITYNO
      AND A.FYEAR = B.FYEAR
      AND A.FPERIOD = B.FPERIOD
      AND A.FACCTNO = B.FACCTNO
      AND A.FCURRENCY = B.FCURRENCY
      AND A.FSTATUS = '0'
      AND A.FENTITYNO = P_FENTITYNO
    GROUP BY A.FENTITYNO, A.FYEAR, A.FPERIOD, A.FACCTNO, A.FCURRENCY;

    -- 3. 替代 IF EXISTS
    SELECT COUNT(*) INTO V_CNT FROM GTT_TEMP1 WHERE FAMOUNT <> 0;
    IF V_CNT > 0 THEN
      RAISE_APPLICATION_ERROR(-20001, '對賬不平!');
      RETURN;  -- 過程無返回值用 RETURN
    END IF;

    -- 4. ON COMMIT DELETE ROWS 自動清理,無需 DROP
  END IF;
EXCEPTION
  WHEN NO_DATA_FOUND THEN
    RAISE_APPLICATION_ERROR(-20002, '系統參數未配置');
  WHEN OTHERS THEN
    RAISE_APPLICATION_ERROR(-20999, '對賬異常: ' || SQLERRM);
END P_GLBalanceWithOtherSys;
/

遷移關鍵點總結

  1. 單值返回改用 **FUNCTION**。
  2. 臨時表 → **全域暫存表 (GTT)**,結構永久、資料隔離、提交自動清理。
  3. `IF EXISTS` → `SELECT COUNT(*) INTO v ... IF v>0`。
  4. `RAISERROR` → `RAISE_APPLICATION_ERROR(-20xxx, 'msg')` (自定義錯誤碼 -20000~-20999)。
  5. 動態 SQL (`EXECUTE IMMEDIATE`) 處理 DDL/動態表名。
  6. 日期處理統一用 `TO_DATE`/`TO_CHAR` 配合 `NLS_DATE_FORMAT`。
  7. 事務邊界明確:`COMMIT`/`ROLLBACK` 由應用或過程控制。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved