Data: 1.01.2026

Tworzenie funkcji tabelarycznych (UDF) w SQL Server

Tworzenie funkcji tabelarycznych (UDF) w SQL Server

Spis treści

W tym artykule wyjaśnię, czym są funkcje tabelaryczne (UDF) w SQL Server oraz pokażę praktyczne przykłady ich zastosowania, które pomogą Ci w czytelnym i efektywnym przetwarzaniu danych.

Tworzenie funkcji tabelarycznych (UDF) w SQL Server

Funkcje tabelaryczne dzielimy na:

  • funkcje proste – zwracają wynik pojedynczego zapytania. W ich definicji możemy umieścić tylko jedno zapytanie
  • funkcje złożone – wykorzystują wiele instrukcji do tworzenia tabeli, która jest następnie zwracana do instrukcji wywołującej. Należy w nich zdefiniować i zdeklarować tabelę

Oprócz funkcji tabelarycznych, które zwracają zbiory danych, SQL Server oferuje także funkcje skalarne zwracające pojedynczy wynik. Jeśli chcesz zgłębić ten temat, polecam artykuł poświęcony tworzeniu funkcji skalarnych (UDF).

Proste funkcje tabelaryczne w SQL Server

Cechy prostych funkcji tabelarycznych (Inline Table-Valued Functions) w SQL Server:

  • zwracają zestaw danych w postaci tabeli
  • zawierają jedno zapytanie SELECT
  • nie posiadają części proceduralnej (BEGIN ... END)
  • nie używają zmiennych ani instrukcji sterujących
  • są traktowane przez optymalizator zapytań jak fragment zwykłego zapytania SQL, co zapewnia dobrą wydajność i przewidywalne działanie

Tabelaryczna funkcja inline z jednym parametrem

Poniższa funkcja zwraca listę klientów z wybranego kraju. Do parametru @Country przekazujemy Kraj

CREATE FUNCTION dbo.CustomersByCountry (@Country NVARCHAR(50))
RETURNS TABLE
AS
RETURN
(
SELECT
CustomerID,
CompanyName,
City
FROM Customers
WHERE Country = @Country
);

Wywołanie funkcji:

SELECT *
FROM dbo.CustomersByCountry('UK');

Wynik:

CustomerIDCompanyNameCity
1AROUTAround the HornLondon
2BSBEVB’s BeveragesLondon
3CONSHConsolidated HoldingsLondon
4EASTCEastern ConnectionLondon
5ISLATIsland TradingCowes
6NORTSNorth/SouthLondon
7SEVESSeven Seas ImportsLondon

Tabelaryczna funkcja inline z dwoma parametrami

Poniższa funkcja zwraca listę klientów z wybranego kraju oraz z wybranego miasta. Do parametru @Country przekazujemy Kraj, a do parametru @City przekazujemy miasto.

CREATE FUNCTION dbo.CustomersByCountryAndCity
(
@Country NVARCHAR(50),
@City NVARCHAR(50)
)
RETURNS TABLE
AS
RETURN
(
SELECT
CustomerID,
CompanyName,
City
FROM Customers
WHERE Country = @Country
AND City = @City
);

Wywołanie funkcji

SELECT *
FROM dbo.CustomersByCountryAndCity('UK', 'London');

Wynik:

CustomerIDCompanyNameCity
1AROUTAround the HornLondon
2BSBEVB’s BeveragesLondon
3CONSHConsolidated HoldingsLondon
4EASTCEastern ConnectionLondon
5NORTSNorth/SouthLondon
6SEVESSeven Seas ImportsLondon

Tabelaryczna funkcja inline z listą wartości w parametrze

Aby wyfiltrować dane na podstawie zmiennej listy wartości np. wybór kilku krajów z tabeli, możemy podać do parametru funkcji listę jako jeden ciąg tekstowy rozdzielony przecinkiem lub innym separatorem.

W przykładzie używamy wbudowanej funkcji STRING_SPLIT(), aby „rozbić” parametr tekstowy na pojedyncze wiersze.

CREATE OR ALTER FUNCTION dbo.CustomersFewCountries
(
-- Parametr przyjmujący długi tekst np. 'France,Germany,UK'
@CountryList NVARCHAR(MAX)
)
RETURNS TABLE
AS
RETURN
(
SELECT
CustomerID,
CompanyName,
Country,
City
FROM Customers
WHERE Country IN (
-- STRING_SPLIT zamienia tekst 'A,B' na tabelę z wierszami A i B
SELECT TRIM(value)
FROM STRING_SPLIT(@CountryList, ',')
)
);

Wywołanie funkcji

SELECT *
FROM dbo.CustomersFewCountries('UK,France,Germany');

Wynik:

CustomerIDCompanyNameCountryCity
ALFKIAlfreds FutterkisteGermanyBerlin
AROUTAround the HornUKLondon
BLAUSBlauer See DelikatessenGermanyMannheim
BLONPBlondessdsl père et filsFranceStrasbourg
BONAPBon app’FranceMarseille

Tabelaryczna funkcja inline w złączeniu JOIN

Funkcja tabelaryczna, zwraca zbiór. Możemy wykonywać z nią złączenia identycznie jak z każdym innym zbiorem (tabelą).

W przykładzie tworzymy funkcję, za pomocą której z tabeli Orders wybieramy wysłane zamówienia.

CREATE FUNCTION dbo.fn_ShippedOrders()
RETURNS TABLE
AS
RETURN
(
SELECT
OrderID,
CustomerID,
OrderDate,
ShippedDate
FROM Orders
WHERE ShippedDate IS NOT NULL
);

Do wyniku zwracanego przez funkcję dołączamy tabelę Customers:

SELECT
o.OrderID,
o.OrderDate,
o.ShippedDate,
c.CompanyName,
c.Country
FROM dbo.fn_ShippedOrders() o
JOIN Customers c
ON o.CustomerID = c.CustomerID
ORDER BY o.OrderDate;

Wynik:

OrderIDShippedDateCompanyNameCountry
102481996-07-16 00:00:00.000Vins et alcools ChevalierFrance
102491996-07-10 00:00:00.000Toms SpezialitätenGermany
102501996-07-12 00:00:00.000Hanari CarnesBrazil
102511996-07-15 00:00:00.000Victuailles en stockFrance
102521996-07-11 00:00:00.000Suprêmes délicesBelgium

Title

Złożone funkcje tabelaryczne w SQL Server

Złożone funkcje tabelaryczne (Multi-Statement Table-Valued Functions, MSTVF) umożliwiają zwracanie zestawu danych w postaci tabeli, przy jednoczesnym użyciu wielu instrukcji SQL wewnątrz funkcji.

Składnia i tworzenie złożonej funkcji tabelarycznej

W przykładzie tworzymy złożoną funkcję tabelaryczną, która przyjmie ID klienta, zwróci listę jego zamówień, pokaże datę zamówienia i kraj wysyłki.

W przypadku funkcji złożonych najpierw tworzymy tabelę, a dopiero później ją wypełniamy.

CREATE FUNCTION dbo.fn_OrdersByCustomer
(
@CustomerID nchar(5)
)
RETURNS @Result TABLE
(
OrderID INT,
OrderDate DATETIME,
ShipCountry NVARCHAR(15)
)
AS
BEGIN
INSERT INTO @Result
SELECT
OrderID,
OrderDate,
ShipCountry
FROM Orders
WHERE CustomerID = @CustomerID;
RETURN;
END;

Wyjaśnienie funkcji:

  • poleceniem CREATE FUNCTION tworzymy w schemacie dbo funkcję użytkownika o nazwie dbo.fn_OrdersByCustomer

  • funkcja przyjmuje jeden parametr o nazwie @CustomerID typu nchar(5), którym będzie identyfikator klienta

  • fragment kodu

    RETURNS @Result TABLE
    (
    OrderID INT,
    OrderDate DATETIME,
    ShipCountry NVARCHAR(15)
    )

    to definicja tabeli wynikowej. Funkcja zwróci tabelę, która będzie miała kolumny OrderID, OrderDate, ShipCountry. W trakcie działania funkcji dane są zapisywane do wewnętrznej tabeli @Result, która istnieje tylko podczas wykonania funkcji. Po zakończeniu działania funkcji zawartość tabeli @Result zostaje zwrócona jako wynik.

  • słowo kluczowe AS rozpoczyna definicję ciała funkcji. Polecenie BEGIN ...END zawiera instrukcje SQL, które zostaną wykonane po wywołaniu funkcji. W tym miejscu możemy używać instrukcji INSERT, zmiennych, instrukcji warunkowych (IF), wielu zapytań

    AS
    BEGIN
    INSERT INTO @Result
    SELECT
    OrderID,
    OrderDate,
    ShipCountry
    FROM Orders
    WHERE CustomerID = @CustomerID;
    RETURN;
    END;
  • Instrukcja INSERT INTO @Result ... SELECT pobiera z tabeli Orders identyfikatory, daty oraz kraje wysyłki zamówień wybranego klienta (CustomerID = @CustomerID) i zapisuje je do tabeli wynikowej @Result, która zostanie zwrócona przez funkcję

  • Instrukcja RETURN nie zwraca danych bezpośrednio – sygnalizuje jedynie zakończenie działania funkcji, a jej wynikiem jest zawartość tabeli @Result, zgodnie z definicją zawartą w klauzuli RETURNS @Result TABLE.

Wywołanie funkcji

SELECT *
FROM dbo.fn_OrdersByCustomer('ALFKI');

Wynik:

OrderIDOrderDateShipCountry
1106431997-08-25 00:00:00.000Germany
2106921997-10-03 00:00:00.000Germany
3107021997-10-13 00:00:00.000Germany
4108351998-01-15 00:00:00.000Germany
5109521998-03-16 00:00:00.000Germany
6110111998-04-09 00:00:00.000Germany

Złożona funkcja tabelaryczna z agregacjami

Funkcja w przykładzie poniżej dbo.order_analysis umożliwia przeprowadzenie analizy zamówień w określonym przedziale dat.

-- zmiana bazy danych na Northwind
USE Northwind;
GO
-- utworzenie funkcji
CREATE OR ALTER FUNCTION dbo.order_analysis(@date_from DATE, @date_to DATE)
RETURNS @Result TABLE (
[OrderID] [int] NOT NULL,
[OrderDate] [datetime] NULL,
[ItemsCount] [int] NULL,
[OrderValue] [float] NULL,
[AvgUnitPrice] [money] NULL,
[OrderSize] [varchar](6) NOT NULL)
AS
BEGIN
-- zapisz rekordy w zmiennej @Result
INSERT INTO @Result
SELECT
o.OrderID,
o.OrderDate,
COUNT(od.ProductID) AS ItemsCount,
SUM(od.UnitPrice * od.Quantity * (1 - od.Discount)) AS OrderValue,
AVG(od.UnitPrice) AS AvgUnitPrice,
CASE
WHEN SUM(od.UnitPrice * od.Quantity * (1 - od.Discount)) < 600 THEN 'Small'
WHEN SUM(od.UnitPrice * od.Quantity * (1 - od.Discount)) <=700 THEN 'Medium'
ELSE 'Large'
END AS OrderSize
FROM Orders o
JOIN [Order Details] od
ON o.OrderID = od.OrderID
WHERE o.OrderDate BETWEEN @date_from AND @date_to
GROUP BY
o.OrderID,
o.OrderDate;
-- powrót z funkcji, zawartość zmiennej @Result jest wynikiem funkcji
RETURN;
END
GO

Wyjaśnienie funkcji:

  • funkcja przyjmuje dwa parametry @date_from (data początkowa analizowanego okresu) i @date_to (data końcowa analizowanego okresu)
  • zapytanie łączy tabelę Orders z tabelą [Order Details] na podstawie identyfikatora zamówienia, a następnie ogranicza zbiór danych do zamówień złożonych w podanym przedziale dat
  • dla każdego zamówienia wykonywane są agregacje, które obliczają liczbę pozycji w zamówieniu, jego łączną wartość z uwzględnieniem rabatów oraz średnią cenę jednostkową produktów
  • na podstawie obliczonej wartości zamówienia przypisywana jest również kategoria zamówienia („Small”, „Medium” lub „Large”)
  • wyniki są grupowane według identyfikatora i daty zamówienia – każdy wiersz wyniku reprezentuje jedno, podsumowane zamówienie

Wywołanie funkcji:

SELECT *
FROM dbo.order_analysis('1996-01-01', '1996-12-31')

Wynik:

OrderIDOrderDateItemsCountOrderValueAvgUnitPriceOrderSize
102481996-07-04 00:00:00.000344019,5333Small
102491996-07-05 00:00:00.00021863,3999938964830,50Large
102501996-07-08 00:00:00.00031552,6000366210922,30Large
102511996-07-08 00:00:00.0003654,06000518798816,40Medium
102521996-07-09 00:00:00.00033597,8999023437531,3333Large

Folder w SSMS przechowujący funkcje tabelaryczne

Funkcje tabelaryczne widoczne są w SQL Server Management Studio w folderze Table-valued Functions:

Title

Modyfikowanie i usuwanie własnych funkcji tabelarycznych

Aby zmodyfikować tabelaryczną funkcję użytkownika możemy użyć polecenia ALTER FUNCTION

W przykładzie modyfikujemy funkcję dbo.order_analysis, ograniczając zwracane kolumny do OrderID oraz wyliczonej sumy.

ALTER FUNCTION dbo.order_analysis
(
@date_from DATE,
@date_to DATE
)
RETURNS TABLE
AS
RETURN
(
SELECT
o.OrderID,
SUM(od.UnitPrice * od.Quantity * (1 - od.Discount)) AS OrderValue
FROM Orders o
JOIN [Order Details] od
ON o.OrderID = od.OrderID
WHERE o.OrderDate BETWEEN @date_from AND @date_to
GROUP BY o.OrderID
);

Aby usunąć funkcję używamy polecenia DROP FUNCTION

Jeśli funkcja nie jest już wykorzystywana przez inne obiekty bazy danych, można ją usunąć

DROP FUNCTION dbo.order_analysis;
GO

Złożone funkcje tabelaryczne są świetnym rozwiązaniem do generowania raportów wymagających wielu kroków obliczeniowych.

Tworzenie funkcji tabelarycznych (UDF) w SQL Server przećwiczysz na wielu praktycznych przykładach w trakcie naszego kursu SQL Server poziom zaawansowany.

Paula Gajewska
Paula Gajewska
Programistka Python, SQL
Udostępnij wpis:udostępnij Facebookudostępnij Linkedinudostępnij e-mail

Polecane