建立資料表、序列、觸發器,實現插入時自動取號:
-- 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;
/
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();
}
}
}
OracleParameter.Direction = ParameterDirection.Output 配合 INTO :ID 回傳值。Convert.ToInt64 或 decimal 接收。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 |