Autor Téma: SQLite Update nefunguje  (Přečteno 2731 krát)

Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 2386
  • Karma: 129
    • Verze Delphi: D2007, XE3, DX10
Re:SQLite Update nefunguje
« Odpověď #15 kdy: 18-03-2018, 15:59:09 »
V debugeri idem v cykle cez qS
Z nej preberam 2 hodnoty Flag a ROWID
Vidim napriklad rowid 17, je tam v CSV flag = 4, vdaka vyrazu v qS   "Flag | 8", ziskam qs.fields[0].AsInteger cislo 12.
Priradim
qU.params[0].AsInteger := 12   -- FLAG
qU.params[1].AsInteger := 17   -- ROWID
Parametre su naplnene ( vidim ich hodnoty v debugeri)
Uplatnim qU.ExecSQL
Tady odestuj hodnotu qU.RowsAffected
Citace
Pozriem vysledok a v riadku s rowid 17, je hodnota Flag stale 4.
Transaction, prebehne cez Commit, nie Rollback
Idem spravit kratky vzor projekt

Offline Stanislav Hruška

  • Padawan
  • ******
  • Příspěvků: 3781
  • Karma: 35
    • Verze Delphi: XE7 professional
Re:SQLite Update nefunguje
« Odpověď #16 kdy: 18-03-2018, 16:19:09 »
Ešte pridám jednu chybu. Ak sa vynechá naplnenie niektorého parametra. Podľa uverejneného kódu by to nemal byť Tvoj prípad.
Skús urobiť update len s jediným záznamom. To jest vyhodiť všetky cykly. Pre testovanie môžeš hodnoty do parametrov dať najprv napevno. Bude sa Ti lepšie hľadať chyba.
Len tak mimochodom, ten ROWID = 17 je v poriadku? Človek nikdy nevie, aj keď ich tam máš vééľa.
Delphi XE7, FireBird
Expert na kladenie nejasne formulovaných otázok.

Online miroB

  • Hrdina
  • ****
  • Příspěvků: 382
  • Karma: 14
    • Verze Delphi: D1,2,3,4,7,2005,2009, XE8,S,B,T10.2.2 Pro
Re:SQLite Update nefunguje
« Odpověď #17 kdy: 18-03-2018, 18:23:16 »
Uff, asi to bude moja chyba. Nočná práca. A ako som sa s tým včera mordoval..
Dnes som spravil samostatný demo projekt, ktorý funguje presne tak, ako som to včera skúšal.
A že sa výsledky neprejavili? Zrejme som v tej únave zabudol refreshnúť zobrazovacie Query.
Psycho.. čakal som tam chyby. Asi aj keď neboli. Ospravedlňujem sa.
Tak prikladám aj ten projekt. Možno sa Vám zíde niečo podobné.
Použitý princíp zadávania parametrov, podstatne zrýchľuje výpočet. Mnohonásobne.
Pre tabuľku 6 000 000 riadkov sa to vypočíta za 20 sekúnd. Bez tohoto riešenia, by bol čas neznesiteľný.
SQLite priamo nepodporuje UPDATE v spojení s JOIN. Niekto môže namietať, že sa to dá obísť.
Lenže časy trvania komplexných SQL voči špecializovaným riešeniam sú dramaticky iné. To poznávam práve na tých 6 mil. riadkoch..
Preto bolo cieľom vyrobiť obecnú simuláciu UPDATE, pre dve a viacero JOIN-ovaných tabuliek, s viacerými priradeniami v jednom kroku.
Obecný tvar tohoto UPDATE je teraz takýto:
Kód: MySQL [Vybrat]
  1. UPDATE dstTableName AS d SET ( Field1, Fied2, .. )
  2.         SELECT a.Field1, a.Field2 ..
  3.         FROM    dstTableName AS d INNER|LEFT JOIN tblName a
  4.                         ON d.FieldXY=a.FieldZX
  5.         WHERE Condition -- Poznámka : tu môže byť napr. aj podmienka
  6.         ORDER BY FieldList asc|desc
  7.         )
  8.  
( Všetky operácie s rowId sa riešia automaticky na pozadí. Samozrejme tá Update tabuľka musí byť klasická SQLite, teda apriori automaticky obsahuje rowId ):
U mňa je kód v skutočnosti omnoho komplexnejší, než v priloženom projekte. Je tam všetko, vrátane lexikálnej analýzy.
Update je stavaný obecne, nie je len na logické operátory, ktoré som použil v vzore.
Pre správne fungovanie priloženého projektu, je treba mať v priečinku pri exe aj databázu "mySQL.db3". V zipe je rovno na troch miestach. Je všade rovnaká
A ďakujem, za Vaše pripomienky
« Poslední změna: 18-03-2018, 18:35:26 od Miroslav Baláž »

Offline Stanislav Hruška

  • Padawan
  • ******
  • Příspěvků: 3781
  • Karma: 35
    • Verze Delphi: XE7 professional
Re:SQLite Update nefunguje
« Odpověď #18 kdy: 18-03-2018, 23:39:45 »
V Tvojom kóde ma zaráža
Kód: [Vybrat]
ORDER BY D.ROWIDNačo to je dobré? Z praktického hľadiska je také radenie o ničom. Berie výkon, čo pri 6 M záznamoch niečo trvá. Možno tam malo byť správne
Kód: [Vybrat]
ORDER BY FieldList asc|descz posledného príspevku.
U mňa sú dve veci, ktorým sa v SQL snažím vždy vyhnúť. A to:
  • DISTINCT - to je priam povinnosť
  • ORDER BY. 
Delphi XE7, FireBird
Expert na kladenie nejasne formulovaných otázok.

Online miroB

  • Hrdina
  • ****
  • Příspěvků: 382
  • Karma: 14
    • Verze Delphi: D1,2,3,4,7,2005,2009, XE8,S,B,T10.2.2 Pro
Re:SQLite Update nefunguje
« Odpověď #19 kdy: 19-03-2018, 01:04:09 »
Nie všetky veci sú v tom SQL príkaze povinné
V SQLite je veľké plus, že sa automaticky vždy vytvorí RowId. (teda Autoincrement, ak sa vyslovene nezakáže)
A tak je s výhodou možné spracovať aj takýto prípad:
Kód: MySQL [Vybrat]
  1. .. tbl a INNER join tbl b ON a.rowId = ( b.rowId + 1 )
Pre počítanie s predošlým, alebo nasledujúcim riadkom tej istej tabuľky.
Vtedy je ORDER BY veľmi významný.
Na báze toho istého princípu mám aj UDF funkcie
  • Counter
  • Changer
  • Grouper
Tie sú tiež závislé na poradí. Sú komplexné a dá sa v nich nastaviť kadečo.
Veľmi urýchľujú a zjednodušujú rutinné výpočty.
Zoradenie preto využívam často.



« Poslední změna: 19-03-2018, 01:08:31 od Miroslav Baláž »

Offline Stanislav Hruška

  • Padawan
  • ******
  • Příspěvků: 3781
  • Karma: 35
    • Verze Delphi: XE7 professional
Re:SQLite Update nefunguje
« Odpověď #20 kdy: 19-03-2018, 08:53:57 »
Citace
V SQLite je veľké plus, že sa automaticky vždy vytvorí RowId. (teda Autoincrement, ak sa vyslovene nezakáže)
A tak je s výhodou možné spracovať aj takýto prípad:
Povedané slovami klasika pf1957 "to je cesta do pekla". RowId môže slúžiť jedine na vytvorenie odkazov/referencie medzi tabuľkami. Master - detail.
Akékoľvek iné použitie považujem za hrubú chybu. Prečo:
  • vymažeš nejaký záznam
  • doplníš nejaký záznam
Prosím netvrď, že sa to nemôže stať :-X  Jednoznačne by si mal na zoradenie používať nejaké iné kritérium. Tebou definované a udržovateľné.
Delphi XE7, FireBird
Expert na kladenie nejasne formulovaných otázok.

Online miroB

  • Hrdina
  • ****
  • Příspěvků: 382
  • Karma: 14
    • Verze Delphi: D1,2,3,4,7,2005,2009, XE8,S,B,T10.2.2 Pro
Re:SQLite Update nefunguje
« Odpověď #21 kdy: 19-03-2018, 10:40:52 »
Citace
V SQLite je veľké plus, že sa automaticky vždy vytvorí RowId. (teda Autoincrement, ak sa vyslovene nezakáže)
A tak je s výhodou možné spracovať aj takýto prípad:
Povedané slovami klasika pf1957 "to je cesta do pekla". RowId môže slúžiť jedine na vytvorenie odkazov/referencie medzi tabuľkami. Master - detail.
Akékoľvek iné použitie považujem za hrubú chybu. Prečo:
  • vymažeš nejaký záznam
  • doplníš nejaký záznam
Prosím netvrď, že sa to nemôže stať :-X  Jednoznačne by si mal na zoradenie používať nejaké iné kritérium. Tebou definované a udržovateľné.
Niekoľko komentárov:
  • Ak použiješ v SQL akúkoľvek techniku, bez poznania jej dôsledkov, môže to dopadnúť fatálne. "Cestou do pekla", by sa dalo označiť celé SQL. S tým však nesúhlasím
  • Mojou preferovanou oblasťou je najmä vyhodnocovanie stávajúcich údajov (nie príprava, ani nie denná údržba. Spravidla už niekto iný, na tom dávno pracuje. ).
  • Zdrojové údaje si na začiatku pripravím podľa svojho gusta. Z takto pripravených údajov môžem bezpečne využívať aj rowid, ako dôležité východisko. Ďalej už môžem používať techniky, ktoré nepredstavujú "Cestu do pekla". Alebo si pripraviť polotovary tak, aby spĺňali moje predpoklady.
  • V prvej fáze rozhodne nemažem. Naopak riešim update a funkcie, alebo vytváram nové pomocné tabuľky, na ktoré sa viem spoľahnúť
  • Pre RowID, používam techniku INTEGER PRIMARY KEY. Má určité bonusy. Viac viď tu: https://www.sqlite.org/lang_createtable.html#rowid
  • Zoraďovanie pre iné účely, než som popisoval, samozrejme riadim inými kritériami.
  • V svojej oblasti spracovania sa pohybujem už 20 rokov. Boli to síce len Paradox, Access a Excel, takže vedomostí okolo transakcií práve nemám
  • Zrejme to je dané tým, že nepracujem v prostredí C/S, triggerov, transakcií, konkurenčných dotazov a pod. Ale s SQL pracujem najmenej 20 rokov. Na úrovni, ktorú potrebujem a ktorú poskytovali vyššie uvedené nástroje
  • FireDAC je pre mňa nový, pretože som používal ADO a DAO a OLE2.
  • SQLite je nové tiež
  • Obe spomenuté technológie sa mi však veľmi pozdávajú a otvárajú nové možnosti pre vlastné vylepšenia.
  • Za tých 20 rokov mám teda predstáv a požiadavok zhromaždených ozaj dosť
Snáď to trochu vysvetľuje aj moje časté dotazy.

PS:
Jediný raz, keď som vyslovene závislý na RowId je práve tá náhrada Update, pretože za užívateľa SQL preberám zodpovednosť do tej miery, že rowId vsuniem ako posledné pole  do dotazu. Pred FROM. Jeho využitie je vždy korektné. Rowid slúži len na zápis do aktuálneho záznamu.
Teda okrem prípadu JOIN .. ON id = ( id + 1 ). Vtedy si užívateľ musí ozaj aktívne uvedomiť, či je Id ( rowId ) pre daný účel "čisté". Alebo použije iné pole. Viď Counter, nižšie.
Náhrada Update pre JOIN-ované tabuľky však nie je UDF funkcia, ale celá funkcionalita.
Vo všetkých UDF Funkciách, kde interne využívam rowid, môže užívateľ vlastne podstrčiť názov akéhokoľvek poľa, ktoré spĺňa nároky potrebnej postupnosti.
Pole s postupnosťou sa dá vytvoriť práve UDF funkciou Counter, ktorú som si vytvoril. Tam samozrejme treba uvažovať aj so sortovaním. Úlohou Counter je vytvoriť postupnosť s ľubovoľným krokom. A to aj v rámci tried (z hľadiska Group By), nielen celej tabuľky.
 
« Poslední změna: 19-03-2018, 11:06:58 od Miroslav Baláž »

Offline Delfin

  • Guru
  • *****
  • Příspěvků: 1470
  • Karma: 60
  • SW konzultant
    • Verze Delphi: 2009, Tokyo
Re:SQLite Update nefunguje
« Odpověď #22 kdy: 19-03-2018, 12:20:10 »
Použitý princíp zadávania parametrov, podstatne zrýchľuje výpočet. Mnohonásobne.

Je pravda ze ten emulovany Array DML je vykonnejsi o vsechny kontroly ktere by pri pouziti ExecSQL a pratel musely probehnout. Kdyz jsi u vykonu, co zkusit low level (nemusel bys "vlacet" kurzor) ;)?

Kód: Delphi [Vybrat]
  1. const
  2.   BatchSize = 10000;
  3. var
  4.   X, Y: Integer;
  5.   Table: TFDDatSTable;
  6.   Command: IFDPhysCommand;
  7.   Connection: IFDPhysConnection;
  8.   Transaction: IFDPhysTransaction;
  9. begin
  10.   Connection := conn.ConnectionIntf;
  11.   Connection.CreateCommand(Command);
  12.   Connection.CreateTransaction(Transaction);
  13.  
  14.   Table := TFDDatSTable.Create;
  15.   try
  16.     Command.CommandText := 'SELECT c.flag | 8, c.rowid from Csv c INNER JOIN Filter f ON c.idZast=f.IdZast';
  17.     Command.Prepare; // pripravime prikaz
  18.     Command.Define(Table); // nechame FireDAC precist metadata datasetu
  19.     Command.Fetch(Table); // preneseme VSECHNY zaznamy do storage
  20.     Command.Close; // prikaz zahodime, tabulka do ktere se prenasela data je nezavisla
  21.  
  22.     Command.CommandText := 'UPDATE Csv SET Flag=? WHERE rowid=?';
  23.     Command.Params[0].DataType := ftInteger;
  24.     Command.Params[1].DataType := ftInteger;
  25.     Command.Params.ArraySize := BatchSize;
  26.     Command.Prepare;
  27.  
  28.     Transaction.StartTransaction; // nastartujeme transakci
  29.     try
  30.       for X := 0 to Table.Rows.Count - 1 do // iterujeme vsemi radky tabulky
  31.       begin
  32.         for Y := 0 to Command.Params.Count - 1 do // pro vsechny parametry (pripadne Table.Columns.Count - 1; musi byt 1:1)
  33.           Command.Params[Y].Values[X mod BatchSize] := Table.Rows[X].GetData(Y); // vlozime do "polniho" parametru data ze storage
  34.         if ((X + 1) mod BatchSize = 0) or (X = Table.Rows.Count - 1) then // pokud je cas na spusteni davky
  35.           Command.Execute(BatchSize); // davku spustime (indexovani parametru je s rotaci od 0 pri dosazeni BatchSize; offset=0)
  36.       end;
  37.       Transaction.Commit;
  38.     except
  39.       Transaction.Rollback;
  40.       raise;
  41.     end;
  42.   finally
  43.     Table.Free;
  44.   end;
  45. end;
« Poslední změna: 19-03-2018, 12:22:44 od Delfin »
I'm a soldier, so don't panic! I know the underground! I like WTFPL license! No more Google, go duck, go!

Online miroB

  • Hrdina
  • ****
  • Příspěvků: 382
  • Karma: 14
    • Verze Delphi: D1,2,3,4,7,2005,2009, XE8,S,B,T10.2.2 Pro
Re:SQLite Update nefunguje
« Odpověď #23 kdy: 19-03-2018, 12:29:42 »
O Low Level som pôvodne uvažoval, ak by nebola postačovala dosiahnutá rýchlosť. Zatiaľ som však bol spokojný. Stále to ostávalo ako výzva.
Teraz keď si mi poslal náčrt, možno to odskúšam, aký prínos to pridá.
Ďakujem

Online miroB

  • Hrdina
  • ****
  • Příspěvků: 382
  • Karma: 14
    • Verze Delphi: D1,2,3,4,7,2005,2009, XE8,S,B,T10.2.2 Pro
Re:SQLite Update nefunguje
« Odpověď #24 kdy: 19-03-2018, 12:31:26 »
V tom mojom nočnom/prvom pokuse, bola predsa nejaká chyba.
Nešlo o zabudnuté refreshnutie Query, ako som písal.
Môj originál  skutočne nefungoval. Časť z neho som prekopal podľa vzorového príkladu, ktorý som zverejnil vyššie. Tam to bolo pekne upratané..
Až teraz mi to funguje.

Podozrievam ten fakt, že som mal to qS použité aj na pomocný výpočet.
Teraz som pomocný výpočet vyhodil do samostatnej funkcie s vlastným interným query.
Takže qS je použité iba pre svoj účel. Aj keď som presvedčený, že ani pôvodný návrh nevykazoval dôvod na nefunkčnosť, tak pre mňa poučenie: budem sa vystríhať v závažnejších prípadoch používať query pre viac účelov.

Online miroB

  • Hrdina
  • ****
  • Příspěvků: 382
  • Karma: 14
    • Verze Delphi: D1,2,3,4,7,2005,2009, XE8,S,B,T10.2.2 Pro
Re:SQLite Update nefunguje
« Odpověď #25 kdy: 19-03-2018, 17:19:40 »
Použitý princíp zadávania parametrov, podstatne zrýchľuje výpočet. Mnohonásobne.
..
Kdyz jsi u vykonu, co zkusit low level (nemusel bys "vlacet" kurzor) ;)?
..
Vyskúšané a prekvapujúce ( dvakrát, po dve merania ):
  • low level :  22 a 20 sekúnd
  • query tak ako bolo v projekte : 18 a 16.9 sekundy


Offline Delfin

  • Guru
  • *****
  • Příspěvků: 1470
  • Karma: 60
  • SW konzultant
    • Verze Delphi: 2009, Tokyo
Re:SQLite Update nefunguje
« Odpověď #26 kdy: 19-03-2018, 17:40:45 »
Použitý princíp zadávania parametrov, podstatne zrýchľuje výpočet. Mnohonásobne.
..
Kdyz jsi u vykonu, co zkusit low level (nemusel bys "vlacet" kurzor) ;)?
..
Vyskúšané a prekvapujúce ( dvakrát, po dve merania ):
  • low level :  22 a 20 sekúnd
  • query tak ako bolo v projekte : 18 a 16.9 sekundy

V obou pripadech probiha spousteni pres TFDPhysCommand implementaci. Mozna bude problem v tom fetch, protoze Ty u sebe soukas kurzorem, zatimto ja u sebe taham vsechny zaznamy najednou (volani Fetch). FireDAC se da optimalizovat na prenos velkych objemu, i kdyz uznavam, z me strany neni zrovna moudre ocekavat prenos 6M zaznamu najednou (nebo kolik jsi psal ze jich mas). Tezko rict, chtelo by to merit profilerem, ale pokud mas zajem muzu pripravit ukazku dotahovani bloku.
« Poslední změna: 19-03-2018, 17:44:27 od Delfin »
I'm a soldier, so don't panic! I know the underground! I like WTFPL license! No more Google, go duck, go!

Online miroB

  • Hrdina
  • ****
  • Příspěvků: 382
  • Karma: 14
    • Verze Delphi: D1,2,3,4,7,2005,2009, XE8,S,B,T10.2.2 Pro
Re:SQLite Update nefunguje
« Odpověď #27 kdy: 19-03-2018, 18:16:39 »
Áno záznamov je 6M.
Sledoval som v Task Manageri. Ani v jednom prípade sa neprekročila Memory 700M. Naopak skôr bol priebeh stále podobný.
Myslíš, že sa dá teoreticky dosiahnuť zrýchlenie aspoň o nejaké to percento? Povedzme niekde na 15 sekúnd?
Potom by to malo zmysel vyskúšať.

Offline Delfin

  • Guru
  • *****
  • Příspěvků: 1470
  • Karma: 60
  • SW konzultant
    • Verze Delphi: 2009, Tokyo
Re:SQLite Update nefunguje
« Odpověď #28 kdy: 19-03-2018, 18:46:06 »
Excellent
Rated 1 time
Áno záznamov je 6M.
Sledoval som v Task Manageri. Ani v jednom prípade sa neprekročila Memory 700M. Naopak skôr bol priebeh stále podobný.
Myslíš, že sa dá teoreticky dosiahnuť zrýchlenie aspoň o nejaké to percento? Povedzme niekde na 15 sekúnd?
Potom by to malo zmysel vyskúšať.

V obou pripadech se dotahnou vsechny zaznamy na "klienta" (do interni storage). Jen v mem pripade je taham najednou (volanim Fetch s parametrem AAll == True), zatimco u Tebe se tahaji on-demand tim jak posouvas kurzorem (volanim Next).

Tady je low level varianta s cistenim rowsetu (ktery ma velikost podle velikosti davky). Funguje to jednoduse, pomoci SrcCmd opakovane tahas packety dat (rowsety) z DBMS, a dokud obsahuji alespon jeden zaznam, naplni se pole parametru a pomoci DstCmd se odesle davka:

Kód: Delphi [Vybrat]
  1. const
  2.   BatchSize = 10000;
  3. var
  4.   X, Y: Integer;
  5.   Table: TFDDatSTable;
  6.   SrcCmd: IFDPhysCommand;
  7.   DstCmd: IFDPhysCommand;
  8.   Connection: IFDPhysConnection;
  9.   Transaction: IFDPhysTransaction;
  10.  
  11.   function FetchRowSet: Integer;
  12.   begin
  13.     SrcCmd.Fetch(Table, False);
  14.     Result := Table.Rows.Count;
  15.   end;
  16.  
  17. begin
  18.   Connection := conn.ConnectionIntf;
  19.   Connection.CreateCommand(SrcCmd);
  20.   Connection.CreateCommand(DstCmd);
  21.   Connection.CreateTransaction(Transaction);
  22.  
  23.   Table := TFDDatSTable.Create;
  24.   try
  25.     SrcCmd.Options.FetchOptions.RowsetSize := BatchSize;
  26.     SrcCmd.CommandText := 'SELECT c.flag | 8, c.rowid from Csv c INNER JOIN Filter f ON c.idZast=f.IdZast';
  27.     SrcCmd.Prepare;
  28.     SrcCmd.Define(Table);
  29.  
  30.     DstCmd.CommandText := 'UPDATE Csv SET Flag=? WHERE rowid=?';
  31.     DstCmd.Params[0].DataType := ftInteger;
  32.     DstCmd.Params[1].DataType := ftInteger;
  33.     DstCmd.Params.ArraySize := BatchSize;
  34.     DstCmd.Prepare;
  35.  
  36.     Transaction.StartTransaction;
  37.     try
  38.       while FetchRowSet > 0 do
  39.       begin
  40.         for X := 0 to Table.Rows.Count - 1 do
  41.           for Y := 0 to Table.Columns.Count - 1 do
  42.             DstCmd.Params[Y].Values[X] := Table.Rows[X].GetData(Y);
  43.         DstCmd.Execute(Table.Rows.Count);
  44.         Table.Clear;
  45.       end;
  46.       Transaction.Commit;
  47.     except
  48.       Transaction.Rollback;
  49.       raise;
  50.     end;
  51.   finally
  52.     Table.Free;
  53.   end;
  54. end;

Da se ovsem vytunit i query objekt.
I'm a soldier, so don't panic! I know the underground! I like WTFPL license! No more Google, go duck, go!

Online miroB

  • Hrdina
  • ****
  • Příspěvků: 382
  • Karma: 14
    • Verze Delphi: D1,2,3,4,7,2005,2009, XE8,S,B,T10.2.2 Pro
Re:SQLite Update nefunguje
« Odpověď #29 kdy: 19-03-2018, 20:08:49 »
..
Tady je low level varianta s cistenim rowsetu (ktery ma velikost podle velikosti davky). Funguje to jednoduse, pomoci SrcCmd opakovane tahas packety dat (rowsety) z DBMS, a dokud obsahuji alespon jeden zaznam, naplni se pole parametru a pomoci DstCmd se odesle davka:
..
Tak v tejto verzii som na 15.4, 15.1, 15.3, niekedy na 16-tich sekundách. To je zlepšenie o viac ako sekundu, oproti FDQuery.
Najlepšie je to, že využitie Memory nebolo v tomto prípade nikdy viac, ako 55 MB.
V predošlých prípadoch to bolo na cca 690 MB. (LowLevel v1 a verzia s FDQuery)
Low level v2 je jasný víťaz. Ďakujem :)

Porovnanie:
  • FDQuery         16.9  - 18 sek      697  MB RAM MAX
  • Low level v1    18    -  20 sek      690  MB RAM MAX
  • Low level v2    15.1 -  15.6 sek     55  MB RAM MAX
« Poslední změna: 19-03-2018, 20:15:30 od Miroslav Baláž »

 

S rychlou odpovědí můžete používat BB kódy a emotikony jako v běžném okně pro odpověď, ale daleko rychleji.

Upozornění: do tohoto tématu bylo naposledy přispěno před 120 dny.
Zvažte prosím založení nového tématu.

Jméno: E-mail:
Ověření:
Datový typ v Delphi, který má True a False: