2017-08-15 64 views
3

我有以下腳本,它以'ABC-1234'格式生成175百萬(!)個獨特的字母數字代碼,範圍從AAA-0000到ZZZ- 9999。如何加快創建大數字表的Alpha數字代碼的SQL腳本

在我的專用MS SQL 2016框中按原樣運行此腳本需要20個小時。加快速度的最佳方法是什麼?從腳本中可以看出,我的SQL技能有點欠缺!

有一個Identity(int)列,ID和CODE列(nvarchar(20))本身。兩列組成的主鍵:

CREATE TABLE [dbo].[ORDERED_CODES](
[ID] [int] NOT NULL, 
[Code] [nvarchar](20) NOT NULL, 
CONSTRAINT [PK_ORDERED_CODES] PRIMARY KEY CLUSTERED 
(
[ID] ASC, 
[Code] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,     
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 
GO 

腳本:

DECLARE @Alpha1 INT; 
DECLARE @Alpha2 INT; 
DECLARE @Alpha3 INT; 
DECLARE @Num INT; 

-- alpha elements 'ABC' 
SET @Alpha1 = 65; 
SET @Alpha2 = 65; 
SET @Alpha3 = 65; 

-- number element '9999' 
SET @Num = 0; 

-- temporary holders 
DECLARE @FINALCODE Nvarchar(50); 
DECLARE @CODE1 Nvarchar(50); 
DECLARE @CODE2 Nvarchar(50); 
DECLARE @CODE3 Nvarchar(50); 

WHILE @Alpha1 < 91 
BEGIN 
    SET @CODE1 = CHAR(@Alpha1) 
     WHILE @Alpha2 < 91 
     BEGIN 
     SET @CODE2 = @CODE1 + CHAR(@Alpha2) 
     SET @Alpha2 = @Alpha2 +1 
      WHILE @Alpha3 < 91 
       BEGIN 
        SET @CODE3 = @CODE2 + CHAR(@Alpha3) 
        SET @Alpha3 = @Alpha3 +1 
         WHILE @Num < 10000 
          BEGIN 
           SET @FINALCODE = RIGHT('0000'+ CAST(@Num as nvarchar(4)),4) + CHAR(45) + @CODE3   
           SET @Num = @Num +1 
           INSERT INTO ORDERED_CODES (CODE) VALUES (@FINALCODE) 
          END 
         SET @FINALCODE = null 
         SET @Num = 0 
       END 
      SET @Alpha3 = 65 
    END 
    SET @Alpha2 = 65 

    SET @Alpha1 = @Alpha1 +1 
END; 

的任何和所有的心思都衷心感謝!

+0

感謝Gordon,Dan&John抽出寶貴時間來幫忙,所有這些都是對同一主題的很好回答,所以我不得不選擇一個作爲答案...所以最好的SO傳統必須去Gordon爲了第一。不用說我將閱讀CTE!最快的是Dan,在我的服務器上將近4分鐘 - 我現在需要試着弄清楚爲什麼我的胖服務器比你的桌面慢5倍!比20小時好得多,我非常感謝。乾杯! –

回答

1

我只想做:

with alphas as (
     select v.ch 
     from (values ('A'), ('B'), . . . 
      ) v(ch) 
    ), 
    digits as (
     select v.ch 
     from values ('0'), ('1'), . . . 
    ) 
select (a1.ch + a2.ch + a3.ch + d1.ch + d2.ch + d3.ch + d4.ch) as code 
from alphas a1 cross join 
    alphas a2 cross join 
    alphas a3 cross join 
    digits d1 cross join 
    digits d2 cross join 
    digits d3 cross join 
    digits d4; 

. . .是要有效字符。如果您願意,可以使用除values以外的其他方法生成值。

1

在臨時理貨表的幫助下。在1分鐘內完成175,760,000條記錄6.799秒(在我的筆記本電腦上)。或者,37.833秒沒有Order By

;with cteC as (
    Select Top 26 C=char(64+Row_Number() Over (Order By (Select NULL))) From master..spt_values n1 
), cteN as (
Select Top 10000 N= right(concat('0000',Row_Number() Over (Order By (Select NULL))-1),4) From master..spt_values n1, master..spt_values n2 
) 
Insert Into Ordered_Codes (Code) 
Select Code=Concat(A.C,B.C,C.C,'-',N.N) 
From cteC A,cteC B,cteC C,cteN N 
Order By 1 

CTEC生成A - Z

CTEN生成0000 - 99999

最後的結果看起來像

enter image description here

1

我期待有一個CTE查詢的性能將比循環好得多:

WITH 
    alpha_values AS (
     SELECT value FROM(VALUES 
      ('A'),('B'),('C'),('D'),('E'),('F'),('G'),('H'),('I'),('J'),('K'),('L'),('M') 
      ,('N'),('O'),('P'),('Q'),('R'),('S'),('T'),('U'),('V'),('W'),('X'),('Y'),('Z')) 
      AS alpha_values(value) 
    ) 
    ,t10 AS (SELECT n FROM (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) t(n)) 
    ,number_values AS (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 0)) - 1 AS value FROM t10 AS a CROSS JOIN t10 AS b CROSS JOIN t10 AS c) 
INSERT INTO dbo.ORDERED_CODES (Code) 
SELECT 

     alpha_values1.value 
    + alpha_values2.value 
    + alpha_values3.value 
    + '-' 
    + RIGHT('000' + CAST(number_values.value AS varchar(4)), 4) 
    AS Code 
FROM alpha_values AS alpha_values1 
CROSS JOIN alpha_values AS alpha_values2 
CROSS JOIN alpha_values AS alpha_values3 
CROSS JOIN number_values 
ORDER BY Code; 

編輯 我沒有看到戈登的類似解決方案,直到我張貼後。上述查詢在我的桌面上運行了35秒。