funciones-definidas-usuario-udf-en-sql

User-Defined Functions (UDF) in SQL

  • 4 min

A User-Defined Function (UDF) is a routine that accepts parameters, performs an action, and returns the result of that action as a value.

They allow us to perform calculations, transformations, and complex operations in a modular way, which improves the readability and maintainability of our T-SQL code.

Functions are designed to be integrated directly within other queries. The philosophy is “Write it once, use it many times”.

There are mainly two types you need to master: Scalar and Table-Valued.

Scalar Functions

They are identical in concept to UPPER() or ABS(). They receive one or more parameters and return a single value (a number, a date, text…).

The syntax is as follows,

CREATE FUNCTION dbo.FunctionName
(
    @Parameter DataType
)
RETURNS ReturnDataType
AS
BEGIN
    DECLARE @Result ReturnDataType;
    
    -- Calculation logic
    SET @Result = ...;
    
    RETURN @Result;
END
Copied!

Scalar functions in older versions of SQL Server (and still today if overused) can be slow because they execute row by row and prevent parallelism.

Use them for simple calculations, but don’t overuse them either. Avoid accessing tables (doing SELECT) inside a scalar function if you are processing millions of rows and can solve it another way.

Table-Valued Functions

These functions do not return a single piece of data, but an entire table. They are like a “View with Parameters”.

We will focus on Inline TVFs, which are the fastest.

The syntax is as follows,

CREATE FUNCTION dbo.ufn_GetOrdersByCustomer
(
    @CustomerID INT
)
RETURNS TABLE
AS
RETURN
(
    SELECT OrderID, Date, Total
    FROM Orders
    WHERE CustomerID = @CustomerID
);
Copied!

They don’t have BEGIN...END. They simply return the result of a query.

To use them, since they return a table, we use them in the FROM or JOIN clause, (not in the SELECT).

SELECT Orders.OrderID, Orders.Total
FROM dbo.ufn_GetOrdersByCustomer(5) AS Orders -- It acts like a table!
WHERE Orders.Total > 100;
Copied!

This is much cleaner and more modular than writing the WHERE repeatedly in every query.

Limitations of UDFs

To maintain integrity and determinism, SQL Server imposes strict rules on functions:

  1. No Side Effects: A function cannot change the state of the database. No INSERT, UPDATE or DELETE to permanent tables.
  2. Non-Determinism: In the past you couldn’t use GETDATE() or NEWID() inside a function because they return different values each time. (In modern versions this has been relaxed a bit, but it remains a conceptual limitation).
  3. Error Handling: You cannot use TRY...CATCH inside a function. If it fails, the entire query stops.

Function or Stored Procedure?

Although they are similar, they have very different purposes and rules.

CharacteristicStored Procedure (SP)Function (UDF)
GoalExecute a complete business logic (Process).Calculate and transform values.
InvocationWith EXEC (independent).Inside a SELECT, WHERE, JOIN.
ReturnMay return nothing, OUTPUT parameters, or multiple tables.Must return a value (scalar or table).
Modify DataYES. Can do INSERT, UPDATE, DELETE.NO. Can only read. Cannot modify base tables.
Try/CatchAllowed.Not allowed inside the function.

In summary

  • Do you need to modify data (INSERT/UPDATE)? Use a Procedure.
  • Do you need to calculate something to display in a column or filter? Use a Function.