Přidat otázku mezi oblíbenéZasílat nové odpovědi e-mailemVyřešeno Delphi - BDE - TQuery - tabuľka v pamäti

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, DB, Grids, DBGrids, DBTables;

type
  TForm1 = class(TForm)
    DBGrid1: TDBGrid;
    DataSource1: TDataSource;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    Query1: TQuery;
  end;

var
  Form1: TForm1;
  Field1: TFloatField;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  Query1 := TQuery.Create(Self);
  Field1 := TFloatField.Create(nil);
  Field1.FieldName := 'Cislo';
//  Field1.Size := 5;
  Field1.DisplayWidth := 5;
  Field1.Precision := 2;
  Query1.Fields.Add(Field1);
  Query1.Active := True;
  DataSource1.DataSet := Query1;

  try
    Query1.Append;
    Query1.Fields[0].AsFloat := 10;
    Query1.Post;
  finally
  end;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  Query1.Free;
end;

end.

Čo robím zle? Ak povolím riadok Field1.Size, tak dostanem chybu, že je to chybná dĺžka, ak to nepovolím, tak pri Active := True dostanem "No SQL statement available". Keďže je tabuľka vytváraná v pamäti, tak jej fyzické meno neexistuje. Zrejme je chyba niekde v tom. Tiež by ma zaujímalo, čo s tou dĺžkou.

Předmět Autor Datum
A co s tim Fieldem chces vlastne delat ? TField se definuje nad existujici tabulkou. Neslouzi k defi…
Jan Fiala 18.07.2006 20:10
Jan Fiala
V helpe som našiel toto: with Table1 do begin Active := False; DatabaseName := 'DBDEMOS'; TableType…
msx. 18.07.2006 20:22
msx.
Table.Exists nekontroluje existenci objektu (to tve vytvoreni), ale existenci tabulky na disku. Muse…
Jan Fiala 18.07.2006 20:39
Jan Fiala
Veď je tu riadok: TableName := 'CustInfo';
msx. 18.07.2006 20:47
msx.
Pises, ze ti to neprojde pres IF - THEN Co ti to napise ? Mas nainstalovane vzorove databaze ? Proto…
Jan Fiala 18.07.2006 21:30
Jan Fiala
Určite tie databázy mám. Nainštaloval som všetko okrem toho, čo sa pýta inštalovať po nainštalovaní…
msx. 18.07.2006 22:22
msx.
Bodejd by nebyla splnena, kdyz ta tabulka existuje :-P Zkousel jsi zmenit jmeno tabulky ? Databazi n…
Jan Fiala 18.07.2006 23:26
Jan Fiala
Áno, už som to zistil. Pri prvom prechode sa nič nestalo, lebo som nenastavil Active na True a nemal…
msx. 18.07.2006 23:59
msx.
Query se pouziva na vyber dat. Takze se nbevytvari zadne struktury, ale pomoci SQL prikazu se vybira…
Jan Fiala 19.07.2006 05:37
Jan Fiala
Pokud chces memory tabulku, jdes na to uplne spatne. Query slouzi pro vyber dat z existujici databaz…
Jan Fiala 18.07.2006 20:12
Jan Fiala
Nie je to celkom tak. Ja chcem toto: ak neexistuje tabuľka vytvoriť; uložiť; otvoriť; pracovať s ňo…
msx. 18.07.2006 20:25
msx.
A neni jednodussi jit cestou: Pokud neexistuje tabulka, zkopiruji ji z adresare, kde mam vychozi pra…
Jan Fiala 18.07.2006 20:38
Jan Fiala
Už som nad tým uvažoval, ale sa mi to riešenie veľmi nepáči. Zdá sa mi to také neprogramátorské. Chc…
msx. 18.07.2006 20:47
msx.
Jestliže chceš vytvořit programově tabulku, když není na disku přítomna, tak na to musíš takto: Na f…
Rce 18.07.2006 22:50
Rce
Ďakujem, ale už mi funguje čisto programový spôsob. Predpokladám, že toto je vlastne to isté, ale ce…
msx. 19.07.2006 00:02
msx.
Program je kratší a přehlednější, když to navrhneš visuálně. Na rychlost a nárok procesoru to bude a…
Rce 19.07.2006 00:13
Rce
A ešte odpoveď na tú otázku naspodu príspevku? http://pc.poradna.net/question/view/47861-delphi-bd e…
msx. 19.07.2006 00:46
msx.
TQuery není tabulka, je to SQL dotaz. TQuery vůbec nemusí mít definované fieldy (ostatně TTable také…
Rce 19.07.2006 01:29
Rce
No, to mi ako odpoveď stačí. S TQuery sa dá pracovať rovnako ako s TTable, ak už súbor existuje. Tak…
msx. 19.07.2006 02:03
msx.
Jestli nepoužiješ SQL dotaz (SELECT), pak TQuery použít nemůžeš (teda můžeš: SELECT * FROM tabulka -…
Rce 19.07.2006 02:28
Rce
Mne sa na SQL páči to, že ak "indexujem" cez SQL, tak nemám plno zbytočných súborov. Okrem toho som…
msx. 19.07.2006 03:42
msx.
Indexy mají hodně do sebe. Když použiješ indexy na pole, podle kterých přes SQL vybíráš, tak je SQL…
Rce 19.07.2006 13:10
Rce
Na form nebo TDataModule prskni TTable. V objektu TTable dvojklikem otevři Field editor a nadefinuj…
msx. 20.07.2006 13:17
msx.
Omlouvám se:-[, vyber volbu "New field" a nadegfinuj sloupec tabulky. Opakováním "New field" nadefin…
Rce 20.07.2006 13:26
Rce
Práveže nie, mal som kliknúť na New Field, teraz som zistil, ale už mi to nedovolilo editovať príspe…
msx. 20.07.2006 13:28
msx.
:-[:-[:-[:-[ Jsi sakra rychlej. Než jsem tu blbost po sobě přečetl, tak jsi jí viděl i ty. :-[:-[:-[
Rce 20.07.2006 13:30
Rce
Nie sme každý neomylný. Stane sa kaaždému. Len najhoršie na tom je, že sa to občas stáva v situáciác…
msx. 21.07.2006 00:41
msx.
Díky. :-);-)
Rce 21.07.2006 00:49
Rce
Takže všetko som urobil. Aj indexy pekne vo vizuále vytváram, ale ako zadám do položky TIndexDef.Fie…
msx. 21.07.2006 02:08
msx.
Do pole Fields oddělíš jména sloupců středníkem. Například: "Prijmeni;Jmeno". Pozor, v BDE je drobná…
Rce 21.07.2006 02:29
Rce
Ej a tu je problém. Ja potrebujem, aby to nemalo vlastnosť "case sensitive".
msx. 21.07.2006 02:50
msx.
No však, [ixCaseInsensitive] znamená: ne "case sensitive".
Rce 21.07.2006 02:58
Rce
To in mi trošku uniklo.:-[
msx. 21.07.2006 03:27
msx.
A ešte otázka: TQuery má vlastne všetky vymoženosti ako aj TTable. Vo vizuále mu môžem nahádzať polo…
msx. 21.07.2006 02:12
msx.
TQuery má téměř všechny vymoženosti, protože stojí na třídě TDBDataSet a tím všechny podobnosti konč…
Rce 21.07.2006 02:46
Rce
To je teraz na mňa trochu moc. Ten súbor mám, pozriem si to.
msx. 21.07.2006 02:56
msx.
Všetko mi funguje, až na jeden nepochopiteľný detail. Na začiatku sa mi vytvorí tabuľka, ktorá na di…
msx. 21.07.2006 03:39
msx.
Podivné. Já to dělám taky tak: procedure GenKdyzNeni (Tab: TTable; const FN: String20; const lJePoI…
Rce 21.07.2006 11:47
Rce
Zistil som, že vlastnosť Exist má stále hodnotu False.
msx. 21.07.2006 11:59
msx.
Ak sa nebojíš mojich kódov, tak ti to asi pošlem. Ja som už nervy s tým stratil. Už som všetky vlast…
msx. 21.07.2006 12:07
msx.
Tak jsem ti před chvílí majlem odpověděl. ;-)
Rce 22.07.2006 00:19
Rce
Nejako ten mail mešká. Ale veď sa dočkám. Ďakujem.:beer:
msx. 22.07.2006 00:50
msx.
Á doprde**.. Já si to z práce forwardoval domů a reply se poslalo zpátky do práce :x:. Už jsem to na…
Rce 22.07.2006 00:59
Rce
Síce meškal, ale práve dorazil, idem čítať, ešte raz ďakujem.
msx. 22.07.2006 00:59
msx.
Nemáš za co.;-):-)
Rce 22.07.2006 01:00
Rce
Ďakujem. Pomohlo. A ja si môžem lámať hlavu. Môžem poprosiť o vysvetlenie významu DatabaseName? V he…
msx. 22.07.2006 01:04
msx.
Je to název databáze. V BDE je databáze řešena jako adresář, tudíž zde jde napsat cesta k datům. Je…
Rce 22.07.2006 01:32
Rce
Ďakujem, teraz už toto multirozvláknené vlákno hádam môžem uzavrieť.:-)
msx. 22.07.2006 01:42
msx.
Dobrá. Kdyžtak založ čerstvé vlákno na nový dotaz.:-);-) poslední
Rce 22.07.2006 01:46
Rce

V helpe som našiel toto:

with Table1 do begin
  Active := False;  
  DatabaseName := 'DBDEMOS';
  TableType := ttParadox;
  TableName := 'CustInfo';

  { Don't overwrite an existing table }

  if not Table1.Exists then begin
    { The Table component must not be active }
    { First, describe the type of table and give }
    { it a name }
    { Next, describe the fields in the table }
    with FieldDefs do begin
      Clear;
      with AddFieldDef do begin
        Name := 'Field1';
        DataType := ftInteger;
        Required := True;
      end;
      with AddFieldDef do begin

        Name := 'Field2';
        DataType := ftString;
        Size := 30;
      end;
    end;
    { Next, describe any indexes }
    with IndexDefs do begin
      Clear;
      { The 1st index has no name because it is
      { a Paradox primary key }
      with AddIndexDef do begin
        Name := '';
        Fields := 'Field1';
        Options := [ixPrimary];
      end;
      with AddIndexDef do begin

        Name := 'Fld2Indx';
        Fields := 'Field2';
        Options := [ixCaseInsensitive];
      end;
    end;
    { Call the CreateTable method to create the table }
    CreateTable;
  end;
end;

Problém je v tom, že mi to neprejde vetvou then. Na začiatku mám toto:

procedure TForm1.FormCreate(Sender: TObject);
begin
  Table1 := TTable.Create(nil);

Určite tie databázy mám. Nainštaloval som všetko okrem toho, čo sa pýta inštalovať po nainštalovaní Delphi. Ako sa to len volalo? Malo to myslím niečo spoločné s Javou, ale neviem si spomenúť na názov. Interbase som nainštaloval tiež. Tie databázy neviem v akom adresári majú byť a neviem ich nájsť.

Ale v príklade je písané, že to vytvorí databázu iba v prípade, že neexistuje na disku, takže aký to má súvis s demo databázami?::)

Edit: Nenapíše to nič, len to prejde na koniec vetvy then. Podmienka je totiž splnená.

Áno, už som to zistil. Pri prvom prechode sa nič nestalo, lebo som nenastavil Active na True a nemal som nadefinovaný DataSet v DataSource. TAkže DBGrid ostal prázdny. Teraz som si uvedomil, že tú tabuľku to niekde muselo vytvoriť, tak som na vašu radu zmenil meno. Vetva then prebehla a potom som si uvedomil to Active a DataSet, tak som zmenil meno znova a pridal som priradenia (je to totiž vo vetve then (ale to len teraz na skúšku)). Funguje to a mám, čo som potreboval. Vyriešené, ďakujem za pomoc.

Teraz ešte taký detail: Ak chcem vytvoriť TQuery, tak to musím urobiť cez TTable a ten následne otvoriť v TQuery? Alebo sa dá nejako vytvoriť priamo TQuery?

Query se pouziva na vyber dat. Takze se nbevytvari zadne struktury, ale pomoci SQL prikazu se vybiraji data z existujicich tabulek:

SELECT a.Cislo, a.Jmeno, b.Plat
FROM Pracovnici a, Platy b
WHERE a.Cislo = b.Cislo and b.Obdobi = '200605'
ORDER BY b.Plat

Vysledkem je tabulka se 3 poli (Cislo, Jmeno, Plat) a jejich typ a velikost je dana poli v puvodnich tabulkach

Pokud chces memory tabulku, jdes na to uplne spatne. Query slouzi pro vyber dat z existujici databaze. Ty potrebujes napr. ClientDataset z Delphi nebo stahnout kbMemTable, tusim, ze i v rx library je jedna memory tabulka.

Jestliže chceš vytvořit programově tabulku, když není na disku přítomna, tak na to musíš takto:
Na form nebo TDataModule prskni TTable. V objektu TTable dvojklikem otevři Field editor a nadefinuj všechny potřebné fieldy (pravá packa myši v prostoru Field Editoru, vybrat Add Fields.. a dál už uvidíš). Dál dvojklikem na IndexDefs (v Object Inspectoru) obdobným způsobem vytvoř potřebné indexy. Nakonec nastav StoreDefs na TRUE a vhodně TableName a DatabaseName. V programu udělej něco podobného:

if not Table1.Exists then begin
    Table1.FieldDefs.Clear (); // Pro sychr, kdyby se to použilo vícekrát
    Table1.CreateTable (); Table1.Close ();
end;

Ďakujem, ale už mi funguje čisto programový spôsob. Predpokladám, že toto je vlastne to isté, ale cez vizuál. Veď časom uvidím, čo mi bude lepšie, ale asi prejdem na vizuál. Ani ma nenapadlo, že aj tak to ide.:-)

Program je kratší a přehlednější, když to navrhneš visuálně. Na rychlost a nárok procesoru to bude asi 1:1. Při visuálním návrhu se většina práce udělá "za oponou" - z resources se to přežvejká do naprosto stejné podoby, kterou ty naprogramuješ růčo. Jako tréning programování je to lepší udělat čistě programově, pro rutinní použití je rychlejší a spolehlivější visuální návrh - od toho byl vymyšlen :)).

TQuery není tabulka, je to SQL dotaz. TQuery vůbec nemusí mít definované fieldy (ostatně TTable také ne, jestliže slouží jen ke zpracování existující tabulky a neslouží k vytvoření nové). Výsledkem TQuery je tabulka, která vznikne dotazem SQL (SELECT f1, f2,... from tabulka where....). Výsledná tabulka je jednosměrná (lze se pohybovat jen vpřed) má-li TQuery.UniDirectional := TRUE a lze v ní dělat změny je-li TQuery.RequestLive := TRUE. Výsledkem TQuery může být i výběr z několika tabulek a změny se promítnou zpět do příslušných tabulek (podmínkou je, aby měly primární klíče). Přístup k polím může být třeba před Query1.FieldByName ('Jmeno').AsString.

No, to mi ako odpoveď stačí. S TQuery sa dá pracovať rovnako ako s TTable, ak už súbor existuje. Takže to urobím tak, že vytvorím TTable, zavriem, otvorím TQuery a môžem s tým veselo pracovať.:-)

Jestli nepoužiješ SQL dotaz (SELECT), pak TQuery použít nemůžeš (teda můžeš: SELECT * FROM tabulka - ale je to zbytečné drbání přes cizí hlavu). Pakli budeš číst tabulku sekvenčně a všechny věty, maximálně seřazenou nějakým indexem, je lépe použít rovnou TTable která míří rvonou do souboru. TQuery nejdřív přenese věty podle SQL dotazu do pracovního souboru na lokálním počítači (v BDE Session.PrivateDir), tam se to zpracuje a případné změny pak zase vrací do tabulky. TTable pracuje se souborem přímo a rychleji (když se nečiní SQL výběr z jedné nebo vícero tabulek). Můžeš klidně vytvořit tabulku přes TTable a dál s ní pracovat přes totéž TTable.
//Edit: I když na druhou stranu by se programátor měl učit pracovat s tabulkama jen přes SQL příkazy... :-);-)
//Edit2: A když už jsme u toho, lze tabulku i v Delphi+BDE založit příkazem SQL (pástnuto z helpu BDE) :-D:

CREATE TABLE "employee.db"
(
  Last_Name CHAR(20),
  First_Name CHAR(15),
  Salary NUMERIC(10,2),
  Dept_No SMALLINT,
  PRIMARY KEY (Last_Name, First_Name)
)

Mne sa na SQL páči to, že ak "indexujem" cez SQL, tak nemám plno zbytočných súborov. Okrem toho som si užil "srandy" s problémovými indexovými súbormi, ktoré som musel vytvárať nanovo. Tých tabuliek bude dosť a ešte pre každú index, tak to je na mňa veľa. Je teda ozaj lepšie používať TTable? Počítam rádovo tisíce záznamov v hlavnej databázi, ktorá bude stále narastať a vytvárať sa bude z iných.

Indexy mají hodně do sebe. Když použiješ indexy na pole, podle kterých přes SQL vybíráš, tak je SQL využije a jede velice podstatně rychleji. Jinak si SQL server (záleží na konkrétní implementaci - BDE, MSSQL, MYSQL, ...) vytvoří tytéž indexy přechodně, což při častých dotazech zdržuje, než když už jsou hotovy. Takže indexové soubory nejsou nikdy "zbytečné". Shrnul bych to asi takto: Když pracuješ s jednou tabulkou bez vazeb na další (bez SELECT ... JOIN) a zpracováváš všechny věty (bez SELECT ... WHERE/HAVING), je rychlejší použít tabulku (i pro jiné SQL servery - třeba MSSQL, MySQL - zde použiješ TAdoTable). TQuery (obecně tedy dotaz SQL - BTW SQL dotaz jde použít přímo přes TDatabase bez TQuery:-)) použij, jestliže spojuješ vícero tabulek do sebe a vybíráš jen některé záznamy podmínkama WHERE popřípadně když vysčítáváš tabulku (SELECT...GROUP). Ufff. :))

Na form nebo TDataModule prskni TTable. V objektu TTable dvojklikem otevři Field editor a nadefinuj všechny potřebné fieldy (pravá packa myši v prostoru Field Editoru, vybrat Add Fields.. a dál už uvidíš).

Nedokážem pridať položku (stĺpec), pretože mi to stále dokola vypisuje toto:
[ttablewv0.gif]Samozrejme, že tabuľka neexistuje. Veď preto ju idem vytvoriť, aby existovala. Čo s tým teraz?

Takže všetko som urobil. Aj indexy pekne vo vizuále vytváram, ale ako zadám do položky TIndexDef.Fields vo vizuále dve položky naraz? Napríklad MENO, SIET? Ide o to, že neviem akým znakom oddeliť tie dve položky v reťazci.

Do pole Fields oddělíš jména sloupců středníkem. Například: "Prijmeni;Jmeno". Pozor, v BDE je drobná chyba: Ve všech indexech (mimo primárního) zaškrtní "ixCaseInsensitive" - i když se jedná třeba o číslo. Jinak to může při vytváření tabulky nebo při obnově indexů řvát neprávem chyby.

A ešte otázka: TQuery má vlastne všetky vymoženosti ako aj TTable. Vo vizuále mu môžem nahádzať položky, indexy už nie. Dá sa takto vytvoriť aj databáza v TQuery? Alebo len tým SQL príkazom spomenutým nižšie (čiže vo vizuále si môžem nahadzovať čo chcem a podstatný je SQL príkaz)?

TQuery má téměř všechny vymoženosti, protože stojí na třídě TDBDataSet a tím všechny podobnosti končí. TTable je prostě přímé spojení s tabulkou, TQuery je výsledek dotazu SELECT (což je v podstatě virtuální tabulka). Přes SQL lze vytvořit tabulku, ale musíš použít buď metodu Execute objektu TDatabase - takto Database1.execute (const SQL: String; Params: TParams = nil; Cache: Boolean = False; Cursor: phDBICur = nil): Integer; - význam parametrů viz help. Nebo rychleší je použít přímo API funkce BDE - jestli máš můj modul pro práci s BDE Rce_BDE (nabízel jsem ho kdysi ke stažení), je to metoda ExecSQL. Může vypadat například takto:

{------------------------------ Provede příkaz SQL za pomocí databáze --------------------------}
function ExecSQL (const ASQL: string; ADB: TDatabase; ACursor: phDBICur = nil): LongInt;
{	ASQL	:= Příkaz SQL (DDL nebo DML)							}
{	ADB	:= Objekt databáze, který je použit pro vykonání SQL příkazu			}
{	ACursor	:= Případné handle tabule, kam se narve výsledek (nutné pro SELECT)		}
{Vrací: Počet vět co vrátil příkaz DML (příkaz DDL vrací vždy 0)				}
begin
	Check (DbiQExecDirect (ADB.Handle, qrylangSQL, PChar (ASQL), ACursor));
	if (ACursor <> nil) then Check (DbiGetRecordCount (ACursor^, Result)) else Result := 0;
end;

//Edit Toto je cesta pro příkazy SQL kategorie DDE. Pro příkazy SQL kategorie DML existuje ještě objekt TUpdateSQL, kterým jdou vyslat příkazy DELTE, UPDATE a INSERT (přes výše uvedenou mojí rutinu jdou tyto příkazy vyslat také).
DDE = data definition language = prostředky na definici dat například příkazy CREATE TABLE (vytvoření tabulky), ALTER TABLE (změny definice tabulky), DROP TABLE (smazání tabulky), CREATE INDEX, DROP INDEX.
DML = Data Manipulation Language = manipulace s daty - příkazy SELECT, DELETE (odstranění vět), INSERT (vložení vět z příkazu nebo jiné tabulky), UPDATE (změna položek tabulky).

Všetko mi funguje, až na jeden nepochopiteľný detail. Na začiatku sa mi vytvorí tabuľka, ktorá na disku nie je a po ukončený programu ju na disku nájdem aj s obsahom. Po opätovnom spustení programu mi to prejde vetvou then a tabuľka je čistá:

procedure TfrmPhoneBook.FormCreate(Sender: TObject);
begin
  tblPhoneBook.TableName := PrgPath + cPhoneBook;
  if not tblPhoneBook.Exists then
    begin
      tblPhoneBook.CreateTable;
      tblPhoneBook.Close;
    end;
  tblPhoneBook.Open;
end;

DatabaseName som doteraz nastavené nemal, tak som to rýchlo nastavil na 'DBDEMOS', ale správa sa to rovnako.

Podivné. Já to dělám taky tak:

procedure GenKdyzNeni (Tab: TTable; const FN: String20; const lJePoInst: boolean);
{	Tab		:= Zdejší master ke generování						}
{	FN		:= Název tabule								}
{	lJePoInst	:= true - je po instalaci, hlásit generování, false - drží hubu		}
begin
	oBDE.SetDataPath (Tab, FN); // Nastaví Table.Name a Database name - viz modul Rce_BDE co máš
	if lJePoInst then RceInf (nil, 'Vytváří se ' + Tab.TableName); //Jen ukáže před xicht, že se generuje tabulka
	if not Tab.Exists then begin
		Tab.StoreDefs	:= true { Hovno platný, musí to být v Tab's }; // StoreDefs nastav v TTable!!
		Tab.FieldDefs.Clear (); // Důležité, jestliže je tabulka Tab použita po druhé za běhu programu
		Tab.CreateTable (); Tab.Close () {sychr}; 
		Tab.StoreDefs	:= false;
	end
end;

Ďakujem. Pomohlo. A ja si môžem lámať hlavu. Môžem poprosiť o vysvetlenie významu DatabaseName? V helpe je napísané niečo v zmysle, že to určuje alias databázy alebo proste názov s akým vystupuje databáza, ale nerozumiem, čo to má spoločné s cestou.

Je to název databáze. V BDE je databáze řešena jako adresář, tudíž zde jde napsat cesta k datům. Je tu možno také uvést Alias databáze (zástupné jméno, zástupce pro označení toho adresáře), které je nadefinováno v BDE administrátoru (nebo API funkcema BDE - viz můj modul Rce_BDE).

Zpět do poradny Odpovědět na původní otázku Nahoru