User-Defined Functions in SQL Server 2005 Andrew Novick 2007
© Copyright Andrew Novick All rights reserved. Agenda What are User-Defined Functions – Three types: Scalar In-Line Table Valued Multi-statement Table Valued Why use User-Defined Functions What You Cant Do With UDFs and Why! Formatting, Naming and Documenting UDFs for Reuse Debugging, Encryption and Schemabinding Performance Implications of UDFs System functions
© Copyright Andrew Novick All rights reserved. Transact-SQL User-Defined Functions
© Copyright Andrew Novick All rights reserved. Novick Software The consulting company of Andrew Novick Business Applications Design, Architecture, Programming, Project Management, Coaching SQL Server, VB.Net, ASP.Net, XML Home of the
© Copyright Andrew Novick All rights reserved. What are User-Defined Functions? Transact-SQL routines used to encapsulate program logic.
© Copyright Andrew Novick All rights reserved. Types of UDFs T-SQL Scalar UDF T-SQL Inline Table-valued UDF T-SQL Multi-statement Table-valued UDF CLR Scalar CLR Multi-Row CLR Aggregate
© Copyright Andrew Novick All rights reserved. T-SQL: Scalar T-SQL routine with zero or more parameters Returns a single scalar value CREATE FUNCTION udf_Area float ) RETURNS float AS BEGIN END
© Copyright Andrew Novick All rights reserved. T-SQL: Inline A View with parameters CREATE FUNCTION dbo.udf_AuthorsByLetter CHAR(1) ) RETURNS TABLE AS RETURN SELECT * FROM pubs..Authors WHERE LEFT(au_lname, 1)
© Copyright Andrew Novick All rights reserved. T-SQL: Multistatement Returns a single defined table CREATE FUNCTION dbo.udf_FactorialsTAB int ) TABLE (Number INT, Factorial INT) AS BEGIN INT = = 1 < BEGIN INSERT END -- WHILE RETURN END
© Copyright Andrew Novick All rights reserved. CLR: Scalar A C# or VB.Net shared function bound to a SQL Function definition
© Copyright Andrew Novick All rights reserved. CLR: Multi-Row A C# or VB.Net Structure or Class that returns a resultset.
© Copyright Andrew Novick All rights reserved. CLR: Aggregate A C# or VB.Net Structure or Class implementing a required set of methods to produce an aggregate result
T-SQL User Defined Functions
© Copyright Andrew Novick All rights reserved. Scalar User-Defined Functions (1) Written in T-SQL like a stored procedure Takes zero or more parameters Return a single value of a scalar data type: int varchar (30) numeric (18,3) varchar(max) varbinary(max) Does not return Text, Timestamp, Image
© Copyright Andrew Novick All rights reserved. Scalar User-Defined Functions (2) CREATE FUNCTION udf_Area float ) RETURNS float AS BEGIN END
© Copyright Andrew Novick All rights reserved. Using Scalar UDFs SELECT List – SELECT dbo.udf_Area(5.5, 4) – SELECT … dbo.udf_Area (measured_length * 1000, total_width) FROM… WHERE CLAUSE JOIN CLAUSE ORDER BY
© Copyright Andrew Novick All rights reserved. Ways to Use Scalar User-Defined Functions? In the SELECT list In the WHERE clause In a CHECK Constraint In the ON clause of a JOIN In an ORDER BY clause
© Copyright Andrew Novick All rights reserved. Data Manipulation in T-SQL UDFs May SELECT from tables and views May not INSERT UPDATE or DELETE Except to TABLE variables SELECT dbo.udf_Addr_ZIP5DistanceMI ('02451', '98052')
© Copyright Andrew Novick All rights reserved. Profiling UDF Execution Turn on T-SQL Statement Start/Complete events. SQL Profiler has a big impact on duration and CPU time. Its difficult to use it as a measure of performance for UDFs of T-SQL Statement events are on.
© Copyright Andrew Novick All rights reserved. Debugging Scalar UDFs in SQL Server 2000 Query Analyzer Debug Menu is Disabled To Debug create a Stored Procedure – Call the UDF in the SP – Step into the UDF Visual Studio.Net Server Explorer allows for direct debugging Every instance of SQL Server must be run as a domain user, not LocalSystem
© Copyright Andrew Novick All rights reserved. Debugging Scalar UDFs in SQL Server 2005 Use Visual Studio 2005 database project
© Copyright Andrew Novick All rights reserved. Things You Cant Do in UDFs INSERT, UPDATE, DELETE rows – Except to TABLE variables – Not to TEMP tables Execute Stored Procedures – Extended SPs that dont return rowsets are OK DBCC RAISERROR PRINT Use nondeterministic built-in functions! BEGIN CATCH…. END TRY
© Copyright Andrew Novick All rights reserved. Deterministic Functions Deterministic functions return the same result any time they are called with a specific set of input values. Udf_Area (5.5, 4) Non-deterministic functions dont. Getdate(), RAND()
© Copyright Andrew Novick All rights reserved. Inline Table-Valued UDFs Return TABLE Are equivalent to a VIEW with parameters. INSERT, UPDATE, DELETE are possible
© Copyright Andrew Novick All rights reserved. Multistatement Table-Valued UDFs Return a table thats defined in the header Multiple T-SQL statements Cant change the state of the database My use extended stored procedures that dont return rowsets
© Copyright Andrew Novick All rights reserved. Encrypting UDFs Protects the text of the UDF Add the with Encryption keyword CREATED FUNCTION udf_xxx () Returns With Encryption SQL Server 2000 encryption has been broken! Dont count on it.
© Copyright Andrew Novick All rights reserved. Schemabinding Create Function () WITH SCHEMABINDING Prevents the alteration of database objects that are referenced by the UDF All objects UDFs and Views referenced must also be schemabound. All Objects referenced must use two part names.
© Copyright Andrew Novick All rights reserved. Schemabinding Recommendations Always bind scalar UDFs when they dont reference any other object. Bind UDFs that reference data only when you have a special reason to do so. Bind inline and multistatement UDFs only to protect your schema from changes.
© Copyright Andrew Novick All rights reserved. Error Handling You will not get the same chance to handle run-time errors that you do in stored procedures or triggers For scalars, the best solution is usually to return NULL as the result of the function. BEGIN CATCH…. END TRY not allowed! Errors can be reported in the SQL Log.
© Copyright Andrew Novick All rights reserved. System UDFs (1) Defined in master Owned by system_function_schema Begin with fn_ All lower case letters Referenced with special :: syntax
© Copyright Andrew Novick All rights reserved. CLR Functions In SQL Server 2005 Scalar User Defined Functions Multi-Row User Defined Functions User Defined Aggregate
SQLCLR Functions
© Copyright Andrew Novick All rights reserved. Types of SQLCLR Code in S2K5 Stored Procedures User Defined Functions User Defined Aggregates User Defined Types Triggers
© Copyright Andrew Novick All rights reserved. Assemblies.Net Code compiled into an IL DLL Assemblies must be added to S2K5 with CREATE ASSEMBLY Bits are stored in the databases sys.assembly_files table CREATE ASSEMBLY my_assembly_name FROM \\myserver\directory…path\MyAssembly.dll
© Copyright Andrew Novick All rights reserved. Code Access Security PERMISSION_SETs SAFE EXTERNAL_ACCESS UNSAFE
© Copyright Andrew Novick All rights reserved. PERMISSION_SET: Safe May not access external resources: registry, file system, or network May not use unmanaged code or PInvoke May access data using the current context but not via SQLClient or any other data provider No thread processing
© Copyright Andrew Novick All rights reserved. PERMISSION_SET: EXTERNAL_ACCESS May access external resources: registry, file system, network, environment variables May not use unmanaged code or PInvoke
© Copyright Andrew Novick All rights reserved. PERMISSION_SET: UNSAFE May access external resources May use unsafe code and PInvoke Can use SQLClient and other data providers Can use thread constructs This is no more unsafe than extended stored procs
© Copyright Andrew Novick All rights reserved. SQLCLR User-Defined Functions Scalar – Return a single value Multi-Statement UDFs – Returns a single result set No.Net Inline UDFs
© Copyright Andrew Novick All rights reserved. Creating a Scalar UDF Create the assembly first Then the T-SQL definition: CREATE FUNCTION udf_myFunction int -- First varcharmax – 2nd Parm ) RETURNS BIT EXTERNAL NAME assemblyname.class.method
© Copyright Andrew Novick All rights reserved. Creating Table Valued UDF Create the assembly Method returns an IEnumerable CREATE FUNCTION script defines the schema of the result
© Copyright Andrew Novick All rights reserved. Type Considerations.Net reference types dont represent NULL System.Data.SQLTypes represent NULL Use the SQLTypes when possible
© Copyright Andrew Novick All rights reserved. Inprocess Data Provider System.Data.SQLServer Provider Implements the IData* interfaces Parallels the SQLClient Provider Exposes Additional Classes via SQLContext
© Copyright Andrew Novick All rights reserved. User Defined Aggregates Aggregates scalar values into another scalar Uses the SqlUserDefinedAggregate attribute CREATE AGGREGATE float) Returns [float] EXTERNAL NAME [SampleAggregate].[SampleAggregate.Product] go GRANT EXEC ON dbo.Product TO PUBLIC go
© Copyright Andrew Novick All rights reserved. User Defined Aggregate Class public class myAggregate { public void Accumulate ( value) { } public Terminate() { } public void Init () { } public void Merge (myAggregate) { } }
© Copyright Andrew Novick All rights reserved. Using the User Defined Aggregate SELECT dbo.product(sample) [Three integers] FROM (SELECT CAST(1.0 as float) as Sample UNION ALL SELECT 3 UNION ALL SELECT 5 ) Numbers (Result) Three integers
© Copyright Andrew Novick All rights reserved. Performance Experiment Test on 1,000,000 row table pinned in memory 2 CPU system TestCPUElapsed Query #0Scan Table Query #1Udf_txt_CharIndexRev Query #2Equivalent SQL Query #3CharIndexRev (.Net)
© Copyright Andrew Novick All rights reserved. Best Practices Pick one.Net language Build assemblies with SQL Server in mind Use the most restrictive Permission Set possible Move as much.Net/CLR code to the middle tier as possible Test via the SQL Interface
© Copyright Andrew Novick All rights reserved. Why Use.Net in S2K5 Replace Extended SPs with a safer alternative Replace COM automation: sp_OA_* Take advantage of.Net Framework classes Run compute intense algorithms Reuse code Programmer productivity New capabilities not available in T-SQL – User Defined Types – User Defined Aggregates
© Copyright Andrew Novick All rights reserved. Why Use SQLCLR in S2K5 Encapsulation – Functions and Aggregates allow the encapsulation of business rules in reusable form.
© Copyright Andrew Novick All rights reserved. Why SQLCLR in S2K5 Many tasks that were awkward or difficult to perform in Transact-SQL can be better accomplished by using managed code..."
© Copyright Andrew Novick All rights reserved. Why Not use SQLCLR in S2K5 We used to joke that SQL stood for "Scarcely Qualifies as a Language" because it has no I/O and can't format output. Its math library is limited because it isn't a computational language. It doesn't do text searching, list processing, or graphics. The only purposes of SQL are data management and retrieval. Period. Joe Cleko
© Copyright Andrew Novick All rights reserved. Why Not Use SQLCLR in S2K5 $
© Copyright Andrew Novick All rights reserved. Why Not Use SQLCLR in S2K5 (2) Scalability – Application servers MAY scale out easily – Web servers USUALLY scale out easily – Desktops ALMOST ALWAYS scale out – Scaling up SQL Server is expensive
© Copyright Andrew Novick All rights reserved. Why Not use.Net in S2K5 (3) Compare cost per CPU with software licenses: Compute LocationExtra Costs~$/CPU Database ServerAdvanced OS SQL Enterprise Management Tools $20,000 To $50,000 Web ServerManagement Tools$4,000 Desktop$1,000
© Copyright Andrew Novick All rights reserved. Download Code Samples Code samples are available with this presentation at:
© Copyright Andrew Novick All rights reserved. Transact-SQL User-Defined Functions
© Copyright Andrew Novick All rights reserved. Thanks for coming! Please send feedback to: