内容来自对 chatgpt 的咨询
前言(INSERT...ON DUPLICATE KEY UPDATE 介绍)
当你在MySQL中插入数据,如果唯一键发生冲突,可以使用 INSERT...ON DUPLICATE KEY UPDATE 语句实现插入和更新操作。其基本语法如下:
INSERT INTO table (col1, col2, ...colN)
VALUES (value1, value2, ...valueN)
ON DUPLICATE KEY UPDATE
col1 = value1, col2 = value2, ...colN = valueN;
这条语句的逻辑是:如果插入的记录与表中现有记录的唯一索引或主键冲突,那么就执行 UPDATE 操作。如果没有冲突,那么就执行 INSERT 操作。
例如,表users有唯一键user_id,现在想插入或更新一条 user_id=1 的记录:
INSERT INTO users (user_id, user_name, user_email)
VALUES (1, 'John', 'john@example.com')
ON DUPLICATE KEY UPDATE
user_name='John', user_email = 'john@example.com';
在以上的例子中,如果 user_id=1 的这条记录已经存在,在执行此语句后,user_name 和 user_email 会被更新为新的值。如果 user_id=1 的记录不存在,那么这个语句就会新插入一条记录。
注意
在 ON DUPLICATE KEY UPDATE 后面的赋值表达式中,你不能使用 VALUES(col) 获取插入语句中的值,因为它可能被认为是值的字面量而不是列表的值。你应该直接使用要输入的值或者变量。
在 grom 中使用 mysql 的这种语法效果
可以使用GORM的 Exec()
函数,执行自定义的SQL语句来实现MySQL的 INSERT...ON DUPLICATE KEY UPDATE
功能。下面这段代码段会尝试插入users数组中的每个用户,并在发生主键冲突的情况下,更新冲突数据的user_name和user_email字段。需要注意的是,VALUES(user_name), VALUES(user_email)中的VALUES函数能引用到插入时的真实数据,占位符会被替换成真实数据。
users := []User{
{UserID: 1, UserName: "John1", UserEmail: "john1@example.com"},
{UserID: 2, UserName: "John2", UserEmail: "john2@example.com"},
{UserID: 3, UserName: "John3", UserEmail: "john3@example.com"},
}
valueStrings := []string{}
valueArgs := []interface{}{}
// 构造插入语句和冲突时的更新语句
for _, user := range users {
valueStrings = append(valueStrings, "(?, ?, ?)")
valueArgs = append(valueArgs, user.UserID)
valueArgs = append(valueArgs, user.UserName)
valueArgs = append(valueArgs, user.UserEmail)
}
stmt := fmt.Sprintf("INSERT INTO users (user_id, user_name, user_email) VALUES %s"+
"ON DUPLICATE KEY UPDATE user_name=VALUES(user_name), user_email=VALUES(user_email)",
strings.Join(valueStrings, ","))
db.Exec(stmt, valueArgs...)
注意点
-
注意使用这种方法时要确保你对用户的数据有100%的信任,或者已经进行了相应的清理,以防止SQL注入攻击。
-
在执行 SQL 语句之前,需要检查 users 数组是否为空。原因是如果 users 长度为0,则跳过构造和执行 SQL 语句的步骤。如果 users 数组为空,那么在构造 SQL 插入语句的过程中,valueStrings 和 valueArgs 切片都将保持为空。这意味着 stmt 字符串将尝试插入空的值,形如:
INSERT INTO users VALUES ON DUPLICATE KEY UPDATE
,这将导致 SQL 语法错误,因为在 "VALUES" 关键字后并未提供任何数据。
- DUPLICATE golang INSERT UPDATE gromduplicate golang insert update duplicate insert update mysql into duplicate replace insert duplicate update mysql key duplicate update key on mybatisplus duplicate update key 子句duplicate效果update 语法sqlalchemy duplicate insert insert_update insert_update组件kettle insert