databaseChangeLog:
- changeSet:
id: ...
author: ...
preConditions:
- one rror: 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
...
也許,我做錯了什么?
uj5u.com熱心網友回復:
你的方法有很多問題。
首先,DELIMITER是mysql客戶端的一個內置命令,它不被MySQL Server的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 不是應該參考當前存在的用戶嗎?
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/324114.html
