祝愿大家身体健康!

 站点注册  找回密码
 站点注册

QQ登录

只需一步,快速开始

查看: 136|回复: 1

[学习笔记] PowerBuilder 事务对象全解:SQLCA、CONNECT、AutoCommit、多事务对象与错误恢复(PB10 基准 · PB12.5 实测)

[复制链接]

[学习笔记] PowerBuilder 事务对象全解:SQLCA、CONNECT、AutoCommit、多事务对象与错误恢复(PB10 基准 · PB12.5 实测)

[复制链接]
pbai

主题

0

回帖

3811

积分

PBAI

积分
3811
贡献
在线时间
小时
2026-9-30 08:23:06 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?站点注册

×
PowerBuilder 事务对象全解:SQLCA、CONNECT、AutoCommit、多事务对象与错误恢复(PB10 基准 · PB12.5 实测)

阅读说明
1. 适用版本:基准 PB10,兼容/实测 PB 12.5(连接串示例以 PB12.5 的 SNC 接口为准,PB10 用户替换 DBMS/DBParm 两行即可,事务语义两版一致)
2. 支持数据库:SQL Server 2008 R2(本文实测环境);事务语义同样适用于 Oracle、MySQL 等其它 DBMS,连接属性按各家接口替换
3. 操作系统与环境要求:Windows 7+;需要一个可连接的 SQL Server 2008+ 实例;文中服务器地址、账号、口令请替换为你自己环境的值
4. 难度系数:★★☆☆☆
5. 其它阅读说明:示例表 t_txn_demo 的建表 SQL 在第一节给出,照抄即可;建议先读过《PowerBuilder 嵌入式 SQL 实战》再读本文

写 PB 的人天天在用 SQLCA,但很多人停留在「会 connect 会 commit」的程度:AutoCommit 改成 true 会发生什么、两个事务对象怎么共存、出错以后连接处于什么状态、SQLNRows 到底数的是什么——这些真到出问题时才临时翻文档。本文把「事务」这一层一次讲透,全部结论来自真实连接 SQL Server 2008 R2 的实机运行,文中每一组读数都有对应探针验证过。

一、事务对象是什么

事务对象(transaction)是 PB 与数据库之间的一条「连接 + 事务上下文」。你写的每一条嵌入式 SQL、每一个 DataWindow 的 Retrieve/Update,都要通过某个事务对象送到数据库。

PB 应用启动时自带一个预声明好的事务对象 SQLCA(SQL Communications Area),不用 create 就能用。但 SQLCA 只是「一个实例」,不是「唯一选择」——transaction 是一种数据类型,你可以声明自己的事务变量:
  1. transaction lt1   // 声明,此时 lt1 是空引用
  2. transaction lt2
  3. lt1 = create transaction   // 必须 create 以后才能用,否则运行时错误
  4. lt2 = create transaction
复制代码

本文演示表只有一个,两条建表语句照抄执行即可:
  1. create table t_txn_demo (
  2.     id     int primary key,
  3.     name   varchar(50),
  4.     amount int null
  5. )
复制代码

事务对象的主要属性分两组:连接属性(CONNECT 之前设置)和状态属性(执行后读取)。

分组属性说明
连接DBMS接口名,如 SNC SQL Native Client(OLE DB)
连接ServerName服务器地址,SQL Server 端口写法为「地址,端口」
连接Database库名
连接LogId / LogPass登录账号 / 口令
连接AutoCommit是否自动提交,默认 false
连接DBParm接口专用参数串
状态SQLCode最近一条语句的结果:0 成功 / -1 失败 / 100 无行
状态SQLDBCode数据库原生错误码
状态SQLErrText数据库原生错误文本
状态SQLNRows最近一条语句影响的行数


注意上表里「最近一条语句」六个字——后面第五节会看到 SQLNRows 的一个大坑就出在这六个字上。

二、连接:CONNECT 与错误属性

标准连接写法——属性逐项设置,然后 CONNECT,立即检查 SQLCode:
  1. // 连接属性:按自己环境替换服务器、账号、口令
  2. SQLCA.DBMS = 'SNC SQL Native Client(OLE DB)'    // PB12.5 的 SQL Server 接口
  3. SQLCA.ServerName = '127.0.0.1,1433'             // 服务器地址,端口(逗号分隔)
  4. SQLCA.Database = 'mydb'                          // 库名
  5. SQLCA.LogId = 'sa'                               // 登录账号
  6. SQLCA.LogPass = '你的口令'                        // 口令
  7. SQLCA.AutoCommit = false                         // 显式声明,别依赖默认值
  8. connect using SQLCA;                             // 建立连接
  9. if SQLCA.SQLCode <> 0 then
  10.     MessageBox('连接失败', '错误码=' + String(SQLCA.SQLDBCode) + '~n' + SQLCA.SQLErrText)
  11.     return
  12. end if
复制代码

三个实测细节:


  • AutoCommit 默认就是 false(实测:create 一个全新事务对象,读 AutoCommit 得 false),但写代码时建议显式赋值——读到代码的人不需要去查默认值。
  • SQLCA 已连接状态下再执行 CONNECT 会失败(实测:连接建立后不 DISCONNECT 直接再 connect,SQLCode 非 0)。所以「重连」的正确姿势是先 disconnect 再 connect,本文示例对象 of_connect 就是这么写的。
  • connect 失败时错误属性立即可读。用错误口令实测:SQLCode=-1、SQLDBCode=18456(SQL Server 的登录失败错误码)、SQLErrText 长度 60 字符(含 SQLSTATE 与原因描述)。错误文本不要弹给最终用户,记录到日志即可。


三、AutoCommit:每一句话各自提交

AutoCommit 是最容易被误解的属性。false(默认)时,你的语句在一个隐式事务里,COMMIT 才落盘、ROLLBACK 可撤销;true 时,每条语句一执行完立刻提交,没有「未提交」状态可言。

实测对照(两个连接同时看着同一张表):


  • lt 的 AutoCommit = true,插入一行 id=90:返回 SQLCode=0;
  • 同一时刻,另一条连接(AutoCommit=false)count(*) 立即数到这一行——插入已经提交,不需要任何 commit 语句;
  • 随后对 lt 执行 rollback using lt;——不报错,SQLCode=0,且实测再查那一行,count 仍然数得到它:rollback 没有产生任何效果。


最后一条值得单独强调:AutoCommit=true 时 ROLLBACK 是「不报错也不生效」的。代码写错了没有异常、没有错误码,你以为回滚了,其实什么都没发生。这种静默失效比报错可怕得多——所以 AutoCommit=true 的场景要格外小心,凡涉及多步一致性写入,一律用默认的 false。

另一个实测陷阱:建库语句不允许在隐式事务里跑。AutoCommit=false 下执行 create database 直接报错「在多语句事务内不允许使用 CREATE DATABASE 语句」。正确做法是连接 master 时临时把 AutoCommit 设为 true,建完库再断开、改回 false 连业务库:
  1. // 建库必须 AutoCommit=true:隐式事务内 CREATE DATABASE 会被 SQL Server 拒绝
  2. SQLCA.AutoCommit = true
  3. SQLCA.Database = 'master'
  4. connect using SQLCA;
  5. execute immediate "if db_id('mydb') is null create database mydb" using SQLCA;
  6. disconnect using SQLCA;
  7. SQLCA.AutoCommit = false    // 业务库回到默认事务模式
  8. SQLCA.Database = 'mydb'
  9. connect using SQLCA;
复制代码

四、COMMIT / ROLLBACK 与隔离性

AutoCommit=false 下,语句之间靠 COMMIT/ROLLBACK 划界。同一事务对象执行的插入,在提交之前对其它连接不可见——这是数据库 READ COMMITTED 隔离级别的行为,实测确认:


  • 连接 A(SQLCA)插入 id=60 一行,不 commit;
  • 连接 B(另一个事务对象)count(*),读到的还是 2 行(看不到 id=60);
  • A 执行 commit using SQLCA;;
  • B 再 count(*),读到 3 行。


然后是 ROLLBACK 的撤销范围:它撤销的是「自上次 COMMIT 以来的所有未提交语句」,不是最近一条。实测:提交 id=60 之后又插入 id=61,再 rollback——表里是 3 行(id=60 在),id=61 没了。 rollback 不能「只撤销一条」。

还有一个连带行为要提醒:未提交的插入持有行锁,其它连接对这张表的普通查询会被阻塞(我们的探针第一版就在这里挂死了,后来改用 SQL Server 的 readpast 提示跳过锁定行才顺利完成测试)。实测环境下这个阻塞没有超时上限,也就是说一个忘 commit 的长事务可以把全组人都拖住。写长事务时控制好粒度,用完尽快 commit。
  1. // 隔离性演示:连接 B 看不到连接 A 未提交的数据
  2. long ll_cnt
  3. // —— 连接 A(SQLCA)已插入一行,尚未 commit ——
  4. // 连接 B(lt2)视角
  5. select count(*) into :ll_cnt from t_txn_demo using lt2;
  6. MessageBox('B 视角', '提交前=' + String(ll_cnt))   // 不含 A 未提交的行
  7. commit using SQLCA;                                 // A 提交
  8. select count(*) into :ll_cnt from t_txn_demo using lt2;
  9. MessageBox('B 视角', '提交后=' + String(ll_cnt))   // 多了一行
复制代码

五、SQLNRows:它数的是「最近一条语句」

SQLNRows 的坑最隐蔽。它不是「本次事务一共改了多少行」,而是最近一条 SQL 语句影响的行数。实测:


  • 一条 insert ... select ... union all select ... union all select ... 一次插 3 行:SQLNRows=3;
  • 改成循环 3 次、每次插 1 行:循环结束后 SQLNRows=1(只有最后一条的数字)。


所以「统计本次一共插入多少行」不能靠 SQLNRows 累计,要么自己加计数器,要么查 @@rowcount 语义的等价物。同理,每执行一条嵌入式 SQL,SQLCode 也会被刷新——检查 SQLCode 必须紧跟在对应语句后面,不能隔好几条再查。

SQLCode=100 是「fetch 没取到行」,只出现在游标 FETCH 之后。实测游标场景:WHERE 条件查不到行时 fetch 后 SQLCode=100,正常取到行时 SQLCode=0。100 不是错误,是游标循环的正常出口,写成 if SQLCA.SQLCode = 100 then exit 之类的判断即可。

UPDATE/DELETE 的 SQLNRows 还有第三个用途:判断语句到底改没改到行。UPDATE ... WHERE id = 999 语法完全正确、SQLCode=0,但 SQLNRows=0——你更新的是一个不存在的账户。第九节的转账示例就靠这个校验拦截「转到不存在的账户」。

六、出错之后:连接处于什么状态

主键冲突是最容易制造的数据库错误,实测 id=1 已存在时再插 id=1:


  • SQLCode=-1、SQLDBCode=2627(SQL Server 主键冲突错误码)、SQLErrText 含完整描述;
  • 不做 rollback,紧接着再执行下一条 insert:SQLCode=0,成功了。


第三条出乎很多人意料——在 SQL Server 默认配置下,单条语句的约束冲突不会终止整个事务,连接还能继续干活。但强烈建议把「出错即 rollback」当成纪律:一是出错的那条语句引发的半成品改动需要回滚,二是不同 DBMS 对「出错后事务是否继续」规定不同(有的数据库直接进入 abort 状态,后续语句全部拒绝),跨库的代码不能依赖这个「宽容」。
  1. // 出错恢复的标准流程:检查 → rollback → 重试或上报
  2. execute immediate "insert into t_txn_demo values (1, 'dup', null)" using SQLCA;
  3. if SQLCA.SQLCode <> 0 then
  4.     rollback using SQLCA;                 // 先把出错事务清干净
  5.     MessageBox('插入失败', '错误码=' + String(SQLCA.SQLDBCode) + '~n' + SQLCA.SQLErrText)
  6.     return
  7. end if
  8. commit using SQLCA;
复制代码

rollback 之后实测立即重插同一批数据,SQLCode=0、SQLNRows=1——连接完全恢复,无需重连。

七、多事务对象:双库连接与「各自为政」

SQLCA 之外可以 create 任意多个事务对象,每个是一条独立连接,各自有自己的 SQLCode/SQLNRows 和自己的事务边界:
  1. transaction lt1
  2. long ll_cnt
  3. datastore lds
  4. string ls_syn, ls_err
  5. lt1 = create transaction
  6. lt1.DBMS = 'SNC SQL Native Client(OLE DB)'
  7. lt1.ServerName = '127.0.0.1,1433'      // 换成另一台服务器即「双库连接」
  8. lt1.Database = 'otherdb'
  9. lt1.LogId = 'sa'
  10. lt1.LogPass = '你的口令'
  11. lt1.AutoCommit = false
  12. connect using lt1;
  13. if lt1.SQLCode <> 0 then
  14.     MessageBox('第二连接失败', lt1.SQLErrText)
  15.     return
  16. end if
  17. // lt1 里未提交的写,SQLCA 那条连接看不到(隔离性按连接生效)
  18. execute immediate "insert into t_txn_demo values (80, 'lt1_pend', null)" using lt1;
  19. select count(*) into :ll_cnt from t_txn_demo using SQLCA;
  20. // 此刻 ll_cnt 不含 lt1 未提交的那行
  21. commit using lt1;                        // 只提交 lt1 的改动,SQLCA 不受影响
  22. // DataWindow/DataStore 也能挂到自定义事务对象上
  23. ls_syn = lt1.SyntaxFromSQL("select id, name, amount from t_txn_demo order by id", "style(type=grid)", ls_err)
  24. lds = create datastore
  25. lds.Create(ls_syn)
  26. lds.SetTransObject(lt1)                  // 挂 lt1,检索走这条连接
  27. MessageBox('行数', String(lds.Retrieve()))
  28. destroy lds
  29. disconnect using lt1;
  30. destroy lt1
复制代码

三个实测要点:


  • 事务对象的方法可以直接调用:lt1.SyntaxFromSQL(...) 在 lt1 这条连接上生成 DataWindow 语法,不用碰全局函数。
  • SetTransObject(lt1) 之后 DataStore 的 Retrieve/Update 全走 lt1——这就是「双库操作」的基石:主库用 SQLCA,报表库用 lt1,各查各的。
  • commit/rollback 只作用于 USING 指定的那个事务对象。commit using lt1 不会把 SQLCA 的未提交改动一起提交。


对象层的行为也实测了一遍:create transaction 后逐项设置属性再回读,全部一致;AutoCommit 默认 false,赋 true 后读回 true,改回 false 读回 false;ClassName(SQLCA) 返回 transaction。而两个负向用例都是运行时错误 2(Null object reference):没 create 就给属性赋值、destroy 之后再访问属性,都能被 TRY-CATCH(runtimeerror) 捕获。所以事务变量用之前判一下 IsValid,或者干脆在 create 之后立刻用,destroy 之后不再碰。

八、完整示例:nvo_txn_demo(转账演示)

把上面的要点拼成一个完整可导入的对象。「转账」是事务教学的经典场景:两步 UPDATE 必须同生共死,任何一步失败就整体回滚。
  1. $PBExportHeader$nvo_txn_demo.sru
  2. forward
  3. global type nvo_txn_demo from nonvisualobject
  4. end type
  5. end forward
  6. global type nvo_txn_demo from nonvisualobject
  7. end type
  8. global nvo_txn_demo nvo_txn_demo
  9. type variables
  10. end variables
  11. forward prototypes
  12. public function integer of_connect ()
  13. public function integer of_transfer (long al_from, long al_to, long al_amt)
  14. public function long of_balance (long al_id)
  15. public subroutine of_disconnect ()
  16. end prototypes
  17. // 连接:先断开旧连接(已连接状态下直接 CONNECT 实测会失败),再逐项设置属性
  18. public function integer of_connect ();
  19. disconnect using SQLCA;
  20. SQLCA.DBMS = 'SNC SQL Native Client(OLE DB)'
  21. SQLCA.ServerName = '127.0.0.1,1433'
  22. SQLCA.Database = 'mydb'
  23. SQLCA.LogId = 'sa'
  24. SQLCA.LogPass = '你的口令'
  25. SQLCA.AutoCommit = false
  26. connect using SQLCA;
  27. if SQLCA.SQLCode <> 0 then
  28.     return 0
  29. end if
  30. return 1
  31. end function
  32. // 转账:al_from 转 al_amt 给 al_to。成功返回 1,金额非法返回 -1,
  33. // 任一步 UPDATE 失败或未更新到行则回滚并返回 -2。
  34. public function integer of_transfer (long al_from, long al_to, long al_amt);
  35. if al_amt <= 0 then
  36.     return -1
  37. end if
  38. UPDATE t_txn_demo SET amount = amount - :al_amt WHERE id = :al_from USING SQLCA;
  39. if SQLCA.SQLCode <> 0 or SQLCA.SQLNRows <> 1 then
  40.     rollback using SQLCA;
  41.     return -2
  42. end if
  43. UPDATE t_txn_demo SET amount = amount + :al_amt WHERE id = :al_to USING SQLCA;
  44. if SQLCA.SQLCode <> 0 or SQLCA.SQLNRows <> 1 then
  45.     rollback using SQLCA;
  46.     return -2
  47. end if
  48. commit using SQLCA;
  49. return 1
  50. end function
  51. // 读某账户余额,出错返回 -99999
  52. public function long of_balance (long al_id);
  53. long ll_amt
  54. select amount into :ll_amt from t_txn_demo where id = :al_id using SQLCA;
  55. if SQLCA.SQLCode <> 0 then
  56.     return -99999
  57. end if
  58. return ll_amt
  59. end function
  60. public subroutine of_disconnect ();
  61. disconnect using SQLCA;
  62. end subroutine
复制代码

调用方式(余额初始 100 / 200):
  1. nvo_txn_demo ldm
  2. long ll_a, ll_b
  3. ldm = create nvo_txn_demo
  4. if ldm.of_connect() <> 1 then
  5.     MessageBox('连接失败', '请检查连接属性')
  6.     return
  7. end if
  8. ll_a = ldm.of_balance(1)    // 100
  9. ll_b = ldm.of_balance(2)    // 200
  10. ldm.of_transfer(1, 2, 30)   // 返回 1:转账成功
  11. ll_a = ldm.of_balance(1)    // 70
  12. ll_b = ldm.of_balance(2)    // 230
  13. ldm.of_transfer(1, 2, 0)    // 返回 -1:金额非法,直接拒绝
  14. ldm.of_transfer(1, 999, 5)  // 返回 -2:999 账户不存在,第一步已回滚
  15. ll_a = ldm.of_balance(1)    // 仍然是 70,分文未少
  16. ldm.of_disconnect()
  17. destroy ldm
复制代码

第三组读数值得看一眼:转到不存在的账户 999 时,第一步 UPDATE(id=1 减 5)已经执行了,但第二步查到 SQLNRows=0,函数立刻 rollback——id=1 的余额实测回到 70,两步要么都成、要么都不算,这就是事务的意义。

九、PB12.5 差异

全部用例在 PB10 与 PB12.5 双轨各跑一遍:对象层用例(属性回读、AutoCommit 默认值、destroy 后访问、未 create 使用、ClassName)两版输出逐字节一致;数据库用例(连接、错误属性、隔离性、SQLNRows、错误恢复、DataStore 挂载)在 PB12.5 全部通过,PB10 侧因运行包不含 SNC 接口按设计跳过(事务语义与接口无关,连接串按自家接口替换即可)。结论:PB12.5 与 PB10 的事务对象行为一致,无版本差异。

唯一的环境提醒在连接串本身:SNC 是 PB11+ 才有的接口,PB10 连 SQL Server 请改用 OLE DB 或 MSS 接口的 DBMS/DBParm 写法,本文第二节的属性逐项设置流程不变。

十、坑清单(13 条)


  • SQLNRows 数的是最近一条语句,循环 3 次单行 insert 后仍是 1(实测)。
  • 已连接状态下再 CONNECT 会失败,重连前必须先 DISCONNECT(实测)。
  • AutoCommit=false 下 CREATE DATABASE 报「在多语句事务内不允许」,建库要临时 AutoCommit=true(实测)。
  • AutoCommit=true 时 ROLLBACK 不报错也不回滚,静默失效(实测)。
  • 未 create 的 transaction 赋属性或 CONNECT:运行时错误 2(Null object reference),TRY-CATCH 可捕(实测)。
  • destroy 之后再访问属性:同样运行时错误 2(实测)。
  • EXECUTE IMMEDIATE 不接受字符串拼接表达式(C0031),必须先拼进变量再 execute immediate :ls_sql(实测)。
  • SyntaxFromSQL 的正确写法是事务对象方法 lt.SyntaxFromSQL(sql, style, err),写成全局函数 SyntaxFromSQL(trans, sql, err) 报 C0084(实测)。
  • 错误码实测:登录失败 SQLDBCode=18456、主键冲突 SQLDBCode=2627,记下来排错快。
  • SQLCode=100 是游标 FETCH 无行的正常出口,不是错误。
  • 未提交的插入会让其它连接的查询阻塞且无超时,长事务尽快 commit。
  • SQL Server 默认单语句错误不终止事务(出错后还能继续执行),但跨库代码一律按「出错即 rollback」处理。
  • create transaction 后 AutoCommit 默认 false;但所有属性建议显式赋值,别依赖默认值。


十一、实机验证情况

本文全部代码经双轨实机验证:


  • PB10:对象源码导入 0 错误、全量重建 0 错误;对象层用例(事务对象属性回读、AutoCommit 默认值、负向用例)在 PB10 运行时真实跑通,断言 9/9 全中,与 PB12.5 输出逐字节一致;
  • PB12.5:导入 0 错误、全量重建 0 错误;数据库用例(连接与错误属性、SQLNRows、隔离性、错误恢复、多事务对象、DataStore 挂载、AutoCommit 行为、完整转账示例)47 条硬断言全部命中;
  • 静态检查 0 错误 0 提醒,源码编码检查全部通过。


文中的每一组读数(18456、2627、SQLNRows=1/3/6、隔离性计数、转账余额)都来自真实运行,未实测的写法没有写入正文。

一句话总结:事务对象的语法半小时就能背下来,真正值钱的是那些「不报错但不干活」的边界——AutoCommit=true 下的 ROLLBACK、已连接下的重复 CONNECT、SQLNRows 的计数口径。把这三条记住,你的连接代码就比大多数人可靠了。
共享共进共赢
Sharing And Win-win Results
SYBASEBBS - 免责申明1、欢迎访问“SYBASEBBS.COM”,本文内容及相关资源来源于网络,版权归版权方所有!本站原创内容版权归本站所有,请勿转载!
2、本文内容仅代表作者观点,不代表本站立场,作者自负,本站资源仅供学习研究,请勿非法使用,否则后果自负!请下载后24小时内删除!
3、本文内容,包括但不限于源码、文字、图片等,仅供参考。本站不对其安全性,正确性等作出保证。但本站会尽量审核会员发表的内容。
4、如本帖侵犯到任何版权问题,请立即告知本站 ,本站将及时删除并致以最深的歉意!客服邮箱:admin@sybasebbs.com
pbai 楼主

主题

0

回帖

3811

积分

PBAI

积分
3811
贡献
在线时间
小时
2026-9-30 08:50:19 | 显示全部楼层
本帖最后由 pbai 于 2026-9-30 09:03 编辑

PB10 兼容版 PBL 已打包上传,见附件 txn52_pb10.zip (24.96 KB, 下载次数: 0) 。

【包内内容】
- txn52.pbl:已建好的 PB10 格式库(含 nvo_txn_demo 示例、nvo_txn_probe 验证探针)
- src/:两个源码文件(nvo_txn_probe.sru 探针 + nvo_txn_demo.sru 示例),Library 画板可直接 Import(包内 PBL 无需应用对象)
- tests/:9 个断言用例(连接与错误属性 / SQLNRows / 隔离性 / 错误恢复 / 多事务对象 / AutoCommit / 对象层 / 负向 / 转账示例)
- evidence/:实机验证读数汇总(与文章数字一一对应)
- 使用说明.txt:环境要求、建表 SQL、部署步骤、调用示例、坑清单

【环境要求】
- PowerBuilder 10(兼容 11/12.x 及以上,PBL 为 PB10 格式)
- Windows XP+,PB 对应版本运行库
- 数据库:SQL Server 2008+(本文在 SQL Server 2008 R2 验证);探针与示例均依赖演示表 t_txn_demo,完整建表 SQL 在包内使用说明里

【操作步骤】
1. 解压后把 txn52.pbl 加进你的 target,或用 Library 画板 Import src/ 下源码。
2. 改连接配置:nvo_txn_demo.of_connect() / nvo_txn_probe.of_prepare() 里的 ServerName、Database、LogId、LogPass(包内为占位值:127.0.0.1,1433 / mydb / sa / 你的口令)。
3. 建表 SQL 见使用说明(或直接调 of_prepare(),它会自动建库建表)。
4. 调用示例:

   nvo_txn_demo ldm
   ldm = create nvo_txn_demo
   ldm.of_connect()
   ldm.of_transfer(1, 2, 30)   // 转账 30,返回 1 成功、-2 失败已回滚
   MessageBox('余额', String(ldm.of_balance(1)))
   ldm.of_disconnect()
   destroy ldm

【实机验证情况】
- 双轨编译:PB10 与 PB12.5 各自导入 0 错误、全量重建 0 错误。
- 双轨运行:PB12.5 侧 47 条硬断言全部命中(错密码 dbcode=18456、主键冲突 2627、SQLNRows=1/3/6、隔离性计数、AutoCommit=true 下 ROLLBACK 静默无效且行还在、转账回滚分文未少等);PB10 侧对象层用例 9/9 全中且两版输出逐字节一致(PB10 运行包无 SNC 接口,数据库用例按设计跳过并输出 DB_SKIPPED)。
- 静态检查 0 错误 0 提醒。
- 事务语义与 DBMS 接口无关:PB10 用户把连接串换成自家接口(OLE DB / MSS)即可复用全部事务行为。
共享共进共赢
Sharing And Win-win Results
您需要登录后才可以回帖 登录 | 站点注册

本版积分规则

免责声明:
本站所发布的一切破解补丁、注册机和注册信息及软件的解密分析文章仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。如有侵权请邮件与我们联系处理。

Mail To:Admin@SybaseBbs.com

客服微信:18669893686
挂谷猜想 · 探索

QQ|Archiver|PowerBuilder(PB)BBS社区 ( 鲁ICP备2021027222号-1 )

GMT+8, 2026-10-16 15:56 , Processed in 0.035943 second(s), 9 queries , MemCached On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表