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

Откуда: Пермь
Сообщений: 306
Добрый день!

Продолжаю осваивать чтение данных через ODBC-источник.
Под спойлером заготовка программы чтения из таблицы MSSQL с помощью %DynamicQueryGW.
Хочу один раз сделать Prepare и много раз Execute с параметрами.
Первый Execute срабатывает, а второй выдает ошибку:
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 выдает ошибку:

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

Если ставлю
Set sc=res.Close()

Set sc=res.Prepare(myQuery,,conn)
второй Execute отрабатывает.
Но это же нехорошо:) Prepare должен быть один раз.
Или повторный Execute только для %DynamicQuery работает, а для %DynamicQueryGW - нет?
+
Test2  ;   
  ;настройка подключения
  
Set conn=##class(%SQLGatewayConnection).%New()
  
Set sc=conn.Connect("Tel4Kky","ois","ois",0) 
  
If $$$ISERR(scdo $System.Status.DisplayError(scquit
  
;определим recordset
  
Set res=##class(%ResultSet).%New("%DynamicQueryGW:SQLGW")
  
  
;подготовим запрос на данные
  
set myQuery="select * from  tel4.dbo.SERVER_ARCHIVE_FLOAT where ABSOLUTE_NUMBER = ? and EVENT_DATETIME> ?"
  
!,myQuery
  
  
Set sc=res.Prepare(myQuery,,conn)
  
If $$$ISERR(scdo $System.Status.DisplayError(scquit
  
  w 
!,"Prepare"
  
  
Set sc=res.Execute("15004YBHVSLB0SOR1T205S","2016-11-14")
  
If $$$ISERR(scdo $System.Status.DisplayError(scquit
  
  w 
!,"Execute 15004YBHVSLB0SOR1T205S"
  
set recCount=0
  
do LoadData  ;чтение res.Next() и подсчет количества записей

  
Set sc=res.Execute("15004YBHVSLB0SOR1T205S","2016-11-14")
  
If $$$ISERR(scdo $System.Status.DisplayError(scquit
  
  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
  


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

  
Quit
15 ноя 16, 14:43    [19896139]     Ответить | Цитировать Сообщить модератору
 Re: SQLGateway  [new]
DirksDR
Member

Откуда: Пермь
Сообщений: 306
И еще вопрос (стратегический:)):
Чем использовать SQLGateway, может лучше использовать внешние программы,
которые с одной стороны считывают данные из MSSQL(Oracle, ets.), а с другой записывают в Cache?
Будет ли это эффективней?
Кстати, какой подход Вы используете?
15 ноя 16, 15:20    [19896403]     Ответить | Цитировать Сообщить модератору
 Re: SQLGateway  [new]
Timur Safin
Member

Откуда:
Сообщений: 54
DirksDR
И еще вопрос (стратегический:)):
Чем использовать SQLGateway, может лучше использовать внешние программы,
которые с одной стороны считывают данные из MSSQL(Oracle, ets.), а с другой записывают в Cache?
Будет ли это эффективней?


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

Т.е. если источник ODBC - Microsoft, то лучше делать из них экспорт в CacheODBC.
15 ноя 16, 17:18    [19897102]     Ответить | Цитировать Сообщить модератору
 Re: SQLGateway  [new]
servit
Member

Откуда: г. Кишинёв, Республика Молдова
Сообщений: 3066
Блог
Timur Safin
Да, так будет проще и надежней.
Проще и быстрее будет воспользоваться мастером связывания и/или импорта/экспорта.
15 ноя 16, 17:33    [19897171]     Ответить | Цитировать Сообщить модератору
 Re: SQLGateway  [new]
DirksDR
Member

Откуда: Пермь
Сообщений: 306
Спасибо, servit!

Для линкованной MSSQL-таблицы повторный %Execute сработал:
TELESKOP>do Test3^Tel4LoadFloat

select ABSOLUTE_NUMBEREVENT_DATETIMEDATA 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
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> ?"
  
!,myQuery
  
  
SET sc tStatement.%Prepare(myQuery)
  
If $$$ISERR(scdo $System.Status.DisplayError(scquit
  
  w 
!,"%Prepare"
  
  
SET tResult tStatement.%Execute("15004YBHVSLB0SOR1T205S","2016-11-14")
  
!,"%Execute"
  
if tResult.%SQLCODE<0 !,tResult.%Message quit
  w 
!,"tResult.%ROWCOUNT=",tResult.%ROWCOUNT
  set 
cc=tResult.%ResultColumnCount
  w 
!,"tResult.%tResultultColumnCount=",cc    
  
set recCount=0
  
do LoadData3(cc)  ;чтение tResult.Next() и подсчет количества записей
  
!,"tResult.%ROWCOUNT=",tResult.%ROWCOUNT
  
  
;2-й %Execute
  
SET tResult tStatement.%Execute("15004YBHVSLB0SOR1T205S","2016-11-15")
  
!,"%Execute"    
  
if tResult.%SQLCODE<0 !,tResult.%Message quit
  w 
!,"tResult.%ROWCOUNT=",tResult.%ROWCOUNT
  set 
cc=tResult.%ResultColumnCount
  w 
!,"tResult.%ResultColumnCount=",cc
  
set recCount=0
  
do LoadData3(cc)  ;чтение tResult.Next() и подсчет количества записей
  
!,"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 !,fld
    
}
    
set recCount=recCount+1
  

  
!,recCount," записей"
  
Quit
Низкоуровневый ODBC доступ использовал к Ораклу, правда без параметров (без повторного Execute).
В документации для него нет примера с параметрами и разобраться сложно.
С помощью Вашего примера, попытаюсь попробовать и такой вариант. Там классный Fetch сразу на пачку записей.
Тем более, что связать/прилинковать табличку Оракла не получалось.
Вообще-то, я собираюсь переносить данные в Каше, поэтому не хочется плодить линкованные таблички.
16 ноя 16, 10:27    [19898939]     Ответить | Цитировать Сообщить модератору
 Re: SQLGateway  [new]
servit
Member

Откуда: г. Кишинёв, Республика Молдова
Сообщений: 3066
Блог
DirksDR
Или повторный Execute только для %DynamicQuery работает, а для %DynamicQueryGW - нет?
Именно так. В WRC уже в курсе.
DirksDR
Не могу сообразить, что надо сделать с %ResultSet, чтобы он опять отработал Execute.
Например, класс %Library.ResultSet расширить методом
Method CloseGW() As %Status PublicList = (Row) ]
{
  
New Row
  
Set i%Row="",i%AtEnd=0,i%IsOpened=0
  
Quit $$$OK
}
И теперь следующий код отработает без ошибок:
...
  Set sc=res.Prepare(myQuery,,conn)
  
If $$$ISERR(scdo $System.Status.DisplayError(scquit
  
  w 
!,"Prepare"
  
  
Set sc=res.Execute("15004YBHVSLB0SOR1T205S","2016-11-14")
  
If $$$ISERR(scdo $System.Status.DisplayError(scquit
  
  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()
16 ноя 16, 10:34    [19898958]     Ответить | Цитировать Сообщить модератору
 Re: SQLGateway  [new]
DirksDR
Member

Откуда: Пермь
Сообщений: 306
servit,
Еще раз спасибо.
Я, пожалуй, погожу добавлять свои методы в системный класс:)
Тем более, что отработал низкоуровневый ODBC доступ.
Вывел названия колонок, читаю по 200 записей.
Перед вторым Execute пришлось поставить CloseCursor, что в принципе логично.
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
TMP
  
Connection=##class(%Library.SQLGatewayConnection).%New()
  
sc=Connection.Connect("Tel4Kky","ois","ois",0)
  
If $$$ISERR(scdo $System.Status.DisplayError(scquit
  w 
!,"Connect"
  
sc=Connection.AllocateStatement(.Statment)
  
If $$$ISERR(scdo $System.Status.DisplayError(scquit
  w 
!,"AllocateStatement"
  
  
SQLString="select * from  tel4.dbo.SERVER_ARCHIVE_FLOAT where ABSOLUTE_NUMBER = ? and EVENT_DATETIME> ?"
  
sc=Connection.Prepare(Statment,SQLString)
  
If $$$ISERR(scdo $System.Status.DisplayError(scquit
  w 
!,"Prepare"
      
  // подготовка параметров
  
Param(1)=$LB(1,1)   ;ptype - input/ouput types of the parameters in the $list format
  
Param(2)=$LB(1,1)    ;dtype - SQL datatypes of parameters in the $list format
  
Param(3)=$LB(22,10)  ;precision - $list of the correponding precision values - used for reseving buffers for parameter values
  
Param(4)=$LB(0,0)    ;scale - $list of the correponding scale values
  
Param(5)=$LB(22,20)  ;cd - $list of column sizes
  
  
sc=Connection.BindParameters(Statment,Param(1),Param(2),Param(3),Param(4),Param(5))
  
If $$$ISERR(scdo $System.Status.DisplayError(scquit
  w 
!,"BindParameters"
    
  //присваиваем параметры
  
sc=Connection.SetParameter(Statment,$LB("15004YBHVSLB0SOR1T205S"),1) ;hstmt, pvalue, pnbr) 
  
If $$$ISERR(scdo $System.Status.DisplayError(scquit
  
  S 
sc=Connection.SetParameter(Statment,$LB("2016-11-14"),2)
  
If $$$ISERR(scdo $System.Status.DisplayError(scquit

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

  
sc=Connection.CloseCursor(Statment;???????????????????
  
If ('scDo DisplayError^%apiOBJ(scquit

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

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

  
sc=Connection.CloseCursor(Statment
  
If ('scDo DisplayError^%apiOBJ(scquit

  S 
sc=Connection.DropStatement(Statment)
  
If $$$ISERR(scdo $System.Status.DisplayError(scquit

  S 
sc=Connection.Disconnect()
  
If $$$ISERR(scdo $System.Status.DisplayError(scquit
  Q
  
TMPLoad  ; чтение записей пачками по 200 шт Fetch-ем
    
recCount=0    
    
;печать имен колонок
    
clist=""
    
sc=Connection.DescribeColumns(Statment, .clistIf ('scDo DisplayError^%apiOBJ(scquit
    Set 
numcols=$ll(clist)
    
For i=1:1:numcols Write i,"=",$lg($lg(clist,i),1),":"
    
      //чтение первой пачки из 200 записей
    
rlist="",sc=Connection.FetchRows(Statment, .rlist,200) if $$$ISERR(scDo DisplayError^%apiOBJ(scquit
    w 
!,"Connection.sqlcode=",Connection.sqlcode
    set 
recno=$ll(rlist)
    
!,"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),";"
        
}
        
recCount=recCount+recno
      
      
//чтение следующей пачки записей
       
set sc=Connection.FetchRows(Statment,.rlist,200) if $$$ISERR(scdo ErrPrint
       
;w !,"Connection.sqlcode=",Connection.sqlcode
       
set recno=$ll(rlist)
      
",recno =",recno

    
}  
    
!,"TMPLoad ",recCount," записей"
  
q
MaVr в посте от 2007 года вызывает Оракловую процедуру с возвратом значения через параметр.
Такая возможность тоже может пригодиться.
17 ноя 16, 09:09    [19902143]     Ответить | Цитировать Сообщить модератору
Все форумы / Caché Ответить