如何识别YugabyteDB中upsert操作是插入还是更新行
问题
请问是否存在可行方法,可通过Java或Golang驱动识别如下所示的upsert操作对目标行执行的是插入还是更新操作?
UPDATE test set value = 'value1', checkpoint = 'cas1' WHERE key = 'key1' IF checkpoint = '' OR NOT EXISTS;
解答
你写的这条带IF条件的UPDATE属于YCQL接口下的轻量事务(LWT)操作,这类语句执行后的返回结果本身就携带操作类型标识,不需要额外做二次查询,Java、Golang驱动都可以直接读取返回值判断:
- Java驱动(兼容官方Yugabyte JDBC驱动、DataStax Java驱动)
语句执行后拿到ResultSet对象,首先通过[applied]字段判断条件是否命中、操作是否执行成功。如果操作执行成功,且返回结果中不存在原行的字段值,说明本次是触发NOT EXISTS逻辑的插入操作;如果返回结果携带了操作前的旧行数据,说明是更新操作。
参考代码:PreparedStatement pstmt = session.prepare("UPDATE test set value = 'value1', checkpoint = 'cas1' WHERE key = 'key1' IF checkpoint = '' OR NOT EXISTS;"); ResultSet rs = session.execute(pstmt.bind()); Row resRow = rs.one(); boolean opApplied = resRow.getBool("[applied]"); if (opApplied) { // 旧checkpoint值为空,说明是首次插入 boolean isInsert = resRow.isNull("checkpoint"); boolean isUpdate = !isInsert; } - Golang驱动(兼容gocql、Yugabyte维护的gocql分支)
执行LWT语句时调用ScanCAS方法获取结果,方法返回的第一个bool值代表操作是否执行成功,同时会把操作前的旧行数据扫描到传入的变量中。如果操作执行成功且扫描到的旧行无有效数据,说明是插入操作;如果扫描到了旧行的有效字段值,说明是更新操作。
参考代码:var oldData struct { Value string Checkpoint string } applied, err := session.Query("UPDATE test set value = 'value1', checkpoint = 'cas1' WHERE key = 'key1' IF checkpoint = '' OR NOT EXISTS;").ScanCAS(&oldData.Value, &oldData.Checkpoint) if err == nil && applied { // 可结合自身业务的初始值规则判断,这里以checkpoint初始为空为例 isInsert := oldData.Checkpoint == "" isUpdate := !isInsert }
如果你使用的是YugabyteDB的YSQL(PostgreSQL兼容)接口,可以在UPDATE语句末尾追加
RETURNING *子句,通过判断返回的旧记录是否为空,区分插入和更新操作,判断逻辑和上述YCQL场景一致。
内容的提问来源于stack exchange,提问作者dh YB
相关产品推荐
相关产品推荐

