Функції проти збережених процедур


88

Скажімо, я повинен реалізувати фрагмент коду T-SQL, який повинен повернути таблицю як результат. Я можу реалізувати табличну функцію або збережену процедуру, яка повертає набір рядків. Що мені використовувати?

Коротше кажучи, я хочу знати:

Які основні відмінності між функціями та збереженими процедурами? Які міркування я повинен враховувати, використовуючи те чи інше?


1
Це здається ідеальним відповідь: stackoverflow.com/a/1179778/365188
Ozair Kafray

Відповіді:


51

Якщо ви, швидше за все, захочете поєднати результат цього фрагмента коду з іншими таблицями, тоді, очевидно, функція, що має значення таблиці, дозволить вам скласти результати в одному операторі SELECT.

Як правило, існує ієрархія (View <TV Function <Stored Proc). Ви можете зробити більше в кожному з них, але здатність складати результати, а також оптимізатор брати активну участь зменшується із збільшенням функціональності.

Тож використовуйте те, що мінімально дозволяє вам виразити бажаний результат.


50

Функції повинні бути детермінованими і не можуть використовуватися для внесення змін до бази даних, тоді як збережені процедури дозволяють робити вставки та оновлення тощо.

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

Але вони, безумовно, корисні для повернення, що оцінюється таблицею, у дуже конкретних випадках.

Якщо вам потрібно проаналізувати список, розділений комами, для імітації передачі масиву процедурі, функція може перетворити список на таблицю для вас. Це звичайна практика для Sql Server 2005, оскільки ми ще не можемо передати таблиці до збережених процедур (ми можемо з 2008).


1
Але ви можете відправити XML збереженої процедури: stackoverflow.com/questions/144550 / ...
cllpse

2
Неправильно, більшість функцій сервера SQL не є детермінованими, наприклад, отримання даних на сервері MS-SQL. Тільки функції ODBC - це канонічні функції (= набагато швидше + індексується) ... Але ви дуже праві, слід максимально обмежити використання функцій у запитах з міркувань продуктивності.
Stefan Steiger

45

З документів :

Якщо збережена процедура відповідає наведеним нижче критеріям, вона є гарним кандидатом для переписування як функції, що має значення таблиці:

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

  • Зберігається процедура не виконує операції оновлення, крім змінних таблиці.

  • Немає необхідності в динамічних операторах EXECUTE.

  • Збережена процедура повертає один набір результатів.

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


12

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

  • Ми можемо використовувати функції у вибраних запитах, але ми не можемо використовувати збережені процедури у вибраних запитах.
  • Ми не можемо використовувати недетерміновані функції у функціях, але можемо використовувати недетерміновані функції у збережених процедурах. Тепер виникає питання, що таке недетермінована функція .. Відповідь така: -

    Недетермінованою функцією є функція, яка повертає різні виходи для однакових вхідних значень у різний час, наприклад getdate (). Він завжди повертає різне значення при кожному запуску.

    Виняток: -

    Раніші версії сервера sql до sql 2000 не дозволяли використовувати функцію getdate () у визначених користувачем функціях, але версія 2005 та новіші версії дозволяють нам використовувати функцію getdate () у визначеній користувачем функції.

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

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

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


Чому операції DML підтримуються у функціях MySQL?
Joey Pinto

@JoeyPinto. Оскільки myNONsql не є скаргою на SQL. Звичайно, у нього є додаткові послуги, але не основи.
PerformanceDBA

8
  1. Процедура може повертати нуль або n значень, тоді як функція може повертати одне значення, яке є обов'язковим.

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

  3. Процедура дозволяє в ньому вибирати як оператор DML, так як функція дозволяє лише оператор select у ньому.

  4. Функції можна викликати з процедури, тоді як процедури не можна викликати з функції.

  5. Виняток може бути оброблений блоком try-catch у процедурі, тоді як блок try-catch не може бути використаний у функції.

  6. Ми можемо використовувати процедуру управління транзакціями, тоді як функціонувати не можемо.

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

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

  9. UDF, які повертають таблиці, можна розглядати як інший набір рядків. Це можна використовувати в JOINs з іншими таблицями.

  10. Вбудовані UDF можуть бути як представленнями, що приймають параметри, і можуть використовуватися в JOINs та інших операціях з набором рядків.


6

Якщо у вас є функція, ви можете використати її як частину вашого оператора SQL, наприклад

SELECT function_name(field1) FROM table

Це не працює таким чином для збережених процедур.


1
Я думаю, що він говорив про функції, які повертають табличні значення.
wcm

1
Ну, я розмовляю загалом. Але для мого конкретного випадку я зараз перебуваю між збереженою процедурою або табличною функцією.
Аурон

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

Я використовував цей прийом у кількох функціях, іноді з довгим списком "необов'язкових" параметрів цього типу.


4

Я особисто використовую функції, що оцінюють таблиці, коли я повертаю лише одну таблицю, яка не впливає. В основному я ставлюсь до них як до параметризованих поглядів.

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

Мої 2 центи


4

Як зазначалося вище, функції є більш читабельними / складовими / самодокументуючими, але загалом менш ефективними і можуть бути серйозно менш ефективними, якщо ви захоплюєтесь ними в таких об'єднаннях, як

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

Часто вам просто потрібно прийняти надмірність коду, яку tvf міг би усунути (за неприйнятної вартості продуктивності).

Ще один момент, про який я ще не бачив, - це те, що ви не можете використовувати тимчасові таблиці, що змінюють стан бази даних, всередині tvf із декількома операторами. Найбільш функціонально еквівалентним механізмом тимчасової таблиці є нестатовий зміна змінної таблиці пам'яті, і для великих наборів даних тимчасова таблиця, швидше за все, буде більш ефективною, ніж змінна таблиці. (Інші альтернативи включають динамічні таблиці та загальні вирази, що оцінюють таблиці, але на певному рівні складності вони перестають бути хорошим варіантом IMO.)


1

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


1

Це залежить :) Якщо ви хочете використовувати табличний результат в іншій процедурі, вам краще використовувати функцію TableValued. Якщо результати стосуються клієнта, збережений процес, як правило, кращий шлях.


-1

Збережені процедури - це попередньо скомпільовані запити, які виконуються швидше та рятують від ін'єкцій sql. Вони можуть повертати значення 0 або N. Ми можемо виконувати операції DML всередині збережених процедур. Ми можемо використовувати функції всередині процедур і можемо використовувати функції у запиті вибору. Функції використовуються для повернення будь-якого значення, а операції DML неможливі у функціях. функції бувають двох типів скалярні та табличні. скалярна функція повертає одне значення, що має табличну функцію, що використовується для повернення рядків таблиць.


Це дуже давнє запитання з великою кількістю відповідей, багато з них (включаючи прийняту відповідь) високо оцінені. Перш ніж додавати чергову відповідь до такої теми, вам слід запитати себе: "чого бракує всім цим існуючим відповідям, що вимагає від мене написання іншого?"
APC
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.