powered by simpleCommunicator - 2.0.37     © 2025 Programmizd 02
Форумы / Caché, Ensemble, DeepSee, MiniM, IRIS, GT.M [игнор отключен] [закрыт для гостей] / SQLGateway
7 сообщений из 7, страница 1 из 1
SQLGateway
    #39347601
Фотография DirksDR
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Добрый день!

Продолжаю осваивать чтение данных через ODBC-источник.
Под спойлером заготовка программы чтения из таблицы MSSQL с помощью %DynamicQueryGW.
Хочу один раз сделать Prepare и много раз Execute с параметрами.
Первый Execute срабатывает, а второй выдает ошибку:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
TELESKOP>do Test2^Tel4LoadFloat
 
select * from  tel4.dbo.SERVER_ARCHIVE_FLOAT where ABSOLUTE_NUMBER = ? and EVENT_DATETIME> ?
Prepare
Execute 15004YBHVSLB0SOR1T205S
583 записей
ОШИБКА #6023: Запрос не подготовлен (Prepared).
TELESKOP>
Не могу сообразить, что надо сделать с %ResultSet, чтобы он опять отработал Execute.
В методах ничего подходящего не нашел.
Если ставлю Prepare перед вторым Execute выдает ошибку:

Код: plaintext
ОШИБКА #5818: Запрос не закрыт

Если ставлю
Код: plaintext
1.
2.
Set sc=res.Close()

Set sc=res.Prepare(myQuery,,conn)
второй Execute отрабатывает.
Но это же нехорошо:) Prepare должен быть один раз.
Или повторный Execute только для %DynamicQuery работает, а для %DynamicQueryGW - нет?
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
Test2  ;   
  ;настройка подключения
  Set conn=##class(%SQLGatewayConnection).%New()
  Set sc=conn.Connect("Tel4Kky","ois","ois",0) 
  If $$$ISERR(sc) do $System.Status.DisplayError(sc) quit
  ;определим recordset
  Set res=##class(%ResultSet).%New("%DynamicQueryGW:SQLGW")
  
  ;подготовим запрос на данные
  set myQuery="select * from  tel4.dbo.SERVER_ARCHIVE_FLOAT where ABSOLUTE_NUMBER = ? and EVENT_DATETIME> ?"
  w !,myQuery
  
  Set sc=res.Prepare(myQuery,,conn)
  If $$$ISERR(sc) do $System.Status.DisplayError(sc) quit
  
  w !,"Prepare"
  
  Set sc=res.Execute("15004YBHVSLB0SOR1T205S","2016-11-14")
  If $$$ISERR(sc) do $System.Status.DisplayError(sc) quit
  
  w !,"Execute 15004YBHVSLB0SOR1T205S"
  set recCount=0
  do LoadData  ;чтение res.Next() и подсчет количества записей

  Set sc=res.Execute("15004YBHVSLB0SOR1T205S","2016-11-14")
  If $$$ISERR(sc) do $System.Status.DisplayError(sc) quit
  
  w !,"Execute 15004YBHVSLB0SOR1T205S"
  set recCount=0
  do LoadData
    
  Set sc=res.%Close() 
  Set sc=conn.%Close() 
   
  quit 

LoadData ;чтение данных с сервера ТМ
  
  While res.Next()
  {     
    merge flds=res.Data
    ;zwrite flds
    set recCount=recCount+1
  } 

  w !,recCount," записей"

  Quit
...
Рейтинг: 0 / 0
SQLGateway
    #39347634
Фотография DirksDR
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
И еще вопрос (стратегический:)):
Чем использовать SQLGateway, может лучше использовать внешние программы,
которые с одной стороны считывают данные из MSSQL(Oracle, ets.), а с другой записывают в Cache?
Будет ли это эффективней?
Кстати, какой подход Вы используете?
...
Рейтинг: 0 / 0
SQLGateway
    #39347770
Timur Safin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DirksDRИ еще вопрос (стратегический:)):
Чем использовать SQLGateway, может лучше использовать внешние программы,
которые с одной стороны считывают данные из MSSQL(Oracle, ets.), а с другой записывают в Cache?
Будет ли это эффективней?


Да, так будет проще и надежней. Когда при необходимости импорта из Access, я устал бороться с проблемами SQLGateway, поставив Access? попытался экспортировать в Cache' то справился с проблемой за 20 секунды. Колонки с русскими именами и пробелами были правильно переименованы, все метаданные корректно расставлены и данные без потерь.

Т.е. если источник ODBC - Microsoft, то лучше делать из них экспорт в CacheODBC.
...
Рейтинг: 0 / 0
SQLGateway
    #39347790
servit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Timur SafinДа, так будет проще и надежней. Проще и быстрее будет воспользоваться мастером связывания и/или импорта/экспорта.
...
Рейтинг: 0 / 0
SQLGateway
    #39348128
Фотография DirksDR
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Спасибо, servit!

Для линкованной MSSQL-таблицы повторный %Execute сработал:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
TELESKOP>do Test3^Tel4LoadFloat
 
select ABSOLUTE_NUMBER, EVENT_DATETIME, DATA from  tel4.dbo.SERVER_ARCHIVE_FLOAT where ABSOLUTE_NUMBER = ? and EVENT_DATETIME> ?
%Prepare
%Execute
tResult.%ROWCOUNT=0
tResult.%tResultultColumnCount=3
15004YBHVSLB0SOR1T205S
2016-11-14 00:07:22.317
11473857.0
871 записей
tResult.%ROWCOUNT=871
%Execute
tResult.%ROWCOUNT=0
tResult.%ResultColumnCount=3
15004YBHVSLB0SOR1T205S
2016-11-15 00:07:22.697
11481296.0
526 записей
tResult.%ROWCOUNT=526
TELESKOP>
Код программы под спойлером.
Жаль, что %ROWCOUNT=0 после %Execute, зато после чтения данных показывает количество строк.
Test3
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
Test3  ;   связанная таблица

  SET tStatement = ##class(%SQL.Statement).%New()
  
  ;подготовим запрос на данные
  set myQuery="select ABSOLUTE_NUMBER, EVENT_DATETIME, DATA from  dbo.SERVER_ARCHIVE_FLOAT "_
        "where ABSOLUTE_NUMBER = ? and EVENT_DATETIME> ?"
  w !,myQuery
  
  SET sc = tStatement.%Prepare(myQuery)
  If $$$ISERR(sc) do $System.Status.DisplayError(sc) quit
  
  w !,"%Prepare"
  
  SET tResult = tStatement.%Execute("15004YBHVSLB0SOR1T205S","2016-11-14")
  w !,"%Execute"
  if tResult.%SQLCODE<0 w !,tResult.%Message quit
  w !,"tResult.%ROWCOUNT=",tResult.%ROWCOUNT
  set cc=tResult.%ResultColumnCount
  w !,"tResult.%tResultultColumnCount=",cc    
  set recCount=0
  do LoadData3(cc)  ;чтение tResult.Next() и подсчет количества записей
  w !,"tResult.%ROWCOUNT=",tResult.%ROWCOUNT
  
  ;2-й %Execute
  SET tResult = tStatement.%Execute("15004YBHVSLB0SOR1T205S","2016-11-15")
  w !,"%Execute"    
  if tResult.%SQLCODE<0 w !,tResult.%Message quit
  w !,"tResult.%ROWCOUNT=",tResult.%ROWCOUNT
  set cc=tResult.%ResultColumnCount
  w !,"tResult.%ResultColumnCount=",cc
  set recCount=0
  do LoadData3(cc)  ;чтение tResult.Next() и подсчет количества записей
  w !,"tResult.%ROWCOUNT=",tResult.%ROWCOUNT    

  quit 

LoadData3(ColumnCount) ;чтение данных с сервера ТМ
  new i,fld
  While tResult.%Next()
  {     
    for i=1:1:ColumnCount {
      set fld=tResult.%GetData(i)
      if recCount=1 w !,fld
    }
    set recCount=recCount+1
  } 
  w !,recCount," записей"
  Quit
Низкоуровневый ODBC доступ использовал к Ораклу, правда без параметров (без повторного Execute).
В документации для него нет примера с параметрами и разобраться сложно.
С помощью Вашего примера, попытаюсь попробовать и такой вариант. Там классный Fetch сразу на пачку записей.
Тем более, что связать/прилинковать табличку Оракла не получалось.
Вообще-то, я собираюсь переносить данные в Каше, поэтому не хочется плодить линкованные таблички.
...
Рейтинг: 0 / 0
SQLGateway
    #39348134
servit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DirksDRИли повторный Execute только для %DynamicQuery работает, а для %DynamicQueryGW - нет?Именно так. В WRC уже в курсе.DirksDRНе могу сообразить, что надо сделать с %ResultSet, чтобы он опять отработал Execute.Например, класс %Library.ResultSet расширить методом
Код: plaintext
1.
2.
3.
4.
5.
Method CloseGW() As %Status [ PublicList = (Row) ]
{
  New Row
  Set i%Row="",i%AtEnd=0,i%IsOpened=0
  Quit $$$OK
}
И теперь следующий код отработает без ошибок:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
...
  Set sc=res.Prepare(myQuery,,conn)
  If $$$ISERR(sc) do $System.Status.DisplayError(sc) quit
  
  w !,"Prepare"
  
  Set sc=res.Execute("15004YBHVSLB0SOR1T205S","2016-11-14")
  If $$$ISERR(sc) do $System.Status.DisplayError(sc) quit
  
  w !,"Execute 15004YBHVSLB0SOR1T205S"
  set recCount=0
  do LoadData  ;чтение res.Next() и подсчет количества записей

   do rs.CloseGW() 
  
Set sc=res.Execute("15004YBHVSLB0SOR1T205S","2016-11-14")
...PS: и вместо

Set sc=res.%Close()
Set sc=conn.%Close()

нужно

Set res=""
do conn.Disconnect()
...
Рейтинг: 0 / 0
SQLGateway
    #39348813
Фотография DirksDR
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
servit,
Еще раз спасибо.
Я, пожалуй, погожу добавлять свои методы в системный класс:)
Тем более, что отработал низкоуровневый ODBC доступ.
Вывел названия колонок, читаю по 200 записей.
Перед вторым Execute пришлось поставить CloseCursor, что в принципе логично.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
TELESKOP>do TMP^Tel4LoadFloat
 
Connect
AllocateStatement
Prepare
BindParameters
Execute1=9:2=ABSOLUTE_NUMBER:3=EVENT_DATETIME:4=DISPATCH_DATETIME:5=DATA:6=STATUS:7=VALID:8=CONFIRM_DATETIME:9=CONFIRM_USER_ID:10=CONFIRM_CODE:
Connection.sqlcode=0
recno =200,recno =200,recno =200,recno =200,recno =200,recno =182,recno =0
TMPLoad 1182 записей
Execute1=9:2=ABSOLUTE_NUMBER:3=EVENT_DATETIME:4=DISPATCH_DATETIME:5=DATA:6=STATUS:7=VALID:8=CONFIRM_DATETIME:9=CONFIRM_USER_ID:10=CONFIRM_CODE:
Connection.sqlcode=0
recno =200,recno =200,recno =200,recno =200,recno =37,recno =0
TMPLoad 837 записей
TELESKOP>
TMP
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
TMP
  S Connection=##class(%Library.SQLGatewayConnection).%New()
  S sc=Connection.Connect("Tel4Kky","ois","ois",0)
  If $$$ISERR(sc) do $System.Status.DisplayError(sc) quit
  w !,"Connect"
  S sc=Connection.AllocateStatement(.Statment)
  If $$$ISERR(sc) do $System.Status.DisplayError(sc) quit
  w !,"AllocateStatement"
  
  S SQLString="select * from  tel4.dbo.SERVER_ARCHIVE_FLOAT where ABSOLUTE_NUMBER = ? and EVENT_DATETIME> ?"
  S sc=Connection.Prepare(Statment,SQLString)
  If $$$ISERR(sc) do $System.Status.DisplayError(sc) quit
  w !,"Prepare"
      
  // подготовка параметров
  S Param(1)=$LB(1,1)   ;ptype - input/ouput types of the parameters in the $list format
  S Param(2)=$LB(1,1)    ;dtype - SQL datatypes of parameters in the $list format
  S Param(3)=$LB(22,10)  ;precision - $list of the correponding precision values - used for reseving buffers for parameter values
  S Param(4)=$LB(0,0)    ;scale - $list of the correponding scale values
  S Param(5)=$LB(22,20)  ;cd - $list of column sizes
  
  S sc=Connection.BindParameters(Statment,Param(1),Param(2),Param(3),Param(4),Param(5))
  If $$$ISERR(sc) do $System.Status.DisplayError(sc) quit
  w !,"BindParameters"
    
  //присваиваем параметры
  S sc=Connection.SetParameter(Statment,$LB("15004YBHVSLB0SOR1T205S"),1) ;hstmt, pvalue, pnbr) 
  If $$$ISERR(sc) do $System.Status.DisplayError(sc) quit
  
  S sc=Connection.SetParameter(Statment,$LB("2016-11-14"),2)
  If $$$ISERR(sc) do $System.Status.DisplayError(sc) quit

  // выполнение запроса
  S sc=Connection.Execute(Statment)
  If $$$ISERR(sc) do $System.Status.DisplayError(sc) quit
  w !,"Execute"
  do TMPLoad  

  s sc=Connection.CloseCursor(Statment) ;???????????????????
  If ('sc) Do DisplayError^%apiOBJ(sc) quit

  //еще раз
  //присваиваем параметры
  S sc=Connection.SetParameter(Statment,$LB("15004YBHVSLB0SOR1T205S"),1) ;hstmt, pvalue, pnbr) 
  If $$$ISERR(sc) do $System.Status.DisplayError(sc) quit
  
  S sc=Connection.SetParameter(Statment,$LB("2016-11-15"),2)
  If $$$ISERR(sc) do $System.Status.DisplayError(sc) quit

  // выполнение запроса
  S sc=Connection.Execute(Statment)
  If $$$ISERR(sc) do $System.Status.DisplayError(sc) quit
  w !,"Execute"  
  do TMPLoad  

  s sc=Connection.CloseCursor(Statment) 
  If ('sc) Do DisplayError^%apiOBJ(sc) quit

  S sc=Connection.DropStatement(Statment)
  If $$$ISERR(sc) do $System.Status.DisplayError(sc) quit

  S sc=Connection.Disconnect()
  If $$$ISERR(sc) do $System.Status.DisplayError(sc) quit
  Q
  
TMPLoad  ; чтение записей пачками по 200 шт Fetch-ем
    s recCount=0    
    ;печать имен колонок
    s clist=""
    s sc=Connection.DescribeColumns(Statment, .clist) If ('sc) Do DisplayError^%apiOBJ(sc) quit
    Set numcols=$ll(clist)
    For i=1:1:numcols Write i,"=",$lg($lg(clist,i),1),":"
    
      //чтение первой пачки из 200 записей
    s rlist="",sc=Connection.FetchRows(Statment, .rlist,200) if $$$ISERR(sc) Do DisplayError^%apiOBJ(sc) quit
    w !,"Connection.sqlcode=",Connection.sqlcode
    set recno=$ll(rlist)
    w !,"recno =",recno
      
      while(Connection.sqlcode=0 & $ll(rlist)>0)  {
      ;перебираем записи пачки
      set recno=$ll(rlist)
      for irec=1:1:recno {
        set rec=$lg(rlist,irec)
        ;выбираем колонки записи
        ;set colno=$ll(rec) w !,"colno=",colno
        ;for j=1:1:colno w j,"=",$lg(rec,j),";"
        }
        s recCount=recCount+recno
      
      //чтение следующей пачки записей
       set sc=Connection.FetchRows(Statment,.rlist,200) if $$$ISERR(sc) do ErrPrint
       ;w !,"Connection.sqlcode=",Connection.sqlcode
       set recno=$ll(rlist)
      w ",recno =",recno

    }  
    w !,"TMPLoad ",recCount," записей"
  q
MaVr в посте от 2007 года вызывает Оракловую процедуру с возвратом значения через параметр.
Такая возможность тоже может пригодиться.
...
Рейтинг: 0 / 0
7 сообщений из 7, страница 1 из 1
Форумы / Caché, Ensemble, DeepSee, MiniM, IRIS, GT.M [игнор отключен] [закрыт для гостей] / SQLGateway
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]