Функция против хранимой процедуры в SQL Server


831

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

Может кто-нибудь сказать мне, почему?





3
как насчет скорости? какой из них выполняет тот же запрос быстрее?
AmiNadimi

Ответы:


708

Функции являются вычисляемыми значениями и не могут выполнять постоянные изменения среды SQL Server(т. Е. Не допускаются INSERTили UPDATEоператоры).

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

Этот момент стоит отметить из комментариев, в которых обобщается ответ. Благодаря @Sean K Андерсон:

Функции следуют компьютерному определению в том смысле, что они ДОЛЖНЫ возвращать значение и не могут изменять данные, которые они получают в качестве параметров (аргументов). Функции не могут ничего менять, должны иметь хотя бы один параметр и возвращать значение. Хранимые процедуры не должны иметь параметр, могут изменять объекты базы данных и не должны возвращать значение.

Как вызвать SQLфункцию из хранимой процедуры и когда мы используем функцию вместо хранимой процедуры.

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

https://programmingtechtutorial.blogspot.com/2020/01/when-use-storeprocedure-and-when-use.html


13
В принципе, DML не допускается?
Дэвид Блейн

173
Функции следуют определению компьютерной науки в том смысле, что они ДОЛЖНЫ возвращать значение и не могут изменять данные, которые они получают в качестве параметров (аргументов). Функции не могут ничего менять, должны иметь хотя бы один параметр и возвращать значение. Хранимые процедуры не должны иметь параметр, могут изменять объекты базы данных и не должны возвращать значение.
Шон Андерсон

23
Фактически в функции могут быть операторы INSERT, UPDATE и DELETE для изменения переменных локальной таблицы.
Ани

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

40
Функция @SeanKAnderson «должна иметь хотя бы один параметр» не соответствует действительности.
Лян

624

Разница между SP и UDF указана ниже:

+---------------------------------+----------------------------------------+
| Stored Procedure (SP)           | Function (UDF - User Defined           |
|                                 | Function)                              |
+---------------------------------+----------------------------------------+
| SP can return zero , single or  | Function must return a single value    |
| multiple values.                | (which may be a scalar or a table).    |
+---------------------------------+----------------------------------------+
| We can use transaction in SP.   | We can't use transaction in UDF.       |
+---------------------------------+----------------------------------------+
| SP can have input/output        | Only input parameter.                  |
| parameter.                      |                                        |
+---------------------------------+----------------------------------------+
| We can call function from SP.   | We can't call SP from function.        |
+---------------------------------+----------------------------------------+
| We can't use SP in SELECT/      | We can use UDF in SELECT/ WHERE/       |
| WHERE/ HAVING statement.        | HAVING statement.                      |
+---------------------------------+----------------------------------------+
| We can use exception handling   | We can't use Try-Catch block in UDF.   |
| using Try-Catch block in SP.    |                                        |
+---------------------------------+----------------------------------------+

21
Функции должны возвращать одно значение или набор.
Рафарино

8
Это произошло через 3 года, но должно быть на высоте, потому что оно читаемо и обширно.
DanteTheSmith

SP может использовать как временные таблицы, так и табличные переменные, тогда как UDF может использовать только табличные переменные. Табличные переменные, в свою очередь, могут не использовать индексы. UDF может быть вызван в CROSS APPLY в отличие от SP
Людовик Обер

190

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

Функции обычно имеют выход и опционально входы. Затем выходные данные можно использовать в качестве входных данных для другой функции (встроенной в SQL Server, такой как DATEDIFF, LEN и т. Д.) Или в качестве предиката для SQL-запроса - например, SELECT a, b, dbo.MyFunction(c) FROM tableили SELECT a, b, c FROM table WHERE a = dbo.MyFunc(c).

Хранимые процедуры используются для связывания запросов SQL вместе в транзакции и взаимодействия с внешним миром. Фреймворки, такие как ADO.NET и т. Д., Не могут напрямую вызывать функцию, но могут напрямую вызывать хранимый процесс.

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

SELECT * FROM dbo.MyTable WHERE col1 = dbo.MyFunction(col2)

Где MyFunction объявлен как:

CREATE FUNCTION MyFunction (@someValue INTEGER) RETURNS INTEGER
AS
BEGIN
   DECLARE @retval INTEGER

   SELECT localValue 
      FROM dbo.localToNationalMapTable
      WHERE nationalValue = @someValue

   RETURN @retval
END

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

Таким образом, вы должны быть осторожны при написании функций. Если вы выполняете SELECT из таблицы в функции, вам нужно спросить себя, может ли она быть лучше выполнена с помощью JOIN в родительском хранимом протоколе или какой-либо другой конструкции SQL (такой как CASE ... WHEN ... ELSE ... КОНЕЦ).


2
Не могли бы вы уточнить, что "такие фреймворки, как ADO.NET и т. Д. Не могут вызывать функцию напрямую"? Я выполнил функции с поставщиками данных ADO.NET без проблем.
Ян Кемп

24
Вы должны вызывать функцию с помощью некоторого оператора SELECT - функция не может быть вызвана как самостоятельный фрагмент кода сама по себе - она ​​должна вызываться как часть некоторого более крупного оператора SQL, даже если этот оператор SQL не более чем SELECT * from dbo.MyTableValuedFunction(). Sprocs, с другой стороны, может быть вызван напрямую из ADO.NET, установив SqlCommand.CommandTypeв CommandType.StoredProcedure.
Крис Дж

60

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

  • Хранимые процедуры нельзя использовать в операторах выбора.
  • Хранимые процедуры поддерживают отложенное разрешение имен.
  • Хранимые процедуры обычно используются для выполнения бизнес-логики.
  • Хранимые процедуры могут возвращать любой тип данных.
  • Хранимые процедуры могут принимать большее количество входных параметров, чем определенные пользователем функции. Хранимые процедуры могут иметь до 21 000 входных параметров.
  • Хранимые процедуры могут выполнять динамический SQL.
  • Хранимые процедуры поддерживают обработку ошибок.
  • Недетерминированные функции могут использоваться в хранимых процедурах.

  • Пользовательские функции могут использоваться в операторах Select.
  • Пользовательские функции не поддерживают отложенное разрешение имен.
  • Пользовательские функции обычно используются для вычислений.
  • Пользовательские функции должны возвращать значение.
  • Пользовательские функции не могут возвращать изображения.
  • Пользовательские функции принимают меньшее количество входных параметров, чем хранимые процедуры. UDF могут иметь до 1023 входных параметров.
  • Временные таблицы не могут использоваться в пользовательских функциях.
  • Пользовательские функции не могут выполнять динамический SQL.
  • Пользовательские функции не поддерживают обработку ошибок. RAISEERRORИЛИ @@ERRORне допускаются в UDF.
  • Недетерминированные функции не могут использоваться в UDF. Например, GETDATE()нельзя использовать в UDF.

1
Цитировать @curiousBoy ниже re. другой незаданный ответ (@Ankit) (<- посмотрите, как я это сделал?;)): «Вы должны были дать ссылку на источник. Это от ( blogs.msdn.microsoft.com/pradeepsvs/2014/10 / 08 /… ). Пожалуйста, уважайте работу, которую делают другие! "
Том

7
Этот блог был написан с 8 октября 2014 года, и этот ответ был написан с 2 мая 2013 года @Tom
Кумар Маниш

1
@Code Rider: Ах, мои извинения! Не могу поверить, что я этого не заметил! Итак, блог скопировал вас (или кто-то еще, кто сделал) без кредита?
Том

GETDATE()может быть использован в функции. Поворот на недетерминированном не является хорошим.
ПроизводительностьDBA

56

Напишите пользовательскую функцию, когда вы хотите вычислить и вернуть значение для использования в других инструкциях SQL; написать хранимую процедуру, когда вы хотите вместо этого сгруппировать возможно сложный набор операторов SQL. В конце концов, это два совершенно разных варианта использования!


18
Существуют различные типы пользовательских функций. Скалярные возвращают только значения; другие типы наборов результатов повторного запуска.
AK

44
              STORE PROCEDURE                 FUNCTION (USER DEFINED FUNCTION)    
 * Procedure can return 0, single or   | * Function can return only single value   
   multiple values.                    |
                                       |
 * Procedure can have input, output    | * Function  can have only input 
   parameters.                         |   parameters.         
                                       |
 * Procedure cannot be called from     | * Functions can be called from 
   function.                           |   procedure.
                                       |
 * Procedure allows select as well as  | * Function allows only select statement 
   DML statement in it.                |   in it.
                                       |
 * Exception can be handled by         | * Try-catch block cannot be used in a 
   try-catch block in a procedure.     |   function.
                                       |
 * We can go for transaction management| * We can't go for transaction 
   in procedure.                       |   management in function.
                                       |
 * Procedure cannot be utilized in a   | * Function can be embedded in a select 
   select statement                    |   statement.
                                       |
 * Procedure can affect the state      | * Function can not affect the state 
   of database means it can perform    |   of database means it can not    
   CRUD operation on database.         |   perform CRUD operation on 
                                       |   database. 
                                       |
 * Procedure can use temporary tables. | * Function can not use 
                                       |   temporary tables. 
                                       |
 * Procedure can alter the server      | * Function can not alter the  
   environment parameters.             |   environment parameters.
                                       |   
 * Procedure can use when we want      | * Function can use when we want
   instead is to group a possibly-     |   to compute and return a value
   complex set of SQL statements.      |   for use in other SQL 
                                       |   statements.

1
UDF может быть вызван в CROSS APPLY, в отличие от SP
Людовик Обер

24

Основная разница

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

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

Функция принимает один входной параметр, это обязательно, но хранимая процедура может принимать o или n входных параметров.

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

Прогресс Разница

Процедура допускает в нем SELECT, а также оператор DML (INSERT / UPDATE / DELETE), тогда как функция допускает только оператор SELECT.

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

Хранимые процедуры не могут использоваться в инструкциях SQL где-либо в разделе WHERE / HAVING / SELECT, тогда как функция может быть.

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

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

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

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

источник


25
Вы должны были дать ссылку на источник. Это из dotnet-tricks.com/Tutorial/sqlserver/… . Пожалуйста, уважайте работу, которую делают другие!
curiousBoy

16
Это не причина не давать ссылку на источник. Вы можете упомянуть в конце этого!
curiousBoy

2
Число рейнольдса «Функция должна возвращать значение, но в хранимой процедуре это необязательно…». Я хотел бы уточнить, что: «Функции должны возвращать одно и только одно значение (которое должно быть сделано с помощью Returnsключевого слова и должно быть скалярным или табличным типом). , но хранимые процедуры могут опционально возвращать: a) Intкод результата 1 типа с помощью оператора Returnи / или b) параметры 1+ (включая Cursorтип) с помощью Outputключевого слова и / или c) наборы строк 1+ с помощью Selectоператоров. Если только 1 набор строк возвращается, его можно использовать в качестве аргумента «execute_statement» оператора «Insert Into».
Том

20

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

SELECT a, lookupValue(b), c FROM customers 

где lookupValueбудет UDF. Этот вид функциональности невозможен при использовании хранимой процедуры. В то же время вы не можете делать определенные вещи внутри UDF. Основное, что нужно запомнить, это то, что UDF:

  • не может создавать постоянные изменения
  • не может изменить данные

хранимая процедура может делать эти вещи.

Для меня встроенное использование UDF является наиболее важным использованием UDF.


14

Хранимые процедуры используются в качестве сценариев . Они запускают ряд команд для вас, и вы можете запланировать их запуск в определенное время. Обычно запускает несколько операторов DML, таких как INSERT, UPDATE, DELETE и т. Д. Или даже SELECT.

Функции используются в качестве методов. Вы передаете это что-то, и оно возвращает результат. Должен быть маленьким и быстрым - делает это на лету. Обычно используется в операторе SELECT.


2
Это хорошее резюме двух, быстрых и грязных способов думать о них.
Эрик Бишард

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

8

Хранимая процедура:

  • Это как миниатюрная программа на SQL Server.
  • Может быть простым как оператор выбора или сложным, как длинный скрипт, который добавляет, удаляет, обновляет и / или считывает данные из нескольких таблиц в базе данных.
  • (Может реализовывать циклы и курсоры, которые позволяют вам работать с меньшими результатами или построчными операциями над данными.)
  • Должен быть вызван с помощью EXECили EXECUTEоператора.
  • Возвращает переменные таблицы, но мы не можем использовать OUTпараметр.
  • Поддерживает транзакции.

Функция:

  • Не может использоваться для обновления, удаления или добавления записей в базу данных.
  • Просто возвращает одно значение или табличное значение.
  • Может использоваться только для выбора записей. Однако его можно легко вызвать из стандартного SQL, например:

    SELECT dbo.functionname('Parameter1')

    или

    SELECT Name, dbo.Functionname('Parameter1') FROM sysObjects
  • Для простых многократных операций выбора функции могут упростить код. Просто будьте осторожны с использованием JOINпредложений в ваших функциях. Если в вашей функции есть JOINпредложение, и вы вызываете его из другого оператора select, который возвращает несколько результатов, этот вызов функции JOIN объединит эти таблицы для каждой строки, возвращенной в наборе результатов. Поэтому, хотя они могут быть полезны для упрощения некоторой логики, они также могут быть узким местом в производительности, если они не используются должным образом.

  • Возвращает значения с помощью OUTпараметра.
  • Не поддерживает транзакции.

8

Пользовательская функция.

  1. Функция должна возвращать значение.
  2. Позволит только операторы Select, это не позволит нам использовать операторы DML.
  3. Это позволит только входные параметры, не поддерживает выходные параметры.
  4. Это не позволит нам использовать блоки try-catch.
  5. Транзакции не разрешены внутри функций.
  6. Мы можем использовать только табличные переменные, это не позволит использовать временные таблицы.
  7. Хранимые процедуры не могут быть вызваны из функции.
  8. Функции можно вызывать из оператора select.
  9. UDF может использоваться в предложении соединения как набор результатов.

Хранимая процедура

  1. Хранимая процедура может возвращать или не возвращать значения.
  2. Может иметь операторы select, а также операторы DML, такие как вставка, обновление, удаление и т. Д.
  3. Может иметь как входные, так и выходные параметры.
  4. Для обработки исключений мы можем использовать блоки try catch.
  5. Можно использовать транзакции в рамках хранимых процедур.
  6. Можно использовать как переменные таблицы, так и временную таблицу в ней.
  7. Хранимые процедуры могут вызывать функции.
  8. Процедуры нельзя вызывать из операторов Select / Где / Имея и т. Д. Оператор Execute / Exec может использоваться для вызова / выполнения хранимой процедуры.
  9. Процедуры не могут быть использованы в предложении Join

6

Чтобы решить, когда использовать то, что могут помочь следующие пункты:

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

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

ура


6

Функции SQL Server, такие как курсоры, предназначены для использования в качестве вашего последнего оружия! У них действительно есть проблемы с производительностью, и поэтому следует избегать использования табличных функций. Говоря о производительности, мы говорим о таблице с более чем 1 000 000 записей, размещенных на сервере на оборудовании среднего класса; в противном случае вам не нужно беспокоиться о падении производительности, вызванном функциями.

  1. Никогда не используйте функцию для возврата набора результатов во внешний код (например, ADO.Net).
  2. Максимально используйте комбинацию представлений и сохраненных процедур. вы можете справиться с будущими проблемами роста производительности, используя рекомендации, которые DTA (Database Tuning Adviser) даст вам (например, индексированные представления и статистика) - иногда!

для дальнейшей ссылки см .: http://databases.aspfaq.com/database/should-i-use-a-view-a-stored-procedure-or-a-user-defined-function.html


1
Спасибо. Написал сегодня функцию для вызова в запросе, чтобы заполнить значения для одного столбца. Execute побежал более 3 минут, прежде чем я остановил его. Выяснил, как присоединиться к этому. Выполнение завершено за 15 секунд. (Набор данных был 3456 строк). Отличная производительность
VISQL

редактирование: выполнение завершается между 15 и 50 секундами в зависимости от того, какой столбец I «ЗАКАЗАТЬ ПО» (набор данных был 3456 строк). Большая разница в производительности.
VISQL

Разница в производительности может иметь корни в разных типах столбцов, по которым вы упорядочиваете результат. SQL Server гораздо лучше работает с числами, чем с символьными данными. Вы можете использовать DTA для этого 50-секундного запроса и посмотреть, сможет ли он предложить какие-то статистические / индексные предложения, чтобы запрос выполнялся немного быстрее.
Ахиллес

1
Я не уверен, что было предоставлено достаточно доказательств, чтобы сказать, что это должно быть последним средством. Вы можете думать о функции как о параметризованном представлении, которым можно в дальнейшем управлять. Например, вы хотите присоединить клиентов к заказам, но только для Мичигана. Вы создаете функцию customerOrders (@StateCode), которая присоединяется только к значению клиента в одном состоянии. Затем я могу работать с этим набором следующим образом: Выбрать FirstName, LastName, OrderTotal, StoreName From CustomerOrders ('MI') INNER JOIN Stores ON Stores.StoreID = Orders.StoreID WHERE OrderTotal> 100; Это будет проблемой для SP, так как вы должны временно копировать.
MPavlak

Сколько записей у вас в этой таблице? Если ваше оборудование справится с этим правильно, вам не придется беспокоиться о выборе оружия. Ложка может сделать работу, когда достаточно трудно сломать меч; эта твердость называется ТС!
Ахилл

3

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

Затем вы можете использовать функцию для параметризованного списка городов. dbo.GetCitiesIn ("NY") Возвращает таблицу, которую можно использовать как объединение.

Это способ организации кода. Знание того, когда что-то можно использовать повторно, а когда это пустая трата времени, приобретается только путем проб, ошибок и опыта.

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


3

Вот практическая причина предпочесть функции хранимым процедурам. Если у вас есть хранимая процедура, которой нужны результаты другой хранимой процедуры, вы должны использовать оператор insert-exec. Это означает, что вам нужно создать временную таблицу и использовать execинструкцию для вставки результатов хранимой процедуры в временную таблицу. Это грязно. Одна проблема с этим состоит в том, что вставка-execs не может быть вложенной .

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

( это еще одна причина, по которой мы должны хранить бизнес-логику вне базы данных )


2
  • Функция обязательно должна возвращать значение, пока оно не для хранимой процедуры.
  • Выберите операторы, принятые только в UDF, тогда как операторы DML не требуются.
  • Хранимая процедура принимает любые операторы, а также операторы DML.
  • UDF допускает только входы, а не выходы.
  • Хранимая процедура учитывает как входы, так и выходы.
  • Блоки захвата не могут использоваться в UDF, но могут использоваться в хранимых процедурах.
  • В функциях UDF не допускаются транзакции, но в хранимых процедурах они разрешены.
  • В UDF могут использоваться только табличные переменные, а не временные таблицы.
  • Хранимая процедура допускает как табличные переменные, так и временные таблицы.
  • UDF не позволяет хранимым процедурам вызываться из функций, в то время как хранимые процедуры позволяют вызывать функции.
  • UDF используется в предложении соединения, в то время как хранимые процедуры не могут использоваться в предложении соединения.
  • Хранимая процедура всегда позволит вернуться к нулю. У UDF, напротив, есть ценности, которые должны вернуться к заданной точке.

1
  • Функции могут использоваться в операторе выбора, тогда как процедуры не могут.

  • Хранимая процедура принимает как входные, так и выходные параметры, но функции принимают только входные параметры.

  • Функции не могут возвращать значения типа text, ntext, image & timestamps там, где это могут сделать процедуры.

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

*** Например: -create table <tablename>(name varchar(10),salary getsal(name))

Здесь getsal - это пользовательская функция, которая возвращает тип заработной платы, когда при создании таблицы не выделяется память для типа зарплаты, и функция getsal также не выполняется, но когда мы выбираем некоторые значения из этой таблицы, функция getal get выполняется и Возвращаемый тип возвращается как набор результатов.


1

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

Функции могут быть ...

  1. Скалярное:

    CREATE FUNCTION ... RETURNS scalar_type AS BEGIN ... END

  2. Таблица с несколькими утверждениями

    CREATE FUNCTION ... RETURNS @r TABLE(...) AS BEGIN ... END

  3. Встроенное табличное значение:

    CREATE FUNCTION ... RETURNS TABLE AS RETURN SELECT ...

Третий вид (встроенное табличное значение) обрабатывается оптимизатором запросов по существу как (параметризованные) представления, что означает, что ссылка на функцию из вашего запроса аналогична вставке копии тела SQL функции (без фактического вставки копирования), что приводит к к следующим преимуществам:

  • Планировщик запросов может оптимизировать выполнение встроенной функции так же, как и любой другой подзапрос (например, исключить неиспользуемые столбцы, выдвинуть предикаты вниз, выбрать различные стратегии JOIN и т. Д.).
  • Комбинирование нескольких встроенных функций не требует материализации результата от первого до передачи его следующему.

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


ПРИМЕЧАНИЕ. Похоже, что в SQL Server 2019 также будет введена некоторая форма скалярного встраивания .


-2

В SQL Server функции и хранимые процедуры представляют собой два разных типа объектов.

Функция: В базе данных SQL Server функции используются для выполнения некоторых действий, и действие немедленно возвращает результат. Функции бывают двух типов:

  1. Система определена

  2. Определяемые пользователем

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

  1. Системные хранимые процедуры
  2. Пользовательские процедуры
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.