Имя: Пароль:
1C
 
v8: Подскажите по ADO и хранимым процедурам SQL
0 Smallrat
 
08.06.11
09:38
Хочу выполнить хранимую процедуру и получить вовращаемое ей значение:
1 Axel2009
 
08.06.11
09:39
действуй
2 Rie
 
08.06.11
09:40
(0) А в чём проблема-то? Всё тот же Execute...
3 Smallrat
 
08.06.11
09:41
мля - случайно нажал отправить.
---
Хочу имитировать вызов процедуры которую выловил профайлером:
такой вот текст:

begin
 set nocount on
 declare @r int
 exec @r = PayBill
   @BillCod      = 0,
----кучи параметров
 set nocount off
   select res = @r
end
будучи запущенным как скрипт оно возвращет числовое значение в res
4 philll
 
08.06.11
09:42
Connection = Новый COMObject("ADODB.connection");
   
   НаборЗаписей=Новый   COMObject("ADODB.recordset");
   
   ConnectionString ="Provider=SQLOLEDB.1;Password=159357;Persist Security Info=True;User ID=User1C;Initial Catalog=HService_New;Data Source=192.168.10.100";//    
   
   
   Connection.ConnectionTimeOut =6000;
   Connection.CommandTimeout   =6000;
   Connection.CursorLocation = 3;
   
   Connection.Open(ConnectionString);



Текст      ="p1C_Order_SaleServiceGet NULL, "+UID+", '"+договор+"'        
               
   Если ОС<>0 тогда                    
   Попытка    
               
               
                               
   НаборЗаписей = connection.Execute(текст);
               
Пока НаборЗаписей.Eof() = 0 Цикл    
               
                           
               
                           
               
   ДатаВыезда=    строка((НаборЗаписей.Fields("Date_Departure").Value));
               

                   
   конецЦикла;                
           
НаборЗаписей.Close();
5 Smallrat
 
08.06.11
09:42
Я написал всё в 1С и всё выполняется, только возвращает какую-то пургу:


Command.CommandType = ТипКомандыАДО("adCmdStoredProc");
Command.CommandText = "SP_PayBill";
Connect.Execute("set nocount on");
RS =  Command.Execute();
RS.MoveFirst();
Connect.Execute("set nocount off");
6 philll
 
08.06.11
09:44
какую пургу?
7 Rie
 
08.06.11
09:44
(6) Полностью результат
8 Rie
 
08.06.11
09:44
+(7) А ему только количество надо.
9 Rie
 
08.06.11
09:46
Если получил RecordSet - то RecordCount возьми. Не оно?
10 Smallrat
 
08.06.11
09:46
там еще параметры выставлялись
так вот - оно выываливается с ошибкой на MoveFirst()

Произошла исключительная ситуация (ADODB.Recordset): Операция не допускается, если объект закрыт.
Несколько часов пропарился, понял что там возврааются наборы, и типа надо делать NextRecordset()
Только RS1 = RS.NextRecordset();
сразу же мне дает Неопределено и ничего из этих наборов вытащить не удается
11 philll
 
08.06.11
09:48
Пока НаборЗаписей.Eof() = 0 Цикл    
               
           
Нужное=    строка((НаборЗаписей.Fields("ИмяПеременной").Value));
               
                   
конецЦикла;              

Это не то?
12 Rie
 
08.06.11
09:48
(10) Так выставь параметры. Прямо в тексте запроса.
13 Smallrat
 
08.06.11
09:55
(9) RecordCount  - ошибка чтения значения.
прочитал v8: 1с + ADO - "Операция не допускается, если объект закрыт" - HELP!
там товарищ сказал что может не получится (
(11) Eof() не отрабатывает на закрытом наборе
(12) с параметрами проблем нет - я все выставил через

Command.Parameters.Append(Command.CreateParameter("@Cli",            2,    1, 9, 1));
14 Smallrat
 
08.06.11
09:57
(12) так нету меня никакого запроса - есть только выполнение команды с типом  "adcmdstoredproc" (4)
15 Rie
 
08.06.11
10:02
(14) А зачем ты выбираешь adCmdStoredProc? Вызвать и без этого можно. То же самое, что в (3) - запихни в CommandText.
16 Smallrat
 
08.06.11
10:04
(15) чессно говоря не знаю, я с ADO первый раз работаю. Просто с примера вызова хранимой процедуры слизал. Думал - так правильней.

До меня только сейчас дошло:
select res = @r  - оно что, возвращает просто количество записей в @r ?
17 Smallrat
 
08.06.11
10:06
(15) там есть параметры типа DateTime (аля  @DateIn = {ts' 2011-06-06 15:21:09' } ), как их передать в текст запроса ?
18 Smallrat
 
08.06.11
10:06
+(17) а блин - это ж просто текст, туплю
19 Rie
 
08.06.11
10:06
(26) Непонятно, что оно возвращает. Оно возвращает результат выполнения PayBill.
Количество записей - это гипотеза. (Причём, боюсь, неверная - не глянул, что там set nocount on выставляется).
20 DmitrO
 
08.06.11
10:07
(16) не не совсем дошло еще..
количество записей в типе int? :)
21 Smallrat
 
08.06.11
10:10
(20) да, точно ))
тогда я не понимаю - раз хранимая процедура возвращает int, то почему в 1С оно возвращает закрытый COM объект ?
22 DmitrO
 
08.06.11
10:12
скажи лучше для начала почему у тебя в примере в (3) процедура называется PayBill, а в (5) называется SP_PayBill?
23 Smallrat
 
08.06.11
10:15
(22) а - перередактировал )), она выполняется и делает всё что надо. ТОлько не могу отловить возвращаемое значение - а там, я так понял, коды ошибок выполнения.
24 DmitrO
 
08.06.11
10:17
(21) Потому что так написана процедура.
25 DmitrO
 
08.06.11
10:19
(23) тебе именно эти коды ошибок и нужно получить?
26 Smallrat
 
08.06.11
10:33
(25) по идее да. я уже правда придумал как без этого обойтись, но мне все равно интересно, я посмотрел текст процедуры там возвращается int.
я плохо знаю ADO и SQL. но может select res = @r как раз преобразует @r в recordset, который можно считать. а просто число Execute() не может вернуть, потому что возвращает рекордсеты ?
27 Smallrat
 
08.06.11
10:37
Если не удастся мне обойтись без кодов ошибок - буду делать commandtext, как сказал (15)

У меня вот еще вопрос: Почему надо соблюдать очередность присвоения параметров процедуры ?
Command.Parameters.Append(Command.CreateParameter("@Par1",            2,1,,1));
Command.Parameters.Append(Command.CreateParameter("@Par2",            2,1,,2));
дает выполнение с параметрами 1,2, а если  поменять местами строчки то даёт 2,1 Зачем тогда имена ?
28 DmitrO
 
08.06.11
10:38
вобщем выполнить процедуру есть два способа:
1. текстом запроса (adCmdText)
текст команды должен быть такой:
declare @r int
exec @r = SP_PayBill ... --параметры процедуры
select @r --для получения статуса возврата процедуры (return_status)

при этом статус возврата будет в рекордсете состоящем из одного поля и одной записи, но похоже во втором рекордсете, т.к. похоже процедура сама выдает один рекордсет (возможно ошибочно).

2. вызовом по RPC (adCmdStoredProc)
текст команды должен быть такой:
SP_PayBill
Чтобы получить статус возврата надо обязательно добавлять параметр (вроде первый он должен быть) с типом направления adParamReturnValue и после выполнения читать его значение.
29 DmitrO
 
08.06.11
10:41
(28)+
во втором случае надо обязательно соблюдать порядок параметров как в объявлении процедуры, имена параметров игнорируются.
30 DmitrO
 
08.06.11
10:42
собственно у MSSQL имена параметров всегда игнорируются.
31 DmitrO
 
08.06.11
10:48
(28)++ да, еще замечание
Значения возвращаемых параметров (adParamOutput, adParamReturnValue) будут доступны только после получения всех результатов команды (после выполнения всех необходимых RS = RS.NextRecordset();).
32 Smallrat
 
08.06.11
10:56
(31) RS = RS.NextRecordset() у меня сразу неопределено возвращает (
Но по второму варианту (через adParamReturnValue ) у меня получилось получить это возвращаемое значение !!! такое же как и через запрос в SQL management studio.
почему то без NextRecordset... просто в Command.Parameters(0).Value, ну да ладно...
Большое спасибо за помощь!!, а то я вчера полдня убил чтобы дотрясти эту штуку, просто из принципа ))
33 DmitrO
 
08.06.11
11:05
>>почему то без NextRecordset... просто в Command.Parameters(0).Value, ну да ладно...
потому что процедура возвращает всего один рекордcет, и он пустой (не содержит записей), поэтому буфер TDS протокола (по которому работает MSSQL) уже можно протолкнуть до возвращаемых параметров и oledb провайдер это делает. По правде говоря, параметры передаются когда последний рекордсет стоит на последней записи.
34 DmitrO
 
08.06.11
11:06
Главное четко понимать, что данные результатов передаются последовательно.
35 Smallrat
 
08.06.11
11:21
(33) кажется я понял %( А что - так будет всегда когда возвращаемый результат не рекордсет, число там или строка ?
36 Smallrat
 
08.06.11
11:22
*(35) то есть когда возвращаемое значение не рекордсет, а число или строка.
37 DmitrO
 
08.06.11
11:55
возвращаемые результаты с MSSQL можно разделить на три типа:
1. рекордсет
Обычно формируется в результате выполнения предложения запроса SELECT (ряд других обычно спец. предложений запроса могут формировать результат такого же типа)
Представляет из себя последовательно перебираемый набор записей с одинаковым набором полей.

2. количество записей
формируется в результате выполнения DML предложения запроса (INSERT, UPDATE, DELETE)
В ADO читается из свойства Recordset::RecordCount.
Представляет из себя значение типа int - количество обработанных записей.

3. значения возвращаемых параметров процедуры (возможно только при RPC вызове)

Первые два всегда выдаются сервером последовательно, по ходу  выполнения. Причем не важно внутри процедуры или внутри процедуры вызванной из процедуры и т.п. или просто в пакете команд идет выполнение, результаты формируются последовательно по ходу выполнения.
А значения возвращаемых параметров процедуры всегда идут вконце.

Во время передачи результата типа рекордсет не известно сколько записей всего в текущем наборе. В общем случае этого не знает даже сервер он просто читает и отправляет записи, поэтому в ADO Recordset::RecordCount равно -1.

Все выше сказанное относится не столько к ADO сколько к протоколу TDS и клиентам его отрабатывающим:
- ODBC драйвер {SQL Server}
- OLEDB провайдер {SQLOLEDB}
- поставщик данных ADO.NET для MSSQL, пространство имен  System.Data.SqlClient
38 Smallrat
 
08.06.11
12:31
(37) Спасиб )) буду переваривать.