Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Delphi Новый топик    Ответить
 ADO Command output параметры  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 9916
Есть простенькая процедура на Oracle
CREATE PROCEDURE SP_E_TEST(
   in_param IN NUMBER,
   out_param OUT NUMBER)
AS
BEGIN
  out_param := in_param + 10;
END;
Вызываю через ADOCommand
  ADOCommand1.CommandText := 'call sp_e_test(:in, :out)';
  ADOCommand1.Parameters.ParamByName('in').Value := 5;
  ADOCommand1.Parameters.ParamByName('out').Direction := pdOutput;
  ADOCommand1.Parameters.ParamByName('out').DataType := ftInteger;
  ADOCommand1.Execute;
  Msg(ADOCommand1.Parameters.ParamByName('out').Value);
все работает. Но не нравятся мне выделенные строки. Можно ли как-то их убрать и заставить клиента самому подтянуть метаданные по параметрам?

Вызов
ADOCommand1.Parameters.Refresh
приводит к полной очистке параметров, т.к. вызов
if OLEDBParameters.GetParameterInfo(ParamCount, PDBPARAMINFO(ParamInfo), @NamesBuffer) = S_OK then
в TParameters.InternalRefreshюRefreshFromOleDB возвращает 0x80040E51

Провайдер OraOLEDB.Oracle.1

С уважением, Vasilisk
17 ноя 17, 18:30    [20964657]     Ответить | Цитировать Сообщить модератору
 Re: ADO Command output параметры  [new]
Гаджимурадов Рустам
Member

Откуда:
Сообщений: 57686
ADOStoredProc не пробовал?

P.S. Не надо АДО для Оракла использовать.
Лучше старый DOA или AnyDAC возьми.

Posted via ActualForum NNTP Server 1.5

17 ноя 17, 19:25    [20964792]     Ответить | Цитировать Сообщить модератору
 Re: ADO Command output параметры  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 9916
Гаджимурадов Рустам
ADOStoredProc не пробовал?
Нет. Интересует именно ADOCommand.

В принципе можно достать все таким запросом
SELECT
  arg."ARGUMENT_NAME",
  arg."IN_OUT",
  arg."DATA_TYPE"
FROM
  sys.all_arguments arg
WHERE
  arg."OWNER" = :schema AND
  arg."OBJECT_NAME" LIKE UPPER(:name) AND
  arg."POSITION" > 0 
ORDER BY
  arg."POSITION"
но не вдохновляет
Гаджимурадов Рустам
P.S. Не надо АДО для Оракла использовать.
Так все плохо?
Гаджимурадов Рустам
Лучше старый DOA или AnyDAC возьми.
Сейчас интересует нечто бесплатное с поддержкой 12 оракла. Вполне вероятно, что впоследствии купим FireDAC.

Я понимаю, что с AnyDAC на FireDAC переползти легко. Но бесплатные версии жутко древние
17 ноя 17, 19:41    [20964822]     Ответить | Цитировать Сообщить модератору
 Re: ADO Command output параметры  [new]
Гаджимурадов Рустам
Member

Откуда:
Сообщений: 57686
_Vasilisk_> В принципе можно достать все таким запросом

Так первый вариант много лучше. Или ты хочешь свой патч делать?

> Так все плохо?

Я не слежу за их потугами, но AFAIU, ADO почти deprecated, нет
смысла связываться для новых проектов, тем более для 12 оракла.

Posted via ActualForum NNTP Server 1.5

17 ноя 17, 20:47    [20964939]     Ответить | Цитировать Сообщить модератору
 Re: ADO Command output параметры  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 9916
Гаджимурадов Рустам
ADO почти deprecated, нет
А на сайте оракла OraOLEDB свежий лежит.

Впрочем, я тебя услышал. Спасибо за инфу
17 ноя 17, 21:11    [20964966]     Ответить | Цитировать Сообщить модератору
 Re: ADO Command output параметры  [new]
Гаджимурадов Рустам
Member

Откуда:
Сообщений: 57686
> А на сайте оракла OraOLEDB свежий лежит.

Так ты OLEDB и Delphi-шные ADO не путай...
Впрочем, не настаиваю, работать с ней можно.
Но заполнение out-параметров - стандартный
подход, даже в .Net так делается.

Posted via ActualForum NNTP Server 1.5

17 ноя 17, 21:53    [20965026]     Ответить | Цитировать Сообщить модератору
 Re: ADO Command output параметры  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 9916
Подниму тему. Для будущих поколений.

_Vasilisk_
Вызов
ADOCommand1.Parameters.Refresh

приводит к полной очистке параметров, т.к. вызов
if OLEDBParameters.GetParameterInfo(ParamCount, PDBPARAMINFO(ParamInfo), @NamesBuffer) = S_OK then

в TParameters.InternalRefreshюRefreshFromOleDB возвращает 0x80040E51

function TParameters.InternalRefresh: Boolean;
  ...........
begin
  BeginUpdate;
  try
    Clear;
    if Command.CommandType = cmdText then
      RefreshFromOLEDB else
      RefreshFromADO;
    Result := Count > 0;
  finally
    EndUpdate;
  end;
end;
RefreshFromOLEDB, действительно не достает параметров. Но параметры достает RefreshFromADO. Чтобы она вызвалась нужно изменить CommandType с cmdText. Т.к. у нас процедура, то устанавливаем cmdStoredProc. Но тогда должен быть другой формат CommandText.

Итого для процедуры
_Vasilisk_
CREATE PROCEDURE SP_E_TEST(
   in_param IN NUMBER,
   out_param OUT NUMBER)

делаем так
ADOCommand1.CommandType = cmdStoredProc;
ADOCommand1.CommandText := 'SP_E_TEST';  // Вместо call sp_e_test(:in, :out) для CommandType = cmdText
ADOCommand1.Parameters.Refresh;  // Подгружаем типы и направления параметров
ADOCommand1.Parameters.ParamByName('in_param').Value := 5;  // Имена параметров поднимаются из базы
ADOCommand1.Execute;
Msg(ADOCommand1.Parameters.ParamByName('out_param').Value);

Все работает. Только нужно помнить, что имя процедуры должно быть записано в том же регистре, что и в базе, иначе ADOCommand1.Parameters.Refresh вываливается с сообщением
Project Project1.exe raised exception class EOleException with message 'Не удается найти текст сообщения с номером 0x80040e51 в файле сообщений OraOLEDB'.
для CommandType = cmdText регистр значения не имеет

А теперь отдельные грабли по возвращаемым строковым параметрам. У параметра есть свойство Size. Для CommandType = cmdText для всех параметров оно выставляется в -1. Для CommandType = cmdStoredProc после Parameters.Refresh оно выставляется в 0. Выполнение запроса (для любого CommandType) с выходными строковыми параметрами и установленных для них Size <= 0, получаем исключение
Project Project1.exe raised exception class EOleException with message 'Неправильно определен объект Parameter. Предоставлены несогласованные или неполные сведения'.
Если указать значение > 0, но меньше, чем длина возвращаемого значения, то для SQL типа CHAR возвращается NULL, а для VARCHAR значение обрезается до указанного числа символов. Если указать значение больше, чем длина возвращаемого значения, то для SQL типа CHAR значение добивается пробелами, а для VARCHAR возвращается как есть.
5 дек 17, 20:11    [21008661]     Ответить | Цитировать Сообщить модератору
 Re: ADO Command output параметры  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 9916
_Vasilisk_
Если указать значение > 0, но меньше, чем длина возвращаемого значения, то для SQL типа CHAR возвращается NULL,
Проверил. Оказалось не так. У меня в CHAR возвращается строковый GUID (38 символов). При Size < 300 возвращается NULL. При Size = 300 возвращается строка длиной 300 символов. 38 символов GUID и 300-38=262 пробелов
5 дек 17, 20:22    [21008684]     Ответить | Цитировать Сообщить модератору
 Re: ADO Command output параметры  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 9916
К слову
Гаджимурадов Рустам
ADOStoredProc не пробовал?
ADOStoredProc - это ADOCommand c CommandType = cmdStoredProc
5 дек 17, 20:44    [21008723]     Ответить | Цитировать Сообщить модератору
Все форумы / Delphi Ответить