在 MySQL 中创建“数字表”
Posted
技术标签:
【中文标题】在 MySQL 中创建“数字表”【英文标题】:Creating a "Numbers Table" in MySQL 【发布时间】:2012-03-17 15:43:06 【问题描述】:我正在尝试在 mysql 中生成一个连续数字的大表。
我只想要 2 列;一个主键和一个范围为 0-X 的数字列,其中 X 非常大。大约。 64,000 行应该这样做。我试过这段代码没有成功:
CREATE TABLE numbers (
number INT NOT NULL
CONSTRAINT XPKnumbers
PRIMARY KEY CLUSTERED (number)
)
INSERT INTO numbers (number) VALUES (0)
DECLARE @i INT
SET @i = 20
WHILE 0 < @i
BEGIN
INSERT INTO numbers (number)
SELECT number + (SELECT 1 + Max(number) FROM numbers)
FROM numbers
SET @i = @i - 1
END
SELECT * FROM numbers
我得到这个错误:
#1064 - 您的 SQL 语法有错误;检查与您的 MySQL 服务器版本相对应的手册,以在第 3 行的 'CONSTRAINT XPKnumbers PRIMARY KEY CLUSTERED (number) ) INSERT INTO n' 附近使用正确的语法
有人对这项工作有什么建议吗?
【问题讨论】:
添加`insert into table(columns) values(values)的'values'部分 【参考方案1】:您缺少分号、逗号,即使在更正语法之后,每次从表中选择 max 以在循环中再插入一行仍然不是一个好主意。
删除它并使用来自http://use-the-index-luke.com/blog/2011-07-30/mysql-row-generator 的生成器:
CREATE OR REPLACE VIEW generator_16
AS SELECT 0 n UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL
SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL
SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL
SELECT 9 UNION ALL SELECT 10 UNION ALL SELECT 11 UNION ALL
SELECT 12 UNION ALL SELECT 13 UNION ALL SELECT 14 UNION ALL
SELECT 15;
CREATE OR REPLACE VIEW generator_256
AS SELECT ( ( hi.n << 4 ) | lo.n ) AS n
FROM generator_16 lo, generator_16 hi;
CREATE OR REPLACE VIEW generator_4k
AS SELECT ( ( hi.n << 8 ) | lo.n ) AS n
FROM generator_256 lo, generator_16 hi;
CREATE OR REPLACE VIEW generator_64k
AS SELECT ( ( hi.n << 8 ) | lo.n ) AS n
FROM generator_256 lo, generator_256 hi;
CREATE OR REPLACE VIEW generator_1m
AS SELECT ( ( hi.n << 16 ) | lo.n ) AS n
FROM generator_64k lo, generator_16 hi;
如果出于某种原因你真的需要一个数字表,那就这样做:
INSERT INTO numbers(number)
SELECT n FROM generator_64k WHERE n < 64000
【讨论】:
哇,这就是我要找的东西。我还不明白代码,但我知道它可以工作。非常感谢! 好吧,这快把我逼疯了。这段代码正是我需要的。它在 phpmyadmin 和 navicat 中工作,但是当我将它带入 dreamweaver 的 sql 编辑器时,它告诉我有一个 mysql 错误。当我保留查询代码(尽管有错误)并尝试测试网页时,页面返回:您的 SQL 语法有错误;检查与您的 MySQL 服务器版本相对应的手册,以在第 1 行的 'CREATE OR REPLACE VIEW generator_256 AS SELECT ( ( hi.n 当我尝试运行查询以将行插入到 phpmyadmin 中的数字表中时,(我无法将所有代码放入 cmets 框中),我得到:#1064 - 你有SQL 语法错误;检查与您的 MySQL 服务器版本相对应的手册,以在第 9 行的“CREATE OR REPLACE VIEW generator_256 AS SELECT ((hi.n <<4) | lo.n) AS n”附近使用正确的语法 好的,尽管有错误,但视图以某种方式创建并且似乎正在工作。问题似乎暂时解决了。谢谢! 字节移位和按位或。这就是二进制魔法。好的!只是自己查了一下。【参考方案2】:这是一种生成数字列表的快速简单的方法。使用 MySQL 运行此查询会在 0.561 秒内生成一个包含 64,000 个数字的列表。
set @i = 0;
SELECT * FROM (
SELECT @i:=@i+1 AS IndexNo FROM my_table -- any real table can be used here
HAVING
@i < 64000
)x
【讨论】:
【参考方案3】:您在列和约束声明之间缺少逗号:
CREATE TABLE numbers (
number INT NOT NULL,
CONSTRAINT XPKnumbers
PRIMARY KEY CLUSTERED (number)
)
【讨论】:
【参考方案4】:从 MySQL 8.0 开始,您可以使用 RECURSIVE CTE 生成计数表:
SET @@cte_max_recursion_depth = 5000;
WITH RECURSIVE cte AS
(
SELECT 1 AS i
UNION ALL
SELECT i+1
FROM cte
WHERE i < 3000
)
SELECT *
FROM cte;
DBFiddle Demo
【讨论】:
【参考方案5】:我今天需要在 MySQL 中创建一个数字表,但没有创建视图对象的权限,所以决定修改 the earlier answer by @piotrm。
因此,一个具有一点“有趣”、二进制风格数学的 CTE 可以代替持久化对象来完成这项工作:
WITH n (number) AS (
SELECT 0
UNION ALL SELECT 1
UNION ALL SELECT 2
UNION ALL SELECT 3
UNION ALL SELECT 4
UNION ALL SELECT 5
UNION ALL SELECT 6
UNION ALL SELECT 7
)
SELECT (d.number * Pow(8, 3))
+ (c.number * Pow(8, 2))
+ (b.number * Pow(8, 1))
+ (a.number * Pow(8, 0)) AS number
FROM n AS a
CROSS
JOIN n AS b
CROSS
JOIN n AS c
CROSS
JOIN n AS d
;
这将为您生成 4,096 个数字,并且可以轻松扩展该模式以根据需要为您提供更多。
P.S.:@piotrm 的答案中的位移魔法很酷,但我发现它更难理解......因此我换成了一些“简单”的数学。
【讨论】:
以上是关于在 MySQL 中创建“数字表”的主要内容,如果未能解决你的问题,请参考以下文章