請問 SQL Server Sequence 的做法 (進階版?)

Oracle 支援 sequence, 可以每次呼叫時都得到不同的號碼. 請問在 SQL Server 上要如何達成?

我的做法是建一個 identity table (整個 table 只有 identity column) 每次插 default 然後取目前值. 但是如果應用程式同時呼叫的話, 無法保證每次給的都是不同的號碼. (batch 或是 multi-thread 的時候)

我的另一個方案是 identity + uid, 但是這樣一來 index 無用, table 大的時候就很有趣了. 請問有魚與熊掌兼得的方式嗎?

(不排斥使用 assembly, 不排斥 row level locking, 只要每次叫都可以拿到不同值就好了)

(同文發問在 ithome)

感恩
pojen_h wrote:
Oracle 支援 ...(恕刪)


CREATE TABLE [dbo].[xxxxx](
[SEQ] [int] IDENTITY(1,1) NOT NULL,

不知道這個是不是你要的,Insert 後,該欄位自動編號,從1 開始編,每次+1
我需要的是取剛加進去的值. 舉例來說, 我有 10 個 table, 每個 table 都有 transactionnid. 假設我要插入一個新的 transaction 到 10 個 table 上, 對於剛插入的 transaction 每個 table 都須要有一樣的 transactionid.

identity column "或許/可能"在某種程度上"建議"在同一個 table 的值是 unique 的, 但我無法保證對於新加入的 transaction, 10 個 table 都有一樣的 transactionid.

--
在 Oracle/DB2 上我可以用 row locking 來達成類似的需求, 但是 SQL Server 上我就找不到類似的方法了.

Oracle
- insert dummy
- select row id (非 row number)
- update dummy status where row id = rowid
- return id or update exception
用trigger來做?



CREATE TABLE [dbo].[test1](
[SEQ] [int] IDENTITY(1,1) NOT NULL,
[Value1] [varchar](20) NULL
)
GO
CREATE TABLE [dbo].[test2](
[SEQ] [int] NOT NULL,
[Value2] [varchar](20) NULL
)
GO
CREATE TABLE [dbo].[test3](
[SEQ] [int] NOT NULL,
[Value3] [varchar](20) NULL
)
GO

CREATE TRIGGER GetSEQ
ON test1
AFTER INSERT
AS
BEGIN
INSERT INTO test2
SELECT SEQ,'TEST' FROM inserted

INSERT INTO test3
SELECT SEQ,'TEST' FROM inserted
END
GO

INSERT INTO test1 (Value1) VALUES ('TEST')
GO
INSERT INTO test1 (Value1) VALUES ('TEST')
GO
INSERT INTO test1 (Value1) VALUES ('TEST')
GO

SELECT * FROM dbo.test1
SELECT * FROM dbo.test2
SELECT * FROM dbo.test3
好方法!

請問如果我不只要每個 table 都有一樣的 transactionid, 這個 transactionid 還要返回給呼叫的應用程式該如何處理?

=== 原始問題
我有一個 transaction table, 應用程式(multi-thread)每次呼叫都要去 transaction table 找一個沒處理過的 transactionid 來處理: (sp 返回一個 cursor)

table: transaction
- transactionid number pk
- some other column (varchar, date, blob..etc)

我在 Oracle 的做法是建一個 lookup, 然後用 sequence 一個一個處理下去. (seq = id 找出對應的 transactionid, 然後處理)

table: lookup
- id identity (1,1)
- transactionid number unique

但在 SQL Server 上我並沒有辦法保證每次應用程式呼叫 sp 時, sp 每次都能給不同的值. 換句話說, 能否用 trigger 以外的方式達成原始的問題? (或是 SQL Server 上的 trigger 可以返回值給 app?)
可以用trigger 搭配stored procedure 來達到你的目的

CREATE TABLE [dbo].[test1](
[SEQ] [int] IDENTITY(1,1) NOT NULL,
[Value1] [varchar](20) NULL
)
GO
CREATE TABLE [dbo].[test2](
[SEQ] [int] NOT NULL,
[Value2] [varchar](20) NULL
)
GO
CREATE TABLE [dbo].[test3](
[SEQ] [int] NOT NULL,
[Value3] [varchar](20) NULL
)
GO

CREATE TRIGGER GetSEQ
ON test1
AFTER INSERT
AS
BEGIN
INSERT INTO test2
SELECT SEQ,'TEST' FROM inserted

INSERT INTO test3
SELECT SEQ,'TEST' FROM inserted
END
GO


CREATE PROCEDURE AddRecord
@VAR1 VARCHAR(200)
AS
BEGIN
DECLARE @OP TABLE(SEQ INT);
INSERT test1 (Value1)
OUTPUT inserted.SEQ INTO @OP
VALUES (@VAR1)

DECLARE @Ret INT
SELECT @Ret = SEQ FROM @OP
RETURN @Ret
END
GO

DECLARE @Ret INT
EXECUTE @Ret = AddRecord 'TEST'
SELECT @Ret

SELECT * FROM dbo.test1
SELECT * FROM dbo.test2
SELECT * FROM dbo.test3


如果可以接受output是一個dataset的話也可以用這個方式

DECLARE @Ret TABLE(SEQ INT);
INSERT test1
(Value1)
OUTPUT inserted.SEQ
INTO @Ret
VALUES ('TEST')

SELECT * FROM @Ret

SELECT * FROM dbo.test1
SELECT * FROM dbo.test2
SELECT * FROM dbo.test3





文章分享
評分
評分
複製連結

今日熱門文章 網友點擊推薦!