我正在从VB调用Oracle中的第三方存储过程,而不是回滚。
代码优先(我正在简化):
连接字符串:
String sqlstr = "SERVER=x.x.x.x;Database=db;uid=sa;pwd=admin;Connect Timeout=60; Min Pool Size=5; Max Pool Size=100;";
调用(我只是在执行后立即强制回滚来测试它):
Dim Oraclecon As New OracleConnection(_OracleConnection)
Dim sqlCon As New SqlConnection(_SQLConnection)
Dim oTrans As OracleTransaction = Nothing
Oraclecon.Open()
oTrans = Oraclecon.BeginTransaction()
Dim myCMD As New OracleCommand()
myCMD.Connection = Oraclecon
myCMD.Transaction = oTrans
myCMD.CommandText = "CREATE_USER"
myCMD.CommandType = CommandType.StoredProcedure
myCMD.Parameters.Add(New OracleParameter("username", OracleType.VarChar)).Value = UserName
myCMD.Parameters.Add(New OracleParameter("passwd", OracleType.VarChar)).Value = Password
myCMD.Parameters.Add(New OracleParameter("speed", OracleType.VarChar)).Value = Speed
myCMD.Parameters.Add(New OracleParameter("monthly_quota", OracleType.VarChar)).Value = Quota
myCMD.Parameters.Add(New OracleParameter("type", OracleType.VarChar)).Value = "H"
Dim oparam As OracleParameter
oparam = New OracleParameter("success_flag", OracleType.VarChar)
oparam.Size = 1
oparam.Direction = ParameterDirection.Output
Dim oparam2 As OracleParameter
oparam2 = New OracleParameter("err_msg", OracleType.VarChar)
oparam2.Direction = ParameterDirection.Output
oparam2.Size = 100
myCMD.Parameters.Add(oparam)
myCMD.Parameters.Add(oparam2)
Dim RowId As OracleString
myCMD.ExecuteOracleNonQuery(RowId)
oTrans.Rollback()
我无法提供存储过程的详细信息,但它在其中进行提交和回滚。
无论哪种方式,它都在进行插入,并且立即回滚不会回滚插入。
有什么想法吗?
答案 0 :(得分:1)
PL / SQL中的提交/回滚逻辑(无论自主事务处理子句 - >除非您是错误记录,否则不要使用它:http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:2212445691154)
因此,如果您在包中发出COMMIT,则会提交数据,即PERIOD。回滚方式相同。
为以下示例创建表:
create table SHOW_TRANSACTION (MISC varchar2(15)) ;
/
看这个例子就说明了:
declare
procedure DOTHEINSERT(DATAM in SHOW_TRANSACTION.MISC%type ,
doCommit IN boolean
)
as
begin
insert into SHOW_TRANSACTION (MISC)
values (DATAM);
if DOCOMMIT then
commit ;
else
ROLLBACK ;
end if;
end ;
begin
DOTHEINSERT('commit1' , true);
DOTHEINSERT('NOcommit1' , false);
DOTHEINSERT('commit2' , true);
DOTHEINSERT('NOcommit2' , false);
DOTHEINSERT('commit3' , true);
ROLLBACK;
end ;
/
select * from SHOW_TRANSACTION ;
/
MISC
---------------
commit1
commit2
commit3
请注意最终的ROLLBACK什么都不做?这是因为过程中的COMMIT / ROLLBACKS正在影响整个范围,请看这个例子:
truncate table SHOW_TRANSACTION; --start with clean slate
declare
procedure DOTHEINSERT(DATAM in SHOW_TRANSACTION.MISC%type ,
doCommit IN boolean
)
as
begin
insert into SHOW_TRANSACTION (MISC)
values (DATAM);
if DOCOMMIT then
commit ;
--else (HERE I AM GETTING RID OF THE PROCEDURES ROLLBACK, SO EVERYTHING IS BEING ROLLBACK'ED
-- ROLLBACK ;
end if;
end ;
begin
DOTHEINSERT('commit1' , true);
DOTHEINSERT('NOcommit1' , false);
DOTHEINSERT('commit2' , true);
DOTHEINSERT('NOcommit2' , false);
DOTHEINSERT('commit3' , true);
ROLLBACK;
end ;
/
select * from SHOW_TRANSACTION ;
/
MISC
---------------
commit1
NOcommit1
commit2
NOCOMMIT2
commit3
这里删除了包ROLLBACK,所以当COMMIT发生时,插入之前所有INSERTS的内容。
如果希望VB应用程序处理事务,则必须从PL / SQL中删除提交/回滚。
此外,提交/回滚的位置无关紧要,它们表示交易中所有项目的整体范围:
truncate table SHOW_TRANSACTION ;
declare
procedure DOTHEINSERT(DATAM in SHOW_TRANSACTION.MISC%type ,
doCommit IN boolean
)
as
procedure DOTHETRANSACTION(doCommit IN boolean) as
begin
if DOCOMMIT then
commit ;
else -- (HERE I AM GETTING RID OF THE PROCEDURES ROLLBACK, SO EVERYTHING IS BEING ROLLBACK'ED
ROLLBACK ;
end if;
END DOTHETRANSACTION;
begin
insert into SHOW_TRANSACTION (MISC)
values (DATAM);
DOTHETRANSACTION(doCommit);
end DOTHEINSERT;
begin
DOTHEINSERT('commit1' , true);
DOTHEINSERT('NOcommit1' , false);
DOTHEINSERT('commit2' , true);
DOTHEINSERT('NOcommit2' , false);
DOTHEINSERT('commit3' , true);
ROLLBACK;
end ;
/
select * from SHOW_TRANSACTION ;
/
MISC
---------------
commit1
COMMIT2
commit3
/ *现在交易处于子子程序* /
答案 1 :(得分:0)
如果没有包装的来源,这个可能会很棘手。
对于初学者,如果在未使用AUTONOMOUS TRANSACTION编译指示标记的包内进行COMMIT或ROLLBACK,Oracle通常会引发异常,无论调用语言如何。
所以我假设如果包中包含COMMIT和ROLLBACK,那么包必须是自治的。 这意味着您的客户端回滚不会产生任何影响。
如果一个包是自治的,那么如果你在没有完成ROLLBACK或COMMIT的情况下退出包也会引发异常 - 即应该没有包可以退出的路由,在数据库上留下一个未提交的行。
可以解释你所看到的唯一情况是回滚是否失败,或者根本没有执行,然后代码继续执行COMMIT。
(另一种可能的选择 - Insert也是作为一个自治事务完成的,具有自包含的提交,以便在回滚之前提交数据?)。
自主交易因(重新) - 引入原子事务要避免的问题(竞争条件,数据完整性,死锁)而臭名昭着 - 它们有其用途,但必须小心处理。