8wDlpd.png
8wDFp9.png
8wDEOx.png
8wDMfH.png
8wDKte.png

如何在 MySQL 中创建序列?

Kjartan 2月前

102 0

我正在尝试在 MySQL 中创建一个序列(我对 SQL 整体上非常陌生)。我正在使用以下代码,但它导致错误:CREATE SEQUENCE ORDID INCREMENT BY 1 START WITH 622;ORDID 指的是...

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

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

帖子版权声明 1、本帖标题:如何在 MySQL 中创建序列?
    本站网址:http://xjnalaquan.com/
2、本网站的资源部分来源于网络,如有侵权,请联系站长进行删除处理。
3、会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。
4、本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
5、站长邮箱:yeweds@126.com 除非注明,本帖由Kjartan在本站《ubuntu》版块原创发布, 转载请注明出处!
最新回复 (0)
  • 将“AUTO_INCREMENT”添加到 ORDID 字段只会导致另一个错误。不过,有一个“INCREMENT”函数。这能行吗?

  • 看看 这篇文章 。我相信它应该能帮助你得到你想要的东西。如果你的表已经存在,并且其中已经有数据,那么你得到的错误可能是由于 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 示例 的链接
    我希望这些信息能有所帮助。

  • 我每次都使用大量代码从头开始创建表(如果出现问题,我会删除表并重新开始)。MySQL 以前从未遇到过 \'numeric(4)\' 问题。

  • 额外的信息:我在 \'phpMyAdmin\' 上使用 MySQL 服务器。不确定这是否有帮助,但我觉得它在 AUTO_INCREMENT 命令上存在问题。

  • Stack Overflow 上还有另一个链接,讨论了 phpMyAdmin 中 AUTO_INCREMENT 的使用:.com/questions/5665571/…

  • 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 语句检索该值。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 serial SET id=LAST_INSERT_ID(id + 1); SELECT LAST_INSERT_ID() AS number; COMMIT; END $$ DELIMITER ;

  • 关于这个十年前的答案,我认为它已从 mysql 手册中删除。这是一个非常粗制滥造的想法,很惊讶他们提出了这个建议。也许我错了,它被移动了还是怎么了?

  • 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.
    

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

  • 你好,Antonov,在像 Firebird 这样的并发 GetSequenceVal 调用中,序列值是否唯一?

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

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

  • 引用 14

    我的意思是你可以使用触发器来做任何事情,它们是一种图灵机,是的,在某些特定的用例中它可能是相关的。

  • twk 2月前 0 只看Ta
    引用 15

    纯粹为了记录这个奇怪的老问题,这里概述了在没有可用序列时模拟序列的标准方法。看来 MySql 没有它们,所以在这里。

    首先,确切的说……

    mysql>  CREATE TABLE `ubersequence` (
        ->  `id` int NOT NULL AUTO_INCREMENT,
        ->  `unused` varchar(32) not null unique,
        ->  PRIMARY KEY (`id`) );
    Query OK, 0 rows affected (0.05 sec)
    
    mysql> insert into ubersequence (unused) values ('snap');
    Query OK, 1 row affected (0.01 sec)
    
    mysql> select * from ubersequence ;
    +----+--------+
    | id | unused |
    +----+--------+
    |  1 | snap   |
    +----+--------+
    1 row in set (0.00 sec)
    

    每次需要下一个值时, just replace in to it ,然后读取新的 ID。

    mysql> replace into ubersequence (unused) values ('snap') ;
    Query OK, 2 rows affected (0.01 sec)
    
    mysql> select * from ubersequence ;
    +----+--------+
    | id | unused |
    +----+--------+
    |  2 | snap   |
    +----+--------+
    1 row in set (0.00 sec)
    
    mysql> replace into ubersequence (unused) values ('snap') ;
    Query OK, 2 rows affected (0.01 sec)
    
    mysql> select * from ubersequence ;
    +----+--------+
    | id | unused |
    +----+--------+
    |  3 | snap   |
    +----+--------+
    1 row in set (0.00 sec)
    

    不要重复超过二十亿次!

    请注意,当然 这两个步骤以及可能更多的步骤必须是代码中的原子事务 .

    感谢@Barmar 明确指出 MySql 没有全局序列。

  • ekse 2月前 0 只看Ta
    引用 16

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

    改变表 ORD 更改 ORDID ORDID int(10) 无符号自动增量;

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

    更改表 ORD AUTO_INCREMENT = 85;

    例如,从 85 开始下一行。

  • 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  |
    
  • 无需任何程序即可从头创建测试数据

    感谢 James Hopbourn 的回答,这里有一些使用该想法的方法。

    这可能是生成具有固定索引(以固定值开始和结束)的测试数据的一个很好的起点。

    为了至少以某种方式提供一个完整的示例,我只添加了随机的 X 和 Y 值:

    -- CREATE TABLE RawData AS
    SELECT 
        Val AS ID,
        floor(RAND() * 1000) AS X,
        floor(RAND() * 1000) AS Y
    FROM 
    (
        WITH RECURSIVE seq AS 
        (
            SELECT 
                1000 AS v 
            UNION ALL 
            SELECT 
                v + 1 
            FROM 
                seq 
            WHERE v < 1030
        ) 
        SELECT v as Val FROM seq 
    ) AS ValsFrom1000to1030;
    

    它将生成如下测试数据:

    +------+------+------+
    |   ID |    X |    Y |
    +------+------+------+
    | 1000 |  157 |  640 |
    ...
    | 1030 |  718 |  902 |
    +------+------+------+
    

    解释:

    • p5

    • p6

    • p7

    • p8

    请查看 MySql/MariaDB CREATE TABLE ... AS 文档以了解详细的列定义,例如键、生成的索引和类型。

    已在 MariaDB 11.3.2 上测试

返回
作者最近主题: