User-defined functions are either scalar-valued or table-valued. Functions are scalar-valued if the RETURNS clause specified one of the scalar data types. Scalar-valued functions can be defined by using multiple Transact-SQL statements.
Functions are table-valued if the RETURNS clause specified TABLE. Depending on how the body of the function is defined, table-valued functions can be classified as inline or multi-statement functions. For more information, see Table-Valued User-Defined Functions.
The following statements are valid in a function:
-
Assignment statements.
-
Control-of-Flow statements except TRY...CATCH statements.
-
DECLARE statements defining local data variables and local cursors.
-
SELECT statements that contain select lists with expressions that assign values to local variables.
-
Cursor operations referencing local cursors that are declared, opened, closed, and deallocated in the function. Only FETCH statements that assign values to local variables using the INTO clause are allowed; FETCH statements that return data to the client are not allowed.
-
INSERT, UPDATE, and DELETE statements modifying local table variables.
-
EXECUTE statements calling extended stored procedures.
-
For more information, see Creating User-Defined Functions (Database Engine).
Nesting User-defined Functions
User-defined functions can be nested; that is, one user-defined function can call another. The nesting level is incremented when the called function starts execution, and decremented when the called function finishes execution. User-defined functions can be nested up to 32 levels. Exceeding the maximum levels of nesting causes the whole calling function chain to fail.
Note: |
|---|
|
Any reference to managed code from a Transact-SQL user-defined function counts as one level against the 32-level nesting limit. Methods invoked from within managed code do not count against this limit.
|
Function Properties
In earlier versions of SQL Server, functions are categorized only as deterministic or nondeterministic. In SQL Server 2005 and later, functions have the following properties. The values of these properties determine whether functions can be used in computed columns that can be persisted or indexed.
|
Property
|
Description
|
Notes
|
|---|
|
IsDeterministic
|
Function is deterministic or nondeterministic.
|
Local data access is allowed in deterministic functions. For example, functions that always return the same result any time they are called by using a specific set of input values and with the same state of the database would be labeled deterministic.
|
|
IsPrecise
|
Function is precise or imprecise.
|
Imprecise functions contain operations such as floating point operations.
|
|
IsSystemVerified
|
The precision and determinism properties of the function can be verified by SQL Server.
|
|
|
SystemDataAccess
|
Function accesses system data (system catalogs or virtual system tables) in the local instance of SQL Server.
|
|
|
UserDataAccess
|
Function accesses user data in the local instance of SQL Server.
|
Includes user-defined tables and temp tables, but not table-variables.
|
The precision and determinism properties of Transact-SQL functions are determined automatically by SQL Server. For more information, see User-Defined Function Design Guidelines. The data access and determinism properties of CLR functions can be specified by the user. For more information, see Overview of CLR Integration Custom Attributes.
To display the current values for these properties, use OBJECTPROPERTYEX.
Indexing Computed Columns That Invoke a User-Defined Function
A computed column that invokes a user-defined function can be used in an index when the user-defined function has the following property values:
-
IsDeterministic = true
-
IsSystemVerified = true (unless the computed column is persisted)
-
UserDataAccess = false
-
SystemDataAccess = false
For more information, see Creating Indexes on Computed Columns.
Calling Extended Stored Procedures from Functions
The extended stored procedure, when it is called from inside a function, cannot return result sets to the client. Any ODS APIs that return result sets to the client will return FAIL. The extended stored procedure could connect back to an instance of SQL Server; however, it should not try to join the same transaction as the function that invoked the extended stored procedure.
Similar to invocations from a batch or stored procedure, the extended stored procedure will be executed in the context of the Windows security account under which SQL Server is running. The owner of the stored procedure should consider this when giving EXECUTE permission on it to users.
Function Invocation
Scalar-valued functions can be invoked where scalar expressions are used. This includes computed columns and CHECK constraint definitions. Scalar-valued functions can also be executed by using the EXECUTE statement. Scalar-valued functions must be invoked by using at least the two-part name of the function. For more information about multipart names, see Transact-SQL Syntax Conventions (Transact-SQL). Table-valued functions can be invoked where table expressions are allowed in the FROM clause of SELECT, INSERT, UPDATE, or DELETE statements. For more information, see Executing User-Defined Functions (Database Engine).
Using Parameters and Return Values in CLR Functions
If parameters are specified in a CLR function, they should be SQL Server types as defined previously for scalar_parameter_data_type. For information about comparing SQL Server system data types to CLR integration data types or .NET Framework common language runtime data types, see Mapping CLR Parameter Data.
For SQL Server to reference the correct method when it is overloaded in a class, the method indicated in <method_specifier> must have the following characteristics:
-
Receive the same number of parameters as specified in [ ,...n ].
-
Receive all the parameters by value, not by reference.
-
Use parameter types that are compatible with those specified in the SQL Server function.
If the return data type of the CLR function specifies a table type (RETURNS TABLE), the return data type of the method in <method_specifier> should be of type IEnumerator or IEnumerable, and it is assumed that the interface is implemented by the creator of the function. Unlike Transact-SQL functions, CLR functions cannot include PRIMARY KEY, UNIQUE, or CHECK constraints in <table_type_definition>. The data types of columns specified in <table_type_definition> must match the types of the corresponding columns of the result set returned by the method in <method_specifier> at execution time. This type-checking is not performed at the time the function is created.
For more information about how to program CLR functions, see CLR User-Defined Functions.
Disallowed SQL Statements
The following Service Broker statements cannot be included in the definition of a Transact-SQL user-defined function:
-
BEGIN DIALOG CONVERSATION
-
END CONVERSATION
-
GET CONVERSATION GROUP
-
MOVE CONVERSATION
-
RECEIVE
-
SEND
Viewing Information About Functions
To display the definition of Transact-SQL user-defined functions, use the sys.sql_modules catalog view in the database in which the function exists.
For example:
USE AdventureWorks;
GO
SELECT definition, type
FROM sys.sql_modules AS m
JOIN sys.objects AS o ON m.object_id = o.object_id
AND type IN ('FN', 'IF', 'TF');
GO
Note: |
|---|
|
The definition of functions created by using the ENCRYPTION option cannot be viewed by using sys.sql_modules; however, other information about the encrypted functions is displayed.
|
To display information about CLR user-defined functions, use the sys.assembly_modules catalog view in the database in which the function exists.
To display information about the parameters defined in user-defined functions, use the sys.parameters catalog view in the database in which the function exists.
For a report on the objects referenced by a function, use sys.sql_expression_dependencies.
Guidance on Using Sort Order
When using the ORDER clause in CLR table-valued functions, follow these guidelines:
-
You must ensure that results are always ordered in the specified order. If the results are not in the specified order, SQL Server will generate an error message when the query is executed.
-
If an ORDER clause is specified, the output of the table-valued function must be sorted according to the collation of the column (explicit or implicit). For example, if the column collation is Chinese (either specified in the DDL for the table-valued function or obtained from the database collation), the returned results must be sorted according to Chinese sorting rules.
-
The ORDER clause, if specified, is always verified by SQL Server while returning results, whether or not it is used by the query processor to perform further optimizations. Only use the ORDER clause if you know it is useful to the query processor.
-
The SQL Server query processor takes advantage of the ORDER clause automatically in following cases:
-
Insert queries where the ORDER clause is compatible with an index.
-
ORDER BY clauses that are compatible with the ORDER clause.
-
Aggregates, where GROUP BY is compatible with ORDER clause.
-
DISTINCT aggregates where the distinct columns are compatible with the ORDER clause.
The ORDER clause does not guarantee ordered results when a SELECT query is executed, unless ORDER BY is also specified in the query. See sys.function_order_columns (Transact-SQL) for information on how to query for columns included in the sort-order for table-valued functions.