Sources
Delphi Russian Knowledge Base
DRKB - это самая большая и удобная в использовании база знаний по Дельфи в рунете, составленная Виталием Невзоровым

Определяемые пользователем функции

01.01.2007

В версии MSSQL 2000 появилась возможность создавать в БД функции. Функции могут быть трех типов:

Скалярные функции

Эти функции возвращают скалярную величину. Они аналогичны функциям в любом языка программирования

CREATE FUNCTION FirstWord (@S VARCHAR(255))
RETURNS VARCHAR
(255)
AS
BEGIN
 DECLARE @I INT
 SET @I
= CHARINDEX(' ', @S)
 RETURN CASE @I WHEN
0 THEN @S
                ELSE LEFT
(@S, @I-1)
       
END
END
GO

SELECT dbo
.FirstWord ('Hello world !')

Inline табличные функции

Эти функции состоят из одного оператора SELECT и возвращают его результат в виде таблицы

CREATE FUNCTION OrdersByCustomer (@S VARCHAR(255))
RETURNS TABLE
AS
  RETURN SELECT
* FROM Orders WHERE CustomerId = @S
GO

SELECT
*
  FROM
OrdersByCustomer('VINET') AS T
    INNER JOIN
[Order Details] OD ON OD.OrderId = T.OrderId

Многооператорные табличные функции

Эти функции наиболее интересны, поскольку позволяют динамически сформировать таблицу с требуемыми данными, которую затем можно использовать в запросе

В качестве примера рассмотрим функцию, генерирующую таблицу, содержащую номера и названия месяцев года. Параметр позволяет сгенерировать эту таблицу за один квартал.

CREATE FUNCTION Months (@Quoter INT)
RETURNS @table_var TABLE
       
(Id int,
         
Name VARCHAR(20))
AS
BEGIN
 DECLARE
@Start INTEGER, @End INTEGER

 SET
@Start = CASE
   WHEN
@Quoter = 2 THEN 4
   WHEN
@Quoter = 3 THEN 7
   WHEN
@Quoter = 4 THEN 10
   ELSE
1
 
END

 SET
@End = CASE
   WHEN
@Quoter = 1 THEN 3
   WHEN
@Quoter = 2 THEN 6
   WHEN
@Quoter = 3 THEN 9
   ELSE
12
 
END

 WHILE
(@Start <= @End) BEGIN
   INSERT @table_var
(Id, Name) VALUES
     
(@Start, DATENAME(month, '1998' + REPLACE(STR(@Start,2),' ','0')+'01'))
   SET
@Start = @Start + 1
 
END

 RETURN
END
GO

SELECT T
.Name, SUM(O.Freight)
 FROM dbo
.Months(NULL) AS T
   INNER JOIN
Orders O ON DATEPART(month, O.OrderDate) = T.Id
GROUP BY T
.Name

Также, при помощи подобных функций можно легко раскрывать иерархии и выполнять прочие задачи, которые в предыдущих версиях сервера требовали временных таблиц.