存储过程
创建存储过程:基本语法
GO
CREATE PROC spEmployee
AS
SELECT * FROM HumanResources.Employee;
使用ALTER 修改存储过程
@LastName nvarchar(50)
AS
SELECT
p.LastName,p.FirstName,e.JobTitle,e.HireDate
FROM Person.Person p LEFT JOIN HumanResources.Employee e ON p.BusinessEntityID = e.BusinessEntityID
WHERE p.LastName LIKE @LastName+'%';
EXEC spEmployeeByName 'Dobney';
create proc spEmployeeByName
@LastName nvarchar(50) = null--设置参数并给默认值
as
if @LastName is not null--判断参数是否为空
begin
select
p.LastName,p.FirstName,e.JobTitle,e.HireDate
from Person.Person p LEFT JOIN HumanResources.Employee e on p.BusinessEntityID = e.BusinessEntityID
where p.LastName LIKE @LastName+'%';
end
else
begin
select
p.LastName,p.FirstName,e.JobTitle,e.HireDate
from Person.Person p LEFT JOIN HumanResources.Employee e on p.BusinessEntityID = e.BusinessEntityID;
end
exec spEmployeeByName;--使用默认值
exec spEmployeeByName 'Dobney';--使用参数
@ErrorLogID int = 0 output--声明输出参数
as
begin
set nocount on;--作用:阻止在结果集中返回显示受T-SQL语句或则usp影响的行计数信息。当SET ONCOUNT ON时候,不返回计数,当SET NOCOUNT OFF时候,返回计数;
set @ErrorLogID = 0;--设置值
--处理错误信息--
begin try
if ERROR_NUMBER() is null--判断错误行号
return;
if XACT_STATE()=-1-- XACT_STATE 指示请求是否有活动的用户事务,以及是否能够提交该事务
begin
print 'Cannot log error since the current transaction is in an uncommittable state.'
+'Rollback the transaction before executing uspLogError in order to successfully log error information.';
return;
end
--插入信息--
insert into dbo.ErrorLog
(
[UserName],
[ErrorNumber],
[ErrorSeverity],
[ErrorState],
[ErrorProcedure],
[ErrorLine],
[ErrorMessage]
)
values(
CONVERT(sysname,CURRENT_USER),
ERROR_NUMBER(),
ERROR_SEVERITY(),
ERROR_STATE(),
ERROR_PROCEDURE(),
ERROR_LINE(),
ERROR_MESSAGE()
)
set @ErrorLogID = @@IDENTITY;--获取插入标识
end try
begin catch
print 'An error occurred in stored procedure uspLogError:';
execute dbo.uspLogErrors;
return -1;
end catch
end
create table OurIFTest(
Col1 int primary key
);
end try
begin catch
declare @MyOutputParameter int;
if error_number() = 2714
begin
print 'WARNING:Skipping CREATE as table already exists';
exec dbo.uspLogError @ErrorLogID = @MyOutputParameter output;
print 'An error was logged.The Log ID for your error was'+ cast(@MyOutputParameter as varchar);
end
else
raiserror('something not good happened this time around',16,1);
end catch
通过返回值确认成功或失败
如何使用RETURN
as
declare @MyMessage varchar(50);
declare @MyOtherMessage varchar(50);
select @MyMessage = 'Hi,it ''s that line before the RETURN';
print @MyMessage;
return 100;
select @MyOtherMessage = 'Sorry,but you won''t get this far';
print @MyOtherMessage;
return;
--测试代码----
declare @Return int;
exec @Return = spTestReturns;
select @Return;
--删除spTestReturns
drop proc spTestReturns;
错误处理
处理内联错误
利用@@ERROR
insert into Person.BusinessEntityContact(BusinessEntityID,PersonID,ContactTypeID)values(0,0,1);
select @Error = @@ERROR;--获取上一条语句的错误状态,并赋值给一个局部变量,因为每一条语句都会是之重置。
print '';
print 'The Value of @Error is '+convert(varchar,@Error);
print 'The Value of @@ERROR is'+convert(varchar,@@ERROR);
create proc spInsertValidateBusinessEntityContact
@BusinessEntityID int,
@PersonID int,
@ContactTypeID int
as
begin
declare @Error int;
insert into Person.BusinessEntityContact(BusinessEntityID,PersonID,ContactTypeID)
values(@BusinessEntityID,@PersonID,@ContactTypeID)
set @Error = @@ERROR;--将@@ERROR赋给局部变量进行保存
if @Error = 0
print N'新记录被插入';
else
begin
if @Error = 547
print 'At least one provided parameter was not found.Correct and retry';
else
print 'UnKnown error occurred.Please contact your system admin';
end
end
exec spInsertValidateBusinessEntityContact 1,1,11;
在错误发生之前处理错误
@BusinessEntityID int,
@JobTitle nvarchar(50),
@HireDate datetime,
@RateChangeDate datetime,
@Rate money,
@PayFrequency tinyint,
@CurrentFlag dbo.Flag
with exec as caller--指定在模块调用方的上下文中执行该模块中的语句。
as
begin
set nocount on;--作用:阻止在结果集中返回显示受T-SQL语句或则usp影响的行计数信息。当SET ONCOUNT ON时候,不返回计数,当SET NOCOUNT OFF时候,返回计数;
declare @BUSINESS_ENTITY_ID_NOT_FOUND int = -1000,--声明常量
@DUPLICATE_RATE_CHANGE int = -2000;--声明常量
begin try
begin transaction;--表示开启一个事务
update HumanResources.Employee
set
JobTitle = @JobTitle,
HireDate = @HireDate,
CurrentFlag = @CurrentFlag
where BusinessEntityID = @BusinessEntityID;
insert into HumanResources.EmployeePayHistory
(
BusinessEntityID,
RateChangeDate,
Rate,
PayFrequency
)
values(
@BusinessEntityID,
@RateChangeDate,
@Rate,
@PayFrequency
);
commit transaction;--提交一个事务
end try
begin catch
if @@TRANCOUNT>0--返回在当前连接上执行的 BEGIN TRANSACTION 语句的数目
begin
--rollback transaction;--将显式事务或隐性事务回滚到事务的起点或事务内的某个保存点
insert into HumanResources.EmployeePayHistory
(BusinessEntityID,RateChangeDate,Rate,PayFrequency)
values
(@BusinessEntityID,@RateChangeDate,@Rate,@PayFrequency);
end
else
begin
print 'BusinessEntityID not Found';
rollback transaction;
return @BUSINESS_ENTITY_ID_NOT_FOUND;
end
end catch
end
消息ID/消息字符串
raiserror(N'引发了消息',1,1);
严重性
重新抛出错误
定义:开发人员使用的不限于T-SQL领域的经验法则是只捕获可以处理的错误,您不知道如何处理的任何错误都应该直接传递给调用者,调用者可能知道(也可能不知道)如何处理错误,但是至少不需要你来处理。如果您没有准备好处理一个错误,则可以向下抛出(THROW)该错误。THROW在某些方面非常类似与RAISERROR,但是有一些重要的区别。insert OurIFTest(Col1) values(1);
end try
begin catch
print 'Arrived in the CATCH block.';
declare @ErrorNo int,
@Severity tinyint,
@State smallint,
@LineNo int,
@Message nvarchar(4000);
select
@ErrorNo = ERROR_NUMBER(),
@Severity = ERROR_SEVERITY(),
@State = ERROR_STATE(),
@LineNo = ERROR_LINE(),
@Message = ERROR_MESSAGE();
if @ErrorNO = 2714
print 'WARNING:object already exists';
else
throw;
end catch
使用sp_addmessage
@msgnum = 60000,
@lang ='us_english',
@severity=10,
@msgtext = '%s is not a valid Order date.Order date must be within 7 days of current date.'
存储过程的缺点
1.对于存储过程不利之处要认识到的最重要的一点是,除非收到的干预(使用WITH RECOMPILE),否则只会在第一次运行存储过程时,或者当查询所涉及的表更新了统计信息时,擦会对存储过程进行优化。存储过程实现递归
create proc spFactorial
@ValueIn int,--输入参数
@ValueOut int OUTPUT--输出参数
as
declare @InWorking int;--输入值替换
declare @OutWorking int;--输出值替换
if @ValueIn>=1--判断输入值是否大于1
begin
select @InWorking = @ValueIn-1;
exec spFactorial @InWorking,@OutWorking OUTPUT;
select @ValueOut = @ValueIn* @OutWorking;
end
else
begin
select @ValueOut =1;
end
return;
go
--执行脚本
declare @WorkingOut int;
declare @WorkingInt int;
select @WorkingInt = 5;
exec spFactorial @WorkingInt,@WorkingOut OUTPUT;
print cast(@WorkingInt as varchar) + 'factorial is'+cast(@WorkingOut as varchar);
751



被折叠的 条评论
为什么被折叠?



