很多人都明白,transaction使用完后忘记disconnect的话,数据库服务端的session连接不会释放,从而浪费了服务器资源。其实这只是一部分后果。如果粗心大意,还会造成更大的影响。
先来做个测试,我新建了一个窗口w_test。在窗口上放置两个按钮cb_1和cb_2。
cb_1的clicked事件下面定义transaction sqlca1,故意漏掉了disconnect,代码如下:
long ll_count
transaction sqlca1
sqlca1= create transaction
sqlca1.DBMS = "MSS Microsoft SQL Server"
sqlca1.Database = "his2015"
sqlca1.LogPass = "sasasa"
sqlca1.ServerName = "."
sqlca1.LogId = "sa"
sqlca1.AutoCommit = False
sqlca1.DBParm = ""
connect using sqlca1;
messagebox('',string(sqlca1.sqlcode) +sqlca1.sqlerrtext)
destroy sqlca1
定义long ll_count的目的是为了和cb_2的变量一样,这样才能保证sqlca1和sqlca2使用到相同的内存
cb_2的clicked事件下面定义一个transaction sqlca2,故意漏掉connect,代码如下:
transaction sqlca2
long ll_count
sqlca2 = create transaction
select count(*) into :ll_count from AAAA using sqlca2;
messagebox('',string(sqlca2.sqlcode)+sqlca2.sqlerrtext)
messagebox('',ll_count)
很多人可能都会说,cb_2的clicked事件下面的sqlca2没有连接到数据库,select不可能查询到数据,但是通过先点击cb_1再点击cb_2,程序运行的结果是查询到了数据。
下面我将解释一下原理:
cb_1被点击完之后,sqlca1对象占据了系统内存,但是随着cb_1的clicked事件执行完毕,sqlca1被销毁。相对应的内存也将会被重新使用。
cb_2被点击完之后,系统会给sqlca2对象分配内存。两个按钮先后被点击,中间没有执行过别的操作。所以sqlca2被分配的内存刚好使用了sqlca1原先使用的那部分内存。而数据库的连接信息是保存在内存中的。所以即便sqlca2没有执行连接到数据库的操作,使用的时候也能够连接到sqlca1所连接的那个数据库。
为了进一步验证我分析的是正确的。我将cb_1的clicked事件修改如下:
long i
transaction sqlca1,sqlca2
sqlca1= create transaction
sqlca1.DBMS = "MSS Microsoft SQL Server"
sqlca1.Database = "his2015"
sqlca1.LogPass = "sasasa"
sqlca1.ServerName = "."
sqlca1.LogId = "sa"
sqlca1.AutoCommit = False
sqlca1.DBParm = ""
connect using sqlca1;
messagebox('',string(sqlca1.sqlcode) +sqlca1.sqlerrtext)
destroy sqlca1
sqlca2= create transaction
sqlca2.DBMS = "O84 Oracle8/8i (8.x.4+)"
sqlca2.LogPass = "bsoft"
sqlca2.ServerName = "GM"
sqlca2.LogId = "portal_his"
sqlca2.AutoCommit = False
sqlca2.DBParm = "PBCatalogOwner='portal_his',CommitOnDisconnect='No'"
connect using sqlca2;
messagebox('',string(sqlca2.sqlcode) +sqlca2.sqlerrtext)
disconnect using sqlca2;
destroy sqlca2
当执行到connect using sqlca2;的时候,系统返回的错误是transaction already connected。这也充分验证了sqlca1和sqlca2 使用了相同的内存,并且数据库的连接信息是保存在内存中的。这样的后果就是由于sqlca1忘记 了disconnect,即便sqlca2写的很正确,也无法连接到oracle数据库了,而且connect using sqlca2如果不判断是否成功直接使用的话,感觉在操作oracle数据库,其实是操作了sqlserver数据库。pb的帮助文档里面也提到了无论是connect 还是 disconnect都要判断是否执行成功。而很多程序员都不会去判断的,所以程序的严谨性是很重要的。