Имя: Пароль:
1C
1С v8
Подскажите по хранимым процедурам через ADODB
0 Euroset1
 
23.03.18
12:48
База ORACLE
Умею вызывать хранимые функции, возвращающие обычный тип. Причем как через OUT параметр, так и через стандартный ретурн.

Сам заголовок функции для примера:
CREATE OR REPLACE FUNCTION BOSS.UPDATEDOC1C
  ( p_IO_ID IN BOSS.INVOICE.IO_ID%TYPE,
    p_Status IN BOSS.INVOICE.DOCOUT%TYPE )

  RETURN  NUMBER IS
       n_Id BOSS.INVOICE.ID%TYPE;
       n_Type  NUMBER(1);

А теперь код ее вызова, который работает:
                Команда                     = Новый COMОбъект("ADODB.Command");
                Команда.ActiveConnection      = Соединение;
                Команда.CommandText          = "boss.updatedoc1c";
                Команда.CommandType         = 4; // stored proc
                
                Парам1                        = Команда.CreateParameter("p_IO_ID", 4, 1);
                Парам2                        = Команда.CreateParameter("p_Status", 3, 1);
                Возвратка                     = Команда.CreateParameter("result", 4, 4);  // 4 тип - флоат сингл, 4 тип параметра - возвратка
                
                Команда.Parameters.Append(Возвратка);
                Команда.Parameters.Append(Парам1);
                Команда.Parameters.Append(Парам2);
                
                Парам1.Value                = Число(ГИД);
                Парам2.Value                = СтатусПодписания;
                
                Команда.Execute();
                
                Сообщить(Возвратка.Value = 0);

Как видите, несмотря на то, что возвратка не прописана как OUT параметр, но объявлять ее в параметрах все равно приходится (причем пофиг с каким именем...). И так все работает.

А мне нужно теперь из другой функции вернуть рекордсет (таблицу). Согласно статьи http://www.askit.ru/custom/vba_office/m9/09_06_ado_command.htm и где-то подобной статьи с самого Майкрософта, это сделать МОЖНО. Но вот как - фиг его знает, помогите плиз.

Проблемы, которые ловлю при разных попытках:
1) Если использую Parameters.Refresh(), то он почему-то не работает. Хотя все сделал к в документации, видно вопросы к провайдеру
2) Если вообще не описываю возвратку, то ругается при выполнении, что мол не найдена такая процедура (ясен пень, ведь это функция.). То есть он явно намекает, что возвратка должна быть описана
3) Пробовал разные типы для возвратки - ну не хочет, понятное дело. Ну нету там типа Recordset в перечне...
4) Кто-то скажет вместо StoredProc использовать SELECT * FROM TABLE(boss.updatedoc1c(444,11)), но увы, этот способ не работает с данной функцией, ибо она делает апдейты и оракл будет ругаться на такую попытку (если бы она чисто селектила, то без проблем конечно).

Как же мне всетаки получить этот несчастный рекордсет, используя StoredProc? Как задекларировать этот параметр возвратка вручную?
1 karabas11
 
23.03.18
13:01
А в чем вопрос? Так много текста, ничего понять нельзя.
2 Euroset1
 
23.03.18
13:07
(1) Желаемый результат - получить таблицу, возвращаемую хранимой оракловой функцией при помощи ADODB с параметром CommandType = 4 (StoredProc).
3 karabas11
 
23.03.18
13:15
(2) RecordSet = Command.Execute();
Неужто не работает?
4 Euroset1
 
23.03.18
13:49
(3) конечно не работает. Почему - я описал в "много текста".
5 karabas11
 
23.03.18
14:43
(4) Команда.CommandType         = 8; // а как обычный селект?
6 Euroset1
 
23.03.18
14:44
(5) "4) Кто-то скажет вместо StoredProc использовать SELECT * FROM TABLE(boss.updatedoc1c(444,11)), но увы, этот способ не работает с данной функцией, ибо она делает апдейты и оракл будет ругаться на такую попытку (если бы она чисто селектила, то без проблем конечно)."

Цитата из (0).
7 karabas11
 
23.03.18
15:46
(6) насколько я понял, вы сами в оракле пишете. Попробуйте не смешивать апдейт с селектом.

RETURN  NUMBER IS  - а не тут ли проблема? Хочется верить, что тут вместо намбера должна таблица возвращаться
https://oracle-base.com/articles/misc/pipelined-table-functions
8 Euroset1
 
23.03.18
15:55
(7) Я не пишу в оракле, просто есть определенные базовые возможности. Код оракловый просто стянул из девелопера. Там намбер стоит потому что функция из примера возвращает число и делает это хорошо. Я как раз акцентировал на том, что в таком виде она работает. А мне теперь нужно вместо намбера вернуть таблицу (уже другая функция).

TYPE GOODS_RECORD IS RECORD (
     IDCODE BOSS.GOODSDETAIL.IDCODE%TYPE,
     NAME BOSS.DEPOTS.NAME%TYPE,
     UNIT BOSS.GOODSDETAIL.UNIT%TYPE,
     RESERV BOSS.GOODSDETAIL.RESERV%TYPE,
     LAYPUT BOSS.GOODSDETAIL.LAYPUT%TYPE
    );

    TYPE GOODS_TABLE IS TABLE OF GOODS_RECORD;

FUNCTION GET_GOODS_LIST (
  ARTICUL_IN BOSS.CATALOGS.ARTICUL%TYPE, SUPPLIER_IN BOSS.CATALOGS.SUPPLIER%TYPE  
) RETURN GOODS_TABLE parallel_enable pipelined;
9 VitShvets
 
23.03.18
16:01
(0) Я, правда с MS-SQL, в таких случаях вместо ADODB.Command пользую ADODB.Recordset:
   RS = Новый COMОбъект("ADODB.Recordset");
   RS.ActiveConnection = Connection;
   RS.Open(ТекстЗапроса);
10 Euroset1
 
23.03.18
16:23
(9) рекордсет не позволяет выполнить хранимую процедуру или функцию напрямую - она только запрос дает выполнить. А мне в запросе нельзя, потому что на запрос с участием данной функции будет ругаться - она изменяет данные.
11 VitShvets
 
23.03.18
17:04
(10) Не правда. У меня нормально отрабатывает:
ТекстЗапроса = "SET DATEFORMAT ymd
     |DECLARE @StartDate datetime = #StartDate#
     |DECLARE @EndDate   datetime = #EndDate#
     | EXEC dbo.spGetMovements @StartDate, @EndDate";
12 VitShvets
 
23.03.18
17:08
(11) + к (12) И вот такое отрабатывает:
    |INSERT INTO
    |    ИмяТаблицы
    |    (Текст_INTO)
    |VALUES Текст_VALUES
    |
    |SELECT @@ROWCOUNT AS InsertCount
13 int32i
 
23.03.18
18:16
14 Euroset1
 
23.03.18
18:32
(13) cmd1.Parameters.Refresh у меня к сожалению не работает, о чем я писал выше. При попытке потом обратиться к параметрам вылезает ошибка выполнения, связанная с неправильным индексом. Каунт по коллекции параметров показывает ноль записей.
Причем в мануале написано, что рефреш не отрабатывает, если не задали соединение, тип команды или текст команды. У меня все это задано.
15 Euroset1
 
23.03.18
18:33
(12) Речь идет о хранимой функции, возвращающей таблицу после того, как она же выполняет в ней изменения.
16 Euroset1
 
23.03.18
18:35
(13) Причем самое интересное, что для не табличного возвратного параметра я нашел решение - я его просто объявил как аут параметр с произвольным именем. А как мне объявить вместо числа таблицу, учитывая дефицит типов, предлагаемых на выбор, непонятно.
17 VitShvets
 
23.03.18
18:57
(15) В (11) процедура как раз возвращает таблицу.
(16) Оракл я не щупал, а не разрешает он делать по принципу (12)? Скармливаешь АДО не одну команду, а последовательность. Последней командой выполняешь select, дабы получился нужный recorset. У сиквела работает.
18 Euroset1
 
23.03.18
22:23
(17) Касаемо (10), не должно работать для описанной мной функции. А именно: для такой функции, которая выполняет апдейт, а потом еще и возвращает таблицу. При попытке выполнить твой запрос оракл вывалит ошибку, что "нельзя использовать апдейт в селекте".

Касаемо замены одной команды пакетом - не выйдет. Дело в том, что функция призвана компенсировать тот факт, что !с-юзеру не хотят давать гранты даже на чтение. Именно поэтому идет переход на хранимки и вьюхи. Для этого мне и нужно вызывать хранимку именно как хранимку, а не как текст запроса.
19 Euroset1
 
24.03.18
15:10
Для оракла ведь тоже разные провайдеры бывают. Тот, что у меня, похоже менее функционален по хранимкам.
Oracle in OraClient11g_Home2 у меня ((
20 Euroset1
 
26.03.18
21:25
Может есть какие-то альтернативы ADODB?
21 VitShvets
 
26.03.18
22:19
(20) АДО в данном случае "шлюз" между 1С и СУБД. Что разрешает СУБД, то сможет 1С выполнить через. ИМХО, надо копать в написание такой хранимой процедуры на стороне СУБД, дабы "делала всё хорошо, возвращая нужный рекордсет". АДО это будет или иные способы взаимодействия с БД, ничего не изменится.
22 VitShvets
 
26.03.18
22:22
(20) Кстати, как совсем костыльный вариант, не возвращать в данном вызове RS, а писать в какую-нибудь общедоступную табличку типа "#MyTmpTable" или "##MyTmpTable". А затем, отдельным запросом, читать "MyTmpTable" с получением уже RS.
Есть два вида языков, одни постоянно ругают, а вторыми никто не пользуется.