SQL Server 2012 的 T-SQL 新功能 – SEQUENCE 物件

本文將介紹如何利用 SQL Server 2012 新的 SEQUENCE 物件來維護流水號。

在 SQL Server 2012 以前的版本,要產生流水號不外乎是在 TABLE中的欄位加上 IDENTITY 或是利用 IDENTITY 方法來產生流水號,如下列的 T-SQL 敘述:

 

   1:  --於欄位中使用 IDENTITY 來產生流水號
   2:  DECLARE @t TABLE 
   3:  (    c1 int IDENTITY
   4:      ,c2 int
   5:  )
   6:   
   7:  INSERT INTO @t VALUES (10),(20),(30)
   8:  SELECT * FROM @t
   9:   
  10:  DELETE @t WHERE c2 = 20
  11:  INSERT INTO @t VALUES (20)
  12:  SELECT * FROM @t
  13:   
  14:   
  15:  --使用 IDENTITY 方法來產生流水號
  16:  IF EXISTS (SELECT * FROM sys.objects WHERE type = 'U' AND name = 'MyTABLE')
  17:      DROP TABLE MyTABLE
  18:  GO
  19:   
  20:  --產生名為MyTable的資料表,其中 c1 為 IDENTITY,c2 為 int 型態
  21:  SELECT IDENTITY(int,1,1) AS c1,0 as c2
  22:  INTO MyTABLE
  23:   
  24:  INSERT INTO MyTABLE(c2) VALUES (10),(20),(30)
  25:  SELECT * FROM MyTABLE
  26:   
  27:  DELETE MyTABLE WHERE c2 = 20
  28:  INSERT INTO MyTABLE(c2) VALUES (20)
  29:  SELECT * FROM MyTABLE

 

從上面的程式碼可知,利用 IDENTITY 產生的流水號必須在實際 INSERT 資料到該欄位時才會產生,而且用過的流水號無法再使用,除非透過 DBCC CHECKIDENT 來限制下一個流水號的起始號碼。

在 SQL Server 2012 可以利用新的 SEQUENCE 物件來維護流水號,不會因為刪除資料而產生跳號,您不需要像以往一樣自行建立 TABLE 來記錄流水號用到幾號,對於有流水號需求將會方便許多。

  • 以下 T-SQL 用來建立 SEQUENCE 物件,起始編號為 1 號,每次增量為 2,最小值為 1,最大值為 10,流水號不循環,為減少磁碟 IO,這個範例筆者快取 3 個序號。

 

   1:  /*
   2:  CREATE SEQUENCE [schema_name . ] sequence_name
   3:      [ AS [ built_in_integer_type | user-defined_integer_type ] ]
   4:      [ START WITH <constant> ]
   5:      [ INCREMENT BY <constant> ]
   6:      [ { MINVALUE [ <constant> ] } | { NO MINVALUE } ]
   7:      [ { MAXVALUE [ <constant> ] } | { NO MAXVALUE } ]
   8:      [ CYCLE | { NO CYCLE } ]
   9:      [ { CACHE [ <constant> ] } | { NO CACHE } ]
  10:      [ ; ]
  11:  */
  12:   
  13:  IF EXISTS (SELECT * FROM sys.sequences WHERE name = 'MySeqNo')
  14:      DROP SEQUENCE MySeqNo
  15:  GO
  16:   
  17:  --建立 Sequence 物件
  18:  CREATE SEQUENCE MySeqNo
  19:  AS tinyint
  20:  START WITH 1
  21:  INCREMENT BY 2
  22:  MINVALUE 1
  23:  MAXVALUE 10
  24:  NO CYCLE
  25:  CACHE 3
  26:   
  27:  GO
  28:   
  29:  --查詢SEQUENCE物件
  30:  SELECT * FROM sys.sequences
  31:  GO

 

  • 您可以利用下列 T-SQL 來取得 SEQUENCE 物件中的下一個流水號:

 

   1:  --使用SEQUENCE物件
   2:  SELECT NEXT VALUE FOR MySeqNo

 

 

  • 當您嘗試從 MySeqNo 物件中取得流水號,將會得到 1、3、5、7、9等五個號碼,若在得到 9 之後再利用 NEXT VALUE FOR 取得下一個流水號時,會遇到如下圖的錯誤訊息:

 

image

  • 您可以利用 ALTER SEQUENCE 來重設流水號,或是把 SEQUENCE 物件設定為自動重頭產生新的號碼。

 

   1:  --方法一:重設 MySequence,故意重新設定由2開始
   2:  ALTER SEQUENCE MySeqNo
   3:  RESTART WITH 2
   4:  GO
   5:   
   6:  --嘗試再取得流水號,預計應該是會得到 2
   7:  SELECT NEXT VALUE FOR MySeqNo
   8:  GO
   9:   
  10:  --方法二:設定為自動循環
  11:  ALTER SEQUENCE MySeqNo
  12:  CYCLE
  13:   
  14:  --因為設定為自動循環,所以重複取號多次也不會發生超出範圍的錯誤
  15:  SELECT NEXT VALUE FOR MySeqNo
  16:  GO 10

 

最後筆者以一個簡單的範例,嘗試舉例說明 SEQUENCE 物件可用來產生生符合特定商業規則的流水號。下列的 T-SQL 用來模擬產生發票號碼:

 

   1:  IF EXISTS (SELECT * FROM sys.sequences WHERE name = 'InvoiceSeqNo')
   2:      DROP SEQUENCE InvoiceSeqNo
   3:  GO
   4:   
   5:  CREATE SEQUENCE InvoiceSeqNo
   6:  AS tinyint
   7:      START WITH 1
   8:      INCREMENT BY 1
   9:      MINVALUE 1
  10:      MAXVALUE 10
  11:      NO CYCLE
  12:      CACHE 3
  13:   
  14:  GO
  15:   
  16:   
  17:  DECLARE @i TABLE
  18:  (    --產生規則為 AB+2位流水號的發票號碼
  19:      InvoiceNo char(10) DEFAULT ('AB'  
  20:  + RIGHT('0' + CONVERT(VARCHAR(10),NEXT VALUE FOR InvoiceSeqNo),2))
  21:      ,Amount int
  22:  )
  23:   
  24:  INSERT INTO @i(Amount) VALUES (100),(200),(100),(500)
  25:  SELECT * FROM @i
  26:   
  27:  GO

 

 

【參考資料】