При работе с Delphi 7 и SQL Server 2008 разработчики могут столкнуться с проблемой, когда хранимая процедура не принимает значение по умолчанию, если параметр не был передан из Delphi. В данном случае, если параметр не задан явно, SQL Server получает явное значение NULL, что не позволяет использовать значение по умолчанию, определенное в хранимой процедуре.
Описание проблемы
Рассмотрим пример создания таблицы и хранимой процедуры в SQL Server:
CREATE TABLE [dbo].[Persons]
(
[P_ID] [int] IDENTITY(1,1) NOT NULL,
[LastName] [varchar](255) NOT NULL
)
CREATE PROCEDURE [dbo].[p_dummy_proc]
@p_id int,
@p_name VARCHAR(10) = 'dummy'
AS
BEGIN
IF (@p_name is null)
RAISERROR 123456 'why are you null'
ELSE
INSERT INTO dbo.persons(LastName)
VALUES(@p_name)
END
При вызове этой процедуры из Delphi через компонент TADOStoredProc, не передавая второй параметр, ожидается, что SQL Server использует значение по умолчанию. Однако, в коде Delphi параметр @p_name не задается явно, и при выполнении хранимой процедуры происходит ошибка с сообщением "why are you null".
procedure TForm1.Button1Click(Sender: TObject);
begin
try
ADOStoredProc1.Parameters.ParamByName('@p_id').Value := 10;
ADOStoredProc1.ExecProc; // ошибка, так как SQL Server получает NULL
except
on E: EDatabaseError do
ShowMessage(e.Message);
end;
end;
Подтвержденный ответ
Чтобы использовать значение по умолчанию для параметра хранимой процедуры, необходимо явно сбросить значение параметра в Delphi. Это можно сделать, установив свойство ParameterObject.Value в Unassigned:
if UseDefaultParameter then
ADOStoredProc1.Parameters.ParamByName('@p_name').ParameterObject.Value := Unassigned
else
ADOStoredProc1.Parameters.ParamByName('@p_name').Value := 'значение параметра';
Такой подход позволяет SQL Server использовать значение по умолчанию, определенное в хранимой процедуре.
Альтернативные решения
Удаление параметра в runtime, если необходимо использовать значение по умолчанию. Это может быть неудобно, если параметров много.
Создание TADOStoredProc в runtime, назначение параметров, выполнение и последующее уничтожение объекта. Это более гибкий подход, но требует больше кода.
Использование метода Parameters.Refresh(), который создаст параметры на основе информации из SQL Server. Это удобно для поддержки, но требует дополнительного запроса к базе данных.
Явное создание параметров в runtime, если они не были созданы в дизайнере.
Выводы
Для корректного использования значения по умолчанию в хранимой процедуре SQL Server, необходимо правильно обрабатывать параметры в Delphi. Использование свойства ParameterObject.Value с значением Unassigned позволяет достичь желаемого результата.
При использовании Delphi 7 и SQL Server 2008 возникает проблема с корректным применением значения по умолчанию для параметров хранимой процедуры, если параметр не был передан из приложения, в результате чего SQL Server получает NULL и
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS