Прямой SQL

Программирование на Атлантисе (VIP, FCOM, ARD), FastReport

Модераторы: m0p3e, edward_K, Модераторы

Den
Местный житель
Сообщения: 1842
Зарегистрирован: 29 мар 2005, 17:49
Откуда: Ярославская область ОАО "Часовой завод Чайка" г. Углич
Контактная информация:

Re: Прямой SQL

Сообщение Den »

если Вы про FCOM то там доступны модификаторы только в рамках логической таблицы
Руслан
Местный житель
Сообщения: 294
Зарегистрирован: 01 ноя 2011, 14:03
Контактная информация:

Re: Прямой SQL

Сообщение Руслан »

Den писал(а):если Вы про FCOM то там доступны модификаторы только в рамках логической таблицы
Так дело в том, что один апдейт сработал на таблицу basedoc, а на таблицу spstep апдейт не проходит.
Yurii38
Сообщения: 1
Зарегистрирован: 24 апр 2013, 11:23

Re: Прямой SQL

Сообщение Yurii38 »

Подскажите, пожалуйста, как передать результаты выборки прямого sql в поток Fastreport?
RAJAH
Местный житель
Сообщения: 932
Зарегистрирован: 18 фев 2008, 12:49

Re: Прямой SQL

Сообщение RAJAH »

Yurii38
В FR доступен компонент ADOQuery, где можно написать запрос. Если сильно хочется использовать DSQL, то, думаю, через таблицу в памяти.
LaaLaa

Re: Прямой SQL

Сообщение LaaLaa »

Yurii38 писал(а):Подскажите, пожалуйста, как передать результаты выборки прямого sql в поток Fastreport?

Код: Выделить всё

/*
Пример использования объектного интерфейса для доступа к прямому SQL и связки
его с потоком данных FastReport
*/

#include Query.vih

Interface FrIQueryDemoReport;

  create view;

  sql query sqlQuery1 =
    SELECT
      sum(o.SumOb) Summa, sum(o.Kol) Kolvo, o.SchetO Debit, O.DatOb DatOb
    FROM Oborot O
    WHERE
      O.DatOb >= :dBegin
      and O.DatOb <= :dEnd
    GROUP BY O.DatOb, o.SchetO
    ORDER BY O.DatOb, o.SchetO;


  var CurrentQuery : IQuery;
  var ExecuteErrorCode : integer
  var FetchErrorCode : integer;

  function CurrentQuerySafeGetValue(AField : string) : variant;
  {
    if( not NullVipRef(CurrentQuery) and (ExecuteErrorCode = tsOk) )
      result := CurrentQuery.row.col(AField).value
    else
      result := '';
  }

  datastream SubTotalStream
  (
    // реквизиты организации для заголовка и подножия отчета
    [ExecuteErrorCode]     ExecuteErrorCode;
    [FetchErrorCode]       FetchErrorCode;

    // элемент потока данных управляемый программно
    dataset IQueryDataSet
    (
      [Summa]  CurrentQuerySafeGetValue('Summa');
      [Kolvo]  CurrentQuerySafeGetValue('Kolvo');
      [Debit]  CurrentQuerySafeGetValue('Debit');
      [DatOb]  LongToDate(CurrentQuerySafeGetValue('DatOb'));
    );
  )

    handleEvent dataset IQueryDataSet
      cmPreProcess:
      {
        // Инициализация запроса Direct-SQL
        CurrentQuery := queryManager.createQuery(sqlQuery1);
        CurrentQuery.SetParam('dBegin', date(1,2,2010));
        CurrentQuery.SetParam('dEnd',   date(28,2,2010));
        ExecuteErrorCode := CurrentQuery.Execute.ErrorCode;
      }

      cmOnProcess:
      {
        if(CurrentQuery.Fetch.ErrorCode = tsOk)
          ContinueDataset;
      }

      cmPostProcess:
      {
        // Де инициализация объекта запроса
        CurrentQuery := NullRef;
      }
    end;

  end;

  handleEvent
    cmInit:
    {
      RunFReport(SubTotalStream, '', false);
      Abort;
    }
  end;

end.
Не самый конечно эффективный пример, но пока только как то так.
zna
Местный житель
Сообщения: 552
Зарегистрирован: 29 мар 2005, 17:49
Откуда: Челябинск
Контактная информация:

Re: Прямой SQL

Сообщение zna »

Всем доброго!
Возникла проблема в применении вложенного цикла в dsql. Вот кусок внешнего цикла, где S$BD_KS_MNPLAN- хранимая процедура, mt- хендл временной таблицы

Код: Выделить всё

...
        stmt := sqlAllocStmt;
        if sqlExecStmt(stmt, 'BD_KS_MNPLAN') = tsOk         
         {
           if sqlFetchIntomt(stmt, mt) = tsOk
             {
                if sqlNavigateMT(mt, ffGetFirst, rec) = tsOk then
                  {
                    do
                     {
...
                       smemo:= sBdMc(nMnPlan, comp(rec[4]));
                     }
                    while sqlNavigateMT(mt, ffGetNext, rec) = tsOk;
                  } else message('sqlNavigateMT <> tsOk!')
             } else message('sqlFetchIntomt <> tsOk!')
         } else message('sqlExecStmt(stmt, BD_KS_MNPLAN) <> tsOk!')
        SqlFreeStmt(stmt);
        SqlFreeMt(mt);
Внешний цикл отрабатывает нормально, а во внутреннем, реализованном функцией sBdMc, происходит падение:

Код: Выделить всё

function sBdMc(cMn: comp; cMcU: comp): string;  //Получить строку со списком ДО
{
  var stmtf, strHandlef: longint; var _sBdMc, sBdn, sBdd: string;
  stmtf := sqlAllocStmt;
  SqlBindParam(stmtf, 1, cMn); SqlBindParam(stmtf, 2, cMcU);
  sqlBindCol( stmtf, 1, sBdn); sqlBindCol(  stmtf, 2, sBdd);
  SQLAddStr(strHandlef, 'select top 100 basedoc.nodoc, IntDateToString(basedoc.ddoc) from basedoc inner join objacct on basedoc.nrec = objacct.cowner inner join');
  SQLAddStr(strHandlef, '              mnplan on objacct.cobject = mnplan.nrec inner join stepdoc on basedoc.nrec = stepdoc.cbasedoc inner join');
  SQLAddStr(strHandlef, ' spstep on stepdoc.nrec = spstep.cstepdoc inner join spmnplan on mnplan.nrec = spmnplan.cmnplan and spstep.cmcusl = spmnplan.cizd');
  SQLAddStr(strHandlef, ' where objacct.typeobj = 17 and objacct.typeown = 34 and basedoc.viddoc = 101 and mnplan.nrec = ? and spmnplan.cizd = ?');
  SQLAddStr(strHandlef, ' order by basedoc.ddoc');
  sqlPrepare(stmtf, strHandlef);                                         // Здесь падение!
  sqlExecute(stmtf);
...
  sqlFreeStr(strHandlef);
  SqlFreeStmt(stmtf);
  if _sBdMc <> '' then sBdMc:= _sBdMc; else sBdMc:= ''
}
Имею лог драйвера:
01.03.2014 10:55:28 [NAZ]:
{CALL GetProcName(?,?,?)}
01.03.2014 10:55:28 [NAZ]:
HY000: [Microsoft][ODBC SQL Server Driver]Подключение занято до получения результатов для другого hstmt
01.03.2014 10:55:28 [NAZ]:
{CALL FT000000000000000000000000000S(? )}
01.03.2014 10:55:28 [NAZ]:
HY000: [Microsoft][ODBC SQL Server Driver]Подключение занято до получения результатов для другого hstmt
...

Как будто внутренний цикл конфликтует с внешним, хотя используются разные обозначения хендлов. Что не так??
edward_K
Заслуженный деятель интернет-сообщества
Сообщения: 5185
Зарегистрирован: 29 мар 2005, 17:49
Откуда: SPB galaxy spb

Re: Прямой SQL

Сообщение edward_K »

Где то в доке было написано про это - что нельзя использовать одновременно 2 DSQL.
Выход один - Выгружать 1 DSQL во временную таблицу, а второй можно оставить и так.
Как то так

Код: Выделить всё

 
    IdTable :=#table // число полей и тип во временной таблице должен строго совпадать с запросом
    vliErrorCode := sqlPrepare(stmt, vliSQLCommand);

  if (vliErrorCode = 0)
    {
          vliErrorCode := sqlExecute(stmt);

          LogSql( 'Выполнение SQL запроса Execute>Таблица	>> Стоп : ' + string(vliErrorCode));
          vliErrorCode := FitchExec(IdTable);
          LogSql( ' FitchExec=	 : ' + string(vliErrorCode));
         ClearQuery(vliSQLCommand);
    }
  else
    LogSql( 'Подготовка SQL запроса	>> ошибка №' + string(vliErrorCode));
    
  sqlFreeStmt(stmt);
  ClearQuery(vliSQLCommand);
Либо вообще объедините запросы в один - будет на порядок шустрее.
zna
Местный житель
Сообщения: 552
Зарегистрирован: 29 мар 2005, 17:49
Откуда: Челябинск
Контактная информация:

Re: Прямой SQL

Сообщение zna »

Понятно. Жаль, конечно..лишние заморочки. Спасибо за ответ!
edward_K
Заслуженный деятель интернет-сообщества
Сообщения: 5185
Зарегистрирован: 29 мар 2005, 17:49
Откуда: SPB galaxy spb

Re: Прямой SQL

Сообщение edward_K »

ЗЫ. Я вообще отказался от sqlBindCol и SqlBindParam - условия генерю сразу в код запроса а выгружаю во временку - тогда sqlBindCol не нужен как и Fetch .
Руслан
Местный житель
Сообщения: 294
Зарегистрирован: 01 ноя 2011, 14:03
Контактная информация:

Re: Прямой SQL

Сообщение Руслан »

Такой вопрос, делаю через прямой sql временную таблицу и заполняю ее данными запроса. Во view читаю эту временную таблицу и заполняю другую времянку. Далее эти данные передаю в excel-файл. Запрос работает, выводит данные. По итогу excel-файл пустой...

Код: Выделить всё

.FORM 'Ведомость наличия норм страхового запаса'
.ard
.var
day1,month1,year1:integer;
day2,month2,year2:integer;
BegDate,EndDate:date;
stmt, astmt : longint;
.endvar
.begin
RunDIALOG('C_COMMON::GETINTERVAL',BegDate, EndDate);
day1:=day(BegDate);
month1:=month(BegDate);
year1:=Year(BegDate);
day2:=day(EndDate);
month2:=month(EndDate);
year2:=Year(EndDate);
end.
.var
T_kmc:longint;
T_mc, T_podr:string;
T_kol_ost, T_kol_norm:double;
sch , x , xlsi, ks : integer ;
.endvar

	table struct tnormost
		(
			mcname : string,
			podrname : string,
			kolost : double,
			kolnorm : double
		)
	with index (n = mcname);

.create view t1
as SELECT *
from tnormost;


.begin
			stmt := sqlAllocStmt;
			//Создаем ВТ
			sqlDropTmpTable('tnormost');
!		  Message('должна удалиться',0)
!		  sqlDropTmpTable(UpCase ( UserName ) +'.MyData');
!		  Message('а теперь?',0)
			sqlCreateTmpTable('Table tnormost (mcname : string, podrname : string, kolost : double, kolnorm : double);', ctmNormal);
		  //Заполняем ВТ
!		sqlExecStmt(stmt,'select basedoc.nrec, basedoc.ddoc, basedoc.nodoc from basedoc inner join ttndoc on (BaseDoc.Nrec = TTNDOC.CDOC) and ttndoc.wtable=1102 inner join attrval on ttndoc.nrec = attrval.CREC inner join attrnam on attrval.cattrnam = attrnam.nrec and attrnam.nrec = comp(''281474976711117'')');
!			sqlExecStmt(stmt,'SELECT t1.name, katpodr.name, t1.kol, t1.normkol from( select s.cmc,mc.name, s.cmol,s.cparty,s.cpodr,s.kolp,s.kolr,s.kol,nzs.kol as normkol, s.srprice,s.dsaldo, max(s.dsaldo) OVER(partition by s.cmc, s.cmol, s.cparty, s.cpodr) as maxdate from katmc mc, NORMZAPAS nz, NORMZAPASSPEC nzs, saldomc s inner join katpodr podr on s.cpodr=podr.nrec where s.dsaldo<=#date(31,12,2100) and NZ.ATL_NREC = NZS.CNORM and NZS.CMC = s.cmc and s.CPODR = NZ.CPODRAZD and s.cmc = mc.nrec and s.cpodr <> (''0000000000000000h'')) t1 inner join katpodr on t1.cpodr=katpodr.nrec left join katmol mol on t1.cmol=mol.nrec left join katparty party on t1.cparty=party.nrec where dsaldo = maxdate and (t1.kolp-t1.kolr)<>0;');
			sqlExecStmt(stmt,'sql SELECT mc.name mcname, katpodr.name podrname, t1.kol kolost, nzs.kol kolnorm from( select s.cmc, s.cmol,s.cparty,s.cpodr,s.kolp,s.kolr,s.kol, s.srprice,s.dsaldo, max(s.dsaldo) OVER(partition by s.cmc, s.cmol, s.cparty, s.cpodr) as maxdate from saldomc s where s.dsaldo<=#date(31,12,2100) and s.cpodr <> (''0000000000000000h'')) t1 right join NORMZAPASSPEC nzs on t1.cmc = NZS.CMC inner join katmc mc on nzs.cmc = mc.nrec inner join NORMZAPAS nz on NZS.CNORM = NZ.ATL_NREC inner join katpodr on nz.cpodrazd=katpodr.nrec where dsaldo = maxdate and (t1.kolp-t1.kolr)<>0');
	  		  //Читаем ВТ
!		  sqlExecStmt(stmt,'select F from MyData');
			sqlFetchInto(stmt, tntnormost);
			sqlFreeStmt(stmt);
end.
.begin
	 T_kmc:=Tblinitnew(12,1);
	 T_mc:=Tblnewfield(T_kmc,12);
	 T_podr:=Tblnewfield(T_kmc,12);
     Tblendkey(t_Kmc);
     T_kol_ost:=Tblnewfield(T_kmc,12);
     T_kol_norm:=Tblnewfield(T_kmc,12);

	 TblSetDuplicate(T_kmc,true);
	 TblClearbuffer(T_kmc);
 end.
.{table 't1'
.begin
     TblClearBuffer(T_kmc);
     TblSfString(T_kmc,T_mc, t1.tnormost.mcname)
     TblSfString(T_kmc,T_podr, t1.tnormost.podrname)

	 If(TblGetEqual(T_kmc))
     {
        TblSfDouble(T_kmc,T_kol_ost,TblgfDouble(T_kmc,T_kol_ost) + t1.tnormost.kolost)
        TblSfDouble(T_kmc,T_kol_norm,TblgfDouble(T_kmc,T_kol_norm) + t1.tnormost.kolnorm)
        TblUpdateCurrent(T_kmc);
     }
     else
     {
        TblSfDouble(T_kmc,T_kol_ost, t1.tnormost.kolost)
        TblSfDouble(T_kmc,T_kol_norm, t1.tnormost.kolnorm)
        TblInsertCurrent(T_kmc);
     }
end.
.}
.begin
 xlCreateExcel('Ведомость наличия норм страхового запаса' , true);
  if (xlIsExcelValid)
    xlSetActiveWorkBookByName('Ведомость наличия норм страхового запаса');
 xlSetSheetName(1, '');
 xlSetActiveSheet(1);

 X:=0;
 xlsi := 3;
 ks := 4;
 SCH:=TBLRECORDS(T_kmc)-1;
xlSetCellStringValue('Ведомость наличия норм страхового запаса',1,1,1,1);
xlSetCellStringValue('с '+BegDate+' по '+EndDate,2,1,2,1);
XLCREATEMATRIX(sch+xlsi, ks);
xlClearMatrix;

xlStWriteToMatrix(1, 1, 'Наименование МЦ');
xlSetColumnWidth(25,1,1,sch,1)
xlStWriteToMatrix(1, 2, 'Количество по остаткам');
xlSetColumnWidth(14,1,2,sch,2)
!xlWrapText(4,1,sch,ks)
xlStWriteToMatrix(1, 3, 'Количество по нормам');
xlSetColumnWidth(10,1,3,sch,3)
xlsi := 3;


end.


.{WHILE X<=SCH
.BEGIN

    xlsi := xlsi + 1
    IF TBLGETINDEX(T_kmc,X)
    { }
    X:=X+1

    xlStWriteToMatrix(xlsi, 1, Substr(TblGfString(T_kmc,T_mc),1,50))
    xlStWriteToMatrix(xlsi, 2, TblgfString(T_kmc,T_kol_ost))
	xlStWriteToMatrix(xlsi, 3, TblgfDouble(T_kmc,T_kol_norm))
!    if Round(TBLGFdouble(T_kmc,T_kol),0)<> 0
!    { xlDoWriteToMatrix(xlsi, 5, TBLGFdouble(T_kmc,T_kol))  }
!    else
!    { xlStWriteToMatrix(xlsi, 5, '')     }   ;
end.
.}


.begin
XLWriteMatrixToExcel(4,1);
xlImportModule('\\SRV31\810_res\06\uchet.bas')
!xlImportModule('d:\program\uchet.bas')
xlRunMacro('rez.rez');
xlKillExcel;
END.

!logstrtofile('d:\name.txt', t1.katmc.name, t1.spsopr.kolfact, t1.)

.endform

savov
Местный житель
Сообщения: 589
Зарегистрирован: 29 мар 2005, 17:49
Откуда: Воронеж ОАО Верофарм. Воронеж

Re: Прямой SQL

Сообщение savov »

Доброго времени суток.
В продолжение темы.
Пробую интерфейс с прямым скулем.
Текст запроса:

Код: Выделить всё

         stmt := sqlAllocStmt;

          sqlAddStr(StmtString,'select t1.dSopr, t1.name, Sum(sale), Sum(sebest), t1.cpodrfrom from ');
          sqlAddStr(StmtString,'(select KatSopr.dSopr, KatSopr.VhodNal, Katmc.name, Sporder.kol*Sporder.srprice  ');
          sqlAddStr(StmtString,' sebest, Spsopr.price*Sporder.kol  sale, KatSopr.cPodrFrom  from vrn.KatSopr, vrn.Katmc, vrn.Sporder, vrn.Spsopr where ');
	  sqlAddStr(StmtString,' KatSopr.VidSopr=201 and KatSopr.dSopr >= '+GetDateAsPascalLongint(dtBegdate)+'  and KatSopr.dSopr <= '+GetDateAsPascalLongint(dtFindate)+' and ');
    sqlAddStr(StmtString,' KatSopr.nRec = Spsopr.cSopr and ');
	  sqlAddStr(StmtString,' Spsopr.nrec=Sporder.cspsopr and Sporder.vidorder=1 and Spsopr.cmcusl = Katmc.fnrec ) t1 group by t1.dsopr, t1.name, t1.cpodrfrom');
          Message(sqlPrepare ( stmt, StmtString ),0);
          Message(sqlExecute ( stmt ),0);


         sqlFetchInto(stmt, tntblsalesNota);
         Message('err='+string(sqlErrorCode(stmt)),0);
         sqlFreeStmt(stmt);
Выдает ошибку (Ora73drv)

Код: Выделить всё

select t1.dSopr, t1.name, Sum(sale), Sum(sebest), t1.cpodrfrom from  
(select KatSopr.dSopr, KatSopr.VhodNal, Katmc.name, Sporder.kol*Sporder.srprice   
 sebest, Spsopr.price*Sporder.kol  sale, KatSopr.cPodrFrom  from vrn.KatSopr, vrn.Katmc, vrn.Sporder, vrn.Spsopr where  
 KatSopr.VidSopr=201 and KatSopr.dSopr >= 132055297  and KatSopr.dSopr <= 132055562 and  
 KatSopr.nRec = Spsopr.cSopr and  
 Spsopr.nrec=Sporder.cspsopr and Sporder.vidorder=1 and Spsopr.cmcusl = Katmc.fnrec ) t1 group by t1.dsopr, t1.name, t1.cpodrfrom 
 
10.02.2015 13:11:31 [SAVINKOV]:
Ошибка(2,21): Таблица или представление не определено KATSOPR 
Причем, если запрос выполнить в суппорте или в Toad (изменив в этом случае имена полей - подставив префикс f ), все работает, данные получаю верные.

В чем ошибка? (Пытался выполнять без имени схемы - ошибок нет, данных нет, пытался ставить поля с префиксом f - та же ошибка)
Oracle-8. Галактика 8.10
savov
Местный житель
Сообщения: 589
Зарегистрирован: 29 мар 2005, 17:49
Откуда: Воронеж ОАО Верофарм. Воронеж

Re: Прямой SQL

Сообщение savov »

Вопрос снят!
savov
Местный житель
Сообщения: 589
Зарегистрирован: 29 мар 2005, 17:49
Откуда: Воронеж ОАО Верофарм. Воронеж

Re: Прямой SQL

Сообщение savov »

Еще раз к вопросу прямого sql в ard отчетах.
Сделал в проекте временную таблицу. DSQL запросом выгрузил в нее данные. А вот еще раз обработать эту таблицу другим прямым скулем не могу. Пишет, что нет такой таблицы.
В view таблица описана. В чем может быть засада? Или все-таки ард с прямым скулем не дружит?
Den
Местный житель
Сообщения: 1842
Зарегистрирован: 29 мар 2005, 17:49
Откуда: Ярославская область ОАО "Часовой завод Чайка" г. Углич
Контактная информация:

Re: Прямой SQL

Сообщение Den »

savov писал(а):А вот еще раз обработать эту таблицу другим прямым скулем не могу
если Вы к ней хотите обратиться в запросе dsql, то ее нужно объявить как временную таблицу dsql (sqlCreateTmpTable)
Хотя в ard это все будет как ходьба по минному полю. Но попробовать можно.
RAJAH
Местный житель
Сообщения: 932
Зарегистрирован: 18 фев 2008, 12:49

Re: Прямой SQL

Сообщение RAJAH »

Den писал(а):Хотя в ard это все будет как ходьба по минному полю.
Не знаю, почему у народа такое предубеждение к ard с DSQL: у меня куча таких отчётов, никаких особых проблем не вижу.
Ответить