Data: 1.01.2026

Tworzenie funkcji tabelarycznych (UDF) w SQL Server
Spis treści
- Tworzenie funkcji tabelarycznych (UDF) w SQL Server
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 TABLEASRETURN( SELECT CustomerID, CompanyName, City FROM Customers WHERE Country = @Country);Wywołanie funkcji:
SELECT *FROM dbo.CustomersByCountry('UK');Wynik:
| CustomerID | CompanyName | City | |
|---|---|---|---|
| 1 | AROUT | Around the Horn | London |
| 2 | BSBEV | B’s Beverages | London |
| 3 | CONSH | Consolidated Holdings | London |
| 4 | EASTC | Eastern Connection | London |
| 5 | ISLAT | Island Trading | Cowes |
| 6 | NORTS | North/South | London |
| 7 | SEVES | Seven Seas Imports | London |
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 TABLEASRETURN( SELECT CustomerID, CompanyName, City FROM Customers WHERE Country = @Country AND City = @City);Wywołanie funkcji
SELECT *FROM dbo.CustomersByCountryAndCity('UK', 'London');Wynik:
| CustomerID | CompanyName | City | |
|---|---|---|---|
| 1 | AROUT | Around the Horn | London |
| 2 | BSBEV | B’s Beverages | London |
| 3 | CONSH | Consolidated Holdings | London |
| 4 | EASTC | Eastern Connection | London |
| 5 | NORTS | North/South | London |
| 6 | SEVES | Seven Seas Imports | London |
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 TABLEASRETURN( 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:
| CustomerID | CompanyName | Country | City |
|---|---|---|---|
| ALFKI | Alfreds Futterkiste | Germany | Berlin |
| AROUT | Around the Horn | UK | London |
| BLAUS | Blauer See Delikatessen | Germany | Mannheim |
| BLONP | Blondessdsl père et fils | France | Strasbourg |
| BONAP | Bon app’ | France | Marseille |
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 TABLEASRETURN( 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.CountryFROM dbo.fn_ShippedOrders() oJOIN Customers c ON o.CustomerID = c.CustomerIDORDER BY o.OrderDate;Wynik:
| OrderID | ShippedDate | CompanyName | Country |
|---|---|---|---|
| 10248 | 1996-07-16 00:00:00.000 | Vins et alcools Chevalier | France |
| 10249 | 1996-07-10 00:00:00.000 | Toms Spezialitäten | Germany |
| 10250 | 1996-07-12 00:00:00.000 | Hanari Carnes | Brazil |
| 10251 | 1996-07-15 00:00:00.000 | Victuailles en stock | France |
| 10252 | 1996-07-11 00:00:00.000 | Suprêmes délices | Belgium |

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))ASBEGIN INSERT INTO @Result SELECT OrderID, OrderDate, ShipCountry FROM Orders WHERE CustomerID = @CustomerID;
RETURN;END;Wyjaśnienie funkcji:
-
poleceniem
CREATE FUNCTIONtworzymy 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
ASrozpoczyna definicję ciała funkcji. PolecenieBEGIN ...ENDzawiera instrukcje SQL, które zostaną wykonane po wywołaniu funkcji. W tym miejscu możemy używać instrukcjiINSERT, zmiennych, instrukcji warunkowych (IF), wielu zapytańASBEGININSERT INTO @ResultSELECTOrderID,OrderDate,ShipCountryFROM OrdersWHERE CustomerID = @CustomerID;RETURN;END; -
Instrukcja
INSERT INTO @Result ... SELECTpobiera 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
RETURNnie zwraca danych bezpośrednio – sygnalizuje jedynie zakończenie działania funkcji, a jej wynikiem jest zawartość tabeli @Result, zgodnie z definicją zawartą w klauzuliRETURNS @Result TABLE.
Wywołanie funkcji
SELECT *FROM dbo.fn_OrdersByCustomer('ALFKI');Wynik:
| OrderID | OrderDate | ShipCountry | |
|---|---|---|---|
| 1 | 10643 | 1997-08-25 00:00:00.000 | Germany |
| 2 | 10692 | 1997-10-03 00:00:00.000 | Germany |
| 3 | 10702 | 1997-10-13 00:00:00.000 | Germany |
| 4 | 10835 | 1998-01-15 00:00:00.000 | Germany |
| 5 | 10952 | 1998-03-16 00:00:00.000 | Germany |
| 6 | 11011 | 1998-04-09 00:00:00.000 | Germany |
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 NorthwindUSE Northwind;GO-- utworzenie funkcjiCREATE 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)ASBEGIN -- 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;ENDGOWyjaś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:
| OrderID | OrderDate | ItemsCount | OrderValue | AvgUnitPrice | OrderSize |
|---|---|---|---|---|---|
| 10248 | 1996-07-04 00:00:00.000 | 3 | 440 | 19,5333 | Small |
| 10249 | 1996-07-05 00:00:00.000 | 2 | 1863,39999389648 | 30,50 | Large |
| 10250 | 1996-07-08 00:00:00.000 | 3 | 1552,60003662109 | 22,30 | Large |
| 10251 | 1996-07-08 00:00:00.000 | 3 | 654,060005187988 | 16,40 | Medium |
| 10252 | 1996-07-09 00:00:00.000 | 3 | 3597,89990234375 | 31,3333 | Large |
Folder w SSMS przechowujący funkcje tabelaryczne
Funkcje tabelaryczne widoczne są w SQL Server Management Studio w folderze Table-valued Functions:

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 TABLEASRETURN( 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;GOZł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.
