我有下一个 SQL 查询:
const val INSERT_OR_UPDATE_ITEM_SQL = "" +
"INSERT INTO `items` (owner_id, object_id, item_id, count, enchant_level, item_location, item_location_data, custom_type1, custom_type2, duration_left, create_time)" +
"VALUES (?,?,?,?,?,?,?,?,?,?,?) " +
"ON DUPLICATE KEY UPDATE owner_id=?,object_id=?,item_id=?,count=?,enchant_level=?,item_location=?,item_location_data=?,custom_type1=?,custom_type2=?,duration_left=?,create_time=?"
这是 PreparedStatement 的准备:
statement.setString(1, item.ownerId)
statement.setInt(2, item.objectId)
statement.setInt(3, item.template.id)
statement.setInt(4, item.count)
statement.setInt(5, item.enchantLevel)
statement.setString(6, item.itemLocation.name)
statement.setInt(7, item.itemLocationData)
statement.setInt(8, item.customType1)
statement.setInt(9, item.customType2)
statement.setInt(10, item.durationLeft)
statement.setLong(11, item.createTime)
这里的问题是当我尝试执行查询时:
Exception in thread "main" java.sql.SQLTransientConnectionException: (conn=352) Parameter at position 12 is not set
这是因为我有 22 个问题标记而不是 11 个(因为 ON CONFLICT UPDATE)
我的简单任务是制作 INSERT 或 UPDATE
就您的查询而言,(某些)参数需要传递两次(一次用于插入,另一次用于更新)。 MySQL 提供
VALUES(...)
函数 以在更新子句中按列名访问插入值 - 这正是为您省去麻烦。
此外:如果只针对非主键列而不是所有列,则
UPDATE
子句会更好地表达。
假设您的表有列
owner_id, object_id, item_id, cnt, enchant_level
,其中前三列是主键:
insert into items (owner_id, object_id, item_id, cnt, enchant_level)
values (?, ?, ?, ?, ?)
on duplicate key update
set cnt = values(cnt),
enchant_level = values(enchant_level)
或者,如果您运行的是 MySQL 8.0.19 或更高版本,则可以使用新的基于别名的语法(
values()
在 MySQL 中是一个不幸的名称选择,因为它在某种程度上与同音异义 SQL 标准行构造函数冲突):
insert into items (owner_id, object_id, item_id, cnt, enchant_level)
values (?, ?, ?, ?, ?) v
on duplicate key update
set cnt = v.cnt,
enchant_level = v.enchant_level