SQL Server - Table Functions

Table functions are Transact-SQL functions that return a table. They are a powerful way to encapsulate complex queries and promote code reusability.

Overview

Table-valued functions (TVFs) allow you to define functions that return a result set, similar to a view, but with the added benefit of accepting input parameters. This makes them highly flexible for scenarios where you need to filter or customize the data returned based on specific criteria.

There are two types of table-valued functions:

Syntax

Inline Table-Valued Function

The basic syntax for an inline table-valued function is:


CREATE FUNCTION schema_name.function_name
(
    @parameter1 datatype,
    @parameter2 datatype
)
RETURNS TABLE
AS
RETURN
(
    -- Single SELECT statement that defines the table to be returned
    SELECT column1, column2, ...
    FROM your_table
    WHERE some_condition
);
        

Multi-Statement Table-Valued Function

The basic syntax for a multi-statement table-valued function is:


CREATE FUNCTION schema_name.function_name
(
    @parameter1 datatype,
    @parameter2 datatype
)
RETURNS @table_variable TABLE
(
    column1 datatype,
    column2 datatype,
    ...
)
AS
BEGIN
    -- Transact-SQL statements
    INSERT INTO @table_variable (column1, column2, ...)
    SELECT columnA, columnB, ...
    FROM another_table
    WHERE condition1;

    -- More statements can follow...

    RETURN;
END;
        

Common Use Cases

Examples

Example 1: Inline TVF to get customers by region

This function returns a table of customers residing in a specified region.


-- Assume a 'Customers' table with columns like CustomerID, Name, Region

CREATE FUNCTION Sales.GetCustomersByRegion
(
    @RegionName NVARCHAR(50)
)
RETURNS TABLE
AS
RETURN
(
    SELECT CustomerID, Name
    FROM Sales.Customers
    WHERE Region = @RegionName
);
GO

-- How to use it:
SELECT * FROM Sales.GetCustomersByRegion('North America');
        

Example 2: Multi-Statement TVF to calculate order totals

This function calculates the total price for each order, including discounts, and returns it as a table.


-- Assume 'Orders' table (OrderID, OrderDate) and 'OrderDetails' table (OrderID, ProductID, Quantity, UnitPrice, Discount)

CREATE FUNCTION Sales.CalculateOrderTotals
(
    @OrderID INT
)
RETURNS @OrderTotals TABLE
(
    OrderID INT,
    TotalPrice DECIMAL(18, 2)
)
AS
BEGIN
    INSERT INTO @OrderTotals (OrderID, TotalPrice)
    SELECT
        od.OrderID,
        SUM(od.Quantity * od.UnitPrice * (1 - od.Discount)) AS CalculatedPrice
    FROM Sales.OrderDetails AS od
    WHERE od.OrderID = @OrderID
    GROUP BY od.OrderID;

    RETURN;
END;
GO

-- How to use it:
SELECT * FROM Sales.CalculateOrderTotals(10248);
        

Performance Considerations

Best Practices

When designing TVFs, consider the data size and query patterns to choose between inline and multi-statement approaches for optimal performance.