最近项目中较为频繁的使用存储过程,边学边用,有些知识点还颇花费了一些功夫查找,现做些总结。
一. 这次写的存储过程大多涉及多条件查询的需求,所以大多以此主题为主。看了很多帖子,大多出自同一人之手,多次复制粘贴转发之后已不知原作者,主要有三种写法:
- 拼sql:
create proc pro_test
@param1='' varchar(20),@param2='' varchar(20) --给参数设置默认值,这样在调用时,不必要的参数就可以不传入
as
declare @sql varchar(1000)='select * from table1 where 1=1 '
if(@param1!='')
set @sql=@sql+' and name= ''' +@param1 +'''' -- @param两边要用单引号包裹,单引号需要另一个单引号转义
.....
exec(@sql)
这种语法灵活性最大,如果条件判断较为复杂,建议采用
create proc pro_test
@param1='' varchar(20),@param2='' varchar(20),@param3 int
as
select * from table1 where 1=1 and
name=case @param1 when '' name else @param1 end and
gender=ISNULL(@param,param) and --sql转换函数
age>CASE WHEN @param3 THEN 10 else 20 END
case...when相当于switch .. case语法,可以部分代替if判断语句.这种写法简单,但的局限性比较大,比如对于in(x,y,z),between ... and..就不支持,它只返回单一值
3.(未实践)
select * from table where (addDate = @addDate or @addDate is null) and (name = @name or @name = '')
二. 存储过程如果涉及到调用另一个存储过程,也很简单.我在程序中遇到A存储过程要从B存储过程返回的结果集中去查询,
create proc pro_A
as
select from exec pro_B
这样写是错误的,pro_B返回的不是一张表,所以应该先定义一张表,将值注入才行
create proc pro_A
as
DECLARE @table TABLE (age INT) --注意:这里定义的表的列必须与pro_B返回结果集的一致
INSERT INTO @table EXEC pro_B
select * from exec @table
三.对于有出参的存储过程:入参出参顺序必须一致
CREATE PROC pro_A
@param1='' varchar(10),
@num INT OUTPUT
ASSET @num=(SELECT COUNT(1) FROM table1
DECLARE @num INT
EXEC pro_A @num OUTPUT
这样会报错,因为入参出参顺序的原因,几遍@param有默认值.所以要么改变出参入参定义顺序,要么就把入参带上, EXEC pro_A 'Lily',@num OUTPUT