What are UDF

SQL server provides list of many predefined functions that are built into the T-SQL language. The supplied functions helps extend the capabilities of T-SQL, providing the ability to perform string manipulation, mathematical calculations, data type conversion etc. but often we need something which is not provided using these functions. So we can create stored procedure to perform custom processing, but the problem is that we can't use the result of stored procedure in WHERE or SELECT list, for this type of scenario we need UDF.

Why to use User Defined Functions

The main benefit of UDF is that we are not just limited to SQL provided functions. We can write our own functions to meet our specific needs or to simplify complex SQL codes.
Let's take an example:
SQL getdate() returns current system date and time. It always includes both data and time components. We want to get just date and have the time always set to midnight. One solution is to to the conversion like below;
  1. select convert(datetime,CONVERT(date,getdate()))
But the problem is that when we want to have date with time always set to midnight, we need to do this conversion. The solution is to make a UDF for this.
  1. create function getonlydate()
  2. returns datetime
  3. as
  4. begin
  5. return(select convert(datetime,convert(date,getdate())))
  6. end
  7. go
Now we can call this UDF in our SQL query.
  1. select dbo.getonlydate()
Let us see how we can use this UDF in other SQL statements.
Let us create a table Order
  1. CREATE TABLE Orders (
  2. OrderID int IDENTITY (1, 1) NOT NULL Primary Key,
  3. CustomerID nchar (5) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
  4. EmployeeID int NULL ,
  5. OrderDate datetime NULL default dbo.getonlydate(),
  6. RequiredDate datetime NULL ,
  7. ShippedDate datetime NULL
  8. )
Let us INSERT values in this table using the UDF function we created.
  1. INSERT Orders(CustomerID,EmployeeID,RequiredDate)
  2. values('BERGS',3,dbo.getonlydate() +7)
Let us UPDATE values in this table using the UDF function we created.
  1. UPDATE Orders set ShippedDate = dbo.getonlydate()
  2. where OrderID=1
  3. SELECT OrderDate,RequiredDate,ShippedDate
  4. FROM orders
  5. WHERE orderdate = dbo.getonlydate()
Orderdate Requireddate Shippeddate
----------------- ---------------------- -----------------------
2011-05-01 00:00:00.000 2011-05-08 00:00:00.000 2011-05-01 00:00:00.000

Types of User Defined Functions

  1. Scalar functions
  2. Table valued function
    1. Inline table valued function
    2. Multistatement table valued functions.
For all examples shared below I have used Pubs database. You can download its MSI file from here and then attach .mdf file in your SQL Sever 2008.
https://www.microsoft.com/en-us/download/details.aspx?id=23654

A) Scalar Function

  1. They are like standard built-in functions provided with SQL Server.
  2. They return scalar values that can be used anywhere a constant expression can be used.
  3. They typically take one or more arguments and returns a value of specified data types.
  4. Every T-SQL function must return a result using the RETURN statement.
Example
The following two functions are variations of a function that returns the average price for a specified type of book from the titles table:
  1. CREATE FUNCTION AverageBookPrice (@booktype varchar(12) = '%')
  2. RETURNS money
  3. AS
  4. BEGIN
  5. DECLARE @Avg money
  6. SELECT @Avg = AVG(price)
  7. FROM titles
  8. WHERE type like @booktype
  9. RETURN @Avg
  10. END
  11. GO
  12. CREATE FUNCTION AverageBookPrice2 (@booktype varchar(12) ='%')
  13. RETURNS money
  14. AS
  15. BEGIN
  16. RETURN (SELECT AVG(PRICE)
  17. FROM TITLES
  18. WHERE TYPE LIKE @booktype)
  19. END
## SQL Server doesn't allow aggregate functions in a WHERE clause unless they are contained in a subquery.
The AvgBookPrice() function lets you compare against the average price without having to use a subquery:
  1. SELECT title_id, type, price from titles
  2. where price > dbo.AverageBookPrice('popular_comp')
titleid type price
-------------------------------------------
PC1035 popular_comp 22.95
PS1372 psychology 21.59
You can return the value from a user-defined scalar function into a local variable in two ways. You can assign the result to a local variable by using the SET statement or an assignment select, or you can use the EXEC statement. The following commands are functionally equivalent:
  1. declare @avg1 money,
  2. @avg2 money,
  3. @avg3 money
  4. select @avg1 = dbo.AverageBookPrice('popular_comp')
  5. set @avg2 = dbo.AverageBookPrice('popular_comp')
  6. exec @avg3 = dbo.AverageBookPrice 'popular_comp'
  7. select @avg1 as avg1, @avg2 as avg2, @avg3 as avg3
  8. go
Result is below
avg1 avg2 avg3
----------------------------------
21.475 21.475 21.475

B) Table Value Function

They are of two types.
1) Inline table valued function
A) An inline table-valued function specifies only the TABLE keyword in the RETURNS clause, without table definition information.
B) The code inside the function is a single RETURN statement that invokes a SELECT statement.
Example
  1. CREATEFUNCTION AveragePriceByType(@price money = 0.0)
  2. RETURNStable
  3. AS
  4. RETURN (SELECTtype,avg(isnull(price,0))as avg_price
  5. FROM titles
  6. GROUP BYtype
  7. HAVINGavg(isnull(price,0))> @price )
  8. select* from AveragePriceByType(15.0)
type averageprice
----------------------------------
trad_cook 15.9633
2) Multi statement table valued function
  1. Multistatement table-valued functions differ from inline functions in two major ways
    • The RETURNS clause specifies a table variable and its definition.
    • The body of the function contains multiple statements, at least one of which populates the table variable with data values.
  2. The scope of the table variable is limited to the function in which it is defined.
  3. Within the function in which a table variable is defined, that table variable can be treated like a regular table. You can perform any SELECT, INSERT, UPDATE, or DELETE statement on the rows in a table variable, except for SELECT INTO.
The following example defines the inline table-valued function AveragePricebyType() as a multistatement table-valued function called AveragePricebyType3():
  1. CREATE FUNCTION AveragePricebyType3 (@price money =0.0)
  2. RETURNS @table table(type varchar(12) null,avg_price money null)
  3. AS
  4. BEGIN
  5. INSERT @table
  6. SELECT type,avg(isnull(price,0)) as avg_price
  7. FROM titles
  8. GROUP BY type
  9. HAVING avg(isnull(price,0))> @price
  10. RETURN
  11. END
  12. SELECT * FROM AveragePricebyType3(15.0), this also gives same result.
type averageprice
---------------------------------
trad_cook 15.9633
Big Question: Why use multi-statement table-valued functions instead of inline table-valued functions?
  1. Generally, we use multi-statement table-valued functions when we need to perform further operations (for example, inserts, updates, or deletes) on the contents of the table variable before returning a result set.
  2. We would also use them if we need to perform more complex logic or additional processing on the input parameters of the function before invoking the query to populate the table variable.
Types of SQL statements allowed in a function include the following:
Nesting of User Defined Function: User-defined functions can also call other user-defined functions, with a limit of 32 levels of nesting. Nesting of functions can help improve the modularity and reusability of the function code.
  1. CREATE FUNCTION dbo.getonlydate3()
  2. RETURNS datetime
  3. as
  4. BEGIN
  5. DECLARE @date datetime
  6. SET @date = dbo.striptime( getdate())
  7. RETURN @date
  8. End

How to get information about Functions

To get information by using the provided system procedures and queries against the INFORMATION_SCHEMA.routines view. The following sections describe these methods.
  1. exec sp_helptext getonlydate
Text
-------
  1. create function getonlydate()
  2. returns datetime
  3. as
  4. begin
  5. return(select convert(datetime,convert(date,getdate())))
  6. end
In addition to sp_helptext, you can write queries against the INFORMATION_SCHEMA.routines view to display the source code for a function:
  1. SELECT routine_definition
  2. from INFORMATION_SCHEMA.routines
  3. where routine_name = 'getonlydate'
  4. and specific_schema = 'dbo'
  5. and specific_catalog = 'bigpubs2008'

Conclusion

User-defined functions in SQL Server 2008 allow you to create reusable routines that can help make your SQL code more straightforward and efficient. Table-valued functions provide a way to create what are essentially parameterized views, and you can include them inline in your queries, just as you would in a table or view.
Hope you enjoyed reading
Cheers.