如何在MySQL中创建序列?

41

我正在尝试在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;

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


3
在MySQL中,你可以使用带有 AUTO_INCREMENT 属性的列。 - Barmar
2
MySQL不支持序列。 - user330315
"引起了另一个错误" --- 您没有提供带有目的的消息吗? - zerkms
可能是如何在MySQL中生成动态序列表?的重复问题。 - Jocelyn
1
MariaDB 10.3将支持序列(https://mariadb.com/kb/en/library/sequences/)。 - Jared Beck
显示剩余2条评论
7个回答

46

这是MySQL手册推荐的解决方案:

If expr is given as an argument to LAST_INSERT_ID(), the value of the argument is returned by the function and is remembered as the next value to be returned by LAST_INSERT_ID(). This can be used to simulate sequences:

Create a table to hold the sequence counter and initialize it:

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

Use the table to generate sequence numbers like this:

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

The UPDATE statement increments the sequence counter and causes the next call to LAST_INSERT_ID() to return the updated value. The SELECT statement retrieves that value. The mysql_insert_id() C API function can also be used to get the value. See Section 23.8.7.37, “mysql_insert_id()”.

You can generate sequences without calling LAST_INSERT_ID(), but the utility of using the function this way is that the ID value is maintained in the server as the last automatically generated value. It is multi-user safe because multiple clients can issue the UPDATE statement and get their own sequence value with the SELECT statement (or mysql_insert_id()), without affecting or being affected by other clients that generate their own sequence values.


这是目前最佳的“序列”解决方案,将其封装成存储过程: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 ;``` - Dai

32

请查看这篇文章。我相信它应该能帮助您获得您想要的内容。如果您的表已经存在,并且已经有数据,那么您遇到的错误可能是由于auto_increment尝试为其他记录分配已经存在的值所致。

简而言之,正如其他人在评论中已经提到的,Oracle中被认为和处理的sequences,在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示例的链接。
希望这些信息能够有所帮助。


谢谢您的帮助,但现在MySQL声称这段代码包含“不正确的列说明符”。 - Ben
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Ben
请忽略我之前的评论。我已将其删除,因为它是不正确的。 - Daileyo
额外的信息:我正在使用“phpMyAdmin”上的MySQL服务器。不确定是否有帮助,但我觉得它与AUTO_INCREMENT命令有问题。 - Ben
这里在 Stack Overflow 上还有一个链接讨论了在 phpMyAdmin 中使用 AUTO_INCREMENT,链接如下:https://dev59.com/pG035IYBdhLWcg3wBLXb#18942684 - Daileyo

8
“SEQUENCES像在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
嗨 Antonov,如果像Firebird一样进行并发的GetSequenceVal调用,那么序列值是否唯一呢? - Steve Kramer

3

1
如果您需要的不是自动递增,仍然可以使用触发器。

0
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
为了读者的利益,提供一些关于答案的解释总是很好的。 - undefined

0

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

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

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

ALTER TABLE ORD AUTO_INCREMENT = 85;

例如,从85开始下一行。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接