Autor Téma: Parametrizované príkazy  (Přečteno 2434 krát)

Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 2045
  • Karma: 103
    • Verze Delphi: D2007, XE3, DX10
Re:Parametrizované príkazy
« Odpověď #30 kdy: 20-12-2017, 18:45:11 »
Da sa chapat, ze aj ked plati:
Kód: Delphi [Vybrat]
  1. Query.Active=False
neuplny SQL kod sa cez to vsetko kontroluje na vykonatelnost? To som nevedel.
Tak jemu ani tak nejde o vykonavatelnost, ale o urceni prikazu, co ma pri open/exec delat a napr. take o vytahani seznamu parametru, abys nasledne mohl psat to tvoje Q.Params[ i ].xxx

Offline Miroslav Baláž

  • Plnoletý
  • ***
  • Příspěvků: 197
  • Karma: 5
    • Verze Delphi: D1,2,3,4,7,2005,2009, XE8,S,B,T10.2.2 Pro
Re:Parametrizované príkazy
« Odpověď #31 kdy: 20-12-2017, 19:24:48 »
Da sa chapat, ze aj ked plati:
Kód: Delphi [Vybrat]
  1. Query.Active=False
neuplny SQL kod sa cez to vsetko kontroluje na vykonatelnost? To som nevedel.
Tak jemu ani tak nejde o vykonavatelnost, ale o urceni prikazu, co ma pri open/exec delat a napr. take o vytahani seznamu parametru, abys nasledne mohl psat to tvoje Q.Params[ i ].xxx
Práve nad tým špekulujem. Hľadal som vo FireDAC zdrojoch a tam sa .QueryChanged nevyskytuje. Iba Oracle má 'DoQueryChanged('.
Možno to trčí už niekde na úrovni DB.pas, či podobne.
Parametre?
Doteraz som veril, že sa zaktivujú až v druhom riadku tohoto príkazu:
Kód: MySQL [Vybrat]
  1.   dm.qry.SQL.Text := 'select eCategSet, eFnFlagSet from sumar where wordItem = ?';
  2.   dm.qry.Params[ 0 ].DataType := ftString;
Kontorloval som. Pravda je, že pred druhým riadkom tie parametre už pozná.

Zase k vyššie zmieneným veciam:
Query.SQL.Text := 'SELECT ..'
volá
procedure TStrings.SetTextStr(const Value: string);  // v System.Classes
a ten začína BeginUpdate;
takže sme u toho môjho
BeginUpdate; Add(


Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 2045
  • Karma: 103
    • Verze Delphi: D2007, XE3, DX10
Re:Parametrizované príkazy
« Odpověď #32 kdy: 20-12-2017, 19:30:08 »
procedure TStrings.SetTextStr(const Value: string);  // v System.Classes
Pozor na to, ze TStrings  je abstraktni trida a SQL property byva nejaka konkretni napr. jak jsem psal TWideStringList u nekterych komponent a ta vubec nemusi volat inherited metodu.
Pokud to chces lustit, musis vychazet z neceho takoveho v constructoru Query:
Kód: Delphi [Vybrat]
  1.   ...
  2.   TWideStringList(SQL).OnChange := QueryChanged;
  3.   ...
  4.  

Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 2045
  • Karma: 103
    • Verze Delphi: D2007, XE3, DX10
Re:Parametrizované príkazy
« Odpověď #33 kdy: 20-12-2017, 19:48:27 »
Kód: MySQL [Vybrat]
  1.   dm.qry.SQL.Text := 'select eCategSet, eFnFlagSet from sumar where wordItem = ?';
  2.  dm.qry.Params[ 0 ].DataType := ftString;
Kontorloval som. Pravda je, že pred druhým riadkom tie parametre už pozná.
Kdyby to tak nebylo, to by Params[ 0 ] skoncilo na OutOfRange exception nebo jak se to v Delphi jmenuje

Offline Miroslav Baláž

  • Plnoletý
  • ***
  • Příspěvků: 197
  • Karma: 5
    • Verze Delphi: D1,2,3,4,7,2005,2009, XE8,S,B,T10.2.2 Pro
Re:Parametrizované príkazy
« Odpověď #34 kdy: 20-12-2017, 20:01:53 »
Jasne. To chapem. Myslel som, ze az prve volanie parametrov to bude aktualizovat. Ale mas pravdu. Je to ako pises.

Ale narazil som na iny problem.
Pre Query neviem zmenit pocet parametrov. Na zaciatku staci SELECT
Kód: Delphi [Vybrat]
  1.   dm.qry.SQL.Text := 'select eCategSet, eFnFlagSet from sumar where wordItem = ?';
Nastavim parametre, presnejsie jeden, spustim. Vsetko OK.
Ked to ukoncim a chcem zmenit SELECT, kde by bol iny pocet parametrov, tak sa najprv pokusim o toto:
dm.qry.SQL.Text :='';    alebo     dm.qry.SQL.Clear;
Ale to mi stavajuce parametre nezrusi.
Furt zostava :    dm.qry.Params.Count = 1
Ked pouzijem dm.qry.Params.Clear;  tak potom plati ocakavane dm.qry.Params.Count = 0
Ale uz mi ziadny SELECT, znovu nove parametre nevyrobi.
Nech robim co robim zostava: dm.qry.Params.Count = 0
Nasledny pokus o zapis do params[0] preto zhavaruje
PS:Pouzivam FireDAC.

Offline Stanislav Hruška

  • Padawan
  • ******
  • Příspěvků: 3212
  • Karma: 30
    • Verze Delphi: XE7 professional
Re:Parametrizované príkazy
« Odpověď #35 kdy: 20-12-2017, 20:50:28 »
Kód: [Vybrat]
dm.qry.Close;
dm.qry.SQL.Text := 'SELECT ...';
dm.qry.Open;
Delphi XE7, FireBird
Expert na kladenie nejasne formulovaných otázok.

Offline Radek Červinka

  • Administrátoři
  • Padawan
  • *****
  • Příspěvků: 1915
  • Karma: 78
    • Verze Delphi: D5,D2007, DXE, DXE2 + 2 poslední (Tokyo)
    • O Delphi v češtině
Re:Parametrizované príkazy
« Odpověď #36 kdy: 20-12-2017, 21:06:55 »
myslim, ze keby si pridal takto, malo by to na rychlost snad stacit.
Kód: Delphi [Vybrat]
  1. qry.SQL.BeginUpdate;
  2. qry.SQL.Add
  3. ..
  4. qry.SQL.EndUpdate;
  5.  
Takto by to slo, ale .Add opakovane pro nekolik radku bez uzamceni stringlistu je vylozene skodlive, protoze to po pridani kazdeho radku vola SQL parser, ktery samozreme na neuplnem SQL prikazu havaruje...

Je otazka, proc delat Begin/EndUpdate, kdyz muzu rovnou napsat Text := a ten text si pred tim slozit v nejakem StringBuilderu

Mas pravdu, samozrejme by to tak melo byt. Mimochodem ty OnChange udalosti jsou

procedure TFDCustomCommand.DoSQLChanging(ASender: TObject);
procedure TFDCustomCommand.DoSQLChange(ASender: TObject);

No ale jelikoz nasleduje dotaz do DB, ktery je 100x - 1000x narocnejsi, tak mne to az tak moc netrapi.
Volani pres Add je protoze tam mam casto ruzne podminky a je to pro mne citelnejsi po nejake dobe, coz ovsem ten stringbuilder resi. Presto si myslím, že kdybych to chtel upravovat tak bych sel pres BeginUpdate


Embarcadero MVP - Czech republic

Offline Radek Červinka

  • Administrátoři
  • Padawan
  • *****
  • Příspěvků: 1915
  • Karma: 78
    • Verze Delphi: D5,D2007, DXE, DXE2 + 2 poslední (Tokyo)
    • O Delphi v češtině
Re:Parametrizované príkazy
« Odpověď #37 kdy: 20-12-2017, 21:10:00 »
Už som si ten "entity framework" vyhľadal. Nič pre mňa.
Ani nič pre Delphistu ;-)

Tohle je celkem slušné https://www.devart.com/entitydac/.
Embarcadero MVP - Czech republic

Offline Delfin

  • Guru
  • *****
  • Příspěvků: 742
  • Karma: 32
  • SW konzultant
    • Verze Delphi: 2009, Tokyo
Re:Parametrizované príkazy
« Odpověď #38 kdy: 20-12-2017, 22:10:17 »
    [/list]Priam so železnou pravidelnosťou sa mi pre rôzne typy SQL opakuje, čo sa dá určite nejako optimalizovať (skryť):
    Kód: [Vybrat]
      Fqry_I.ParamByName('FKFOCS').AsInteger := oGlobalVar.IDFOC;  // Vždy pracujem len s jedným domom
      Fqry_I.ParamByName('YEARS').AsInteger := oGlobalVar.CurrentYear;  // a jedným rokom
    Posledný Radkov príspevok mi toho dosť objasňuje.

    Zkus se na to schema podivat pohledem dedicnosti objektu. Spolecny predek trid prece muze delat stejnou vec, stejne jako muze obsahovat spolecna pole ;)
    I'm a soldier, so don't panic!

    Offline Miroslav Baláž

    • Plnoletý
    • ***
    • Příspěvků: 197
    • Karma: 5
      • Verze Delphi: D1,2,3,4,7,2005,2009, XE8,S,B,T10.2.2 Pro
    Re:Parametrizované príkazy
    « Odpověď #39 kdy: 20-12-2017, 22:12:13 »
    Kód: [Vybrat]
    dm.qry.Close;
    dm.qry.SQL.Text := 'SELECT ...';
    dm.qry.Open;
    Z potreby qry.Open ovsem vyplyva, ze parametre nie su riesene v stadiu zadania kodu do qry.SQL.Text, ako bol naznacene vyssie?
    Ešte dopľňam: Sa mi len zdá, že pri prvom použití Query, v runtime, keď je prázdne, tak sa parametre predsa len upgradujú hneď po zadaní SQL.Text := xy ?
    Veru nezdá. Toto funguje, aj za predpokladu, že je na začiatku Query prázdne.
    Kód: Delphi [Vybrat]
    1.   dm.qrySQLite.Params.Clear;
    2.   dm.qrySQLite.SQL.Clear;
    3. k := dm.qrySQLite.Params.Count;  // k = 0
    4.   dm.qrySQLite.SQL.Text := 'select eCategSet, eFnFlagSet from sumar where wordItem = ?';
    5. k := dm.qrySQLite.Params.Count;  // k = 1 !!!
    6.   dm.qrySQLite.Params[ 0 ].DataType := ftString;
    « Poslední změna: 20-12-2017, 22:29:30 od mibainfo »

    Offline Delfin

    • Guru
    • *****
    • Příspěvků: 742
    • Karma: 32
    • SW konzultant
      • Verze Delphi: 2009, Tokyo
    Re:Parametrizované príkazy
    « Odpověď #40 kdy: 20-12-2017, 22:30:36 »
    Kód: [Vybrat]
    dm.qry.Close;
    dm.qry.SQL.Text := 'SELECT ...';
    dm.qry.Open;
    Z potreby qry.Open ovsem vyplyva, ze parametre nie su riesene v stadiu zadania kodu do qry.SQL.Text, ako bol naznacene vyssie?
    Ešte dopľňam: Sa mi len zdá, že pri prvom použití Query, v runtime, keď je prázdne, tak sa parametre predsa len upgradujú hneď po zadaní SQL.Text := xy ?
    Veru nezdá. Toto funguje, aj za predpokladu, že je na začiatku Query prázdne.
    Kód: Delphi [Vybrat]
    1.   dm.qrySQLite.Params.Clear;
    2.   dm.qrySQLite.SQL.Clear;
    3. k := dm.qrySQLite.Params.Count;  // k = 0
    4.   dm.qrySQLite.SQL.Text := 'select eCategSet, eFnFlagSet from sumar where wordItem = ?';
    5. k := dm.qrySQLite.Params.Count;  // k = 1 !!!
    6.   dm.qrySQLite.Params[ 0 ].DataType := ftString;

    Ano, protoze by default, s prirazenim (nebo jakoukoli zmenou) textu prikazu se prikaz parsuje a to proto, aby se pro nej daly ze zastupnych symbolu vytvorit placeholdery pro kolekci parametru a maker. S vychozim nastavenim jde o:

    Kód: Delphi [Vybrat]
    1. Query.SQL.Text := 'SELECT !MyMacro FROM MyTable WHERE MyColumn = :MyParam'; // "by default" pripravi kolekci parametru a maker
    2. Query.MacroByName('MyMacro').AsIdentifier := 'MyColumn'; // existuje diky nastaveni ResourceOptions.MacroCreate a parsovani prikazu
    3. Query.ParamByName('MyParam').AsInteger := 666; // existuje diky ResourceOptions.ParamCreate a parsovani prikazu
    4. Query.Open;
    « Poslední změna: 20-12-2017, 22:48:27 od Delfin »
    I'm a soldier, so don't panic!

    Offline Miroslav Baláž

    • Plnoletý
    • ***
    • Příspěvků: 197
    • Karma: 5
      • Verze Delphi: D1,2,3,4,7,2005,2009, XE8,S,B,T10.2.2 Pro
    Re:Parametrizované príkazy
    « Odpověď #41 kdy: 20-12-2017, 23:21:29 »
    Dobre. Takto to funguje pri prvom spusteni Query.
    Lenze ked to chcem vsetko s tym istym query spustiti druhy raz (napr select s inym poctom parametrov), tak uz neplatia tie iste pravidla ako pri povodnom cistom Query.
    Uz nestaci priradenie textu. Vyssie som uviedol priklad. Je to dokumentovane na Params.Count.
    Ziadne SQL.Text:= nepomoze, tak ako pomohlo na zaciatku
    A zase naopak, ked dam nestastny Params.Clear, co jedine ozaj pomoze, tak neviem co dalej. A ak Clear nedam, tak sa starych paremetrov viac nezbavim. Ako ale potom znovu ozivit parametre?

    Ked vuzijem Params.Clear, tak potom musim spravit qry.Open? ako niekde vyssie odporuca Stano?
    Ale to uz je neskoro, aby sa obcerstvovali parametre. Nie?..
    Keby to fungovalo ocakavane, tak aj v opätovnom pripade využitia query postupujem rovnako ako na začiatku. Lenže to u mňa s istotou nefunguje. Vie niekto ponúknuť funkčnú vzorku druhého naplnenia SELECT do toho istého query, tak aby sa poctivo zmenili parametre podla noveho prikazu?
    « Poslední změna: 20-12-2017, 23:32:21 od mibainfo »

    Offline Delfin

    • Guru
    • *****
    • Příspěvků: 742
    • Karma: 32
    • SW konzultant
      • Verze Delphi: 2009, Tokyo
    Re:Parametrizované príkazy
    « Odpověď #42 kdy: 20-12-2017, 23:34:43 »
    Excellent
    Rated 1 time
    Dobre. Takto to funguje pri prvom spusteni Query.

    Ne, tak to funguje porad. To nema se spustenim co delat. Zmenis text SQL prikazu, preprocesor ho rozparsuje (bez kooperace s DBMS) a v pripade povoleneho nastaveni (ResourceOptions.ParamCreate a ResourceOptions.MacroCreate) se vytvori placeholdery kolekce parametru a maker.

    Lenze ked to chcem vsetko s tym istym query spustiti druhy raz (napr select s inym poctom parametrov).

    Ta veta je mutualne exkluzivni. Pokud mas stejny SQL prikaz, nemuze mit "jiny pocet parametru". To uz je pak jiny SQL prikaz.



    Jinak pokud je dotaz smerovan k tomu, proc je kolekce parametru zachovana i po uzavreni kurzoru (napr. metodou Close), je to jednoduse proto, ze muzes kurzor znovu otevrit beze zmeny SQL prikazu. Prikaz se tak nemusi znova zpracovavat preprocesorem pro sestaveni stejnych kolekci.
    « Poslední změna: 21-12-2017, 00:02:43 od Delfin »
    I'm a soldier, so don't panic!

    Offline Delfin

    • Guru
    • *****
    • Příspěvků: 742
    • Karma: 32
    • SW konzultant
      • Verze Delphi: 2009, Tokyo
    Re:Parametrizované príkazy
    « Odpověď #43 kdy: 21-12-2017, 00:35:44 »
    Jinak pokud je dotaz smerovan k tomu, proc je kolekce parametru zachovana i po uzavreni kurzoru (napr. metodou Close), je to jednoduse proto, ze muzes kurzor znovu otevrit beze zmeny SQL prikazu. Prikaz se tak nemusi znova zpracovavat preprocesorem pro sestaveni stejnych kolekci.

    Napr.:

    Kód: Delphi [Vybrat]
    1. Query.SQL.Text := 'SELECT !MyMacro FROM MyTable WHERE MyColumn = :MyParam'; // "by default" pripravi kolekci parametru a maker
    2. Query.MacroByName('MyMacro').AsIdentifier := 'MyColumn'; // existuje diky nastaveni ResourceOptions.MacroCreate a parsovani prikazu
    3. Query.ParamByName('MyParam').AsInteger := 666; // existuje diky ResourceOptions.ParamCreate a parsovani prikazu
    4. Query.Open; // otevre se kurzor
    5.  
    6. Query.Close; // kurzor se zavre avsak kolekce Macros a Params zustavaji beze zmen protoze nedoslo ke zmene SQL prikazu
    7. Query.Open; // otevre se kurzor a prikaz se spusti se stejnymi definicemi parametru a maker jako pri prvnim otevreni kurzoru

    Jinak pro ty co veri ze ma v pripade pripravy kolekce parametru prsty DBMS (s vychozim nastavenim FireDAC), necht spusti:

    Kód: Delphi [Vybrat]
    1. Query.SQL.Text := '?????';
    2. ShowMessage(Format('Parameter placeholder count: %d', [Query.ParamCount]));

    K cemuz dodam, ze se tady nejedna o chybu, ale pridanou vlastnost. Preprocesor FireDAC neresi syntaxi SQL jako takoveho (ta je jen na DBMS). Jen si z textu prikazu vyparsuje znacky a nazvy parametru, maker, nahradi zastupky a pripravi pro vse kolekce - ale to je jen dalsi podana ruka. Vyvojar totiz musi znat nazvy a datove typy jednotlivych parametru, coz mu nijak nebrani v tom si takove kolekce vyrobit manualne (po vypnuti prislusnych nastaveni). Takze preventivne uvedu, ze v pripade vyse zmineneho prikladu 5 otazniku nereste ze FireDAC vytvori 5 placeholderu pro parametry namisto vyhozeni vyjimky o nesmyslnem SQL prikazu - na to prijde DBMS s pripravou prikazu ke spusteni a je na vyvojari zajistit korektni plneni parametru prikazu ktery uvedl.
    « Poslední změna: 21-12-2017, 00:45:20 od Delfin »
    I'm a soldier, so don't panic!

    Offline Stanislav Hruška

    • Padawan
    • ******
    • Příspěvků: 3212
    • Karma: 30
      • Verze Delphi: XE7 professional
    Re:Parametrizované príkazy
    « Odpověď #44 kdy: 21-12-2017, 08:44:08 »
    Citace
    Tohle je celkem slušné https://www.devart.com/entitydac/.
    Je to zaujímavé. Ale musel by som byť profesionál a hlavne na vývoji zarábať. Čo sa nedeje. 250 € je už pre mňa veľký peniaz. Neviem odhadnúť, čo by mi to prinieslo vzhľadom na skutočnosť, že nepoužívam žiadne vizuálne DB komponenty. Všetko je TSM.
    Citace
    Zkus se na to schema podivat pohledem dedicnosti objektu. Spolecny predek trid prece muze delat stejnou vec, stejne jako muze obsahovat spolecna pole
    K tomu som sa ešte nedostal. Veď ma čaká:
    • dokončenie jadra aplikácie
    • otestovanie správnosti výsledkov
    • oprava obrovskej kopy známych problémov
    • optimalizácia aplikácie z pohľadu výkonu - hlavne odozvy formulárov ako takých
    • ošetrenie výnimiek! To ešte len bude sranda
    • vyhodenie tvorby objektov z formulárov
    • a až potom sa môžem/mám venovať tvorbe SQL

    Delphi XE7, FireBird
    Expert na kladenie nejasne formulovaných otázok.

     

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

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