【问题标题】:How to create two auto increment columns using MySQL?如何使用 MySQL 创建两个自增列?
【发布时间】:2021-11-23 22:30:02
【问题描述】:
databaseChangeLog:
  - changeSet:
      id: ...
      author: ...
      preConditions:
        - onError: MARK_RAN
        - not:
            - tableExists:
                tableName: ORDERS
      changes:
        - createTable:
            tableName: ORDERS
            columns:
              - column:
                  name: ID
                  type: INT
                  autoIncrement: true
                  constraints:
                    primaryKey: true
              - column:
                  name: ID_USER
                  type: INT
              ...

        - sql:
            "DELIMITER $$
             CREATE FUNCTION autoInc ()
                 RETURNS INT(10)
                 BEGIN
                     DECLARE getCount INT(10);

                     SET getCount = (
                         SELECT COUNT(USER_ID)
                         FROM ORDERS) + 1;

                     RETURN getCount;
                 END$$
             DELIMITER ;"

我正在使用这种方法。当我在订单中插入新条目时,它也应该增加 user_id。因为我需要 user_id 作为另一个自动增量列。我正在使用 Liquibase 迁移来创建此表,但出现错误:

Caused by: java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'DELIMITER $$ CREATE FUNCTION autoInc () RETURNS INT(10) BEGIN DECLARE getCount I' at line 1
    ...

也许,我做错了什么?

【问题讨论】:

  • MySQL 不支持每个表有多个自增列。据我所知,只有 PostgreSQL 可以。我不明白你为什么需要这个,但如果你真的需要,我可以看到的选项是创建一个带有一些生成逻辑的“生成”列,或者使用触发器来填充第二列的值。

标签: mysql sql exception syntax-error liquibase


【解决方案1】:

您的方法存在各种问题。

首先,DELIMITER 是一个built-in command of the mysql client,它不能被 MySQL 服务器的 SQL 解析器识别。另外,我想知道你为什么不使用https://docs.liquibase.com/change-types/pro/create-function.html

其次,您模拟第二次自动增量的方法存在缺陷。它受到竞争条件的影响,因为如果多个并发事务正在插入一行,它们都会从您的 SELECT COUNT(*) 查询中获得相同的结果,因此都尝试为 user_id 插入相同的值。

MySQL 中真正的自动增量机制在事务范围之外工作,因此可以确保多个会话读取每个表的相同增量值。当每个会话递增表的计数器时,还有一个简短的表锁。

为了使您的函数免受竞争条件的影响,您必须锁定表,以确保一次只有一个会话可以读取该值。

第三,如果您要计算下一个更高的值,自动增量应该基于MAX(USER_ID),而不是COUNT(USER_ID)。如果您要从表中删除几行,那么COUNT(USER_ID) 将生成一个低于最大值的值。

最后,我不明白您为什么要让订单表的 user_id 自动递增。您真的希望 每个 订单生成一个新的 user_id 吗? user_id 不应该引用当前存在的用户吗?

【讨论】:

    猜你喜欢
    • 2023-03-08
    • 2019-12-29
    • 2011-07-21
    • 1970-01-01
    • 1970-01-01
    • 2020-11-20
    • 1970-01-01
    • 2016-03-23
    • 2013-07-27
    相关资源
    最近更新 更多