如何在MySQL中创建序列?

How do I create a sequence in MySQL?

提问人:Ben 提问时间:10/27/2014 最后编辑:Ben 更新时间:10/19/2023 访问量:222392

问:

我正在尝试在MySQL中创建一个序列(我对整个SQL非常陌生)。我正在使用以下代码,但它会导致错误:

CREATE SEQUENCE ORDID INCREMENT BY 1 START WITH 622;

ORDID 是指我正在使用的表中的字段。如何正确创建序列?

编辑:

据称,MySQL不使用序列。我现在使用以下代码,但这也会导致错误。如何解决这些问题?

CREATE TABLE ORD (
ORDID NUMERIC(4) NOT NULL AUTO_INCREMENT START WITH 622,
//Rest of table code

编辑:

我想我找到了解决方法。对于phpMyAdmin(我正在使用),您可以使用以下代码。

ALTER TABLE ORD AUTO_INCREMENT = 622;

我不知道为什么它更喜欢这个,但如果其他人需要帮助,那么你去吧。:)

MySQL SQL 序列

评论

0赞 Barmar 10/27/2014
MySQL中没有这样的东西。你想做什么?
3赞 Barmar 10/27/2014
在 MySQL 中,使用具有 attribute 的列。AUTO_INCREMENT
2赞 10/27/2014
MySQL不支持序列
0赞 Ben 10/27/2014
将“AUTO_INCREMENT”添加到 ORDID 字段只会导致另一个错误。不过,有一个“INCREMENT”功能。那行得通吗?
1赞 Jared Beck 12/28/2017
MariaDB 10.3 将支持序列 (mariadb.com/kb/en/library/sequences)

答:

32赞 Daileyo 10/27/2014 #1

看看这篇文章。我相信它应该帮助你得到你想要的东西。如果表已存在,并且其中已包含数据,则出现错误可能是由于auto_increment尝试为其他记录分配已存在的值。

简而言之,正如其他人在评论中已经提到的那样,在Oracle中思考和处理的序列在MySQL中并不存在。但是,您可以使用auto_increment来完成您想要的。

如果没有关于特定错误的更多详细信息,就很难提供更具体的帮助。

更新

CREATE TABLE ORD (
  ORDID INT NOT NULL AUTO_INCREMENT,
  //Rest of table code
  PRIMARY KEY (ordid)
)
AUTO_INCREMENT = 622;

此链接还有助于描述auto_increment的用法。 设置AUTO_INCREMENT值似乎是一个表选项,而不是专门指定为列属性的选项。

此外,根据上面的链接之一,您也可以通过更改表来设置自动递增开始值。

ALTER TABLE ORD AUTO_INCREMENT = 622;

更新 2下面是一个使用自动增量的工作 sqlfiddle 示例的链接。
我希望这些信息有所帮助。

评论

0赞 Ben 10/27/2014
感谢您的帮助,但现在MySQL声称此代码包含“不正确的列说明符”。
0赞 Ben 10/27/2014
我每次都使用大量代码从头开始创建表(如果出现问题,我会删除表并重新开始)。MySQL 以前从未遇到过 “numeric(4)” 的问题。
0赞 Daileyo 10/27/2014
无视我之前的评论。我已经删除了它,因为它是不正确的。
0赞 Ben 10/27/2014
额外的信息:我正在使用“phpMyAdmin”上的MySQL服务器。不确定这是否有帮助,但我觉得AUTO_INCREMENT命令有问题。
0赞 Daileyo 10/27/2014
在 Stack Overflow 上还有另一个链接,讨论了 phpMyAdmin 中 AUTO_INCREMENT 的使用: stackoverflow.com/questions/5665571/...
46赞 pupitetris 9/10/2015 #2

这是 MySQl 手册建议的解决方案:

如果 expr 作为 LAST_INSERT_ID() 的参数给出,则 参数由函数返回,并被记住为下一个参数 LAST_INSERT_ID() 返回的值。这可用于模拟 序列:

创建一个表来保存序列计数器并对其进行初始化:

    mysql> CREATE TABLE sequence (id INT NOT NULL);
    mysql> INSERT INTO sequence VALUES (0);

使用该表生成如下所示的序列号:

    mysql> UPDATE sequence SET id=LAST_INSERT_ID(id+1);
    mysql> SELECT LAST_INSERT_ID();

UPDATE 语句递增序列计数器,并导致下一次调用 LAST_INSERT_ID() 返回更新的值。这 SELECT 语句检索该值。The mysql_insert_id() C API 函数也可用于获取值。参见第 23.8.7.37 节, “mysql_insert_id()”。

您可以在不调用 LAST_INSERT_ID() 的情况下生成序列,但 以这种方式使用函数的效用是 ID 值为 在服务器中作为最后一个自动生成的值进行维护。它 是多用户安全的,因为多个客户端可以发出 UPDATE 语句,并使用 SELECT 语句获取自己的序列值 (或 mysql_insert_id()),而不影响或受其他影响 生成自己的序列值的客户端。

评论

0赞 Dai 10/22/2020
这是迄今为止最好的“序列”解决方案,包装到存储过程中:DELIMITER $$ CREATE PROCEDURE seq_next_id() BEGIN START TRANSACTION; UPDATE sequence SET id=LAST_INSERT_ID(id + 1); SELECT LAST_INSERT_ID() AS number; COMMIT; END $$ DELIMITER ;
3赞 JNZ 3/31/2016 #3

通过创建增量表,您应该注意不要删除插入的行。这样做的原因是为了避免在数据库中存储带有 ID-s 的大型哑数据。否则,在mysql重新启动的情况下,它将获得最大现有行,并从该点继续递增,如文档中所述 http://dev.mysql.com/doc/refman/5.0/en/innodb-auto-increment-handling.html

1赞 Marek Lisiecki 4/25/2018 #4

如果您需要与AUTO_INCREMENT不同的 sth,您仍然可以使用触发器。

8赞 Antonov Gazolov 10/19/2019 #5

SEQUENCES like it works on firebird:

-- =======================================================

CREATE TABLE SEQUENCES  
(  
  NM_SEQUENCE VARCHAR(32) NOT NULL UNIQUE,  
  VR_SEQUENCE BIGINT      NOT NULL  
);  

-- =======================================================
-- 创建一个序列 sSeqName 并设置其初始值。
-- =======================================================

DROP PROCEDURE IF EXISTS CreateSequence;  

DELIMITER :)  
CREATE PROCEDURE CreateSequence( sSeqName VARCHAR(32), iSeqValue BIGINT )  
BEGIN  
  IF NOT EXISTS ( SELECT * FROM SEQUENCES WHERE (NM_SEQUENCE = sSeqName) ) THEN  
    INSERT INTO SEQUENCES (NM_SEQUENCE, VR_SEQUENCE)  
    VALUES (sSeqName   , iSeqValue  );  
  END IF;  
END :)  
DELIMITER ;  

-- CALL CreateSequence( 'MySequence', 0 );  

-- =======================================================================
-- 将 sSeqName 的序列值递增 iIncrement 并返回。
-- 如果 iIncrement 为零,则返回 sSeqName 的当前值。

-- =======================================================================

DROP FUNCTION IF EXISTS GetSequenceVal;  

DELIMITER :)  
CREATE FUNCTION GetSequenceVal( sSeqName VARCHAR(32), iIncrement INTEGER )  
RETURNS BIGINT  -- iIncrement can be negative  
BEGIN  
  DECLARE iSeqValue BIGINT;  

  SELECT VR_SEQUENCE FROM SEQUENCES  
  WHERE  ( NM_SEQUENCE = sSeqName )  
  INTO   @iSeqValue;  

  IF ( iIncrement <> 0 ) THEN  
    SET @iSeqValue = @iSeqValue + iIncrement;  

    UPDATE SEQUENCES SET VR_SEQUENCE = @iSeqValue  
    WHERE  ( NM_SEQUENCE = sSeqName );  
  END IF;

  RETURN @iSeqValue;
END :)  
DELIMITER ;  

-- SELECT GetSequenceVal('MySequence', 1);  -- Adds 1 to MySequence value and returns it.

-- ===================================================================

评论

4赞 Moby Duck 1/28/2021
笑脸分隔符本身就值得一票
0赞 Steve Kramer 10/1/2022
嗨,安东诺夫,序列值对于像 Firebird 这样的并发 GetSequenceVal 调用是唯一的吗?
0赞 Steve Stilson 8/12/2022 #6

我发现这对我有用。告诉 MYSQL 您正在更改列,但保留相同的名称:

alter table ORD change ORDID ORDID int(10) unsigned auto_increment;

这将告知 ORD 表中的 ORDID 列开始自动递增。然后发出以下命令:

更改表 ORD AUTO_INCREMENT = 85;

例如,从 85 开始下一行。

0赞 James Hopbourn 10/19/2023 #7
WITH RECURSIVE seq AS (
  SELECT 1 AS v UNION ALL SELECT v + 1 FROM seq WHERE v < 30
) SELECT v FROM seq;
+----+
| v  |
+----+
| 1  |
| 2  |
| 3  |
| 4  |
| 5  |
| 6  |
| 7  |
| 8  |
| 9  |

评论

1赞 DailyLearner 10/20/2023
为了读者的利益,提供一些关于答案的解释总是好的。