版权声明: https://blog.csdn.net/ClearLoveQ/article/details/82803252
1.创建存储过程:
USE SIPC
GO
CREATE PROC ASelectDepartment
AS
select * from B_Department
2.删除存储过程:
DROP PROC|PROCEDURE 过程名
存储过程的参数:从存储过程外部向存储过程传递参数,可以采用传值或者传引用;而在内部用相同的方法来声明
参数声明:名称 数据类型 默认值 方向
@参数名 [AS] 数据类型 [=默认值|NULL] [varying] [OUTPUT|OUT]
在声明cursor类型时,必须同时使用[varying] [OUTPUT|OUT]
变量总是被初始化成NULL值,而参数则不然,如果不为参数指派默认值,那么就等于必须提供参数,在调用存储过程时就必须为其提供一个初始值
注意:被作为输出结果变量不能同存储过程中的内部变量同名
如果对存储过程的调用是批中的第一件事,那么可以省略,但还是强烈建议不这么做
3.修改存储过程为有参数的:
出国存储过程A调用存储过程B,然后删除重建存储过程B,此时就看不到这两者的依懒性了;如果仅仅是修改存储过程B,其依赖性任然存在
ALTER PROC [dbo].[ASelectDepartment]
@Dept_Name nvarchar(100)=NULL
AS
IF @Dept_Name is NULL
select * from B_Department
ELSE
select * from B_Department b
where Dept_Name=@Dept_Name
4.SQL Server中执行带参数的存储过程的方法是:
EXEC 存储过程名字 '参数1','参数2',数值参数
EXEC 是一个关键字。
字符串参数使用单引号括起来,数值参数不需要使用单引号
不带参数的存储过程执行直接加名字就可以
5.RETURN
存储过程完成时,SQL SERVER会默认返回一个0;
要从存储过程向调用它的代码传递返回值,可以简单地使用RETURN: RETURN [<整数返回值>] 注意返回值一定是整数
想要取到存储过程运行后的返回值,只需要在EXEC语句执行时,将之赋值到一个变量中,如下:
DECLARE @ReturnVal INT --声明返回值
EXEC @ReturnVal=ARETURN
SELECT @ReturnVal
注:请确保你总是显示的定义了返回值,这样你就可以根据需要返回相应的值,而不是某些偶然性的东西
6.错误处理
SQL SERVER中发生4中常见类型的错误:
错误1:在运行时创建错误,同时终止错误发生之后的代码
错误2:直接产生错误提示,这时会返回一个非0值,但并不生成任何错误
错误3:在运行时创建错误,但是在SQL SERVER中继续执行下去,这样就可以捕获该错误,并选择自己的应对方法
错误4:本质上符合逻辑的错误,但是SQL SERVER会忽略它
7.@@ERROR 每当执行了一条新语句时,它的值都将被重设
大小写敏感与否取决于服务器的配置方式
@符号的数量决定了变量的独立性以及同其他变量的区别
8.手工生成错误:使用RAISERROR命令
RAISERROR (<消息ID|消息字符串>,<严重级别>,<状态> [,<参数>[,<...n>]]) [WITH option[,...n]]
e1.消息ID在系统master库中,的视图sysMessages中
消息字符串的默认消息ID为50000,可以通过WITH SETERROR来覆盖它
e2.严重级别,20或者更高的严重级别错误将会终止用户连接
e3.状态是一种特殊值,它是某些用于识别代码中的多个位置上确实可能发生同样错误的东西
e4.错误参数
所有的占位符都以%号打头
例如:
RAISERROR('这是一个%s,is %+010d',1,1,'String',33333)
占位符类型标识:D 有符号整数
O 无符号八进制数
P 指针
S 字符串
U 无符号整数
X或x 无符号十六进制数
同时还有一些选项可以作为这些占位符的前缀,以表示额外的标识或宽度信息
- (破折号或减号) 左对齐,只在使用固定宽度时起作用
+ (加好) 如果参数是有符号的数值类型,则表示正负类型
0 告诉SQL SERVER数值左方补0,直到达到指定宽度
# (磅号) 只用于8进制和16进制,依赖于是8进制还是16进制,告诉SQL SERVER使用合适的前缀(0或0x)
' ' 对于正数在左边用空格补齐
宽度:上例中的10就是宽度,必须是整数值,也可以指定*,这时SQL SERVER会根据你所设置的精度,自动确定其宽度
精度:确定最大输出数字的个数
长/度:当参数类型是整数,八进制,十六进制,可以通过h(短)或l(长)来设置
上面例子的结果:
这是一个String,is +000033333
消息 50000,级别 1,状态 1
9.WITH <option>
当产生错误时,可以匹配三个选项;
WITH LOG: 告诉SQL SERVER将错误记录到SQL SERVER错误日志和Windows的应用程序日志中,当严重级别为19或者更高时,需要使用该选项
WITH SETERROR: 默认情况下,RAISERROR命令不会用产生的错误值来对@ERROR赋值,但是SETERROR对它进行了重载,并将@@ERROR的值设置为等同于错误的ID
WITH NOWALT: 立刻通知错误的客户端
10.添加自己定义地错误消息
利用系统的存储过程sp_addmessage,该存储过程在master库下,语法如下:
sp_addmessage [@msgnum=] <消息ID>,
[@severity=] <严重级别>,
[@msgtext=] <'消息字符串'>
[,[@lang=] <'语言'>]
[,[@with_log=] [TRUE|FALSE]]
[,[@replace=] 'replace']
参数介绍:
@lang 如果从sys.syslanguage中选择语言列表,这等同于其别名
@with_log 如果为TRUE ,当产生错误时,消息会被记录到SQL SERVER错误日志,以及Windows的应用程序日志当中去
@replace 如果是正在编辑一个现有的消息,而不是创建新的消息,则必须将@replace 参数设置为 'replace' 如果没有进行设置,若消息已经存在,则会得到一个错误
使用方法:
sp_addmessage
@msgnum=60000,
@severity=10,
@msgtext='It is not a valid other date.order date must be within 7 days of current date.',
@lang='us_english',
@with_log=false,
@replace='replace'
删除自定义消息: sp_dropmessage <msgnum>,<lang>
sp_dropmessage 60000,'us_english'
11.使用存储过程的好处:
增强安全性;
提高性能; 当指定了WITH RECOMPILE,则跳过优化的编译 EXEC 存储过程名字 WITH RECOMPILE 仅仅跳过这一次优化执行,如果想永久跳过,可以写到存储过程中在AS之前
允许创建需要可调用过程行为的过程 简而言之:存储过程调用存储过程,2005中最多可以进行32层嵌套
12.用户定义函数UDF
很像存储过程,是一系列T-SQL语句的有序集合,它可以被预优化和编译,并且可以在工作中被作为一个单一的单元来调用;
它和存储过程的不同之处在于结果是如何被返回的;
UDF分为:
x1.返回标量值的UDF
除了BLOB,CURSOR,timestamp之外,可以返回任何有效的SQL Server数据类型(包括用户定义地数据类型);
可以在查询中作为内联执行函数;
x2.返回表的UDF
13.返回标量值的UDF
CONVERT() 函数是把日期转换为新数据类型的通用函数。
CONVERT() 函数可以用不同的格式显示日期/时间数据。
CONVERT(data_type(length),data_to_be_converted,style)
data_type(length) 规定目标数据类型(带有可选的长度)。data_to_be_converted 含有需要转换的值。style 规定日期/时间的输出格式。
Style ID Style 格式
100 或者 0 mon dd yyyy hh:miAM (或者 PM)
101 mm/dd/yy
102 yy.mm.dd
103 dd/mm/yy
104 dd.mm.yy
105 dd-mm-yy
106 dd mon yy
107 Mon dd, yy
108 hh:mm:ss
109 或者 9 mon dd yyyy hh:mi:ss:mmmAM(或者 PM)
110 mm-dd-yy
111 yy/mm/dd
112 yymmdd
113 或者 13 dd mon yyyy hh:mm:ss:mmm(24h)
114 hh:mi:ss:mmm(24h)
120 或者 20 yyyy-mm-dd hh:mi:ss(24h)
121 或者 21 yyyy-mm-dd hh:mi:ss.mmm(24h)
126 yyyy-mm-ddThh:mm:ss.mmm(没有空格)
130 dd mon yyyy hh:mi:ss:mmmAM
131 dd/mm/yy hh:mi:ss:mmmAM
如果用下面的方式查询,如果有一大堆这样的时间需要翻来覆去的转换,无疑太可怕了:
SELECT * FROM Orders WHERE CONVERT(varchar(12),OrdersDate,101)=CONVERT(varchar(12),GETDATE(),101)
所以编写一个简单的UDF(标量值函数):
CREATE FUNCTION dbo.DayOnly(@Date datetime)
RETURNS varchar(12)
AS
BEGIN
RETURN CONVERT(varchar(12),@Date,101)
END
使用:
SELECT * FROM Orders WHERE dbo.DayOnly(OrdersDate)=dbo.DayOnly(GETDATE())
你也可以用函数封装子查询,让他感觉像单值一样
14.返回表的UDF
USE [SIPC]
GO
/****** Object: UserDefinedFunction [dbo].[fnContactList] Script Date: 09/21/2018 09:38:37 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: <Author,,Name>
-- Create date: <Create Date,,>
-- Description: <Description,,>
-- =============================================
CREATE FUNCTION [dbo].[fnContactList]()
RETURNS
TABLE
AS
RETURN (SELECT DB_Name,Dept_Code+','+Dept_Name AS Name FROM B_Department)
GO
使用:
SELECT * FROM fnContactList()
15.检查函数是否是确定性的:可以使用函数
SELECT OBJECTPROPERTY(OBJECT_ID('DayOnly'),'IsDeterministic')