Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Şunlar için geçerlidir:SQL Server
Azure SQL Veritabanı
Azure SQL Yönetilen Örneği
Azure Synapse Analytics
Analytics Platform Sistemi (PDW)
Microsoft Fabric'te SQL Veritabanı
Bu makalede, Transact-SQL kullanarak SQL Server'da kullanıcı tanımlı bir işlevin (UDF) nasıl oluşturulacağı açıklanır.
Sınırlamalar
Kullanıcı tanımlı işlevler, veritabanı durumunu değiştiren eylemler gerçekleştirmek için kullanılamaz.
Kullanıcı tanımlı işlevler, hedef olarak tablo içeren bir OUTPUT INTO yan tümcesi içeremez.
Kullanıcı tanımlı işlevler birden çok sonuç kümesi döndüremez. Birden çok sonuç kümesi döndürmeniz gerekiyorsa kayıtlı prosedür kullanın.
Kullanıcı tanımlı bir işlevde hata işleme kısıtlandı. UDF, TRY...CATCH, @ERROR veya RAISERROR'yi desteklemez.
Kullanıcı tanımlı işlevler saklı yordamı çağıramaz, ancak genişletilmiş saklı yordamı çağırabilir.
Kullanıcı tanımlı işlevler dinamik SQL veya geçici tablolardan yararlanamaz. Tablo değişkenlerine izin verilir.
SET deyimlerine kullanıcı tanımlı bir işlevde izin verilmez (örneğin, SET NOCOUNT ON;). Değişken değeri atamak için SET kullanılabilir.
FOR XML yan tümcesine izin verilmez.
İç içe kullanıcı tanımlı işlevler
Kullanıcı tanımlı işlevler iç içe yerleştirilmiş olabilir. Başka bir ifadeyle, kullanıcı tanımlı bir işlev başka bir işlev çağırabilir. Çağrılan işlev yürütmeyi başlattığında iç içe geçme düzeyi artırılır ve çağrılan işlev yürütmeyi bitirdiğinde iç içe geçme düzeyi azaltılır.
Kullanıcı tanımlı işlevler en fazla 32 düzey iç içe yerleştirilebilir. İç içe yerleştirme düzeylerinin üst sınırının aşılması, çağıran işlev zincirinin tamamının başarısız olmasına neden olur. Transact-SQL kullanıcı tanımlı işlevden yönetilen koda yapılan tüm başvurular, 32 düzeyli iç içe geçme sınırına karşı bir düzey olarak sayılır.
Yönetilen kodun içinden çağrılan yöntemler bu sınıra karşı sayılmaz.
Service Broker ifadeleri
Aşağıdaki Hizmet Aracısı deyimleri Transact-SQL kullanıcı tanımlı işlevin tanımına eklenemez:
BEGIN DIALOG CONVERSATIONEND CONVERSATIONGET CONVERSATION GROUPMOVE CONVERSATIONRECEIVESEND
Yan etki işlevleri
Aşağıdaki belirsiz yerleşik işlevler Transact-SQL kullanıcı tanımlı bir işlevde (UDF) kullanılamaz .
NEWIDNEWSEQUENTIALIDRANDTEXTPTR
UDF içinde bu işlevlerden birine başvurursanız aşağıdaki hatayı alırsınız:
Msg 443, Level 16, State 1
Invalid use of a side-effecting operator <operator> within a function.
Belirleyici ve belirsiz yerleşik sistem işlevlerinin listesi için bkz. Deterministic ve nondeterministic functions.
Bu sorunu çözmek için, yan etki yaratan işlevi bir görünüme sarmalayabilir ve bir işlev içerisinde görünümü çağırabilirsiniz.
İzinler
Veritabanında CREATE FUNCTION izni ve işlevin oluşturulduğu şema üzerinde ALTER izni gerektirir. İşlev kullanıcı tanımlı bir tür belirtiyorsa, tür üzerinde EXECUTE izni gerektirir.
Skaler işlev örnekleri
Skaler işlev (skaler UDF)
Aşağıdaki örnek, AdventureWorks2025 veritabanında çoklu ifadeli bir skaler fonksiyon (skaler UDF ) oluşturur. İşlev bir giriş değeri, bir ProductIDalır ve envanterde belirtilen ürünün toplam miktarı olan tek bir veri değeri döndürür.
IF OBJECT_ID(N'dbo.ufnGetInventoryStock', N'FN') IS NOT NULL
DROP FUNCTION ufnGetInventoryStock;
GO
CREATE FUNCTION dbo.ufnGetInventoryStock (@ProductID INT)
RETURNS INT
AS
-- Returns the stock level for the product.
BEGIN
DECLARE @ret AS INT;
SELECT @ret = SUM(p.Quantity)
FROM Production.ProductInventory AS p
WHERE p.ProductID = @ProductID
AND p.LocationID = '6';
IF (@ret IS NULL)
SET @ret = 0;
RETURN @ret;
END
Aşağıdaki örnek, 75 ile 80 arasında ufnGetInventoryStock olan ürünlerin geçerli stok miktarını döndürmek için ProductModelID işlevini kullanır.
SELECT ProductModelID,
Name,
dbo.ufnGetInventoryStock(ProductID) AS CurrentSupply
FROM Production.Product
WHERE ProductModelID BETWEEN 75 AND 80;
Skaler işlevler hakkında daha fazla bilgi ve örnek için bkz. CREATE FUNCTION .
Tablo değerli işlev örnekleri
Doğrudan tablo değerli fonksiyon (TVF)
Aşağıdaki örnek, AdventureWorks2025 veritabanında satır içi tablo değerli bir fonksiyon (TVF) oluşturur. İşlev, bir giriş parametresi olarak müşteri (mağaza) kimliği alır ve mağazada satılan her bir ürün için ProductID, Nameve yılın başından bugüne kadar olan satışların toplamını YTD Total olarak geri döndürür.
IF OBJECT_ID(N'Sales.ufn_SalesByStore', N'IF') IS NOT NULL
DROP FUNCTION Sales.ufn_SalesByStore;
GO
CREATE FUNCTION Sales.ufn_SalesByStore (@storeid INT)
RETURNS TABLE
AS
RETURN
(
SELECT P.ProductID,
P.Name,
SUM(SD.LineTotal) AS 'Total'
FROM Production.Product AS P
INNER JOIN Sales.SalesOrderDetail AS SD
ON SD.ProductID = P.ProductID
INNER JOIN Sales.SalesOrderHeader AS SH
ON SH.SalesOrderID = SD.SalesOrderID
INNER JOIN Sales.Customer AS C
ON SH.CustomerID = C.CustomerID
WHERE C.StoreID = @storeid
GROUP BY P.ProductID, P.Name
);
Aşağıdaki örnek işlevi çağırır ve 602 müşteri kimliğini belirtir.
SELECT *
FROM Sales.ufn_SalesByStore(602);
Çok ifadeli tablo değer döndüren işlev (MSTVF)
Aşağıdaki örnek, AdventureWorks2025 veritabanında çoklu ifade tablo değerli bir fonksiyon (MSTVF) oluşturur. İşlev tek bir giriş parametresi, bir EmployeeID alır ve belirtilen çalışana doğrudan veya dolaylı olarak rapor veren tüm çalışanların listesini döndürür. İşlev daha sonra çalışan kimliği 109 belirterek çağrılır.
IF OBJECT_ID(N'dbo.ufn_FindReports', N'TF') IS NOT NULL
DROP FUNCTION dbo.ufn_FindReports;
GO
CREATE FUNCTION dbo.ufn_FindReports (@InEmpID INT)
RETURNS @retFindReports TABLE
(
EmployeeID INT PRIMARY KEY NOT NULL,
FirstName NVARCHAR (255) NOT NULL,
LastName NVARCHAR (255) NOT NULL,
JobTitle NVARCHAR (50) NOT NULL,
RecursionLevel INT NOT NULL
)
--Returns a result set that lists all the employees who report to the
--specific employee directly or indirectly.*/
AS
BEGIN
WITH EMP_cte (EmployeeID, OrganizationNode, FirstName, LastName, JobTitle, RecursionLevel) -- CTE name and columns
AS (
-- Get the initial list of Employees for Manager n
SELECT e.BusinessEntityID,
e.OrganizationNode,
p.FirstName,
p.LastName,
e.JobTitle,
0
FROM HumanResources.Employee AS e
INNER JOIN Person.Person AS p
ON p.BusinessEntityID = e.BusinessEntityID
WHERE e.BusinessEntityID = @InEmpID
UNION ALL
SELECT e.BusinessEntityID,
e.OrganizationNode,
p.FirstName,
p.LastName,
e.JobTitle,
RecursionLevel + 1
-- Join recursive member to anchor
FROM HumanResources.Employee AS e
INNER JOIN EMP_cte
ON e.OrganizationNode.GetAncestor(1) = EMP_cte.OrganizationNode
INNER JOIN Person.Person AS p
ON p.BusinessEntityID = e.BusinessEntityID)
-- copy the required columns to the result of the function
INSERT @retFindReports
SELECT EmployeeID,
FirstName,
LastName,
JobTitle,
RecursionLevel
FROM EMP_cte;
RETURN;
END
GO
Aşağıdaki örnek işlevi çağırır ve çalışan kimliği 1'i belirtir.
SELECT EmployeeID,
FirstName,
LastName,
JobTitle,
RecursionLevel
FROM dbo.ufn_FindReports(1);
Satır içi tablo değerli işlevler (satır içi TVF'ler) ve çok deyimli tablo değerli işlevler (MSTVF'ler) hakkında daha fazla bilgi ve örnek için bkz. CREATE FUNCTION.
En iyi yöntemler
SCHEMABINDING yan tümcesiyle kullanıcı tanımlı bir işlev (UDF) oluşturulmazsa, temel nesnelerde yapılan değişiklikler işlevin tanımını etkileyebilir ve çağrıldığında beklenmeyen sonuçlar üretebilir. temel nesnelerinde yapılan değişiklikler nedeniyle işlevin güncelliğini yitirmemesini sağlamak için aşağıdaki yöntemlerden birini uygulamanızı öneririz:
UDF'yi oluştururken
WITH SCHEMABINDINGyan tümcesini belirtin. Bu, işlev tanımında başvuruda bulunulan nesnelerin, işlev de değiştirilmediği sürece değiştirilemeyeceğini sağlar.UDF tanımında belirtilen herhangi bir nesneyi değiştirdikten sonra sp_refreshsqlmodule saklı yordamını yürütün.
Verilere erişmeyen bir UDF oluşturuyorsanız, sorgu iyileştiricisinin bu UDF'leri içeren sorgu planları için gereksiz biriktirici işleçleri oluşturmasını önlemek için SCHEMABINDING seçeneğini belirtin. Biriktiriciler hakkında daha fazla bilgi için bakınız Mantıksal ve fiziksel showplan işleç referansı. Şema bağlı işlevi oluşturma hakkında daha fazla bilgi için bkz. Şemaya bağlı işlevler.
FROM yan tümcesinde MSTVF'ye katılmak mümkündür, ancak performansın düşmesine neden olabilir. SQL Server, MSTVF'ye dahil edilebilen bazı deyimlerde optimize edilmiş tekniklerin tümünü kullanamıyor, bu da optimal olmayan bir sorgu planına neden oluyor. Mümkün olan en iyi performansı elde etmek için, mümkün olduğunda işlevler yerine temel tablolar arasında birleştirmeler kullanın.
MSTVF'ler, SQL Server 2014 (12.x) ile başlayan 100 ve SQL Server'ın önceki sürümleri için 1 sabit kardinalite tahminlerine sahiptir.
SQL Server 2017 (14.x) ve sonraki sürümlerde, MSTVF'ler kullanan bir yürütme planını iyileştirmek için iç içe geçmiş yürütme kullanılabilir ve bu da daha önce bahsedilen buluşsal yöntemler yerine gerçek kardinalitenin kullanılmasına yol açar.
Daha fazla bilgi için bkz. çok deyimli tablo değerli işlevler için Birleşik yürütme.
ANSI_WARNINGS saklı yordamda, kullanıcı tanımlı işlevde parametre geçirirken veya bir batch deyiminde değişkenleri bildirdiğinizde ve ayarladığınızda kabul edilmez. Örneğin, bir değişken karakter(3) olarak tanımlanırsa ve üç karakterden büyük bir değere ayarlanırsa, veriler tanımlanan boyuta yuvarlanır ve INSERT veya UPDATE deyimi başarılı olur.
İlgili içerik
- kullanıcı tanımlı işlevleri
- fonksiyon oluştur (Transact-SQL)
- FONKSİYONU DEĞİŞTİR (Transact-SQL)
- DROP İŞLEVI (Transact-SQL)
- PARTITION FONKSİYONUNU SİL (Transact-SQL)