如何在 MySQL 中创建序列?

Posted

技术标签:

【中文标题】如何在 MySQL 中创建序列?【英文标题】:How do I create a sequence in MySQL? 【发布时间】:2014-12-22 02:03:24 【问题描述】:

我正在尝试在 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 中没有这样的东西。你想做什么? 在 MySQL 中,您使用具有AUTO_INCREMENT 属性的列。 MySQL 不支持序列 将“AUTO_INCREMENT”添加到 ORDID 字段只会导致另一个错误。不过,有一个“增量”功能。这行得通吗? MariaDB 10.3 将支持序列 (mariadb.com/kb/en/library/sequences) 【参考方案1】:

这是一个解决方案suggested by the MySQl manual:

如果 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 语句检索该值。 mysql_insert_id() C API 函数也可用于获取值。见第 23.8.7.37 节, “mysql_insert_id()”。

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

【讨论】:

这是迄今为止最好的“序列”解决方案,包装到存储过程中: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 ;【参考方案2】:

查看this article。我相信它应该可以帮助您获得想要的东西。如果您的表已经存在,并且其中已经有数据,那么您得到的错误可能是由于 auto_increment 试图为其他记录分配一个已经存在的值。

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

如果没有关于具体错误的更多细节,很难提供更具体的帮助。

更新

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

This link 也有助于描述 auto_increment 的用法。 设置 AUTO_INCREMENT 值似乎是 table option,而不是专门指定为列属性的东西。

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

ALTER TABLE ORD AUTO_INCREMENT = 622;

更新 2 这是working sqlfiddle example 的链接,使用自动增量。 我希望这些信息对您有所帮助。

【讨论】:

感谢您的帮助,但现在 MySQL 声称此代码包含“不正确的列说明符”。 我每次都使用大量代码从头开始创建表(如果出现问题,我会删除表并重新开始)。 MySQL 之前从未遇到过“numeric(4)”的问题。 忽略我之前的评论。我已经删除了它,因为它不正确。 额外信息:我在“phpMyAdmin”上使用 MySQL 服务器。不确定这是否有帮助,但我觉得 AUTO_INCREMENT 命令有问题。 Stack Overflow 上还有一个链接在这里讨论了 phpMyAdmin 中 AUTO_INCREMENT 的使用:***.com/questions/5665571/…【参考方案3】:

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】:

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

中所述

【讨论】:

【参考方案5】:

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

【讨论】:

以上是关于如何在 MySQL 中创建序列?的主要内容,如果未能解决你的问题,请参考以下文章

如何在clojure中创建一个惰性随机数序列

如何在 kafka 中创建自定义序列化程序?

即使删除一个数字,如何在序列号中创建列

如何在 HSQL DB 中创建具有最大行值的序列?

如何在Postgresql中创建序列数并应用在数据表

如何在Postgresql中创建序列数并应用在数据表