一、存储过程中使用事务的简单语法
在存储过程中使用事务时非常重要的,使用数据可以保持数据的关联完整性,在Sql server存储过程中使用事务也很简单,用一个例子来说明它的语法格式:
CreateProcereMyProcere
(@Param1nvarchar(10),
@param2nvarchar(10)
)
AS
Begin
SetNOCOUNTON;
SetXACT_ABORTON;
BeginTran
Deletefromtable1wherename=’abc’;
Insertintotable2values(value1,value2,value3);
CommitTran
End
说明:
1 、使用存储过程执行事物,需要开启XACT_ABORT参数(默认值为Off),将该参数设置为On,表示当执行事务时,如果出错,会将transcation设置为uncommittable状态,那么在语句块批处理结束后将回滚所有操作;如果该参数设置为Off,表示当执行事务时,如果出错,出错的语句将不会执行,其他正确的操作继续执行。
2、当SET NOCOUNT 为 ON 时,不返回计数(计数表示受 Transact-SQL 语句影响的行数,例如在Sql server查询分析器中执行一个delete操作后,下方窗口会提示(3)Rows Affected)。当 SET NOCOUNT 为 OFF 时,返回计数,我们应该在存储过程的头部加上SET NOCOUNT ON 这样的话,在退出存储过程的时候加上 SET NOCOUNT OFF这样的话,以达到优化存储过程的目的。
二、事务内设置保存点
用户可以在事务内设置保存点或标记。保存点定义如果有条件地取消事务的一部分,事务可以返回的位置。如果将事务回滚到保存点,则必须(如果需要,使用更多的 Transact-SQL 语句和 COMMIT TRANSACTION 语句)继续完成事务,或者必须(通过将事务回滚到其起始点)完全取消事务。若要取消整个事务,请使用 ROLLBACK TRANSACTION transaction_name 格式。这将撤消事务的所有语句和过程。如:
代码
CreateProcereMyProcere
AS
Begin
SetNOCOUNTON;
SetXACT_ABORTON;
begintranok--开始一个事务OK
deletefromrxqzwhereqz='rx015'--删除数据
savetranbcd--保存一个事务点命名为bcd
updateszsetname='李丽s'wherename='李丽'--修改数据
if@@error<>0--判断修改数据有没有出错
begin--如果出错
rollbacktranbcd--回滚事务到BCD的还原点
committranok--提交事务
end
else--没有出错
committranok--提交事务
End
说明:1、@@error判断是否有错误,为0表示没有错误,但是对那种重大错误无法捕捉,而且@@error只能前一句sql语句生效。
三、存储过程使用try…catch捕获错误
在存储过程中可以使用try…catch语句来捕获错误,如下:
CreateProcereMyProcere
(@Param1nvarchar(10),
@param2nvarchar(10)
)
AS
Begin
SetNOCOUNTON;
Begintry
Deletefromtable1wherename=’abc’;
Insertintotable2values(value1,value2,value3);
Endtry
BeginCatch
SELECTERROR_NUMBER()ASErrorNumber,
ERROR_MESSAGE()ASErrorMessage;
EndCatch
End
说明:1、捕获错误的函数有很多,如下:
ERROR_NUMBER() 返回错误号。
ERROR_SEVERITY() 返回严重性。
ERROR_STATE() 返回错误状态号。
ERROR_PROCEDURE() 返回出现错误的存储过程或触发器的名称。
ERROR_LINE() 返回导致错误的例程中的行号。
ERROR_MESSAGE() 返回错误消息的完整文本。该文本可包括任何可替换参数所提供的值,如长度、对象名或时间。
2、有些错误,如sql语句中的表名称输入错误,这是数据库引擎无法解析这个表名称时,所发生的错误在当前的try…catch语句中无法捕获,必须由外层调用该存储过程的地方使用 try…catch来进行捕获。
四、存储过程中事务和try…catch联合使用
在存储过程中使用事务时,如果没有try…catch语句,那么当set xact_abort on时,如果有错误发生,在批处理语句结束后,系统会自动回滚所有的sql操作。当set xact_abort off时,如果有错误发生,在批处理语句结束后,系统会执行所有没有发生错误的语句,发生错误的语句将不会被执行。
在存储过程中使用事务时,如果存在try…catch语句块,那么当捕获到错误时,需要在catch语句块中手动进行Rollback操作,否则系统会给客户端传递一条错误信息。如果在存储过程开始处将set xact_abort on,那么当有错误发生时,系统会将当前事务置为不可提交状态,即会将xact_state()置为-1,此时只可以对事务进行Rollback操作,不可进行提交(commit)操作,那么我们在catch语句块中就可以根据xact_state()的值来判断是否有事务处于不可提交状态,如果有则可以进行rollback操作了。如果在存储过程开始处将set xact_abort off,那么当有错误发生时,系统不会讲xact_state()置为-1,那么我们在catch块中就不可以根据该函数值来判断是否需要进行rollback了,但是我们可以根据@@Trancount全局变量来判断,如果在catch块中判断出@@Trancount数值大于0,代表还有未提交的事务,既然进入catch语句块了,那么还存在未提交的事务,该事务应该是需要rollback的,但是这种方法在某些情况下可能判断的不准确。推荐的方法还是将set xact_abort on,然后在catch中判断xact_state()的值来判断是否需要Rollback操作。
下面我们来看看两个例子:
一.使用Set xact_abort on
CreateprocmyProcere
As
begin
setxact_aborton;
begintry
begintran
insertintoTestStuvalues('Terry','boy',23);
insertintoTestStuvalues('Mary','girl',21);
committran
endtry
begincatch
--在此可以使用xact_state()来判断是否有不可提交的事务,不可提交的事务
--表示在事务内部发生错误了。Xact_state()有三种值:-1.事务不可提交;
--1.事务可提交;0.表示没有事务,此时commit或者rollback会报错。
ifxact_state()=-1
rollbacktran;
endcatch
end
二.使用Set xact_abort off
CreateprocmyProcere
As
begin
setxact_abortoff;
begintry
begintran
insertintoTestStuvalues('Terry','boy',23);
insertintoTestStuvalues('Mary','girl',21);
committran
endtry
begincatch
--在此不可以使用xact_state来判断是否有不可提交的事务
--只可以使用@@Trancount来判断是否有还未提交的事务,未提交的事务未必
--就是不可提交的事务,所以使用@@TranCount>0后就RollBack是不准确的
if@@TranCount>0
rollbacktran;
endcatch
end
另外,对于@@Trancount需要说明的是,begin tran 语句将 @@Trancount加 1。Rollback tran将 @@Trancount递减到 0,但 Rollback tran savepoint_name 除外,它不影响 @@Trancount。Commit tran 或 Commit work 将 @@Trancount 递减 1。
❷ SQL 跟踪问题 在 SQL 跟踪中,如何判断SQL语句执行是否错误。
SQL Server Profiler工具是来捕获当前执行的SQL语句,并不能反馈执行结果和错误信息在查询分析器窗口执行语句错误自然会提示,要知道错误语句在哪里,可以像楼上那种做法,设置一些Print语句,哪里没打印错误就到哪里。一般我这边写则会定义一个变量用语存放SQL语句,在执行之前加多一句print,这样执行错误就知道语句是那句了如:declare @Sql varchar(2000)set @Sql='select 1'print @Sqlexec(@Sql)set @Sql='update table set abc=124'print @Sqlexec(@Sql)
❸ sql语句的错误原因
如果是在access里面直接执行的话,你的语句应该没有错误,
但如果要在SQL Server里面达到同样效果的话,
需要将通配符'*'改为'%',即:
select top 5 c_name,c_stu from class where c_stu>30 and c_type=true and c_name like '%二班%' order by c_stu asc,c_type desc
试试,应该没有问题
❹ SQL出现错误什么原因
先把原库文件备份一份,然后
在其它机器上直接附加数据库,不要日志文件!试试!如果不行再按以下方法试试!
在其他机器上,用这个试试:
1.设置数据库为紧急模式
Use Master
GO
sp_configure 'allow updates', 1
reconfigure with override
GO
UPDATE sysdatabases SET status = 32768 where name = 'DB_SUSPECT'
GO
2.停掉SQL Server服务:
NET STOP MSSQLSERVER
3.把原始数据库的数据文件DBNAME_DAT.MDF,DBNAME_LOG.LDF移走:
4.启动SQL Server服务:
NET START MSSQLSERVER
❺ 请教CI如何捕获SQL语句异常
try{
//代码 代码中通常会出现不知情却在情理中的错误
int age = a.getAge();//如果a对象为空,你却调用它的方法就会报NullPointerException异常
}catch(//异常类型 NullPointerException ne){//获取你可以预知的异常
//异常处理就是你捕获了这个异常你要这个异常进行哪种操作
//一般的操作就是记录到日志里
//然后抛出去或者返回状态
}catch(Exception ex){//这个是所有异常的父类
//因为很多异常是不可预知的
//记录到日志里
//然后抛出去或者返回状态
}
❻ 你09年问的关于VB捕捉Sql过程中错误,错误前面有select 语句,就不回报错
可以啊,比如说exec netFeiPiao 'weq'
执行出错的话,数据库会把这个错误信息返回回来的。
你只需要在VB中捕获就可以,vb中应该有个connection吧
connection.errorMsg大概就是这么个意思,具体怎么写我不知道,我是搞C++的。
❼ 在SQL Server中如何进行错误捕捉
如果在Transact-SQL中发生了错误,一般有两种捕捉错误的方法,一种是在客户端代码(如c#、delphi等)中使用类似try...catch的语句进行捕捉;另外一种就是在Transact-SQL中利用Transact-SQL本身提供的错误捕捉机制进行捕捉。如果是因为Transact-SQL语句的执行而产生的错误,如键值冲突,使用第一种和第二种方法都可以捕捉,但是如果是逻辑错误,使用客户端代码进行捕捉就不太方便。因此,本文就如何使用Transact-SQL进行错误捕捉进行了讨论。 非致命错误(non-fatal error)的捕捉 通过执行Transact-SQL而产生的错误可分为两种:致命错误(fatal error)和非致命错误(non-fatal error)。在Transact-SQL中只可以捕捉非致命错误(如键值冲突),而无法捕捉致命错误(如语法错误)。在Transact-SQL中可以通过系统变量@@ERROR判断最近执行的一条语句是否成功执行。如果发生了错误,@@Error的值大于0,否则值为0。下面举一个例子说明@@ERROR的使用。 假设有一个表table1,在这个表中有两个字段f1,f2。其中f1是主键。 INSERTINTOtable1VALUES(1,'aa')INSERTINTOtable1VALUES(1,'bb')--这条语句将产生一个错误IF@@ERROR0PRINT'键值冲突'当执行第二条语句时发生键值冲突错误,@@ERROR被赋为错误号2627,因此输出结果显示'键值冲突'。使用@@ERROR系统变量时需要注意,@@ERROR只记录最近一次执行的Transact-SQL语句所发生的错误,如果最近一次执行的Transact-SQL没有发生错误,@@ERROR的值为0。因此,只能在被捕捉的那条Transact-SQL语句后使用@@ERROR。 在SQL Server中,不仅可以捕捉系统提供的错误,还可以自定义错误。有两种方法可以定义错误信息。 1. 使用sp_addmessage系统存储过程添加错误信息,然后使用RAISERROR抛出错误。 sp_addmessage将错误号,错误级别、错误描述等信息添加到系统表中,然后使用RAISERROR根据相应的错误号抛出错误信息。用户自定义的信息应该从50001开始。EXECsp_addmessage@msgnum=50001, @severity=16,@msgtext='sql encounter an error(%s).',@lang='us_english'EXECsp_addmessage@msgnum=50001, @severity=16,@msgtext='sql遇到了一个错误(%1!).'如果使用的SQL Server版本是非英语版本,在添加本地错误信息时必须首先添加英文的错误信息。错误描述可以象c语言中的printf的格式字符串一样使用参数,如%s、%d。但要注意的是在英文版的错误信息中要使用%s、%d等形式,而在本地化的错误信息中要使用%1!、%2!等形式,在每个%?(1 <= ? <= n)后需要加一个!,而且%?的数目必须和英文版的错误信息的参数一致。 在未插入本地化错误信息时,RAISERROR将使用英文版的错误信息。当插入本地化错误信息时,RAISERROR使用本地化的错误信息。 RAISERROR(50001,16,1,'测试') 输出的结果: 服务器: 消息50001 ,级别16 ,状态1 ,行1sql遇到了一个错误(测试). 其中'测试'字符串通过%1传入本地化的错误描述字符串中。 2. 直接使用RAISERROR将错误抛出。 使用第一种方法虽然使Transact-SQL语句看上去更整洁(这种方法类似于在编程语言中使用常量定义错误信息,然后在不同的地方通过错误编号引用这些错误信息。),但是这样做却使错误信息和数据库的耦合度增加,因为如果将这些带有RAISERROR的Transact-SQL放到别的SQL Server数据库上执行,由于在其它的数据库中还未添加错误信息,因此会产生RAISERROR调用错误,除非使用sp_addmessage将所需的错误信息再加入到其它的数据库中。 基于上述原因,RAISERROR不仅可以根据错误代码抛出错误信息,也可以直接通过错误描述格式字符串抛出错误信息。
❽ 有什么办法能捕捉SQL数据库异常使其不退出对话框
很多方法可以做到
1,数据库后台写存储过程,所有操作数据库得到均通过存储过程来进行,在存储过程里可以用try(sql 2005支持,sql 2000可以判断语句的返回)来捕获错误,并把错误信息返回
2,前台代码里面做,和数据库相关的调用,判断其返回值,进行过滤处理,或者直接进行try catch捕获异常,一般前台语言均支持try
❾ 如何捕获sqlserver数据库的异常
Result.next()只会在两种情况发生异常:一是数据库本身故障,二是已经关闭。
而在你的程序中只是为了防止出现一个异常不影响其它的,那么可以假定了,前面的访问是正确的。所以,第一个异常原因不可能出现的。而你不会自己主动在另一个线程关闭数据库吧?那么第二个异常原因也不可能出现。
所以,这个异常捕获了,不必做任何处理,直接进行下一个就行。
while(rs.next()){
try{
//..........
}
catch(SQLException ex){}
}