SQL Server创建用户定义函数

一、UDF的定义

和存储过程很相似,用户自定义函数也是一组有序的T-SQL语句,UDF被预先优化和编译并且可以作为一个单元来进行调用。

UDF和存储过程的主要区别在于返回结果的方式:

  • 使用UDF时可传入参数,但不可传出参数。输出参数的概念被更为健壮的返回值取代了。
  • 和系统函数一样,可以返回标量值,这个值的好处是它并不像在存储过程中那样只限于整形数据类型,而是可以返回大多数SQL Server数据类型。

UDF有以下两种类型:

  • 返回标量值的UDF。
  • 返回表的UDF。

创建语法:

CREATE FUNCTION [<schema name>.]<function name>
(
[ <@parameter name> [AS] [<schema name>.]<data type> [= <default value> [READONLY]] [,...n] ]
)
RETURNS { <scalar type> | TABLE [(<table definition>)] }
[ WITH [ENCRYPTION] | [SCHEMABINDING] | [RETURNS NULL ON NULL INPUT | CALLED ON NULL INPUT ] |
[EXECUTE AS {CALLER|SELF|OWNER|<'user name'>}]
[AS] { EXTERNAL NAME <externam method> |
BEGIN
[<function statements>]
{RETURN <type as defined in RETURNS clause | RETURN (<SELECT statement>)}
END}[;]

二、标量值函数:

这种类型的UDF和大多数SQL Server内置函数一样,会向调用脚本或存储过程返回标量值,像GETDATE()或USER()函数就会返回标量值。

UDF的返回值并不限于整数,而是可以返回除了BLOB、游标(cursor)和时间戳以外的任何有效的SQL Server数据类型(包括用户自定义类型)。

与存储过程不同,用户自定义函数返回值的目的是提供有意义的数据(而对于存储过程来说,返回值只能说明成功或失败,如果失败,则会提供一些关于失败性质的特定信息。)

可在查询中内联执行函数(如作为SELECT语句的一部分),而用存储过程则不行。

例1:应用在where语句中

CREATE FUNCTION DateOnly(@Date DateTime)
  RETURNS varchar(12)
AS
  BEGIN
      RETURN CONVERT(varchar(12),@Date,102)
  END

然后试着,运用一下:

SELECT * FROM Nx_comment
  WHERE dbo.DateOnly(com_posttime) = '2012.04.28'  --注意前面的dbo是必须的。

其实以上SQL语句相当于:

SELECT * FROM Nx_comment
  WHERE CONVERT(varchar(12),com_posttime,102) = '2012.04.28'

例2:应用在select语句中

SELECT Name,Age,
      (SELECT AVG(Age) FROM Person) AS AvgAge,
       Age - (SELECT AVG(Age) FROM Person) AS Difference
  FROM Person

这里要说明一下,列的意思分别是,姓名,年龄,平均年龄以及与平均年龄的差值。

下面我们用UDF来实现,先定义两个UDF如下:

CREATE FUNCTION dbo.AvgAge()
  RETURNS int
AS
  BEGIN
      RETURN (SELECT AVG(Age) FROM Person)
  END
GO

CREATE FUNCTION dbo.AgeDifference(@Age int)
  RETURNS int
AS
  BEGIN
      RETURN @Age - dbo.AvgAge();        --在一个UDF内引用另外一个UDF,好华丽的说
  END

然后执行查询:

SELECT Name,Age,dbo.AvgAge() AS AvgAge,dbo.AgeDifference(Age) as Difference
  FROM Person

三、内联表值函数

SQL Server中的用户自定义函数并不只限于返回标量值,也可以返回表。返回的表在很大程度上和其他表是一样的。

可以对返回 表的UDF执行JOIN,甚至对结果应用WHERE条件。

改为用表作为返回值并不难,对于UDF来说,表就像任何其他SQL Server数据类型一样。

例1:像表一样地用UDF

CREATE FUNCTION dbo.fnContactName()
  RETURNS TABLE
AS
  RETURN (
          SELECT Id,LastName + ',' + FirstName AS Name  FROM Man
          )

然后我们就可以像表一样地用UDF了。

SELECT * FROM dbo.fnContactName()

例2:带参数返回表

CREATE FUNCTION dbo.fnNameLike(@LName varchar(20))
  RETURNS TABLE
  AS
  RETURN (
          SELECT Id,LastName + ',' + FirstName AS Name FROM Man WHERE LastName Like @LName + '%'
          )

然后查询的时候可以这样用:

SELECT * FROM dbo.fnNameLike('刘')

没有WHERE子句,没有过滤SELECT列表,就可以反复使用该函数,而不需要进行"剪切和粘贴"。

四、多语句表值函数

语法:

CREATE FUNCTION Funtion_name
(
    --这里定义传入参数及类型
)
RETURNS
@table_name TABLE
(
    --这里定义@table_name的列名
)
AS
BEGIN
    --这里写sql语句并且将最终需要返回的结果集塞到@table_name 这张表里面
    RETURN
END
GO

这个函数通过传入一个十进制的数字,分别返回对应的二进制、八进制、十六进制。

Create FUNCTION F_TConversion
(
    @NUM INT
)
RETURNS
@t_table TABLE
(
    [Binary] varchar(64),
    Octal varchar(16),
    Hexadecimal varchar(8)
)
AS
BEGIN
    DECLARE @RESULT2 VARCHAR(500)='',@RESULT8 VARCHAR(500)='',@RESULT16 VARCHAR(500)='';
    WITH CTE AS(
        SELECT @NUM/2 D2,@NUM%2 S2,@NUM/8 D8,@NUM%8 S8,@NUM/16 D16,@NUM%16 S16,1 [INDEX]
        UNION ALL
        SELECT D2/2 , D2%2,D8/8 , D8%8,D16/16 , D16%16,[INDEX]+1 FROM CTE WHERE D2>0
    )
    SELECT @RESULT2+=CAST(S2 AS VARCHAR(1))
          ,@RESULT8+=CASE WHEN D8=0 AND S8=0 THEN '' ELSE CAST(S8 AS VARCHAR(1)) END
          ,@RESULT16+=CASE WHEN D16=0 AND S16=0 THEN ''
                           ELSE CASE CAST(S16 AS VARCHAR(5))
                                WHEN '10' THEN 'A'
                                WHEN '11' THEN 'B'
                                WHEN '12' THEN 'C'
                                WHEN '13' THEN 'D'
                                WHEN '14' THEN 'E'
                                WHEN '15' THEN 'F'
                                ELSE CAST(S16 AS VARCHAR(5))
                            END
                        END
    FROM CTE ORDER BY [INDEX] DESC
    INSERT INTO @t_table
    SELECT @RESULT2,@RESULT8,@RESULT16
    RETURN
END
GO

五、理解确定性

用户自定义函数可以是确定性的也可以是非确定性的。如果给定了一组特定的有效输入,每次函数就都能返回相同的结果,那么就说该函数是确定性的。

SUM()就是一个确定性的内置函数。3、5、10的总合永远都是18,而GETDATE()的值就是非确定性的,因为每次调用它的时候GETDATE()都会改变。

如果视图或计算列引用非确定性函数,则在该视图或列上将不允许建立任何索引。

如果判定函数是否是确定性的?除了上面描述的规则外,这些信息存储在对象的IsDeterministic属性中,可以利用OBJECTPROPERTY属性检查。

SELECT OBJECTPROPERTY(OBJECT_ID('DateOnly'),'IsDeterministic');  --只是刚才的那个自定义函数

输出结果如下:

居然是非确定性的。原因在于之前在定义该函数的时候,并没有加上这个"WITH SCHEMABINDING"。

ALTER FUNCTION dbo.DateOnly(@Date date)
  RETURNS date
  WITH SCHEMABINDING  --当我们加上这一句之后
  AS
  BEGIN
    RETURN @Date
  END

在执行查询,该函数就是确定性的了。

到此这篇关于SQL Server用户自定义函数的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Sql Server中常用的6个自定义函数分享

    在日常应用中,往往根据实际需求录入一些值,而这些值不能直接使用,所以Sql中经常会对字段值进行一些常规的处理.这里搜集了(提取数字.英文.中文.过滤重复字符.分割字符的方法),方便日后查询使用. 一.判断字段值是否有中文 --SQL 判断字段值是否有中文 create function fun_getCN(@str nvarchar(4000)) returns nvarchar(4000) as begin declare @word nchar(1),@CN nvarchar(4000) s

  • Sqlserver 自定义函数 Function使用介绍

    一.FUNCTION: 在sqlserver2008中有3中自定义函数:标量函数/内联表值函数/多语句表值函数,首先总结下他们语法的异同点: 同点: 1.创建定义是一样的: a, CREATE FUNCTION F_NAME(传入的参数名称 传入参数的类型) b,RETURNS 返回值类型 c,AS 异点:1.标量函数返回的是一个数据类型值,内联表值函数返回的是一个table,而多语句返回的是一个table的变量(类似前面两个的结合): 2.语法的结构:标量函数和多语句函数都是要有begin,,

  • 谈谈sqlserver自定义函数与存储过程的区别

    一.自定义函数: 1. 可以返回表变量 2. 限制颇多,包括 不能使用output参数: 不能用临时表: 函数内部的操作不能影响到外部环境: 不能通过select返回结果集: 不能update,delete,数据库表: 3. 必须return 一个标量值或表变量 自定义函数一般用在复用度高,功能简单单一,争对性强的地方. 二.存储过程 1. 不能返回表变量 2. 限制少,可以执行对数据库表的操作,可以返回数据集 3. 可以return一个标量值,也可以省略return 存储过程一般用在实现复杂的

  • SQL server使用自定义函数以及游标

    编号 标准宗地编码(landCode) 所在区段编码(sectCode) 1 131001BG001 G001 2 131001BG002 G001 3 131001BG003 G001 4 131001BG004 G002 5 131001BG005 G003 现在需要将表中的数据转换为如下表所示结果: 编号 区段编码 包含的标准宗地 1 G001 131001BG001,131001BG002,131001BG003 2 G002 131001BG004 3 G003 131001BG005

  • sqlserver中的自定义函数的方法小结

    "自定义函数"是我们平常的说法,而"用户定义的函数"是 SQL Server 中书面的说法. SQL Server 2000 允许用户创建自定义函数,自定义函数可以有返回值. 自定义函数分为:标量值函数或表值函数 如果 RETURNS 子句指定一种标量数据类型,则函数为标量值函数.可以使用多条 Transact-SQL 语句定义标量值函数. 如果 RETURNS 子句指定 TABLE,则函数为表值函数. 表值函数又可分为:内嵌表值函数(行内函数)或多语句函数 如果

  • 在sql Server自定义一个用户定义星期函数

    文件:.wmv:大小:19,535KB:长度:00:26:39. 下载地址:SqlFunction_udf_Week.rar以下内容于20120105更新: 2012年刚到,开发的软件使用这个函数发现bug.2012年第一周应该是2012-01-01至2012-01-07,但此函数却把2012-01-08至2012-01-14当作第一周. 就此bug对此函数修改如下: 复制代码 代码如下: SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO ALTE

  • SQL Server创建用户定义函数

    一.UDF的定义 和存储过程很相似,用户自定义函数也是一组有序的T-SQL语句,UDF被预先优化和编译并且可以作为一个单元来进行调用. UDF和存储过程的主要区别在于返回结果的方式: 使用UDF时可传入参数,但不可传出参数.输出参数的概念被更为健壮的返回值取代了. 和系统函数一样,可以返回标量值,这个值的好处是它并不像在存储过程中那样只限于整形数据类型,而是可以返回大多数SQL Server数据类型. UDF有以下两种类型: 返回标量值的UDF. 返回表的UDF. 创建语法: CREATE FU

  • CREATE FUNCTION sqlserver用户定义函数

    创建用户定义函数,它是返回值的已保存的 Transact-SQL 例程.用户定义函数不能用于执行一组修改全局数据库状态的操作.与系统函数一样,用户定义函数可以从查询中唤醒调用.也可以像存储过程一样,通过 EXECUTE 语句执行. 用户定义函数用 ALTER FUNCTION 修改,用 DROP FUNCTION 除去. 语法 标量函数 CREATE FUNCTION [ owner_name.] function_name ( [ { @parameter_name [AS] scalar_p

  • sql server数据库中raiserror函数用法的详细介绍

    sql server数据库中raiserror函数的用法 server数据库中raiserror的作用就和asp.NET中的throw new Exception一样,用于抛出一个异常或错误.这个错误可以被程序捕捉到. raiserror的常用格式如下: raiserror('错误的描述',错误的严重级别代码,错误的标识,错误的描述中的参数的值(这个可以是多个),一些其它参数),在官方上的格式描述如下: RAISERROR ( { msg_id | msg_str | @local_variab

  • SQL Server创建数据库和数据表的相关约束实现方法

    本文分析了SQL Server创建数据库和数据表的相关约束实现方法.分享给大家供大家参考,具体如下: 创建约束语法如下: CREATE DATABASE [test] ON (NAME=N'test',FILENAME=N'd:\SQL2kt_Data\test.mdf',SIZE=3mb,MAXSIZE=UNLIMITED,FILEGROWTH=1MB) LOG ON (NAME=N'test_log',FILENAME=N'd:\SQL2kt_Data\test_log.ldf',SIZE=

  • SQL SERVER中常用日期函数的具体使用

    1 GETDATE() 返回当前系统日期 SELECT GETDATE() 2 DATEADD(日期部分,常数,日期) 返回将日期的指定日期部分加常数后的结果返回 常数为正 SELECT DATEADD(YY,1,GETDATE()) 等同于 SELECT DATEADD(YEAR,1,GETDATE()) 常数为负数 SELECT DATEADD(YY,-2,GETDATE()) 常数为小数(直接舍去小数部分) SELECT DATEADD(YY,2.4,GETDATE()) SELECT D

  • SQL Server中的排名函数与分析函数详解

    一.排名开窗函数概述 SQL Server的排名函数是对查询的结果进行排名和分组,TSQL共有4个排名函数,分别是:ROW_NUMBER.RANK.DENSE_RANK和NTILE. 他们和OVER()函数搭配使用,按照特定的顺序排名. 排名开窗函数可以单独使用ORDER BY 语句,也可以和PARTITION BY同时使用. PARTITION BY用于将结果集进行分组,开窗函数应用于每一组. ODER BY 指定排名开窗函数的顺序.在排名开窗函数中必须使用ORDER BY语句. 1.ROW_

  • sql server 2005用户权限设置深入分析

    关于什么是用户权限,最简单的定义可能是,"用户能做什么和不能做什么."在这里,简单的定义就相当不错了. 用户的权限分为3类: l 登录的权限: l 访问特定数据库的权限: l 在数据库中具体的对象上执行特定操作的权限. 既然我们已经看过了创建登录账户,这里将把重点放在登录账户能够拥有的特定权限上. 22.3.1 授予访问特定数据库的权限 如果想要一个用户可以访问数据库,你需要做的第一件事情是授予用户访问那个数据库的权限.可以在Management Studio中,通过把用户加入到服务器

  • sql server 创建临时表的使用说明

    临时表产生:A: SELECT INTO和B:CREATE TABLE + INSERT INTO 1. A 要比B 快很多.但是A会锁定tempdb的SYSOBJECTS.SYSINDEXES.SYSCOLUMNS表,在多用户并发的时候,容易产生阻塞其他的进程. 2. 在并发系统中是用B. 大数量的单个语句中,使用A. 创建临时表的方法: 方法一:      create table #临时表名(字段1 约束条件,                       字段2 约束条件,        

  • SQL Server中的RAND函数的介绍和区间随机数值函数的实现

    工作中会遇到SQL Server模拟数据生成以及数值列值(如整型.日期和时间数据类型)随机填充等等任务,这些任务中都要使用到随机数.鉴于此,本文将对SQL Server中随机数的使用简单做个总结 . T-SQL 随机有关的三个函数 RAND([seed] 此函数生成从0到1之间随机 float 值(详细说明查看https://technet.microsoft.com/zh-cn/library/ms177610(v=sql.90).aspx). CHECKSUM ( * | expressio

  • SQL Server创建链接服务器的存储过程示例分享

    创建链接服务器.链接服务器让用户可以对 OLE DB 数据源进行分布式异类查询.在使用 sp_addlinkedserver 创建链接 服务器后,可对该服务器运行分布式查询.如果链接服务器定义为 SQL Server 实例,则可执行远程存储过程. http://msdn.microsoft.com/zh-cn/library/ms190479(SQL.90).aspx EXECUTE sp_addlinkedserver @server='DB1', @srvproduct='',@provid

随机推荐