Все три компании, в которых я работаю, использовали хранимые процедуры для своей логики приложения с SQL Server. Я не видел вещи по-другому. Но для меня они большой беспорядок. Как правило, не очень хорошие средства обработки ошибок или средства повторного использования кода с хранимыми процедурами.
Допустим, у вас есть хранимая процедура, которая возвращает набор данных, который вы хотите использовать, как вы можете использовать его в будущих хранимых процедурах? Механизмы на SQL Server для этого не очень хороши. EXEC INTO ... работает только на один или два уровня вложенности (я забыл сейчас). Или вы должны предварительно определить рабочую таблицу и настроить ее обработку. Или вам нужно предварительно создать временную таблицу и заполнить ее процедурой. Но что, если два человека называют временную таблицу одним и тем же в двух разных процедурах, которые они никогда не планировали использовать одновременно? На любом обычном языке программирования вы можете просто вернуть массив из функции или указать на объект / глобальную структуру, совместно используемую между ними (за исключением функциональных языков, где вы должны вернуть структуру данных, а не просто изменить глобальную структуру ... )
Как насчет повторного использования кода? Если вы начнете помещать общие выражения в UDF (или, что еще хуже, в подзапросы), вы замедляете выполнение кода. Вы не можете вызвать хранимую процедуру, чтобы выполнить вычисление для столбца (если только вы не используете курсор, передайте значения столбца одно за другим, а затем каким-то образом обновите свой набор таблиц / данных). Таким образом, чтобы получить максимальную производительность, вам нужно вырезать / вставлять общие выражения повсеместно, что является кошмаром обслуживания ... С помощью языка программирования вы можете создать функцию для генерации общего SQL, а затем вызывать ее из любого места при сборке. строка SQL. Тогда, если вам нужно изменить формулу, вы можете внести изменения в одном месте ...
Как насчет обработки ошибок? SQL Server имеет много ошибок, которые немедленно останавливают выполнение хранимой процедуры, а некоторые даже приводят к отключению. С 2005 года есть try / catch, но все еще есть ряд ошибок, которые не могут быть обнаружены. Также происходит то же самое с дублированием кода в коде обработки ошибок, и вы действительно не можете передавать исключения так же легко, как это происходит с большинством языков программирования .....
Также просто скорость. Многие операции над наборами данных не ориентированы на SET. Если вы попытаетесь сделать что-то ориентированное на строки, вы либо будете использовать курсор, либо вы будете использовать «курсор» (когда разработчики часто запрашивают каждую строку одну за другой и сохраняют содержимое в переменные @ точно так же, как курсор. ..Даже это часто медленнее, чем курсор FORWARD_ONLY). С SQL Server 2000 у меня было что-то, что работало в течение 1 часа, прежде чем я убил это. Я переписал этот код на Perl, и он закончился через 20 минут. Когда язык сценариев, который в 20-80 раз медленнее, чем С, курит производительность SQL, у вас точно не будет бизнес-написания операций, ориентированных на строки, в SQL.
Теперь SQL Server имеет интеграцию с CLR, и многие из этих проблем исчезают, если вы используете хранимые процедуры CLR. Но многие администраторы баз данных не знают, как писать .NET-программы или отключать CLR из-за проблем безопасности и придерживаются Transact SQL .... Также даже с CLR у вас все еще остаются проблемы совместного использования данных между несколькими процедурами эффективным способом. ,
Кроме того, в общем, сложнее всего масштабировать базу данных. Если вся ваша бизнес-логика находится в базе данных, то когда база данных станет слишком медленной, у вас возникнут проблемы. Если у вас есть бизнес-уровень, вы можете просто добавить больше кэширования и больше бизнес-серверов для повышения производительности. Традиционно другой сервер для установки Windows / Linux и запуска .NET / Java гораздо дешевле, чем покупка другого сервера базы данных и лицензирование большего количества SQL Server. SQL Server теперь имеет большую поддержку кластеризации, хотя изначально у него не было никакой поддержки. Поэтому, если у вас много денег, вы можете добавить кластеризацию или даже сделать доставку журналов, чтобы сделать несколько копий только для чтения. Но в целом это будет стоить намного больше, чем просто кеширование с записью или что-то в этом роде.
Также посмотрите на средства Transact-SQL. Манипулирование строкой? Я возьму классы Java String Class / Tokenizer / Scanner / Regex в любой день. Хеш-таблицы / связанные списки / и т.д. Я возьму фреймворки Java Collection и т. Д. ... И то же самое для .NET ... И C #, и Java гораздо более развитые языки, чем Transact SQL ... Хек-кодирование с Transact-SQL заставляет меня ревновать к C ... ,
Кроме того, хранимые процедуры более эффективны для работы с большим набором данных и применения нескольких запросов / критериев для его сокращения перед возвратом на бизнес-уровень. Если вам нужно отправить кучу огромных наборов данных клиентскому приложению и разбить данные на клиенте, это будет гораздо более неэффективно, чем просто выполнение всей работы на сервере.
Также хранимые процедуры хороши для безопасности. Вы можете отключить весь доступ к базовым таблицам и разрешить доступ только через хранимые процедуры. С некоторыми современными методами, такими как XML, вы можете иметь хранимые процедуры, которые выполняют пакетные обновления. Затем весь доступ контролируется с помощью хранимых процедур, так что пока они безопасны / корректны, данные могут быть более целостными.
Аргумент SQL-инъекций больше не применяется, поскольку у нас есть параметризованные запросы на стороне языка программирования. Кроме того, даже раньше, чем параметризованные запросы, небольшая замена ("'", "' '") также работала большую часть времени (хотя есть еще приемы, позволяющие пройти через конец строки, чтобы получить то, что вы хотите).
В целом, я думаю, что SQL и Transact SQL - отличные языки для запроса / обновления данных. Но для кодирования любого типа логики, выполнения строковых манипуляций (или манипуляций с чертовым файлом ... вы удивитесь тому, что вы можете сделать с помощью xp_cmdshell ....), пожалуйста, нет. Я надеюсь найти будущее место, где в основном не используются хранимые процедуры. С точки зрения ремонтопригодности кода это кошмар. Кроме того, что произойдет, если вы захотите сменить платформу (хотя на самом деле, если вы заплатили за Oracle / DB2 / Sybase / Sql Server / и т. Д., Вы также можете получить от них все, что можете, используя каждое проприетарное расширение, которое вам поможет. ..).
Также на удивление часто бизнес-логика не одинакова. В идеальном мире вы должны поместить всю логику в хранимые процедуры и разделить ее между приложениями. Но довольно часто логика различается в зависимости от приложений, и ваши хранимые процедуры становятся слишком сложными монолитами, которые люди боятся изменить и не понимают всех последствий. В то время как с хорошим объектно-ориентированным языком вы можете кодировать слой доступа к данным, который имеет некоторые стандартные интерфейсы / перехватчики, которые каждое приложение может переопределять для своих собственных нужд.