【数据库】函数

函数可以单独使用,也可以套在select查询语句中使用,灵活得多,一个函数定义后,可以当库函数一样使用。

聚合函数

如:sum(列)avg(列)count() max( )min( )

用于数据的统计的,针对数据库表操作的,是系统类的函数

系统内置函数

sql提供的通用函数,不是用于表的统计的,与上面聚合函数不一样。如sin( ) convert( )year( )getdate( )

日期时间类

1> Getdate( )

2> Year(日期) 返回日期的年份 month(日期) day(日期)

3> Dateadd(日期时间的部分量,偏差值, 日期) 返回指定日期的指定分量的偏移后的日期结果

例: 求今天后的95天后是哪一天?

dateadd(year,95,getdate()) 

其中的日期部分量:

year, month,quarter,day,week,hour,minute,second,millisecond

如:

select GETDATE()+105
select DATEADD(day,105,getdate())
select DATEADD(hour,200,getdate())
select DATEADD(hour,200,'1990-2-1 11:05:30')
select 姓名,出生日期,DATEADD(day,100,出生日期) from 学生表

4>datediff(日期时间部分量,起始日期,结束日期)

求两个日期的指定部分偏移量 (是上面dateadd反操作,根据两个日期求出指定部分的偏差量)

print Datediff(month,'1986-12-1','2001-9-2') 
declare @d1 datetime,@d2 datetime
set @d1='2021-4-20 12:00:00'
select @d2=GETDATE()
print datediff(minute,@d1,@d2)

字符串函数

1> left(串,n) 取串左n个字符

2> right(串,n) 取串右n个字符

3>substring(串,m,n) 从串的第m个字符开始共取n个字符出来(如果要取的字符串超过的实际,取完即可,容错处理)

4>len(串) 求串长

5>Ltrim(串) 去掉串左边多余的空格 Rtrim(串) 去掉串的右边多余空格

select RIGHT(学号,3) from 学生表
select SUBSTRING(学号,2,3) from 学生表
select REPLACE('很多坏人信法轮功,在中国法轮法是不允许','法轮功',REPLICATE('*',len('法轮功')))

数据类型转换

1>convert(目标类型及宽度,被转换前原值[,其它附加参数]

Convert(nchar(5), n) 
Convert(nchar(10),生日,21)  /*其中21是针对日期的格式参数*/

2> cast(表达式 as 新类型[长度])

select CAST(身高 as numeric(4,1)) from 学生表
select 姓名+'同学的身高是:'+convert(nchar(4),身高) from 学生表
select 姓名+'同学的身高是:'+cast(身高 as NCHAR(4)) from 学生表

自定义函数

标量函数

返回的是一个标准量,如一般数据类型int, char. 这种函数相对简单,通过函数体计算,返回调用处一个标量。

与其它语言类似,有参数时通过函数名后面参数表带去,也可以无参函数(但空括号不能省)。

定义格式:

Create function 函数名(形式参数表) returns 返回值的数据类型
 Begin
  函数体语句
 End

引例:输入两个整数a,b,返回之和.

C**:**

int f1(int a,int b)
{ 
   int t; 
   t=a+b;
   return t;
}

Sql中:

create function f1(@a int,@b int) returns int
begin
 declare @t int
 set @t=@a+@b
 return @t
end

print dbo.f1(5,1)

说明:C,java为把早期过程和函数概念合在一起,当函数不需要返回数据时,定义全时函数类型为void。 不需要返回值(所有输出返回操作都是过程内完成)的函数就是过程procedure。

例:传入一个正整数n,使用函数jc(n)求n! , f(n)=n!

create function jc(@n int) returns bigint
begin
 declare @t bigint,@i int
 set @t=1
 set @i=1
 while(@i<=@n)
  begin
   set @t=@t*@i
   set @i=@i+1
  end
 return @t
end

print dbo.jc(5)

完整: 如要经常根据成绩值计算实得学分(cfx(课程号,成绩)),根据成绩值评等级,90及以上为优秀,70-90为良好,60-70为合格,60重修(DJPD(成绩)

create function djpd(@cj int) returns nchar(2)
begin
 declare @dj nchar(2)
 if(@cj>=90)  set @dj='优秀'
 else if(@cj>=70) set @dj='良好'
 else if(@cj>=60) set @dj='合格'
 else set @dj='重修'
 return @dj
end

create function cxf(@kch char(3),@cj int) returns int
begin
 declare @xf int
 select @xf=学分 from 课程表 where 课程号=@kch
 if(@cj<60) set @xf=0
 return @xf
end

select 学号,课程号,成绩,dbo.cxf('103',成绩) from 成绩表 where 课程号='103'

select 学号,课程号,成绩,dbo.cxf(课程号,成绩)as 实得学分,dbo.djpd(成绩) as 等级 from 成绩表

删除一个函数:

drop function dbo.jc 

注意:函数调用时,最后加上名字空间的。

例:把上面法轮功例子函数化

create function myrepl(@str1 nvarchar(800),@str2 nvarchar(10)) returns nvarchar(800)
begin
 declare @strT nvarchar(800)
 set @strT=replace(@str1,@str2,replicate('*',len(@str2)))
 return @strT
end

select dbo.myrepl('abcdefcdaax','cd')
select 学号,姓名,家庭住址,dbo.myrepl(家庭住址,'成都') from 学生表

例:定义一个函数dj(n)判断成绩的等级。90以上为优,80以上为良,70以上中,60以上及格,60以下为差

create function dj(@n int) returns nchar(2)
begin
 declare @dj0 nchar(2)
 if(@n>=90) set @dj0='优'
 else if(@n>=80) set @dj0='良'
 else if(@n>=70) set @dj0='中'
 else if(@n>=60) set @dj0='及格'
 else set @dj0='差'
 return @dj0
end

select *,dbo.dj(成绩) as 等级 from 成绩表

例:编写函数实现:根据学生学号,课程名称,查出该生该课的实际所得学分(60及以上得学分,不及格该科学分为0)

create function sdxf(@xm nchar(6),@kcm nchar(10))returns int
begin 
 declare @xf int,@cj int
 select @cj=成绩 from 成绩表 where 学号=(select 学号 from 学生表 where 姓名=@xm) and 课程号=(select 课程号 from 课程表 where 名称=@kcm)
 if(@cj>=60) 
  select @xf=学分 from 课程表 where 名称=@kcm
 else set @xf=0;
 return @xf 
end

select 学号,姓名,dbo.sdxf(姓名,'大学英语')as 实得学分 from 学生表

表值函数: 内联表值函数

一般函数返回的一个标量值,表值函数返回的是一个表(视图),由此得名

这种表是一个关系,在结构表头与一般的物理表相没区别,可以随意存放多行多列数据—故使用表值函数可以返回大量数据。表值函数内部函数体的核心任务是,把所有需要的返回给调用处的数据计算出来,存放到内存表中。最后一次性返回。

格式:

create function 函数名(形式参数表) returns table
As
 Begin 
   函数体
 End

引例:输入一个姓氏,查出该姓所有人的学号,姓名,生日,该姓氏比姓杨的人多几个?

理论上看,一个函数无法返回这么大一堆数据的,现在可以使用表值函数返回多个数。

create function my15(@xs nchar(1)) returns @table1 table(学号 CHAR(11),XM nchar(6),生日 smalldatetime,人数 int ,多于杨人数 int)
as 
begin
 insert into @table1(学号,XM,生日) select 学号,姓名,出生日期 from 学生表 where LEFT(姓名,1)=@xs
 declare @rs int ,@rsY int
 select @rs=COUNT(*) from 学生表 where left(姓名,1)=@xs
 select @rsY=COUNT(*) from 学生表 where left(姓名,1)='杨'
 insert into @table1(人数,多于杨人数)values(@rs,@rs-@rsY)
 return 
end

select * from dbo.my15('李')                             

因为内部的select查询的结果本身就是表视图,生成的返回临时表也它查询结果一致,不需要再自定义临时表。对表值函数的理解:当表一样的用,是一个带参数的,带条件查询的结果,返回的满足条件的结果

例:多语句表值函数。输入一个课程名,返回此课程平均分,最高分,选课人数, 总实得学分,不及格门数,该门课最高分的学生姓名.

分析:以上结果数据太多,难以一句sql命名搞定,又在不增加访问物理数据库次数情况下,减少服务器与客户端的数据来往次数,一次性在服务器完成所有计算,把结果一次性返回给客户端----使用表值函数

create function fun11(@kcm nchar(10)) returns @t table(课程名 nchar(10),平均分 numeric(4,1),最高分 numeric(4,1), 选课人数 int,得到学分人数 int,不及格比例 numeric(4,1))
as 
begin
  insert into @t(课程名) values(@kcm)
  update @t set 平均分=(select AVG(成绩) from 成绩表 where 课程号=(select 课程号 from 课程表 where 名称=@kcm))
  update @t set 最高分=(select MAX(成绩) from 成绩表 where 课程号 =(select 课程号 from 课程表 where 名称=@kcm))
  update @t set 选课人数=(select COUNT(*) from 成绩表 where 课程号 =(select 课程号 from 课程表 where 名称=@kcm))
  update @t set 得到学分人数=(select COUNT(*) from 成绩表 where 课程号=(select 课程号 from 课程表 where 名称=@kcm) and 成绩>=60 )
  Update @t set 不及格比例=((select COUNT(*) from 成绩表 where 课程号=(select 课程号 from 课程表 where 名称=@kcm))- select COUNT(*) from 成绩表 where 课程号=(select 课程号 from 课程表 where 名称=@kcm) and 成绩>=60)/(select COUNT(*) from 成绩表 where 课程号=(select 课程号 from 课程表 where 名称=@kcm)))*100
  Declare @xm0 nchar(10)
  Select @xm0=姓名 from 学生表 where 学号=(select top 1 学号 from 成绩表 where 课程号=(select 课程号 from 课程表 where 名称=@kcm) order by 成绩 desc )
 insert into @t(课程名)values(@xm0)
 return 
end

select * from dbo.fun11('大学英语')
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zhugenmi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值