Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > БД в Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 07.06.2017, 10:53   #1
artemavd
Старожил
 
Аватар для artemavd
 
Регистрация: 05.06.2008
Сообщений: 4,194
Вопрос Передача параметров в хранимую процедуру в MS SQL

Добрый день!
Сто лет ничего не писал.
Изучаю работу с MS SQL из Delphi через dbGo (ADO).
Есть хранимая процедура на сервере MS SQL:
Код:
USE [db1023802552531]
GO
/****** Object:  StoredProcedure [dbo].[InsertNewAddress]    Script Date: 07.06.2017 12:18:44 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[InsertNewAddress] (
	-- Add the parameters for the stored procedure here
	@A_STATUS	 int, 
	@A_CITY		 varchar(50),
	@A_AREA		 varchar(100),
	@A_STREET	 varchar(50),
	@A_HOUSE	 int,
	@A_APARTMENT varchar(50),
	@A_INDEX	 varchar(6),
	@A_STRUCTURE varchar(50),
	@A_COUNTRY	 varchar(50)
)	
AS
BEGIN
	-- SET NOCOUNT ON added to prevent extra result sets from
	-- interfering with SELECT statements.
	SET NOCOUNT ON;

    -- Insert statements for procedure here
	INSERT INTO dbo.Addresses (
							   A_STATUS,
							   A_CITY,
							   A_AREA,
							   A_STREET,
							   A_HOUSE,
							   A_APARTMENT,
							   A_INDEX,
							   A_STRUCTURE,
							   A_COUNTRY)
							   VALUES (
									   @A_STATUS,
									   @A_CITY,
									   @A_AREA,
									   @A_STREET,
									   @A_HOUSE,
									   @A_APARTMENT,
									   @A_INDEX,
									   @A_STRUCTURE,
									   @A_COUNTRY)

END
Вызываю и обращаюсь к ней из клиентского приложения так:
Код:
begin
 with DM.ADOStoredProc do
 begin
  Active:=False;
  Parameters.Clear;
  ProcedureName:='[dbo].[InsertNewAddress]';
  Active:=True;
  Parameters.ParamByName('@A_COUNTRY').Value:=Trim(FormAddresses.Country.Text);
  Parameters.ParamByName('@A_CITY').Value:=Trim(FormAddresses.City.Text);
  Parameters.ParamByName('@A_AREA').Value:=Trim(FormAddresses.Area.Text);
  Parameters.ParamByName('@A_HOUSE').Value:=Trim(FormAddresses.House.Text);
  Parameters.ParamByName('@A_APARTMENT').Value:=Trim(FormAddresses.Apartment.Text);
  Parameters.ParamByName('@A_INDEX').Value:=Trim(FormAddresses.PostIndex.Text);
  Parameters.ParamByName('@A_STRUCTURE').Value:=Trim(FormAddresses.Structure.Text);
  Parameters.ParamByName('@A_STATUS').Value:=1;
  Parameters.ParamByName('@A_STREET').Value:=Trim(FormAddresses.Street.Text);
  ExecProc;
 end;
end;
Но получаю ошибку (см.вложение).
Прошу помощи.
Изображения
Тип файла: png Безымянный.png (6.8 Кб, 182 просмотров)
Не стоит смеяться над человеком делающим шаг назад, возможно он делает разбег.
artemavd вне форума Ответить с цитированием
Старый 07.06.2017, 11:07   #2
Sciv
Старожил
 
Аватар для Sciv
 
Регистрация: 16.05.2012
Сообщений: 3,211
По умолчанию

Помнится, были у меня Адские наброски на работу с параметрами ХП:

Код:
// Получение количества параметров хранимой процедуры
function GetParamCount(ConnectID: TADOConnection; ProcedureName: string): integer;
var
  StoredProc: TADOStoredProc;

begin

  if ConnectID.Connected then
  begin

    Result := -1;
    StoredProc := nil;
    StoredProc := TADOStoredProc.Create(nil);

    try

      StoredProc.ProcedureName := ProcedureName;
      StoredProc.Connection := ConnectID;
      StoredProc.Parameters.Refresh;

      Result := StoredProc.Parameters.Count;

    finally

      FreeAndNil(StoredProc);

    end;

  end;

end; // GetParamCount
Код:
// Заполнение именами параметров массива TStoredProcParamsArray
procedure SetParamNamesAndDirections(ConnectID: TADOConnection; ProcedureName: string; var Params: TStoredProcParamsArray);
var
  StoredProc: TADOStoredProc;
  i: Integer;

begin

  if ConnectID.Connected then
  begin

    StoredProc := nil;
    StoredProc := TADOStoredProc.Create(nil);

    try

      StoredProc.ProcedureName := ProcedureName;
      StoredProc.Connection := ConnectID;
      StoredProc.Parameters.Refresh;

      SetLength(Params, GetParamCount(ConnectID, ProcedureName));

      for i := 0 to GetParamCount(ConnectID, ProcedureName) - 1 do
      begin

        Params[i].ParamName := StoredProc.Parameters[i].Name;

        // Все параметры с директивой pdInputOutput приравниваем к pdOutput
        // Непонятно, в чём причина, но в pdInputOutput значения из хранимки не возвращаются
        if StoredProc.Parameters[i].Direction = pdInputOutput then
        begin

          Params[i].ParamDirection := pdOutput

        end
        else
        begin

          Params[i].ParamDirection := StoredProc.Parameters[i].Direction;

        end;

      end;

    finally

      FreeAndNil(StoredProc);

    end;

  end;

end; // SetParamNamesAndDirections

Код:
// Запуск хранимой процедуры
procedure ExecStoredProcedure(ConnectID: TADOConnection; ProcedureName: string; var Params: TStoredProcParamsArray);
var
  StoredProc: TADOStoredProc;
  i: Integer;

begin

  if ConnectID.Connected then
  begin

    StoredProc := nil;
    StoredProc := TADOStoredProc.Create(nil);

    try

      StoredProc.ProcedureName := ProcedureName;
      StoredProc.Connection := ConnectID;
      StoredProc.Prepared := True;
      StoredProc.Parameters.Refresh;

      // Заполняем значения параметров INPUT
      // По умолчанию параметр №0 - @RETURN_VALUE
      for i := 0 to Length(Params) - 1 do
      begin

        StoredProc.Parameters.ParamByName(Params[i].ParamName).Value := Params[i].ParamValue;

      end;

      StoredProc.ExecProc();

      // Получаем значения параметров после выполнения процедуры, чтобы получить OUTPUT
      for i := 0 to Length(Params) - 1 do
      begin

        if Params[i].ParamDirection = pdOutput then
        begin

          Params[i].ParamValue := StoredProc.Parameters.ParamByName(Params[i].ParamName).Value;

        end;

      end;

    finally

      FreeAndNil(StoredProc);

    end;

  end;

end; // ExecStoredProcedure
Ну и для полноты картины, чтоб было понятно, чего за массив я там заполняю:

Код:
type
  // Структура - описание параметра для ХП
  // ParamName - имя параметра
  // ParamValue - значение параметра
  // ParamDirection - определяет, входной или выходной. По умаолчанию - pdInput.
  TStoredProcParam = record
                       ParamName: string;
                       ParamValue: Variant;
                       ParamDirection: TParameterDirection;
                     end;

  // Тип - массив записей параметров для ХП
  TStoredProcParamsArray = array of TStoredProcParam;
Начал решать проблему с помощью регулярных выражений. Теперь решаю две проблемы...

Последний раз редактировалось Sciv; 07.06.2017 в 11:58.
Sciv вне форума Ответить с цитированием
Старый 07.06.2017, 11:12   #3
Serge_Bliznykov
Старожил
 
Регистрация: 09.01.2008
Сообщений: 26,238
По умолчанию

сначала попробуйте убрать
Код:
Parameters.Clear;
а потом так:
Код:
Parameters.ParamValues['@A_COUNTRY'] := Trim(FormAddresses.Country.Text);
впрочем, должно и через Parameters.ParamByName() работать...

а Вы не забыли в дизайн-тайм добавить параметры в запрос?


пока собирался написать, уже ответили...

Последний раз редактировалось Serge_Bliznykov; 07.06.2017 в 11:16.
Serge_Bliznykov вне форума Ответить с цитированием
Старый 07.06.2017, 11:14   #4
Sciv
Старожил
 
Аватар для Sciv
 
Регистрация: 16.05.2012
Сообщений: 3,211
По умолчанию

Цитата:
Сообщение от Serge_Bliznykov Посмотреть сообщение
сначала попробуйте убрать
И написать вместо ней Parameters.Refresh
Начал решать проблему с помощью регулярных выражений. Теперь решаю две проблемы...
Sciv вне форума Ответить с цитированием
Старый 07.06.2017, 11:17   #5
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 19,042
По умолчанию

Цитата:
Active:=True;
Не нужно
Цитата:
Parameters.ParamByName('@A_HOUSE'). Value:=Trim(FormAddresses.House.Tex t);
числовой параметр, чего туда строку присваивать?
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Аватар вне форума Ответить с цитированием
Старый 08.06.2017, 06:49   #6
artemavd
Старожил
 
Аватар для artemavd
 
Регистрация: 05.06.2008
Сообщений: 4,194
По умолчанию

Братья!
Спасибо! Заработало!
Теперь у меня вопрос: как лучше всего переоткрыть набор данных, чтобы это было быстрее и правильнее с точки зрения реализации?
Получился такой код:
Код:
 with DM.ADOStoredProc do
 begin
  Active:=False;
  ProcedureName:='[dbo].[InsertNewAddress]';
  Parameters.Refresh;
  Parameters.ParamValues['@A_COUNTRY']:=Trim(FormAddresses.Country.Text);
  Parameters.ParamValues['@A_CITY']:=Trim(FormAddresses.City.Text);
  Parameters.ParamValues['@A_AREA']:=Trim(FormAddresses.Area.Text);
  Parameters.ParamValues['@A_HOUSE']:=Trim(FormAddresses.House.Text);
  Parameters.ParamValues['@A_APARTMENT']:=Trim(FormAddresses.Apartment.Text);
  Parameters.ParamValues['@A_INDEX']:=Trim(FormAddresses.PostIndex.Text);
  Parameters.ParamValues['@A_STRUCTURE']:=Trim(FormAddresses.Structure.Text);
  Parameters.ParamValues['@A_STATUS']:=1;
  Parameters.ParamValues['@A_STREET']:=Trim(FormAddresses.Street.Text);
  ExecProc;
 end;
 DM.ADOStoredProc.ProcedureName:='[dbo].[ReopenListAddresses]';
 DM.ADOStoredProc.Active:=True;
 DM.ADOStoredProc.ExecProc;
 DM.ADOStoredProc.Refresh;
 FormAddresses.sRollOutPanel1.Hide;
 FormAddresses.AddAddress.Enabled:=True;
 FormAddresses.DBGridEh1.Enabled:=True;
Но, чувствую, что можно проще и правильнее сделать.
Не стоит смеяться над человеком делающим шаг назад, возможно он делает разбег.
artemavd вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Не могу переделать хранимую процедуру Zicise Общие вопросы .NET 1 06.11.2014 18:09
Добавление пользователя через хранимую процедуру Muramidaza БД в Delphi 2 18.03.2014 22:41
Delphi. Передача параметров в процедуру *stRong* Помощь студентам 1 30.05.2012 19:15
ПЕРЕДАЧА МАССИВА В ПРОЦЕДУРУ ЧЕРЕЗ СПИСОК ФОРМАЛЬНЫХ ПАРАМЕТРОВ. sifa Помощь студентам 1 29.11.2011 22:13
добавление через хранимую процедуру пауэрлифтинг БД в Delphi 2 27.05.2010 16:21