zoukankan      html  css  js  c++  java
  • 关于ADO中的隐性事务

    KeyLife富翁笔记
    作者: HongYuan
    标题: 关于ADO中的隐性事务
    关键字:
    分类: 我学习Delphi,我努力
    密级: 保护
    (评分: , 回复: 0, 阅读: 230) »»

    测试代码:
      ADOQuery1.sql:='select * from region'
      ADOQuery2.sql:='exec SP_test'='select * from region'


      ADOConnection1.BeginTrans;
      ADOQuery1.Post;
     
      //必需发送一次语句重新从数据库提取一次更新后的数据;个人认为同一进程(ADOConnection连接,在SQL Server为一个连接进程,或者一个会话),未提交数据也可以访问,但需人为重新发送一个语句以便从数据库中提出数据返回到数据集TDataSet  
      ADOQuery2.Close;
      ADOQuery2.Open;
      ShowMessage(ADOQuery2.FieldByName('Name').AsString);

      if CheckBox1.Checked then
        ADOConnection1.CommitTrans
      else ADOConnection1.RollbackTrans;
    //撤销事务时,因为ADOQuery1做为TDataSet中的数据为修改后,必需刷新一下,ADOQuery2因为修改后,事务提交前重新提过数据,所以现在必需再提一次撤销后数据
      ADOQuery1.Close;
      ADOQuery1.Open;
      ADOQuery2.Close;
      ADOQuery2.Open;

    执行跟踪产生的SQL语句与解读:

    set implicit_transactions on 开始隐性事务
    go
    exec sp_executesql N'UPDATE "public".."region" SET "Name"=@P1 WHERE "Code"=@P2 AND "Name"=@P3 AND "Postcode"=@P4 AND "AreaCode"=@P5 AND "Area"=@P6', N'@P1 varchar(7),@P2 varchar(6),@P3 varchar(12),@P4 varchar(2),@P5 varchar(3),@P6 varchar(4)', 'abdasdf', 'efasdf', '111111111111', 'as', 'asd', 'asdf'
    --ADOQuery1执行数据修改
    go
    select * from region
    --ADOQuery2执行,这里可以提取到修改后数据,虽然没有提交
    go
    IF @@TRANCOUNT > 0 COMMIT TRAN 提交事务或IF @@TRANCOUNT > 0 ROLLBACK TRAN回滚
    go
    set implicit_transactions off 关闭隐性事务
    go
    select * from region --ADOQuery1重新提取

    go
    select * from region --adoquery2重新提取

    go

    注意:
       1.Adoquery1和adoquery2使用同一个ADOConnection1
       2.本事务未结束,则其它进程里无法读取region表数据


    2005-11-4 11:55:39   
     2005-11-23 14:39:27    不能返回客户端ADOCONNECTION错误信息,但在查询分析器里可能看到

    ALTER   procedure SP_test
      as
      Begin Transaction T_SP_AlterFeeTable

      select * from sysobjects

      RAISERROR ('修改核算数据表异常,系统将自动删除指定的工艺项目数据!', 16, 1)  

      commit transaction T_SP_AlterFeeTable

     
     2005-11-23 14:41:33    可以返回客户端ADOCONNECTION错误信息

    ALTER   procedure SP_test
      as
      Begin Transaction T_SP_AlterFeeTable

      RAISERROR ('修改核算数据表异常,系统将自动删除指定的工艺项目数据!', 16, 1)    

      select * from sysobjects  

      commit transaction T_SP_AlterFeeTable

     
     2005-11-23 14:44:22    能返回客户端ADOCONNECTION错误信息,但在查询分析器里可能看到

    ALTER   procedure SP_test
      as
      Begin Transaction T_SP_AlterFeeTable

      select * from sysobjects  

      commit transaction T_SP_AlterFeeTable

      RAISERROR ('修改核算数据表异常,系统将自动删除指定的工艺项目数据!', 16, 1)    

     
     2005-11-23 15:59:19    关于Raiserror与ADO分析结果

    ADO调用执行存储过程的时都会(SET FMTONLY ON),比如,在ADOQuery2.sql中填入exec sp_test,则相应的程序调用以下代码:
    SET FMTONLY ON exec sp_test SET FMTONLY OFF
    可见,只要在执行存储过程sp_test时发生异常,仅将元数据返回给客户端,且将不对行进行处理,也不将行作为请求的结果发送到客户端。而RAISERROR,PRINT产生的信息,都将不会返回客户端,但SQLSERVER产生的ERROR信息除外。并且SET FMTONLY在存储过程中全局有效,执行完后则无效。

    由上可见,系统不包括的错误信息,比如业务安全检查,需要通过RAISERROR返回信息时,一定要在存储过程中SET FMTONLY OFF RAISERROR('错误',16,1)这样才能在客户端得到错误信息

     
     2005-11-23 16:34:07    最后的测试代码

    delphi+ado:

    var
      i:Integer;
    begin
      try
        ADOConnection1.BeginTrans;
        ADOQuery1.Post;
        with ADOQuery2 do
        begin
          Close;
          SQL.Clear;
          SQL.Add('exec sp_test ');
          Open;
        end;

        ADOConnection1.CommitTrans;

      except
        for i:=0 to ADOConnection1.Errors.Count-1 do
              ShowMessage(ADOConnection1.Errors[i].Description);
        ADOConnection1.RollbackTrans;
        ADOQuery1.Close;
        ADOQuery1.Open;
        //ADOQuery2.Close;
        //ADOQuery2.Open;
      end;

    下面是Query2调用存储过程代码

    SET QUOTED_IDENTIFIER ON
    GO
    SET ANSI_NULLS ON
    GO
    /*
    SET FMTONLY ON
    exec sp_test
    SET FMTONLY OFF
    */
    ALTER   procedure SP_test
      as
     
      declare @sql nvarchar(1000),@FiledName varchar(128)
      select top 1 @FiledName='['+isnull(Name,'')+']' from Region

      if rtrim(@FiledName)='[ ]'
      begin
        SET FMTONLY OFF
        RAISERROR ('指定的字段名不能空', 16, 1)
        return
      end

      set @sql ='alter table tt add '+@FiledName+' int'
      Begin Transaction T_SP_AlterFeeTable

      execute(@sql)


      if @@ERROR<>0
      begin
        ROLLBACK transaction T_SP_AlterFeeTable


        select * from tt
        return
      end
      else
      begin

      commit transaction T_SP_AlterFeeTable

      select * from tt
     
      end

    GO
    SET QUOTED_IDENTIFIER OFF
    GO
    SET ANSI_NULLS ON
    GO

     
     2005-11-23 16:57:39   

      for i:=0 to ADOConnection1.Errors.Count-1 do
              ShowMessage(ADOConnection1.Errors[i].Description);

    用raise代替也能提示错误信息

    var
      i:Integer;
    begin
      try
        ADOConnection1.BeginTrans;
        ADOQuery1.Post;
        with ADOQuery2 do
        begin
          Close;
          SQL.Clear;
          SQL.Add('exec sp_test ');
          Open;
        end;

        ADOConnection1.CommitTrans;

      except
        //for i:=0 to ADOConnection1.Errors.Count-1 do
        //begin
        //      ShowMessage(ADOConnection1.Errors[i].Description);
        //end;

          ADOConnection1.RollbackTrans;
          ADOQuery1.Close;
          ADOQuery1.Open;
          raise;
        //ADOQuery2.Close;
        //ADOQuery2.Open;
      end;
    end;

     
     2005-11-23 17:20:08   

    只要DELPHI使用try+事务处理,其实就算调用了存储过程执行多步操作,也可以回滚,而不必在存储过程中额外进行事务处理,但如果想部分修改有效的话,就得不使用DELPHI的ADO事务,而使用数据库存储过程中处理事务也可以。

  • 相关阅读:
    03:信号与槽,以字体修改为例
    赞不绝口点赞器原作者的撤项信
    钉钉魔铃 铃声切换器 1.0 项目失败
    KC开发组官方网站
    搜索引擎知识
    现在的手机厂家真浮躁
    02:QT的第一个程序
    第一次做编程语言的英语阅读理解
    mysql 报错[Err] [Dtf] 1292
    Mysql 精确查询是否字段中包含某个字符串
  • 原文地址:https://www.cnblogs.com/ZhouXiHong/p/568101.html
Copyright © 2011-2022 走看看