需在不使用 IDENTITY 欄位的情況下,實現從 100 起始、遞增 1 的序號產生機制(如訊息編號)。
CREATE TABLE common_info (
name VARCHAR(10),
value INT
)
INSERT INTO common_info VALUES ('msg_count', 100)
CREATE PROC p_ins_alm_msg
@msg_count INT OUTPUT
AS
BEGIN
-- 取得目前值
SELECT @msg_count = value
FROM common_info
WHERE name = 'msg_count'
-- 嘗試原子性更新:舊值比對確保無競爭
UPDATE common_info
SET value = @msg_count + 1
WHERE name = 'msg_count' AND value = @msg_count
-- 若更新 0 列表被並發修改,回傳錯誤
IF @@ROWCOUNT = 0
RETURN -1000
-- 使用新序號插入業務表
INSERT INTO table1 (field0) VALUES (@msg_count)
RETURN 0
END
GO
WHERE value = @msg_count 確保更新基於讀取時的值,避免競爭條件-1000 表並發衝突,呼叫端可重試DECLARE @next_id INT
EXEC @ret = p_ins_alm_msg @next_id OUTPUT
IF @ret = 0
PRINT '配發序號:' + CAST(@next_id AS VARCHAR)
ELSE
PRINT '並發衝突,請重試'
| 方案 | 優點 | 缺點 |
|---|---|---|
| IDENTITY 欄位 | 原生、高效、無並發問題 | 難以重設種子、跨表同步困難 |
| 序號表 + 預存程序 | 彈性控制、跨表共用、可手動調整 | 需自行處理並發、效能略低 |
| SEQUENCE (SQL 2012+) | 原生序列物件、支援快取、跨表 | 舊版不支援 |