faqs.org.ru

 Главная > Программирование > Языки Pascal/Delphi >

FAQ по работе с СУБД на Delphi

Секция 3 из 3 - Предыдущая - Следующая
Все секции - 1 - 2 - 3

var S: TBlobStream;
    B: pointer;
    c: integer;

Table1.Edit;
S := TBlobStream.Create(Table1BlobField as TBlobField, bmWrite); {кажется, так}
C := S.Write(B, C);
Table1.Post;
S.Destroy;

или так

var S: TMemoryStream;
    B: pointer;
    C: integer;

S := TMemoryStream.Create;
...
Table1.Edit;
S.Clear;
S.SetSize(C);
C := S.Write(B,C);
(Table1BlobField as TBlobField).LoadFromStream(S);
S.Clear;
Table1.Post;
...
S.Destroy;

Alexey Kats
(2:463/201.9)
.

Q>:
(DBF) Как открыть индексированную таблицу dBase, если нет файла *.MDX?
A>:
Для DBASE-таблицы встроенными средствами ты не перестроишь индекс,
если его нет.  Для этой цели мне пришлось написать процедуру для
физического удаления признака индексации в самом dbf файле и после ее
применения добавлять индексы заново. Для этого в заголовок файла dbf
по смещению 28(dec) записываешь 0. По другому никак не выходит(я долго
бился)- вот для Paradox таблиц все Ok.

Олег (GOS)
oleg@avia.cmw.ru
.

Q>:
(MSSQL) Можно ли вызвать Stored Procedure через TQuery, если она
не возвращает курсора?
A>:
В случае MS SQL нужно написать:
Query1.Sql:='declare @res'+#13#10+'exec MyFunc :Param1,:Param2,@res OUTPUT';
Query1.Open;
Result:=Query1.FieldByName('Column1').Value;
Query1.Close;

Konstantin Suslov
(2:5020/300.16)
.

Q>:
(Oracle) Как настроить Personal Oracle с русским языком на корректную работу
с числами и BDE?
A>:
прописать в \HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE параметр:
NLS_NUMERIC_CHARACTERS = '.,'
или
после соединения с ORACLE выполнить
ALTER SESSION SET NLS_NUMERIC_CHARACTERS = '.,'

Aleksei Alekseenko
(2:5030/548.2)
Voice phone: 007-812-694-8625
.

Q>:
(MSSQL) Как настроить MS SQL Server 6.5 на корректную работу
с числами и BDE при выполнении UPDATE?
A>:
  Дело в том, что SQL Links на _NT_ишном клиенте шлет на сеpвеp дату как
1-янв-97, что сеpвеp не пpиемлет. Совеpшенно случайно я нашел системный скpипт,
котоpый подключает pусский и болгаpский языки.

   - выполни sp_configure и убедись, что у тебя default sortorder id==106 (rus
case insens) или 105 (rus case sens). Если нет - пеpеставь сеpвеp.

   - найди в каталоге c:\mssql\install скpипт instlang.sql и запусти его.

   - либо pуками каждому пpоставь каждому логину, pаботающему с NT, язык
pусский, либо поставь его как default language сеpвеpу. В этом случае 95-м
клиентам пpидется pуками пpописать в логине язык us_english, иначе они
пеpестанут pаботать.

   Для установки russian как default надо выполнить скpипт:

   exec sp_configure 'default language', 2
   go
   reconfigure
   go

Vadim Shcolin
vadim@vsh.spb.su
(2:5030/87.91)
.

Q>:
Как научить VCL делать Refresh для запросов правильно?
Особенно интересует Refresh для связки Master-Detail.
A>:
(IB?)
Старо как мир, и нет ничего военного:

=== Cut ===
procedure  RefreshQuery (Query : TQuery; F : boolean);
var B : TBookMark;
begin
 with Query do
   if Query.Active then
   begin
     B:=GetBookMark;
     try
       Close;
       Unprepare;  {Если не поставить этого, то если используется select
SP, то иногда последующая операция вешает сервер.
                    Кто скажет почему?!}
       Active:=True;
       if F then begin
         try
           GotoBookMark(B)
         except
           on EDatabaseError do First;
         end
       end
       else First;
     finally
       FreeBookmark(B);
     end;
   end;
end;
=== Cut ===

Eugene Zhilkin
(2:461/88)

Уфф! Кажется, лyчше yже не сделать. :)

dbtables можно опционально пpопатчить (см.в конце), чтобы иметь такой вот
pyлезный Detail query.

>== Режем pаз ==<

Update for dbtables.pas

    New interface function DoRefreshQuery can Refresh TQuery component in
master-detail scheme and alone.
    TQuery.RefreshParams should be updated

function GetFieldNamesStr(DataSet: TDataSet): String;
var
  I: Integer;
begin
  Result := '';
  with DataSet do
    for I := 0 to FieldCount - 1 do
      Result := Result + Fields[I].FieldName + ';';
end;

procedure DoRefreshQuery(Query: TQuery; KeyFields: String; BookMarkSearch:
Boolean);
var
  Fields: TList;
  KeyValues: Variant;
  KeyNames: String;
  Bmk: TBookmark;
  I: Integer;
  BookmarkFound: Boolean;
  CanLocate: Boolean;
begin
  Fields := TList.Create;
  if KeyFields = '' then KeyFields := GetFieldNamesStr(Query);
  try
    Query.GetFieldList(Fields, KeyFields);
    for I := Fields.Count - 1 downto 0 do
      with TField(Fields[I]) do
        if Calculated or Lookup then Fields.Delete(I);
    CanLocate := Fields.Count > 0;
    if CanLocate then
    begin
      if Fields.Count = 1 then
        KeyValues := TField(Fields[0]).Value
      else begin
        KeyValues := VarArrayCreate([0, Fields.Count - 1], varVariant);
        KeyValues[0] := TField(Fields[0]).Value;
      end;
      KeyNames := TField(Fields[0]).FieldName;
      for I := 1 to Fields.Count - 1 do
      begin
        KeyNames := KeyNames + ';' + TField(Fields[I]).FieldName;
        KeyValues[I] := TField(Fields[I]).Value;
      end;
    end;
  finally
    Fields.Free;
  end;
  with Query do
  begin
    Bmk := nil;
    DisableControls;
    try
      BookmarkFound := False;
      if BookMarkSearch then
        Bmk := GetBookmark;
      Close;
      Open;
      if Assigned(Bmk) then
      try
        GotoBookMark(Bmk);
        BookmarkFound := True;
      except  end;
      if not BookmarkFound and CanLocate then
        Locate(KeyNames, KeyValues, []);
    finally
      EnableControls;
      Screen.Cursor := crDefault;
      FreeBookmark(Bmk);
    end;
  end;
end;


procedure TQuery.RefreshParams;
var
  DataSet: TDataSet;
begin
  DisableControls;
  try
    if FDataLink.DataSource <> nil then
    begin
      DataSet := FDataLink.DataSource.DataSet;
      if DataSet <> nil then
        if DataSet.Active and (DataSet.State <> dsSetKey) then
          DoRefreshQuery(Self, GetFieldNamesStr(Self), False);
    end;
  finally
    EnableControls;
  end;
end;

>== Режем два ==<

Vladimir Gaitanoff
(2:5020/880.5)
.

Q>:
Как пересчитать все Calculated Fields без переоткрытия TDataSet?
A>:
    Resync([rmExact, rmCenter])

Vladimir Gaitanoff
(2:5020/880.5)
.

Q>:
(Oracle) Как в Oracle создать sequence с некоторого номера?
A>:
create sequence minvalue 10;

Andrey V. Petrow
(2:5030/53.334)
.

Q>:
Как создать текстовую таблицу с поддержкой русских букв?
A>:
Делай pаз - create database ... без всяких default character set
Делай два - запускай BDE Config и создавай алиас
Делай тpи - делай настpойки:

стpаница   паpаметp        значение         Пpимечание
Drivers    LANGDRIVER      'ascii' ANSI     У INTERBASE
Alias      LANGDRIVER      пусто
System     LANGDRIVER      'ascii' ANSI
System     DEFAULT DRIVER  ASCIIDRV

Alexey Malinin
(2:5057/19.18)
.

Q>:
(Oracle) Как решать некоторые вопросы при подключении к Oracle?
A>:

 DD> 1. Все поля (TField), опpеделенные в фоpмах, имеющие типы TDateField,
 DD> TSmallIntField - пpи откpытии таблицы pугаются: Field "..." is not of
 DD> expected type. Посмотpел - пpи пеpеопpеделении их под Oracle'ом они

     Чтобы "увидеть" integer-поля нужно в настройке Alias'а Oracle в BDE
установить Enable Integers -> True (и напрочь будет потерян Locate по этим якобы
int/smallint полям).  С датами, возможно, тоже надо разбираться
через настройки Win & Oracle. У меня в Win дата формата "дд.мм.гггг", в Oracle
NLS_LANG -> AMERICAN_AMERICA.CL8MSWIN1251 и с датами все гут.

 DD> 2. Используя в SQL
 DD> стpоки типа 'SELECT XX FROM YY WHERE XX="QQQ"' мы поступали
 DD> непpавильно,
 DD> т.к. двойные кавычки в Oracle обpабатывабтся не так, как в Btrieve.
 DD> Тут мы

    Oracle в данном случае не причем. Это глюк BDE. Лечилось просто - вместо
обрамления двойными кавычками строкового значения, нужно обрамлять его с
помощью #39, примерно так

      MySQLString:='SELECT XX FROM YY WHERE XX='+#39+'QQQ'+#39;

Belsky Roman
(2:450/94.75)

 SS> У кого-нибудь есть опыт по настройке BDE ? Откликнитесь плиз! При
 SS> попытке соединиться с базой вылезает ошибка: Vendor failed init!
 SS> Delphi запускаю под 95. На всякий случай пути к \BDE и ORAWIN\BIN я
 SS> проставил! orant71.dll (родной или переименнованый ora72win.dll)
 SS> закидывал куда угодно, но.... все равно вылетает ошибка BDE Error
 SS> 15879 Vendor failed init :-(

   Клиент у тебя NT, как я понял?
   ora7x.dll - 32bit клиент для win95
   orant7x.dll - 32bit клиент для NT
   ora7xwin.dll - 16bit клиент для win

   т.е. ora7xwin в Delphi3 вообще ставить бесполезно (16bit для 32bit appl).
  ora*71.dll у меня изначально к ORACLE 7.2 не коннектился - они там как-то
  резко сменили OCI. Правда потом ora72win.dll с Pers. Oracle 7.3 работал,
  но все равно лучше, наверное, чтобы номер версии dll был не ниже версии
  сервера.

    А вообще я 32bit дельфях в Vendor Init давно прописываю OCIW32.dll -
  он всегда для последней версии сервера с которым ты работаешь.

  Это IMHO. Но у меня Delphi3 и Delphi1 коннектятся как с Oracle 7.1 на
  Unix'е, так и с Pers. Oracle 7.3

Alex Mironov
http://WWW.MEB.RU/igorvl.html
(2:5020/238.46)
.

Q>:
Как заставить BDE сохранять в БД поле времени с сотыми долями секунды?
A>:
Если руками, то в BDE Administrator. Если в в инсталлялке, то -

В пункте Make Registry Changes InstallShield'а создай ключ
HKEY_LOCAL_MACHINE\SOFTWARE\Borland\Database Engine\Settings\SYSTEM\
FORMATS\TIME\MILSECONDS=TRUE

Alexey Yashin
(2:5020/62.31)
.

Q>:
Как создать Calculated Fields в RunTime?
A>:
See book "Developing Custom Delphi Components" by Ray Konopka.

This is little bit corrected example from this book:

function TMyClass.CreateCalcField( const AFieldName:string;
AFieldClass:TFieldClass; ASize:Word ) : TField;
begin
  Result := FDataSet.FindField(AFieldName); // Field may already exists!
  if Result<>nil then Exit;
  if AFieldClass=nil then DBErrorFmt( SUnknownFieldType, [AFieldName] );
  Result := FieldClass.Create(Owner);
  with Result do
  try
    FieldName := AFieldName;
    if (Result is TStringField) or
       (Result is TBCDField) or
       (Result is TBlobField) or
       (Result is TBytesField) or
       (Result is TVarBytesField)
    then Size := ASize;
    Calculated := True;
    DataSet := FDataset;
    Name := FDataSet.Name+AFieldName;
  except
    Free;  // We must release allocated memory on error!
    raise;
  end;
end;

Alex Konshin
(2:5030/217.217)
.

Q>:
Как создать новый запрос и скопировать туда точно такие же описания полей?
A>:
Копируешь FieldDefs. Проходишь циклом по FieldDefs.Items[i].CreateField(Owner);

Alex Konshin
(2:5030/217.217)
.

Q>:
(DB2) Почему DB2 ругается на Create Trigger?
A>:
  Я тут писал по поводу того, что у меня не pаботали тpиггеpы. Все дело
оказалось в пpавиле написания команды "create trigger". Если все остальные
команды коppектно воспpинимаются на любом pегистpе, то эта только набpанная
одними большими буквами.

Aleksey Sushko
(2:4615/7.32)
.

Q>:
(IB) Как заставить Interbase принять COLLATE PXW_CYRL по умолчанию?
(AA: Это очень полезно при прямой работе с IB из PowerDesigner)
A>:
Чтобы не писать каждый раз COLLATE я сделал следующее:

1) Создал сохраненную процедуру

create procedure fix_character_sets
as
begin
  update rdb$character_sets
    set rdb$default_collate_name = 'PXW_CYRL'
    where rdb$character_set_name = 'WIN1251' and
        rdb$default_collate_name = 'WIN1251';
end

2) Запустил ее один раз.

3) Создаю таблицы без COLLATE.

4) После восстановления из архива, запускаю еще раз.

Кудрин Олег, АТС-55, Красноярск.
oleg@ats.telecom.krasnoyarsk.su
.

Q>:
Есть некоторая таблица и требуется при нажатии на кнопку создавать
таблицы такой же структуры, подскажите как это удобнее всего сделать.
A>:
Удобней всего, напpимеp, так -
with bmovMyBatchMove do
begin
Mode := bmCopy;
RecordCount := 1;
Execute;
Destination.Delete;
end;

Akzhan Abdulin
(2:5040/55.46)

  Неправда Ваша! ;) Этот загадочный BatchMove имеет одну очень неприятную
особенность (по крайней мере при работе с DBF таблицами и в D1), как-то:
увеличивает в создаваемых таблицах в полях типа NUMBER количество значащих
цифирей после запятой (не помню - возможно, что и до), если там указаны
небольшие (~ 1-3 цифр) значения :(. Я эту особенность побороть не сумел, а
мириться с ней в условиях нашей конторы (когда приходится бороться за место под
солнцем с программистами на Clipper и FoxPro совершенно неприемлимо.
  Кроме того, в предложенном выше варианте еще и запись удалять приходится...:)
  Решалась же эта проблема следующим способом:

>============  Cut Begin  Myutils.Pas ====================

procedure CopyStruct(SrcTable,DestTable: TTable; cpyFields: array of string);
var
  i: Integer;
  bActive: Boolean;
  SrcDatabase,DestDatabase: TDatabase;
  iSrcMemSize,iDestMemSize: Integer;
  pSrcFldDes: PFldDesc;
  CrtTableDesc: CRTblDesc;
  bNeedAllFields: Boolean;
begin
  SrcDatabase:=Session.OpenDatabase(SrcTable.DatabaseName);
  try
    DestDatabase:=Session.OpenDatabase(DestTable.DatabaseName);
    try
      bActive:=SrcTable.Active;
      SrcTable.FieldDefs.Update;
      iSrcMemSize:=SrcTable.FieldDefs.Count*SizeOf(FLDDesc);
      pSrcFldDes:=AllocMem(iSrcMemSize);
      if pSrcFldDes = nil then
        raise EOutOfMemory.Create('=х iтрEрхE ярь Eш!');
      try
        SrcTable.Open;
        Check(DbiGetFieldDescs(SrcTable.Handle,pSrcFldDes));
        SrcTable.Active:=bActive;
        FillChar(CrtTableDesc,SizeOf(CrtTableDesc),0);
        with CrtTableDesc do
        begin
          StrPcopy(szTblName,DestTable.TableName);
          StrPcopy(szTblType,'DBASE');
          if(Length(cpyFields[0]) = 0) or (cpyFields[0] = '*') then
          begin
            bNeedAllFields:=True;
            SrcTable.FieldDefs.Update;
            iFldCount:=SrcTable.FieldDefs.Count;
          end
          else
          begin
            bNeedAllFields:=False;
            iFldCount:=High(cpyFields)+1;
          end;
          iDestMemSize:=iFldCount*Sizeof(FLDDesc);
          CrtTableDesc.pFLDDesc:=AllocMem(iDestMemSize);
          if CrtTableDesc.pFLDDesc = nil then
            raise EOutOfMemory.Create('=х iтрEрхE ярь Eш!');
        end;
        try
          if bNeedAllFields then
            for i:=0 to CrtTableDesc.iFldCount-1 do
              Move(PFieldDescList(pSrcFldDes)^[i],
              PFieldDescList(CrtTableDesc.pFLDDesc)^[i],SizeOf(FldDesc))
          else
            for i:=0 to CrtTableDesc.iFldCount-1 do
              Move(PFieldDescList(pSrcFldDes)^[SrcTable.FieldDefs.Find(cpyField
s[i]).FieldNo-1],
              PFieldDescList(CrtTableDesc.pFLDDesc)^[i],SizeOf(FldDesc));
          Check(DbiCreateTable(DestDatabase.Handle,True,CrtTableDesc));
        finally
          FreeMem(CrtTableDesc.pFLDDesc,iDestMemSize);
        end;
      finally
        FreeMem(pSrcFldDes,iSrcMemSize);
      end;
    finally
      Session.CloseDatabase(DestDatabase);
    end;
  finally
    Session.CloseDatabase(SrcDatabase);
  end;
end;

>============   Cut End   ====================

Vlad Fillippov
(2:5055/34.3)
.

Q>:
(SAW) Как бы мне соорудить в SP исключение, чтобы его увидел Delphi-клиент?
A>:

 SS>   sqlstate='99999' не подходит, т.к. хочется на клиенте видеть код
 SS> исключения.

  Используй RAISERROR с кодом >20000. Если еще пpи этом научишься без потеpь
пеpедавать на Delphi-клиента pусские pугательства, то скажи мне как ты этого
добился :). У меня для этого pаботает pедкостный извpат, даже людям показать
стыдно :).

Alexander Tesanov
(2:5015/23.5)
.

Секция 3 из 3 - Предыдущая - Следующая

Вернуться в раздел "Языки Pascal/Delphi" - Обсудить эту статью на Форуме
Главная - Поиск по сайту - О проекте - Форум - Обратная связь

© faqs.org.ru