首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

C# 結合 Oracle 序列與觸發器實現自動編號並回傳新增記錄 ID

     編輯:關於C#

資料庫端準備 (Oracle)

建立資料表、序列、觸發器,實現插入時自動取號:


-- 1. 建立資料表
CREATE TABLE TESTTAB (
    ID NUMBER PRIMARY KEY,
    NAME VARCHAR2(10)
);

-- 2. 建立序列
CREATE SEQUENCE TESTTABSEQ
    MINVALUE 1
    MAXVALUE 999999999999999999999999999
    START WITH 1
    INCREMENT BY 1
    CACHE 20;

-- 3. 建立觸發器:插入前自動填入序列下一值
CREATE OR REPLACE TRIGGER Tr_testtabid
BEFORE INSERT ON TESTTAB
FOR EACH ROW
BEGIN
    SELECT TESTTABSEQ.NEXTVAL INTO :NEW.ID FROM DUAL;
END Tr_testtabid;
/

C# 端核心程式碼:使用匿名 PL/SQL 區塊綁定變數回傳 CURRVAL


using System;
using System.Data;
using System.Data.OracleClient; // 需參考 System.Data.OracleClient.dll
using System.Windows.Forms;

public partial class MainForm : Form
{
    private OracleConnection _conn;

    public MainForm()
    {
        InitializeComponent();
        _conn = new OracleConnection("Data Source=ORCL;User Id=scott;Password=tiger;");
    }

    private void btnInsertAndGetId_Click(object sender, EventArgs e)
    {
        try
        {
            // 關鍵:使用 PL/SQL 區塊執行插入並選取 CURRVAL 到輸出參數
            string sql = @"
                BEGIN 
                    INSERT INTO TESTTAB (NAME) VALUES ('test'); 
                    SELECT TESTTABSEQ.CURRVAL INTO :ID FROM DUAL; 
                END;";

            using (var cmd = new OracleCommand(sql, _conn))
            {
                // 定義輸出參數
                var param = new OracleParameter("ID", OracleType.Number);
                param.Direction = ParameterDirection.Output;
                cmd.Parameters.Add(param);

                if (_conn.State == ConnectionState.Closed)
                    _conn.Open();

                cmd.ExecuteNonQuery();

                // 取得新增記錄的 ID
                long newId = Convert.ToInt64(cmd.Parameters["ID"].Value);
                txtResult.Text = $"新增成功,ID = {newId}";
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show($"發生錯誤:{ex.Message}", "錯誤", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
        finally
        {
            if (_conn.State == ConnectionState.Open)
                _conn.Close();
        }
    }
}

關鍵技術點解析

  1. 匿名 PL/SQL 區塊 (BEGIN ... END;):將 DML 與查詢封裝在單一資料庫往返中,保證原子性。
  2. CURRVAL vs NEXTVAL:觸發器已消耗 NEXTVAL,同一 Session 中 CURRVAL 即為剛生成的值。
  3. 輸出參數綁定:OracleParameter.Direction = ParameterDirection.Output 配合 INTO :ID 回傳值。
  4. OracleType.Number:對應 Oracle NUMBER 型別,C# 端用 Convert.ToInt64 或 decimal 接收。

現代替代方案:Oracle.ManagedDataAccess (ODP.NET)

System.Data.OracleClient 已被微軟標記為過時。新專案建議使用 Oracle 官方提供的 Oracle.ManagedDataAccess NuGet 套件:


// NuGet: Install-Package Oracle.ManagedDataAccess
using Oracle.ManagedDataAccess.Client;

// 連線字串格式相同
using (var conn = new OracleConnection(connStr))
using (var cmd = new OracleCommand(sql, conn))
{
    // 參數寫法相同,效能更好、支援 .NET Core
}

常見問題排查

現象可能原因解決方案
ORA-08004: sequence CURRVAL not yet defined同 Session 未先呼叫 NEXTVAL確認觸發器確實在 INSERT 前執行 NEXTVAL
參數值為 null參數名稱不符或 Direction 未設 Output檢查 :ID 與 ParameterName="ID" 大小寫一致
連線逾時連線字串錯誤/防火牆/Listener 未啟動用 tnsping 測試、檢查 TNSNAMES.ORA
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved