2017-08-15 12 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秒。