根据用户定义函数返回值的类型,可将用户定义函数分为如下三个类别:
(1) 返回值为可更新表的函数
若用户定义函数包含单个 SELECT 语句且该语句可更新,则该函数返回的表也可更新,这样的函数称为内嵌表值函数。
(2) 返回不可更新数据表的函数
若用户定义函数包含多个 SELECT 语句,则该函数返回的表不可更新。这样的函数称为多语句表值函数。
(3) 返回标量值的函数
用户定义函数返回值为标量值,这样的函数称为标量函数。
用户定义函数不支持输出参数。用户定义函数不能修改全局数据库状态。
利用ALTER FUNCTION对用户定义函数修改,用 DROP FUNCTION 删除。
1. 标量函数
(1) 标量函数的定义
Format:
CREATE FUNCTION [ owner_name.] function_name /*函数名部分*/
( [ { @parameter_name [AS] scalar_parameter_data_type [ = default ] }
[ ,...n ] ] ) /*形参定义部分*/
RETURNS scalar_return_data_type /*返回参数的类型*/
[ WITH < function_option> [ [,] ...n] ] /*函数选项定义*/
[ AS ]
BEGIN
function_body /*函数体部分*/
RETURN scalar_expression /*返回语句*/
END
< function_option > ::={ ENCRYPTION | SCHEMABINDING }
说明:
SCHEMABINDING:用于指定将函数绑定到它所引用的数据库对象。
函数与其引用对象的绑定关系只有在发生以下两种情况之一时才被解除。
(1)删除了函数。
(2)在未指定 SCHEMABINDING 选项的情况下更改了函数。
从上述语法形式,归纳出标量函数的一般定义形式如下:
CREATE FUNCTION [所有者名.] 函数名
( 参数1 [AS] 类型1 [ = 默认值 ] ) [ ,...参数n [AS] 类型n [ = 默认值 ] ] ] )
RETURNS 返回值类型
[ WITH ENCRYPTION | SCHEMABINDING [ [,] ...n] ]
[ AS ]
BEGIN
函数体
RETURN 标量表达式
END
eg:
1 /*计算全体学生某门功课的平均成绩*/ 2 use XSCJ 3 create function average(@cnum char(20)) returns int 4 as 5 begin 6 declare @var int 7 select @var= 8 ( 9 select AVG(Ccj) 10 from XS_KC 11 where Cno = @cnum 12 group by Cno 13 ) 14 return @var 15 end 16 go
(2) 标量函数的调用
当调用用户定义的标量函数时,必须提供至少由两部分组成的名称(所有者名.函数名)。可有以下方式调用标量函数:
在SELECT语句中调用
调用形式:所有者名.函数名(实参1,…,实参n)
实参可为已赋值的局部变量或表达式。
eg1:
如下程序对上例定义的函数调用
1 USE XSCJ /*用户函数在此数据库中已定义*/ 2 /* 定义局部变量 */ 3 DECLARE @course1 char(6) 4 DECLARE @aver1 int 5 /* 给局部变量赋值 */ 6 SELECT @course1 = ‘101’ 7 /* 调用用户函数,并将返回值赋给局部变量 */ 8 SELECT @aver1=dbo.average(@course1) 9 /* 显示局部变量的值 */ 10 SELECT @aver1 AS ‘101课程的平均成绩’
Result:
利用EXEC语句执行
用T-SQL EXECUTE语句调用用户函数时,参数的标识次序与函数定义中的参数标识次序可以不同。
调用形式:
所有者名.函数名 实参1,…,实参n
或
所有者名.函数名 形参名1=实参1,…, 形参名n=实参n
eg2:
1 【例6.36】调用上述计算平均成绩的函数。 2 USE XSCJ /* 用户函数在此数据库中已定义 */ 3 DECLARE @aver1 int /* 显示局部变量的值 */ 4 EXEC @aver1 = dbo.average @cnum = ‘101’ 5 /*通过EXEC调用用户函数,并将返回值赋给局部变量*/ 6 SELECT @aver1 AS ‘101课程的平均成绩’ 7 GO
eg3:
1 USE XSCJ /*用户函数在此数据库中已定义*/ 2 CREATE TABLE course 3 ( 4 cno int, /*课程号*/ 5 cname nchar(20), /*课程名*/ 6 credit int, /*学分*/ 7 aver AS /*将此列定义为计算列*/ 8 ( 9 dbo.average(cno) 10 ) 11 )
Result:
内嵌函数可用于实现参数化视图。
eg:
1 CREATE VIEW View1 AS 2 SELECT 学号, 姓名 3 FROM XSCJ.dbo.XS 4 WHERE 专业名= '计算机'
若希望设计更通用的程序,让用户能指定感兴趣的查询内容,可将WHERE 专业名= ‘计算机’替换为WHERE 专业名= @para, @para用于传递参数,但视图不支持在WHERE子句中指定搜索条件参数,为解决这一问题可使用内嵌用户定义函数。
eg:
1 create function fn_view1 (@para char(10) = 'QW') returns table 2 as 3 return 4 ( 5 select Sno,Sname 6 from XS 7 where Sdept = @para 8 ) 9 go 10 select *from fn_view1(default)
Result:
(1) 内嵌表值函数的定义
Format:
CREATE FUNCTION [ owner_name.] function_name /*定义函数名部分*/
( [ { @parameter_name [AS] scalar_parameter_data_type [ = default ] }
[ ,...n ] ] ) /*定义参数部分*/
RETURNS TABLE /*返回值为表类型*/
[ WITH < function_option > [ [,] ...n ] ] /*定义函数的可选项*/
[ AS ]
RETURN [ ( ) select-stmt [ ] ] /*通过SELECT语句返回内嵌表*/
< function_option > ::={ ENCRYPTION | SCHEMABINDING }
eg:
1 /*对于XSCJ数据库,为了让学生每学期查询其各科成绩可以利用XS、KC、XS_KC三个表,创建视图*/ 2 create view st_view 3 as 4 select XS.Sno,XS.Sname,KC.Cno,XS_KC.Ccj 5 from KC inner join 6 XS_KC on KC.Cno = XS_KC.Cno inner join 7 XS on XS_KC.Xno =XS.Sno 8 go
Result:
在上面创建的视图的基础上定义如下内嵌表值函数:
eg:
1 /*在上面创建的视图的基础上定义如下内嵌表值函数*/ 2 create function st_score(@student_id char(3)) returns table 3 as return 4 ( 5 select * 6 from st_view 7 where st_view.Sno = @student_id 8 ) 9 go
Result:
(2) 内嵌表值函数的调用
内嵌表值函数只能通过SELECT语句调用,内嵌表值函数调用时,可以仅使用函数名。
eg:
1 /*调用st_score()函数,查询学号为“001”学生的各科成绩及学分。*/ 2 select * 3 from XSCJ.dbo.st_score('002') 4 go
Result:
3.多语句表值函数
内嵌表值函数和多语句都返回表,二者不同之处在于:内嵌表值函数没有函数主体,返回的表是单个SELECT语句的结果集;而多语句表值函数在 BEGIN...END 块中定义的函数主体包含T-SQL语句,这些语句可生成行并将行插入至表中,最后返回表。
(1) 多语句表值函数定义
Format:
CREATE FUNCTION [ owner_name.] function_name /*定义函数名部分*/
( [ { @parameter_name [AS] scalar_parameter_data_type [ = default ] }
[ ,...n ] ] ) /*定义函数参数部分*/
RETURNS @return_variable TABLE < table_type_definition > /*定义作为返回值的表*
[ WITH < function_option > [ [,] ...n ] ] /*定义函数的可选项*/
[ AS ]
BEGIN
function_body /*定义函数体*/
RETURN
END
< function_option > ::={ ENCRYPTION | SCHEMABINDING }
< table_type_definition > ::= /*定义表,请参考第二章*/
( { column_definition | table_constraint } [ ,...n ] )
@return_variable:为表变量,用于存储作为函数值返回的记录集;
function_body:为T-SQL语句序列,function_body只用于标量函数和多语句表值函数。
eg:
1 /*在XSCJ数据库中创建返回table的函数,通过以学号作为实参,调用该函数,可显示该学生各门功课的成绩和学分*/ 2 create function score_table (@st_id char(3)) returns @score table 3 ( 4 student_id char(3), 5 Student_name char(8), 6 kc_name char(12), 7 student_ci tinyint, 8 student_sf tinyint 9 ) 10 as 11 begin 12 insert @score 13 select XS.Sno,Sname,Cname,Ccj,Cfen 14 from XS join XS_KC join KC on XS_KC.Cno =KC.Cno on XS.Sno=XS_KC.Xno 15 where XS.Sno=@st_id 16 return 17 end 18 go
Result:
(2) 多语句表值函数的调用
多语句表值函数的调用与内嵌表值函数的调用方法相同。如下例子是上述多语句表值函数score_table()的调用。
eg:
1 /*如下语句查询学号为”005”学生的各科成绩和学分。*/ 2 use XSCJ 3 select *from score_table('102') 4 go 5 /*结果怎么什么都没有?我不明白。*/
Result:
图片1
4.用户函数的建立
用户函数的建立可利用查询分析器完成,也可利用企业管理器完成。
(1) 利用查询分析器创建用户定义函数
例如在XSCJ数据库中要建立前面求立方体体积的用户函数,可在查询分析器窗口输入例中的程序并执行,然后在查询分析器的目录树上XSCJ数据库对应的函数子目录图标上右击,选择“刷新”,即可看到函数SphereVolume()对象的图标。
定义用户函数SphereVolume()后,在查询分析器中即可调用该函数。
(2) 利用企业管理器创建用户定义函数
5.用户定义函数的删除
对于一个已创建的用户定义函数,可有两种方法删除:
通过企业管理器删除,这非常简单,请读者自己练习;
利用T-SQL语句DROP FUNCTION删除,下面介绍其语法格式。
语法格式:DROP FUNCTION { [ owner_name .] function_name } [ ,...n ]
说明:
owner_name:指所有者名。
function_name:指要删除的用户定义的函数名称。可以选择是否指定所有者名称,但不能指定服务器名称和数据库名称。
n:表示可以指定多个用户定义的函数予以删除。