☰
仓颉标准库 database.sql 之 UpdateResult 接口详解:掌握 Insert/Update/Delete 执行结果处理
2026/10/15 2:51:12 网站建设 项目流程
  • 人工智能
  • AI 技能
  • 文档
  • 开发工具

【免费下载链接】DocAgent

项目地址:https://gitcode.com/Cangjie-SIG/DocAgent
点击查看免费下载

UpdateResult是仓颉标准库std.database.sql包中专门承载数据变更类 SQL 语句执行结果的接口,它通过rowCount与lastInsertId两个属性,让开发者能够准确获知每次INSERT、UPDATE、DELETE语句影响的行数以及自增主键等信息。阅读本文后,你将掌握UpdateResult的接口定义、属性语义,以及结合Statement.update()在实际增删改场景中的完整用法。

接口定位:数据变更语句的结果载体

std.database.sql包为仓颉语言提供了访问数据库的通用接口,配合数据库驱动Driver完成对数据库的各项操作。在该包中,SQL 语句的执行结果被划分为两类接口:

  • QueryResult:执行SELECT查询语句产生的结果接口,用于遍历查询到的数据行;
  • UpdateResult:执行INSERT、UPDATE、DELETE语句产生的结果接口,用于反映数据变更的执行效果。

二者的分工在包总览(database_sql_package_overview.md)与模块说明(readme.md)中均有明确记载:UpdateResult归入"SQL 语句执行"分组,紧邻Statement与QueryResult。也就是说,凡是会修改数据库内容的语句,其返回值类型基本都是UpdateResult。

接口定义与成员属性

在 API 参考文档 database_sql_package_interfaces.md 中,UpdateResult的完整定义为:

public interface UpdateResult { prop lastInsertId: Int64 prop rowCount: Int64 }

接口本身不继承任何父类型,仅声明两个只读属性,其语义如下表所示(源自 UpdateResult_interface.md):

属性原型说明
lastInsertIdprop lastInsertId: Int64执行INSERT语句自动生成的最后 row ID,如果不支持则 row ID 为 0。
rowCountprop rowCount: Int64执行INSERT、UPDATE、DELETE语句影响的行数。

任何继承该接口的class、interface、struct,都需要遵守上述属性的类型与语义约定。

prop lastInsertId:获取自动生成的主键 ID

lastInsertId的类型为Int64(对应核心库 Int64),用于获取执行INSERT语句时数据库自动生成的最后一条 row ID。

需要特别注意的边界行为:当数据库驱动不支持该能力时,返回值为0。因此在实际业务中,lastInsertId的值并不总是可靠的"自增主键",是否支持取决于具体数据库驱动实现,建议先验证驱动能力再做主键回填等业务逻辑。

prop rowCount:获取影响行数

rowCount的类型同样为Int64,表示INSERT、UPDATE、DELETE语句实际影响的数据行数。它是判断语句是否真正生效的通用手段:

  • 执行UPDATE时,若rowCount为0,通常表示没有匹配到满足WHERE条件的记录;
  • 执行DELETE时,rowCount直接反映被删除的行数;
  • 执行INSERT时,单行插入的rowCount一般为1。

实战:从 Statement.update() 获取更新结果

UpdateResult是Statement接口中update()方法的返回类型。在 API 文档 Statement_interface.md 中,Statement预执行接口定义了如下两个更新入口:

名称原型说明
update(): UpdateResult执行 sql 语句,得到更新结果。
update(deprecated)(params: Array<SqlDbType>): UpdateResult执行 sql 语句,得到更新结果。未来版本即将废弃不再使用,可使用update()替代。

典型的调用链是:DriverManager.getDriver()获取驱动 →Driver.open()打开数据源 →Datasource.connect()获取连接 →Connection.prepareStatement(sql)预执行语句 →Statement.set<T>()绑定参数 →Statement.update()得到UpdateResult。下面结合仓库中的官方示例逐一演示。

插入数据并读取结果

以下代码来自示例文档 db_operations.md,演示了连续执行两次插入并打印rowCount与lastInsertId:

import std.database.sql.* main() { // 获取数据库连接示例 let drv = DriverManager.getDriver("opengauss") ?? return let ds = drv.open("opengauss://testuser:testpwd@localhost:5432/testdb", []) let conn = ds.connect() // 插入数据 1 var stmt = conn.prepareStatement("INSERT INTO test VALUES(?, ?)") stmt.set<String>(0, "li lei") stmt.set<Int32>(1, 12) var ur = stmt.update() println("Update Result: ${ur.rowCount} ${ur.lastInsertId}") // 插入数据 2 stmt.set<String>(0, "han meimei") stmt.set<Int32>(1, 13) ur = stmt.update() println("Update Result: ${ur.rowCount} ${ur.lastInsertId}") stmt.close() }

其中set<String>(0, ...)、set<Int32>(1, ...)将仓颉原生类型绑定到 SQL 语句的?占位符,调用update()后返回的ur.rowCount即本次插入影响的行数,ur.lastInsertId为数据库自动生成的最后 row ID。

更新与删除数据

同一示例文档中的更新与删除操作同样借助UpdateResult反馈执行效果:

import std.database.sql.* main() { // 获取数据库连接示例 let drv = DriverManager.getDriver("opengauss") ?? return let ds = drv.open("opengauss://testuser:testpwd@localhost:5432/testdb", []) let conn = ds.connect() // 更新操作示例 var stmt = conn.prepareStatement("update test set age = ? where name = ?") stmt.set<Int32>(0, 15) stmt.set<String>(1, "li lei") var ur = stmt.update() println("Update Result: ${ur.rowCount} ${ur.lastInsertId}") stmt.close() }
import std.database.sql.* main() { // 获取数据库连接示例 let drv = DriverManager.getDriver("opengauss") ?? return let ds = drv.open("opengauss://testuser:testpwd@localhost:5432/testdb", []) let conn = ds.connect() // 删除操作示例 var stmt = conn.prepareStatement("delete from test where name = ?") stmt.set<String>(0, "li lei") var ur = stmt.update() println("Update Result: ${ur.rowCount} ${ur.lastInsertId}") stmt.close() }

从示例可见,无论是更新还是删除,rowCount都是判断匹配行数的最直接依据。

建表、删表等 DDL 场景

update()同样可以执行不返回数据集的 DDL 语句,返回的UpdateResult同样提供执行反馈。示例 db_modify_table.md 中演示了删表与建表:

import std.database.sql.* main() { // 获取数据库链接示例 let drv = DriverManager.getDriver("opengauss") ?? return let opts = [ ("cachePrepStmts", "true"), ("prepStmtCacheSize", "250"), ("prepStmtCacheSqlLimit", "2048") ] let ds = drv.open("opengauss://testuser:testpwd@localhost:5432/testdb", opts) let conn = ds.connect() // 删除和创建表 var stmt = conn.prepareStatement("DROP TABLE IF EXISTS test") var ur = stmt.update() println("Update Result: ${ur.rowCount} ${ur.lastInsertId}") stmt.close() stmt = conn.prepareStatement("CREATE TABLE test(id SERIAL PRIMARY KEY, name VARCHAR(20) NOT NULL, age INT)") ur = stmt.update() println("Update Result: ${ur.rowCount} ${ur.lastInsertId}") stmt.close() }

示例中的建表语句为id SERIAL PRIMARY KEY,这正是lastInsertId得以生效的典型场景——SERIAL自增列由数据库自动生成主键值。

深入:如何可靠获取插入后的主键 ID

lastInsertId依赖驱动支持,若驱动不支持则固定返回0。如果需要稳妥地在插入后拿到主键,仓库示例还提供了一种通用的替代方案:在 SQL 语句中使用RETURNING子句,再通过Statement.query()以QueryResult形式读取返回的主键列。见 db_operations.md:

import std.database.sql.* main() { // 获取数据库连接示例 let drv = DriverManager.getDriver("opengauss") ?? return let ds = drv.open("opengauss://testuser:testpwd@localhost:5432/testdb", []) let conn = ds.connect() // 如果需要在插入数据后返回插入的 id 值,可以参考如下方式: let sql = "INSERT INTO test (name, age) VALUES (?,?) RETURNING id, name" try (stmt = conn.prepareStatement(sql)) { stmt.set<String>(0, "li lei") stmt.set<Int32>(1, 12) let qr = stmt.query() while (qr.next()) { println("id = ${qr.get<Int32>(0)}, name=${qr.get<String>(1)}") } } catch (e: Exception) { e.printStackTrace() } stmt.close() }

因此,在业务设计中可以按需选择:

  • 仅需确认语句执行成功/影响行数:使用update()+rowCount;
  • 需要拿到自动生成的主键:优先使用RETURNING+query(),或在驱动支持的前提下使用lastInsertId(注意不支持时为0的约定)。

与 QueryResult 的分工与注意事项

UpdateResult与QueryResult分别面向"数据变更"与"数据查询"两类语句,二者都是Statement接口的返回值类型。实践中需要注意以下几点:

  1. 类型对齐:rowCount与lastInsertId均为Int64。在包总览 database_sql_package_overview.md 的 SQL 与仓颉类型对照表中,BIGINT对应Int64、INTEGER对应Int32,因此读取行数、ID 这类数值结果时按对应类型取值即可。
  2. lastInsertId的兼容性:接口文档明确约定"如果不支持则 row ID 为 0",因此不能假设每次插入后该属性都有意义;对不支持自增列或驱动不提供该能力的数据库,应以0兜底处理。
  3. 语句执行失败的处理:Statement.update()在执行过程中发生异常(如网络中断、服务器超时、参数个数不正确)时会抛出 SqlException,异常对象携带数据库供应商返回的errorCode与五字符sqlState,可用于错误定位与排查。
  4. 资源释放:从示例中可以看到,Statement在使用完毕后均调用stmt.close()释放资源;在多语句、长连接场景下应养成良好的关闭习惯。

小结

UpdateResult是仓颉std.database.sql包中处理数据变更语句结果的核心接口:rowCount提供通用的影响行数反馈,lastInsertId提供驱动能力允许时的自增主键获取。结合Statement.update()与仓库中的官方示例,即可在插入、更新、删除乃至建表、删表等各类语句执行后,准确掌握数据库端的执行效果;如需稳妥获取插入主键,可进一步采用RETURNING子句配合QueryResult读取。相关完整 API 与示例可继续查阅:

  • 接口完整定义:database_sql_package_interfaces.md
  • 语句执行接口:Statement_interface.md
  • 增删改实战示例:db_operations.md
  • 建表删表示例:db_modify_table.md
  • 人工智能
  • AI 技能
  • 文档
  • 开发工具

【免费下载链接】DocAgent

项目地址:https://gitcode.com/Cangjie-SIG/DocAgent
点击查看免费下载

相关推荐

上一篇:让老 Mac 免费装上新系统:OpenCore Legacy Patcher 完整上手教程
下一篇:TrollInstallerX:iOS越狱安装神器终极方案

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询