Microsoft first implemented user-defined functions (UDFs) in SQL 2000. Probably you are already familiar with many built-in functions, for example GetDate() and User_Name(). You may not have noticed, though, that the master database has a collection of UDFs as well--some encrypted, others available for your inspection. To see the list of UDFs in SQL Management Studio, open System Databases , master , Programmability , then Functions .SQL 2000 lets you write two kinds of UDF—-scalar functions and table functions. Scalar functions return a single value of any data type, much the same as user-defined functions in languages such as Visual Basic. Table functions return tables. I'll discuss both in this article. Before we begin our exploration, however, we must address two concepts: determinism and schema binding. Determinism A routine (built-in or user-defined) is deterministic if the same set of inputs to it will always yield exactly the same result. If that is not the case, the routine is non-deterministic. Functions like DateAdd() are deterministic, since given the same set of parameters, they're guaranteed to return the same results. Functions such as GetDate() are non-deterministic, because while they're always called with the same parameters, they return different results every time. For UDFs the rules are a little more complicated, since their code could contain almost anything. A UDF is deterministic if:
Imagine a function fn_Problematic_Select() , which selects * from one or more tables. Imagine that after writing this function, you insert a new column in said table(s). Subsequent invocations of fn_Problematic_Select() will not show your new column.So the question becomes, should you ever select * from table(s)? In my opinion, the answer is emphatically no. You may disagree. The way around this difficulty is schema binding, which binds the function to the objects it references, making it impossible to alter the referenced objects (tables, views, or other functions) unless the function is either dropped or modified without using the schema-binding directive. You can use the schema-binding option only if all the following conditions are met:
CREATE FUNCTION ... will fail.What exactly can you do within a multi-statement function? Any of the following types of statement are permitted:
Scalar functions In the Access Northwind sample database, the Order Details table has no column for the extended total value of the order. This is as it should be, the general principle being "do not store what can be calculated." However, when you need to calculate this value, you have to rewrite its formula over and over, and as you escalate (calculate the total extended amount for each order and then for each customer), the expression grows awkwardly. Here is a function that automates it:
That function lets us write a query such as the following to sum the extended amounts for a given order.
Better yet, let’s write a function to automate the calculation:
Moving up the relational hierarchy, we now create a function to derive the total purchases of a given customer:
We can now call this function in a query like this:
The query results look like this: ![]() Calling built-in UDFs The syntax is slightly different: the function name must be prefixed with a pair of colons. For example, if you try to call the function sp_helpcollations() in the normal way, you get the error “Invalid object name.” You must call it this way:
Table functions There are two types of table functions: in-line functions and standard table functions. We conclude with a list of the characteristics of the more powerful in-line functions, which form a subset of table functions:
|