我试图预生成一些字母数字字符串并将结果插入表中.字符串的长度为5.示例:a5r67.基本上我想为客户生成一些可读字符串,以便他们可以访问他们的订单
www.example.com/order/a5r67.现在我有一个select语句:
;WITH
cte1 AS(SELECT * FROM (VALUES('0'),('1'),('2'),('3'),('4'),('5'),('6'),('7'),('8'),('9'),('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 v(t)),
cte2 AS(SELECT * FROM (VALUES('0'),('1'),('2'),('3'),('4'),('5'),('6'),('7'),('8'),('9'),('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 v(t)),
cte3 AS(SELECT * FROM (VALUES('0'),('1'),('2'),('3'),('4'),('5'),('6'),('7'),('8'),('9'),('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 v(t)),
cte4 AS(SELECT * FROM (VALUES('0'),('1'),('2'),('3'),('4'),('5'),('6'),('7'),('8'),('9'),('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 v(t)),
cte5 AS(SELECT * FROM (VALUES('0'),('1'),('2'),('3'),('4'),('5'),('6'),('7'),('8'),('9'),('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 v(t))
INSERT INTO ProductHandles(ID, Used)
SELECT cte1.t + cte2.t + cte3.t + cte4.t + cte5.t, 0
FROM cte1
CROSS JOIN cte2
CROSS JOIN cte3
CROSS JOIN cte4
CROSS JOIN cte5
Run Code Online (Sandbox Code Playgroud)
现在的问题是我需要写这样的东西来从表中获取一个值:
SELECT TOP 1 ID
FROM ProductHandles
WHERE Used = 0
Run Code Online (Sandbox Code Playgroud)
我将在Used列上有索引,所以它会很快.这个问题是它带有顺序:
00000
00001
00002
...
Run Code Online (Sandbox Code Playgroud)
我知道我可以订购NEWID(),但这会慢得多.我知道除非我们指定Order By条款,否则无法保证订购.需要的是相反的.我需要保证混乱,但不是NEWID()每次客户创建订单时都要订购.
我将使用它像:
WITH cte as (
SELECT TOP 1 * FROM ProductHandles WHERE Used = 0
--I don't want to order by newid() here as it will be slow
)
UPDATE cte
SET Used = 1
OUTPUT INSERTED.ID
Run Code Online (Sandbox Code Playgroud)
如果添加标识列的表,并使用order by newid()插入记录时(这将是缓慢的,但它是一个的被从我了解离线进行一次性的事情),那么你可以使用order by在identity列,选择记录的顺序他们插在桌子上.
来自Microsoft Docs中页面的限制和限制部分INSERT:
使用SELECT和ORDER BY来填充行的INSERT查询保证了如何计算标识值,但不保证插入行的顺序.
这意味着,通过执行此操作,您可以有效地使identity列按照与insert...select语句中选定的行相同的随机顺序排序.
此外,没有必要重复相同的cte 5次 - 你已经在重复交叉申请:
CREATE TABLE ProductHandles(sort int identity(1,1), ID char(5), used bit)
;WITH
cte AS(SELECT * FROM (VALUES('0'),('1'),('2'),('3'),('4'),('5'),('6'),('7'),('8'),('9'),('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 v(t))
INSERT INTO ProductHandles(ID, Used)
SELECT a.t + b.t + c.t + d.t + e.t, 0
FROM cte a
CROSS JOIN cte b
CROSS JOIN cte c
CROSS JOIN cte d
CROSS JOIN cte e
ORDER BY NEWID()
Run Code Online (Sandbox Code Playgroud)
然后cte可以有一个order by子句,它保证了与填充此表的select语句返回的行相同的随机顺序:
WITH cte as (
SELECT TOP 1 *
FROM ProductHandles
WHERE Used = 0
ORDER BY sort
)
UPDATE cte
SET Used = 1
OUTPUT INSERTED.ID
Run Code Online (Sandbox Code Playgroud)
您可以在rextester上看到现场演示.(只有数字,因为它花了太长时间)
| 归档时间: |
|
| 查看次数: |
126 次 |
| 最近记录: |