2008-10-07 3 views
83

Предположим, что мне нужно реализовать фрагмент кода T-SQL, который должен возвращать таблицу в качестве результата. Я могу реализовать функцию, ориентированную на таблицу, или же хранимую процедуру, которая возвращает набор строк. Что я должен использовать?Функции против хранимых процедур

Короче, что я хочу знать:

Каковы основные различия между функциями и хранимыми процедурами? Какие соображения я должен учитывать при использовании одного или другого?

+1

Это кажется идеальным ответ: http://stackoverflow.com/a/1179778/365188 – 2015-10-27 05:04:24

ответ

48

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

Как правило, существует иерархия (вид < Функция TV < Хранимый Proc). Вы можете делать больше в каждом из них, но способность создавать выходные данные и для того, чтобы оптимизатор действительно задействован, уменьшается по мере увеличения функциональности.

Таким образом, использование любого минимально позволяет вам выразить желаемый результат.

4

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

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

Мои 2 цента

6

Если у вас есть функция вы можете использовать его как часть вашего SQL заявления, например

SELECT function_name(field1) FROM table 

Это не работает таким образом, для хранимых процедур.

+1

Я думаю, что речь идет о функциях, которые возвращают значение таблицы. – wcm 2008-10-07 12:08:15

+1

Ну, я говорю вообще. Но для моего конкретного случая я сейчас между хранимой процедурой или табличной функцией. – Auron 2008-10-07 12:22:41

48

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

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

Но они, безусловно, полезны для табличных возвратов в особых случаях.

Если вам нужно разобрать список с разделителями-запятыми, чтобы имитировать передачу массива в процедуру, функция может превратить список в таблицу для вас. Это обычная практика с Sql Server 2005, поскольку мы еще не можем передавать таблицы в хранимые процедуры (мы можем с 2008 года).

+1

Но вы можете отправить XML в хранимую процедуру: http://stackoverflow.com/questions/144550/sql-server-dynamic-where-clause – roosteronacid 2008-10-07 12:24:46

+2

Неправильно, большинство функций SQL-сервера не детерминированы, например getdate в MS- SQL-сервер. Только функции ODBC являются каноническими функциями (= намного быстрее + ​​индексируемыми) ... Но вы очень правы, нужно максимально ограничивать использование функций в запросах по соображениям производительности. – 2010-12-07 08:25:35

1

Это зависит :) Если вы хотите использовать результат, полученный в таблице, в другой процедуре, вам лучше использовать функцию TableValued. Если результаты для клиента, то хранимый процесс обычно является лучшим способом.

41

From the docs:

Если хранимая процедура соответствует следующим критериям, он является хорошим кандидатом для переписать в виде таблицы-функции:

  • Логика представима в одном SELECT, но является хранимой процедурой, а не представлением, только из-за необходимости в параметрах.

  • Хранимая процедура не выполняет операции обновления, за исключением переменных таблицы.

  • Нет необходимости в динамических операциях EXECUTE.

  • Хранимая процедура возвращает один результирующий набор.

  • Основной целью хранимой процедуры является создание промежуточных результатов, которые должны быть загружены во временную таблицу, которая затем запрашивается в инструкции SELECT.

1

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

4

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

SELECT * 
FROM dbo.tvfVeryLargeResultset1(@myVar1) tvf1 
INNER JOIN dbo.tvfVeryLargeResultset1(@myVar2) tvf2 
    ON (tvf1.JoinId = tvf2.JoinId) 

Часто , вам просто нужно принять избыточность кода, который может устранить tvf (при неприемлемых эксплуатационных затратах.)

Еще один момент, о котором я еще не видел, это то, что вы не можете использовать температуру изменения состояния базы данных таблицы внутри многозадачного tvf. Наиболее функционально эквивалентным механизмом для таблицы temp является изменение состояния без изменений, в переменной таблицы памяти и для больших наборов данных таблица temp, вероятно, будет более результативной, чем табличная переменная. (Другие альтернативы включают динамические таблицы & общие табличные выражения, но на некотором уровне сложности они перестают быть хорошим вариантом IMO.)

5

Я провел несколько тестов с длинным ходом логики с одним и тем же битом код (длинный оператор SELECT), выполняющийся как в таблице, так и в хранимой процедуре, и прямой EXEC/SELECT, и каждый выполняется одинаково.

На мой взгляд, всегда используйте функцию, отмеченную таблицей, а не хранимую процедуру, чтобы вернуть результирующий набор, поскольку он делает логику намного проще и читабельнее в запросах, которые впоследствии присоединяются к ним, и позволяет вам повторно использовать ту же логику. Для того, чтобы избежать слишком много удара по производительности, я часто использую «необязательные» параметры (например, вы можете передать NULL для них), чтобы включить функцию для возврата результирующего набора, чтобы быть быстрее, например:

CREATE FUNCTION dbo.getSitePermissions(@RegionID int, @optPersonID int, optSiteID int) 
AS 
RETURN 
    SELECT DISTINCT SiteID, PersonID 
    FROM dbo.SiteViewPermissions 
    WHERE (@optPersonID IS NULL OR @optPersonID = PersonID) 
    AND (@optSiteID IS NULL OR @optSiteID = SiteID) 
    AND @RegionID = RegionID 

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

SELECT * FROM dbo.getSitePermissions(@RegionID) WHERE SiteID = 1 

Я использовал эту технику в нескольких функциях, иногда с длинным списком «необязательных» параметры этого типа.

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

  2. Процедуры могут иметь параметры ввода/вывода для него, тогда как функции могут иметь только входные параметры.

  3. Процедура позволяет выбирать, а также оператор DML, в то время как функция допускает в нем только оператор выбора.

  4. Функции могут быть вызваны из процедуры, тогда как процедуры не могут быть вызваны из функции .

  5. Исключение может быть обработано блоком try-catch в процедуре, тогда как блок try-catch не может использоваться в функции.

  6. Мы можем пойти для управления транзакциями в процедуре, тогда как мы не можем войти в функцию.

  7. Процедуры не могут использоваться в операторе select, тогда как функция может быть встроена в оператор select.

  8. UDF (User Defined функция) может быть использован в любом месте заявления SQL в разделе WHERE/HAVING/SELECT, тогда как хранимые процедуры не могут быть.

  9. UDF, которые возвращают таблицы, могут рассматриваться как другой набор строк. Его можно использовать в JOIN с другими таблицами.

  10. Inline UDFs может быть хотя и представлением, которое принимает параметры и может использоваться в JOIN s и других операций с наборами строк.

10

Я собираюсь написать несколько интересных различий между хранимыми процедурами и функциями.

  • Мы можем использовать функции в отдельных запросах, но мы не можем использовать хранимые процедуры в отдельных запросах.
  • Мы не можем использовать не детерминированные функции в функциях, но мы можем использовать не детерминированные функции в хранимых процедурах . Теперь возникает вопрос, что не детерминированная функция .. Ans является: -

    Беспоставочной детерминированной функцией является функция, которая возвращает различные выходы для тех же входных значений в разное время, как GETDATE(). Он всегда возвращает различное значение всякий раз, когда он запускается.

    Исключение: -

    В более ранних версиях SQL сервера ранее в SQL Server 2000 не позволяют использовать GETDATE() функции в определенных пользователем функций, но версия 2005 и далее позволяет использовать GETDATE() функции в пределах определенной пользователем функции.

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

  • Мы можем использовать DML (вставка, обновление, удаление) заявления в пределах хранимой процедуры , но мы не можем использовать операторы DML в функциях физических таблиц или постоянных таблиц. Если мы хотим выполнить операцию DML в функциях , мы можем сделать это над табличными переменными не на постоянных таблицах.

  • Мы не можем использовать обработку ошибок внутри функции, но мы можем сделать ошибку обработки в хранимых процедурах.

Смежные вопросы