Компонент TFDStoredProc

Самые частые заблуждения при использовании TFDStoredProc
Начинающие разработчики ошибочно воспринимают TFDStoredProc как универсальную замену TFDQuery для вызова хранимых процедур. На деле это узкоспециализированный инструмент, и его слепое применение «на все случаи» — путь к потере контроля над результатами. Я обращаю внимание: наибольшие проблемы возникают, когда программист забывает, что поведение компонента сильно зависит от СУБД за фасадом FireDAC.
- Заблуждение 1: «Мне нужны выходные параметры, значит — только TFDStoredProc». На практике, если процедура возвращает один простой набор данных (SELECT), TFDQuery с
ExecSQLзачастую эффективнее и прозрачнее в отладке. - Заблуждение 2: «Всегда нужно устанавливать
StoredProcNameявно». Профессионалы знают: FireDAC умеет подтягивать метаданные о параметрах процедуры автоматически через свойствоFetchOptions.Items(режимfiMeta). Если вы каждый раз вручную задаёте параметры, вы теряете время и вносите риск рассинхронизации с реальной сигнатурой процедуры. - Заблуждение 3: «Свойство
ParamBindMode— техническая деталь, не влияет на логику». Катастрофическая ошибка: по умолчаниюpbByName, но если процедура перегружена (overloaded) именами параметров с разными типами — FireDAC начнёт путаться. Я рекомендую в таких случаях переключаться наpbByNumberи жёстко следить за порядком объявления аргументов.
Неочевидные настройки и «молчаливые» глюки
Когда я вижу в коде TFDStoredProc без настройки ResourceOptions.ParamCreate и MacroCreate, сразу понимаю: разработчик никогда не сталкивался с ситуацией, когда процедура на сервере менялась, а клиент об этом «не знал». FireDAC кэширует метаданные, и если не принудить его перечитывать параметры — получите „Parameter 'X' not found“ при следующем вызове. Совет: для критичных участков используйте ADStoredProc.ParamCreate := False; и явно задавайте Params через коллекцию — это даёт полный контроль.
Ещё один нюанс — работа с возвращаемыми наборами данных через Open vs ExecProc. Новички забывают, что TFDStoredProc наследует от TFDDataSet, и базовая команда .Open срабатывает, даже если процедура не возвращает курсор. Результат — зависание интерфейса или выброс исключения „Cannot open a non-cursor-based stored procedure“. Профессионалы всегда проверяют: if ADStoredProc.IsSelect then ADStoredProc.Open else ADStoredProc.ExecProc;.
Советы эксперта: контроль над памятью и потоками
- Транзакции и автообновление параметров. В FireDAC есть скрытая оптимизация — если вы используете
TFDTransactionсOptions.AutoCommit, после вызоваExecProcпараметры со статусомpdInputOutputсбрасываются автоматически. Это приводит к потере значений, если процедура модифицируетINOUTпеременные. Решение: всегда явно копируйте значения изParamsдо закрытия соединения. - Производительность при пакетных вызовах. Забудьте про цикл
for i := 1 to 1000 do StoredProc.ExecProc;. ИспользуйтеTFDStoredProc.Params.ArraySizeи методExecProc(1, true)с флагомAParamsArraySize. Это превращает последовательные запросы в один пакетный вызов — прирост скорости на SQL Server и PostgreSQL до 20 раз. - Метаданные vs реальность. Никогда не полагайтесь на
FieldDefsдо вызоваOpenилиExecProc. Баги с неверной типизацией полей (например,ftWideStringвместоftString) в FireDAC — следствие того, что СУБД не всегда отдаёт полную метаинформацию до выполнения. ВызовStoredProc.Active := False; StoredProc.Prepare;принудительно обновляет метаданные, но это медленная операция — кэшируйте ее при инициализации модуля.
Специфика для разных СУБД: то, о чём молчат документации
Вот где скрываются настоящие грабли. Разработчики часто пишут код «универсально», и при переключении с MSSQL на PostgreSQL — получают странные ошибки.
- InterBase/Firebird: Тип возврата через
RETURNSв FireDAC транслируется как отдельный набор данных, а не как выходной параметр. Если процедура имеетOUTпараметры и курсор — используйтеFetchOptions.Mode := fmOneRecordдля оптимизации. - Oracle: Частая ошибка — привязка к ref cursor. FireDAC требует явного указания
StoredProc.CommandKind := skStoredProcWithResult, иначе компонент не увидит курсор, а вернёт только скалярные параметры. Дополнительно: всегда выставляйтеResourceOptions.MacroCreate := False— макросы взаимодействуют с PL/SQL конфликтуют с ref cursor. - MSSQL: Вложенные процедуры с
WITH RECOMPILEприводят к тому, что FireDAC игнорирует свойствоPreparedи каждый раз заново парсит метаданные. Оптимальный способ: кешировать параметры вручную и обходить вызовPrepare.
Итоговый профессиональный совет: TFDStoredProc — мощный, но капризный инструмент. Не используйте его как «чёрный ящик». Всегда тестируйте на целевой СУБД с реальными данными, отключайте автоматическое управление параметрами, где это критично, и помните: в 70% случаев TFDQuery с явным SQL даёт больше предсказуемости, а TFDStoredProc оправдан лишь тогда, когда структура процедуры меняется динамически или требуется глубокое использование специфики СУБД (например, временные таблицы внутри процедуры).
Добавлено: 27.04.2026
