在 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 中创建“数字表”的主要内容,如果未能解决你的问题,请参考以下文章

数据库中创建一个学生表

在mysql中创建出来的数据表,性别用这个类型enum(‘男’,‘女'),为啥不显示呢,如图

是否可以在 sql 语句中定义表?

在VC中创建Mysql数据库

在一个语句中创建一个带有名称的数字向量?

如何在mysql中创建存储过程