Autor Téma: Zostavenie zloženého SQL textu  (Přečteno 1077 krát)

Offline Stanislav Hruška

  • Padawan
  • ******
  • Příspěvků: 5959
  • Karma: 43
    • Verze Delphi: W10 + D11
Zostavenie zloženého SQL textu
« kdy: 06-10-2021, 12:44:09 »

Užívateľ si vyberie voľby pre tlačovú zostavu. Na základe týchto volieb, okrem iného, si zostavím SQL text. Postup je nasledovný:
  • zložím si jednotlivé časti - Select, From...
  • tieto časti zložím do výsledného textu
Tento spôsob mi dobre funguje pri jednoduchom SQL. Samozrejme nefunguje pre SQL s
  • WITH
  • subQuery
Ja mám problém ako na to. Moje otázky:
  • Existuje na to niečo jednoduché? Samozrejme zadarmo
  • Čo hľadať na internete? Kľúčové slová
  • Má niekto návod/návrh na riešenie?
Ďakujem.
W10 64b, Delphi 10.4, FireBird 3.05
Expert na kladenie nejasne formulovaných otázok.

Offline Jirka

  • Hrdina
  • ****
  • Příspěvků: 431
  • Karma: 9
    • Verze Delphi: XE2
Re:Zostavenie zloženého SQL textu
« Odpověď #1 kdy: 06-10-2021, 12:50:42 »
Můžeš zkusit používat "VIEW" nebo "SELECT * FROM STORED PROCEDURE"

Offline Stanislav Hruška

  • Padawan
  • ******
  • Příspěvků: 5959
  • Karma: 43
    • Verze Delphi: W10 + D11
Re:Zostavenie zloženého SQL textu
« Odpověď #2 kdy: 06-10-2021, 12:59:42 »
Citace
Můžeš zkusit používat "VIEW" nebo "SELECT * FROM STORED PROCEDURE"
VIEW mi to nevyrieši. Nepozná parametre. K druhej možnosti sa ani neviem vyjadriť.
Ešte som zabudol na UNION
Uvádza jeden príklad:
Voľba názvu:
  • Skratka - 'FO.Short AS FOTitle'
  • Plný názov - 'FO.Title as FOTitle'
Tých možností je pre SELECT viac. Tak isto pre FROM, WHERE a ORDER BY.
Niektoré texty získavam dosť komplikovane.
« Poslední změna: 06-10-2021, 13:01:45 od Stanislav Hruška »
W10 64b, Delphi 10.4, FireBird 3.05
Expert na kladenie nejasne formulovaných otázok.

Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 3285
  • Karma: 139
    • Verze Delphi: D2007, XE3, DX10
Re:Zostavenie zloženého SQL textu
« Odpověď #3 kdy: 06-10-2021, 16:15:19 »
Můžeš zkusit používat "VIEW" nebo "SELECT * FROM STORED PROCEDURE"
Ale to by pak musel sestavovat ten SQL na urovni impotentniho jazyka SQL uvnitr te SP.

Videl jsem to v praxi a udrzovat bych to nechtel  -to bude IMHO nejmene radove vetsi onanie, nez to sestavit v Delphi...

Offline Jirka

  • Hrdina
  • ****
  • Příspěvků: 431
  • Karma: 9
    • Verze Delphi: XE2
Re:Zostavenie zloženého SQL textu
« Odpověď #4 kdy: 06-10-2021, 16:22:18 »
Můžeš zkusit používat "VIEW" nebo "SELECT * FROM STORED PROCEDURE"
Ale to by pak musel sestavovat ten SQL na urovni impotentniho jazyka SQL uvnitr te SP.

Videl jsem to v praxi a udrzovat bych to nechtel  -to bude IMHO nejmene radove vetsi onanie, nez to sestavit v Delphi...

Třeba  takto  ?
Kód: Delphi [Vybrat]
  1. Format(' SELECT * FROM VIEW_TABLE WHERE %s  ORDER BY %s',[ASqlWhere,ASql_Order]

Offline Stanislav Hruška

  • Padawan
  • ******
  • Příspěvků: 5959
  • Karma: 43
    • Verze Delphi: W10 + D11
Re:Zostavenie zloženého SQL textu
« Odpověď #5 kdy: 06-10-2021, 16:24:57 »
Urobil som analýzu a mám 39 (ten počet klesne) jednoduchých a 3 zložené SQL.
Najjednoduchšie bude ponechať tie 3 tak ako ich mám.
Riešiť budem tých 39. Tam to má zmysel.
Neviem ako by som to riešil v tej SP. V Delphi si načítam stav jednotlivých komponentov a podľa toho sa rozhodujem. Ale v SP? Aj keby som je podhodil tie hodnoty, tak neviem ako na to. Doteraz som nepoužil ani jedinú SP ;)  Vyhýbal som sa tomu. Úspešne.
W10 64b, Delphi 10.4, FireBird 3.05
Expert na kladenie nejasne formulovaných otázok.

Offline Stanislav Hruška

  • Padawan
  • ******
  • Příspěvků: 5959
  • Karma: 43
    • Verze Delphi: W10 + D11
Re:Zostavenie zloženého SQL textu
« Odpověď #6 kdy: 06-10-2021, 16:27:03 »
Citace
Format(' SELECT * FROM VIEW_TABLE WHERE %s  ORDER BY %s',[ASqlWhere,ASql_Order]
A tie parametre získam kde?
W10 64b, Delphi 10.4, FireBird 3.05
Expert na kladenie nejasne formulovaných otázok.

Offline Jirka

  • Hrdina
  • ****
  • Příspěvků: 431
  • Karma: 9
    • Verze Delphi: XE2
Re:Zostavenie zloženého SQL textu
« Odpověď #7 kdy: 06-10-2021, 16:31:43 »
Doteraz som nepoužil ani jedinú SP ;)  Vyhýbal som sa tomu. Úspešne.
Na 99 % takto vytvářených dotazu použiji  VIEW  a tam kde potřebuji vrátit  i nějaké výpočty  na základě podmínek které jsou známy až  v té SP
použiji SP.
Technicky vzato ji můžeš volat stejně jako ten VIEW ale otázkou je efektivita dotazu ...

Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 3285
  • Karma: 139
    • Verze Delphi: D2007, XE3, DX10
Re:Zostavenie zloženého SQL textu
« Odpověď #8 kdy: 06-10-2021, 16:33:34 »
  • Existuje na to niečo jednoduché? Samozrejme zadarmo
Snad nejaky SQL builder napr. https://openhms.sourceforge.io/sqlbuilder/, ale buhvi, co to umi...

Citace
  • Čo hľadať na internete? Kľúčové slová
SQL run-time builder

Citace
  • Má niekto návod/návrh na riešenie?
Trend je jasny: pokud mozno SQL uplne vyfuckovat a pouzit LINQ nebo jOOQ apod., ale ani tam se nevyhnes nejakemu dynamickemu skladani

V Delphi jsme to vzdycky skladali v run-time, ale meli jsme nejakou vlastni vrstvu mezi Delphi a SQL a sadu utility funkci. V podstate jsme beznou logikou sestavovali SQL do seznam radku a do seznamu variantu jsme cpali k tomu hodnoty parametru. A pak jsme to predhodili nasi DB mezivrstve, ktera zajistila vykonani nad odpovidajici konektivitou a RDBMS. Ukazka
Kód: Delphi [Vybrat]
  1.   [...]
  2.   ASQLCmd.Add('where');
  3.   ASQLCmd.Add('  lnk.IDEXCHANGEORDER = exo.id and dp.idpackettype=:EXOUT and dp.idconvoy is not null');
  4.   ASQLCmd.Add(') dlv');
  5.   ASQLCmd.Add('outer apply (');
  6.   ASQLCmd.Add('  SELECT');
  7.   ASQLCmd.Add('    count(dp.IDPACKETTYPE) as inhibitedpacketcount');
  8.   ASQLCmd.Add('  from');
  9.   ASQLCmd.Add('    PACKET dp');
  10.   ASQLCmd.Add('  inner join EXCHANGEORDER_PACKET lnk');
  11.   ASQLCmd.Add('    on dp.Id=lnk.IDPACKET');
  12.   ASQLCmd.Add('where');
  13.   ASQLCmd.Add('  lnk.IDEXCHANGEORDER = exo.id and dp.idpackettype=:EXOUTINH');
  14.   ASQLCmd.Add(') inh');
  15.   ASQLCmd.Add('where (1=1)');
  16.   case AEditorMode of
  17.     TExEdOrderMode.FromCounting:
  18.       ;
  19.     TExEdOrderMode.FromRegister:
  20.       ASQLCmd.Add('  and exo.ICode is not null and exo.ICode<>''''');
  21.   else
  22.     raise ...
  23.   end;
  24.   [...]
  25.  
a pak treba
Kód: Delphi [Vybrat]
  1.   [...]
  2.   if ClientId >= 0 then
  3.   begin
  4.     ASQLCmd.Add('and exo.IDCLIENT = :IDCLIENT');
  5.     ASQLPar.AddVariant('IDCLIENT', ClientId);
  6.   end;
  7.  
  8.   if edBranchFilter.HasValue then
  9.   begin
  10.     ASQLCmd.Add('and exo.IDBRANCH = :IDBRANCH');
  11.     ASQLPar.AddVariant('IDBRANCH', EdBranchFilter.AsInteger);
  12.   end;
  13.  
  14.   AppendRealizationDateFilterWhereClause(ASQLCmd, ASQLPar);
  15.  
  16.   if edICode.HasValue then
  17.   begin
  18.     ASQLCmd.Add('and exo.Id = :ICODEPATTERN');
  19.     ASQLPar.AddVariant('ICODEPATTERN', edICode.AsInteger);
  20.   end;
  21.   [...]
  22.  


« Poslední změna: 06-10-2021, 16:52:39 od pf1957 »

Offline Jirka

  • Hrdina
  • ****
  • Příspěvků: 431
  • Karma: 9
    • Verze Delphi: XE2
Re:Zostavenie zloženého SQL textu
« Odpověď #9 kdy: 06-10-2021, 16:33:56 »
Citace
Format(' SELECT * FROM VIEW_TABLE WHERE %s  ORDER BY %s',[ASqlWhere,ASql_Order]
A tie parametre získam kde?

Jake parametry máš na mysli ?

Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 3285
  • Karma: 139
    • Verze Delphi: D2007, XE3, DX10
Re:Zostavenie zloženého SQL textu
« Odpověď #10 kdy: 06-10-2021, 16:42:23 »
Ale v SP? Aj keby som je podhodil tie hodnoty, tak neviem ako na to. Doteraz som nepoužil ani jedinú SP ;)  Vyhýbal som sa tomu. Úspešne.
O nic jsi neprisel :-) To vypada nejak takhle:

Kód: SQL [Vybrat]
  1. CREATE OR ALTER PROCEDURE GETUSERLOGVIEW (
  2.     SESSIONID INTEGER,
  3.     DATEFROM TIMESTAMP,
  4.     DATETO TIMESTAMP,
  5.     SOURCE INTEGER,
  6.     NAMEUSER VARCHAR(20),
  7.     SERIALNO VARCHAR(20),
  8.     WORKSTATION VARCHAR(20),
  9.     INEVENT INTEGER,
  10.     INERESULT INTEGER,
  11.     LANG VARCHAR(5))
  12. RETURNS (
  13.     EVENTDATE TIMESTAMP,
  14.     ENDESCRIPTION VARCHAR(80),
  15.     SKDESCRIPTION VARCHAR(80),
  16.     CZDESCRIPTION VARCHAR(80),
  17.     USERNAME VARCHAR(30) CHARACTER SET ASCII,
  18.     ESOURCE VARCHAR(30) CHARACTER SET ASCII,
  19.     ERESULT VARCHAR(20) CHARACTER SET ASCII,
  20.     WORKSTATIONIP VARCHAR(15) CHARACTER SET ASCII,
  21.     WORKSTATIONNAME VARCHAR(20) CHARACTER SET ASCII,
  22.     TCRIP VARCHAR(15) CHARACTER SET ASCII,
  23.     TCRSERIALNO VARCHAR(20) CHARACTER SET ASCII,
  24.     ERESULTID INTEGER,
  25.     EVENTNOTE VARCHAR(255),
  26.     EVENTID INTEGER)
  27. AS
  28. DECLARE variable STRSQL VARCHAR(1000);
  29. BEGIN
  30.   strsql = 'select u.eventdate,t.endescription, t.skdescription, t.czdescription,u.username,s.source, r.result,u.workstationip,
  31.            u.workstationname,u.tcrip,u.tcrserialno,u.result, u.eventnote, u.event from userlog u,
  32.            logeventresult r,logeventsource s,logeventtype t
  33.             where u.eventsource=s.id and u."EVENT"=t.id and u.result=r.id';
  34.   IF (NOT :datefrom IS NULL) THEN
  35.   BEGIN
  36.     strsql = strsql || ' AND u.eventdate>=''' || :datefrom || '''';
  37.   END
  38.   IF (NOT :dateto IS NULL) THEN
  39.   BEGIN
  40.     strsql = strsql || ' AND u.eventdate<=''' || :dateto || '''';
  41.   END
  42.   IF (NOT :SOURCE IS NULL) THEN
  43.   BEGIN
  44.     strsql = strsql || ' AND s.id=' || :SOURCE;
  45.   END
  46.   IF (NOT :nameuser IS NULL) THEN
  47.   BEGIN
  48.     strsql = strsql || ' AND u.username like ''' || :nameuser || '%''';
  49.   END
  50.   IF (NOT :serialno IS NULL) THEN
  51.   BEGIN
  52.     strsql = strsql || ' AND u.tcrserialno=''' || :serialno || '''';
  53.   END
  54.   IF (NOT :workstation IS NULL) THEN
  55.   BEGIN
  56.     strsql = strsql || ' AND u.workstationname=''' || :workstation || '''';
  57.   END
  58.   IF (NOT :inevent IS NULL) THEN
  59.   BEGIN
  60.     strsql = strsql || ' AND t.id=' || :inevent;
  61.   END
  62.   IF (NOT :ineresult IS NULL) THEN
  63.   BEGIN
  64.     strsql = strsql || ' AND r.id=' || :ineresult;
  65.   END
  66.   strsql = strsql || ' order by u.eventdate;';
  67.   FOR
  68.   EXECUTE statement :strsql
  69.   INTO :eventdate, :endescription, :skdescription, :czdescription, :username, :esource, :eresult, :workstationip,
  70.        :workstationname, :tcrip, :tcrserialno, :eresultid, :eventnote, :eventid
  71.   do
  72.     suspend;
  73. END^
  74.  


Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 3285
  • Karma: 139
    • Verze Delphi: D2007, XE3, DX10
Re:Zostavenie zloženého SQL textu
« Odpověď #11 kdy: 06-10-2021, 16:43:29 »
Jake parametry máš na mysli ?
No treba hodnoty filtru, pro ktere ma vytahnout z DB vysledek aj. viz priklady, co jsem posilal

Offline Stanislav Hruška

  • Padawan
  • ******
  • Příspěvků: 5959
  • Karma: 43
    • Verze Delphi: W10 + D11
Re:Zostavenie zloženého SQL textu
« Odpověď #12 kdy: 06-10-2021, 16:56:19 »

Citace
Jake parametry máš na mysli ?
Tie
Citace
ASqlWhere,ASql_Order
nie sú parametre? Lebo ja som si myslel, že sú.
W10 64b, Delphi 10.4, FireBird 3.05
Expert na kladenie nejasne formulovaných otázok.

Offline Jirka

  • Hrdina
  • ****
  • Příspěvků: 431
  • Karma: 9
    • Verze Delphi: XE2
Re:Zostavenie zloženého SQL textu
« Odpověď #13 kdy: 06-10-2021, 16:58:34 »
To jsou obycejne lokální promenné typu string do kterých si poskládáš "where" a  "order by" řetězec   


Offline Stanislav Hruška

  • Padawan
  • ******
  • Příspěvků: 5959
  • Karma: 43
    • Verze Delphi: W10 + D11
Re:Zostavenie zloženého SQL textu
« Odpověď #14 kdy: 06-10-2021, 17:12:54 »
Nebudem si to komplikovať a pre jednu jednorazovú vec študovať niečo nové. Tie jednoduché aktualizujem na nový stav. Zložené nechám tak. Ešte uvediem spôsob, ako to robím.
Kód: Delphi [Vybrat]
  1.  
  2.   TPrintWithOption = class(TPrintBase)
  3.  
  4.     FTextAndParam: TTextAndParam;
  5.  
  6.     procedure CompleteText;
  7. procedure TPrintWithOption.CompleteText;
  8.  
  9. begin
  10.   FQryText := 'SELECT ' + FTextAndParam.Select + ' FROM ' + FTextAndParam.From;
  11. .
  12.   if FTextAndParam.Where <> '' then
  13.     FQryText := FQryText + ' WHERE '+ FTextAndParam.Where;
  14. ...
  15.   TTextAndParam = class  //  Jednotka na získanie čiastočných textov
  16.  
  17.     FSelectList: TStringList;
  18. procedure TTextAndParam.GetBasicSelect;
  19.  
  20. const
  21.   FocSelect = '04B.TITLE AS BTITLE, E.TITLEFULL AS ETITLEFULL, ';
  22. var
  23.   Text: string;
  24. begin
  25.   case FPrintType of
  26.     ptFlat: Text := FocSelect + 'F.FLATNUMBER';
  27.   else
  28.     Text := FocSelect + 'F.FLATNUMBER, O.FULLNAME AS OFULLNAME';
  29.   end;
  30.   FSelectList.Add(Text);
  31. end;
  32. ...
  33. //Po získaní všetkých string
  34. procedure TTextAndParam.SetSelect;
  35.  
  36.  
  37. var
  38.  I: Integer;
  39. begin
  40.   FSelectList.Sort;
  41. { TODO : Odstrihnúť číslo }
  42.   FSelect := FSelectList[0];
  43.   for I := 1 to FSelectList.Count - 1 do
  44.     FSelect := FSelect + ', ' + FSelectList[I];
  45. end;
  46. ...
  47.   CompleteText;
Vždy mi totálne rozhádže formátovanie. Kašlem naň.

W10 64b, Delphi 10.4, FireBird 3.05
Expert na kladenie nejasne formulovaných otázok.