美文网首页
Mysql使用序列

Mysql使用序列

作者: 子宇楚歌 | 来源:发表于2023-07-18 17:08 被阅读0次

mysql官方目前仍不支持序列,当前docker镜像mysql最新版本为8.0.33,经测试不支持

解决方案一:自定义序列

通过创建一个序列表,定义有序列名,步长,当前值等,再创建自定义函数nextval, currval等

解决方案二:选择非官方版本mysql

1. mysql的阿里云版本alisql支持序列,对于使用阿里云RDS的数据库选择mysql即可

2. 选择mysql的替代版mariadb,mariadb10.4开始支持序列

不同版本的序列语法略有不同

mariadb和alisql8.0创建和删除序列的语法基本一致

```

-- 创建序列

CREATE SEQUENCE student_seq [STARTWITH 1] [MINVALUE 1] [MAXVALUE 999999] [INCREMENTBY 1] [CACHE 100| NOCACHE] [CYCLE|NOCYCLE];

-- 删除序列

DROP SEQUENCE IF EXISTS student_seq;

```

使用序列作为列默认值

mariadb支持DDL直接指定nextval作为默认值

```

CREATE TABLE `student` (

        `id` bigint(20) NOT NULL DEFAULT NEXTVAL(student_seq) COMMENT 'ID',

        `name` varchar(20) NOT NULL COMMENT '姓名',

        PRIMARY KEY (`id`),

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='学生表';

```

mariadb也支持使用触发器的方式设置序列为默认值

注意:mariadb对于非空数值列插入前会自动使用默认值0,判断的时候不是null

```

CREATE TRIGGER student_sequence_trigger BEFORE INSERT

ON student FOR EACH ROW

IF new.id = 0 THEN

    SET new.id = nextval(student_seq);

END IF;

```

alisql8.0只支持使用触发器的方式设置序列为默认值

```

CREATE TRIGGER student_sequence_trigger BEFORE INSERT

ON student FOR EACH ROW

IF new.id IS NULL THEN

    SET new.id = nextval(student_seq);

END IF;

```

为了兼容本地mariadb和阿里云服务器的兼容性写法

```

CREATE TABLE `student` (

        `id` bigint(20) NOT NULL COMMENT 'ID',

        `name` varchar(20) NOT NULL COMMENT '姓名',

        PRIMARY KEY (`id`),

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='学生表';

DELIMITER $$

CREATE TRIGGER student_sequence_trigger BEFORE INSERT

ON student FOR EACH ROW

-- id不可为空时,alisql的new.id是null,mariadb的new.id是0

IF (new.id IS NULL OR new.id = 0) THEN

    SET new.id = nextval(student_seq);

END IF;

$$

DELIMITER ;

```

本想使用alisql的docker镜像本地搭建数据库测试,但奈何alisql的docker镜像版本目前最高只有5.6

另外,alisql还有诸多限制:

1. alisql不支持动态创建sequence,使用prepare对创建sequence的动态sql预处理会导致mysql服务器挂掉,不知道什么原因,联系阿里云的技术支持也没个结果。如果创建sequence需要动态指定初始值可以分为两步,先直接创建sequence,指定初始值为1,再更新

```

-- mariadb不支持update sequence,想要更新需要使用select setval(student_seq, maxId)

SET @seqStr ='UPDATE student_seq SET start = @maxId';

SET @sqlStr = REPLACE(@seqStr,'@maxId', maxId);

PREPARE sqlStrFROM @sqlStr;

EXECUTE sqlStr;

```

2. alisql不支持动态创建触发器,而且也不能在存储过程中创建触发器,这也是官方mysql的限制。mariadb创建触发器支持CREATE TRIGGER IF NOT EXISTS或者CREATE OR REPLACE TRIGGER,alisql只支持直接CREATE TRIGGER。

使用prepare动态创建触发器报错:

This command is not supported in the prepared statement protocol yet

在存储过程中创建触发器报错:

Can't create a TRIGGER from within another stored routine

想要使用动态sql创建触发器目前我想到的解决方案只有通过上层应用实现,如通过mybatis拼串后程序调用执行,又因为这是数据库结构变更,需要用flyway管理,采用java migration调用:

```

// TriggerMapper.xml

<select id="createTrigger">

    CREATE TRIGGER student${suffix}_sequence_trigger BEFORE INSERT

    ON student${suffix} FOR EACH ROW

    IF (new.id IS NULL OR new.id = 0) THEN

        SET new.id = nextval(student_seq);

    END IF;

</select>

// java migration,和sql文件migration效果相同

@Component

public class R__Create_trigger extends BaseJavaMigration {

    @Autowired

    private TriggerMapper triggerMapper;

    @Override

    public void migrate(Context context) throws Exception {

        // 获取动态参数后传给mapper拼串

        triggerMapper.createTrigger(suffix)

    }

}

```

测试环境:

alisql8.0.28(阿里云)

mariadb10.6.5

参考链接:

mariadb和对应的mysql版本功能对比

阿里云sequence引擎

相关文章

  • MySQL 教程下

    AUTO_INCREMENT 详解 MySQL 中最简单使用序列的方法就是使用 AUTO_INCREMENT 来定...

  • mysql数据库实现nextval函数

    在oracle中使用序列(Sequence)来处理主键字段,现在想要在Mysql中也实现类似的效果。 1、新建序列...

  • 数据库序列

    创建序列 查询序列 使用序列 使用序列下一个值 序列名.nextval 使用序列当前值 序列名.currva...

  • 如何存储字典类型的值

    MySQL:使用MySQL插入数据前确保数据库和插入的表已经存在这里用join方法将序列中的元素以指定的字符连接生...

  • MyBatis中调用Mysql存储过程实现序列码自增

    背景 项目中使用mysql作为数据库,针对项目中各种需要自增返回序列码值的场景(批次ID数据、自定义规则的序列码I...

  • Shell 小技巧

    使用shell求DNA序列的反向序列: 使用Shell 求 DNA 的互补序列: 使用 Shell 求DNA反向互...

  • mysql使用自增主键有何优势

    mysql使用什么字段做主键,是重点考虑两方面:业务场景和效率问题。在满足业务场景的前提下,使用自增序列做主键是最...

  • C#序列化

    序列化操作 序列化对象声明 对类使用序列化时,标注那些不需要序列化的字段。 序列化只能针对字段使用。 使用序列化相...

  • MySql序列生成

    序号序列 常见场景: 为每行记录添加序号 日期序列 常见场景: 生成某段范围内的时间(如某月每天, 某天每时等)生...

  • brew mysql 安装后进不去(forgot passwor

    使用brew安装mysql 但是使用mysql.server start 启动后使用mysql -uroot提示访...

网友评论

      本文标题:Mysql使用序列

      本文链接:https://www.haomeiwen.com/subject/bugnudtx.html