[SQL Server] シリアル番号とかクーポン番号を作成・発行しよう。
Create Serial Number / Create Serial Key / Create Coupon Number
下記のようなシリアル番号やクーポン番号を作成する必要時があります。
シリアル番号・クーポン番号 |
シリアル番号・クーポン番号(4文字ずつ「-」で区別したバージョン) |
E272CC7F6F472FA8 |
E272-CC7F-6F47-2FA8 |
3FECD682A4846A8B |
3FEC-D682-A484-6A8B |
B374D6C8574D5DB6 |
B374-D6C8-574D-5DB6 |
7486F9334427F99B |
7486-F933-4427-F99B |
D2729FF72FF4C359 |
D272-9FF7-2FF4-C359 |
4FB78842E249F5BB |
4FB7-8842-E249-F5BB |
2D37D3FEF4358394 |
2D37-D3FE-F435-8394 |
BAD66CE83C58448A |
BAD6-6CE8-3C58-448A |
57BB486AE8448844 |
57BB-486A-E844-8844 |
7428E42C842DAA24 |
7428-E42C-842D-AA24 |
今回は16文字のシリアル番号やクーポン番号を発行する方法について説明したいと思います。
まずは発行されたシリアル番号を保存するためのテーブルを作成する。
CREATE TABLE dbo.SerialInfo
(
SerialNo char(16)
)
発行の為には色々な方法があるが、その中で下記の2つの方法について説明します。
1. WHILE文でLOOPしながら発行する。
2. tComDayテーブルを利用して一括で発行する。
ここで私がおすすめする方法は2番の一括で発行する方法です。
理由は処理速度が速いしもっと効率的だからです。
下記に1番と2番のテスト用SQLを準備しましたので、実際にテストをしながら理解して頂ければと思います。
まず、1番のWHILE文でLOOPしながら発行する方法です。
「@SerialCnt」変数の値が発行数を意味しますので、下記のクエリでは10個のシリアル番号を作成すると意味になります。
DECLARE @SerialCnt int
SET @SerialCnt = 10
DECLARE @i int
SET @i = 1
WHILE (@i <= @SerialCnt)
BEGIN
INSERT INTO dbo.SerialInfo (SerialNo)
SELECT SerialNo FROM
(
SELECT LEFT(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(NEWID(),'-',''),'1',''),'I',''),'L',''),'0',''),'O',''), 16) SerialNo
) A
WHERE NOT EXISTS (SELECT TOP 1 1 FROM dbo.SerialInfo WHERE SerialNo = A.SerialNo)
-- 発行したシリアル番号が「dbo.SerialInfo」テーブルに正常に登録された場合、@i変数にをプラスする。
-- もし重複されたデータがあった場合、@i値は変更せず再度シリアル番号を発行するようにして発行数個に合わせる。
IF @@ROWCOUNT > 0
SET @i = @i + 1
END
これはNEWID()を使ってランダム値のクーポン番号やシリアル番号を作成します。
NEWID()についてよく分からないと言う方は下記のSQLを何回も実行してみてください。
実行するたびにランダムな値を返します。
SELECT NEWID()
実行結果 - 1回目
実行結果 - 2回目
この実行結果は皆さんそれぞれ違う結果が出ます。
このランダム値を利用してクーポン番号やシリアル番号を生成します。
上記のSQLではREPLACEが多くて複雑に見えますが、
REPLACEを削除してみれば、すごく単純なSQLになります。
あのREPLACEの役割はNEWID()をすると表示される「-」を表示させないため。
また、分かりにくい文字の「1」、「I」、「l」なども含まれないようにするためです。
上記のSQLが正常に実行されたら件数とデータを確認しましょう。
--件数確認
SELECT COUNT(*) FROM dbo.SerialInfo
--データ確認
SELECT TOP 20 * FROM dbo.SerialInfo
件数とデータの確認が終わりましたら、
次の2番目のtComDayテーブルを利用して一括で発行する方法について説明します。
テーブルは既に作成されていると思いますので、「dbo.SerialInfo」テーブルのデータを一旦削除しましょう。
DELETE TABLE dbo.SerialInfo
その後、下記のSQLを実行したいと思いますが、
下記のSQLを良くみると「dbo.tComDay」というテーブルがあります。
DECLARE @SerialCnt int
SET @SerialCnt = 10
INSERT INTO dbo.SerialInfo
SELECT TOP (@SerialCnt) SerialNo
FROM
(
SELECT LEFT(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(NEWID(),'-',''),'1',''),'I',''),'L',''),'0',''),'O',''), 16) SerialNo
FROM dbo.tComDay WHERE Idx <= @SerialCnt*2
) A
WHERE NOT EXISTS (SELECT TOP 1 1 FROM dbo.SerialInfo WHERE SerialNo = A.SerialNo)
「dbo.tComDay」テーブルは作成しておけばすごく便利なテーブルになります。
詳しくは下記のリンクをご参考ください。
「dbo.tComDay」テーブルを作成する前に上記のSQLを簡単に説明すると
dbo.tComDayのところのWHERE句に「WHERE Idx <= @SerialCnt*2」がありますが、
「@SerialCnt*2」にした理由はNEWID()がランダム値を返しますので、既に発行されたシリアル番号がまた発行される可能性があるの重複データ登録を防止するためです。
それで既に多くのシリアル番号を作成してその中で登録されてない番号を抽出して登録するためであります。
「dbo.tComDay」テーブルの作成と詳細データの登録は下記のSQLを実行して登録してください。
CREATE TABLE [dbo].[tComDay](
[Idx] [int] NOT NULL,
[ComDay] [datetime] NOT NULL,
CONSTRAINT [PK_tComDay] PRIMARY KEY CLUSTERED
(
[Idx] ASC
)WITH (PAD_INDEX = ON, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90) ON [PRIMARY]
) ON [PRIMARY]
GO
CREATE NONCLUSTERED INDEX [IX_tComDay_ComDay] ON [dbo].[tComDay]
(
[ComDay] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
--######## データの登録は2999年12月31日まで登録する。 ##############################################
DECLARE @i int
SET @i = 0
WHILE @i <= 365242
BEGIN
INSERT INTO dbo.tComDay
SELECT @i+1, DATEADD(DD, @i, '2000-01-01')
SET @i = @i + 1
END
--######## データを確認 ##############################################
SELECT TOP 10 * FROM [dbo].[tComDay] ORDER BY Idx
「tComDay」テーブルは日付のデータが入っているテーブルです。
個人的にはこのテーブルを意外と良く使っています。
このSQLの実行時間はPC環境によりますが、40秒~15分程度所要されます。
「tComDay」テーブルまで作成が終わりましたら、2番目のシリアル番号やクーポン番号を一括で生成するSQLを実行してみてください。
そして件数とデータの確認を行ってください。
現在は10個を発行するSQLですので、どれが効率的かは分かりません。
発行個数を15000枚程度設定して発行を1番目のSQLと2番目のSQLをそれぞれ実行してみてください。
私の場合、実行時間は。。。。。
1番のSQL : 40秒
2番のSQL : 0秒
データが多くなればなるほど1番の場合は遅くなります。
またシリアル番号を4文字ずつ切ってその間に「-」を入れて表示したい場合は、
下記のSQLを実行してみてください。
SELECT TOP 10 SUBSTRING(SerialNo,1,4)+'-'+SUBSTRING(SerialNo,5,4)+'-'+SUBSTRING(SerialNo,9,4)+'-'+SUBSTRING(SerialNo,13,4)
FROM dbo.SerialInfo
実行結果