Rady začátečníkům
Obecná doporučení a povídání
--Raul 12:59, 10. 4. 2008 (CEST)
Nespoléhejte na různé administrační nástroje
Když mi před pár týdny Pavel Stěhule povídal o pg (pravda, povídal mi o tom už o dost dříve, ale jak se říká zvyk je železná košile, v mém případě zvyk na mysql), řekl mi mezi řečí pár zajímavých bodů :
- SQL příkazy piš ručně
- piš je do zvlášť souboru a pak na něj v programu odkazuj
- nespoléhej na administrační klikátko
Řekl jsem si huh, uff, ghe. Nicméně měl Pavel pravdu a během pár dní jsem zjistil, že velkou pravdu.
- různé programy mají různé všelijaké rádoby optimalizace a grafický "Query Builder" např. v EMS pg Manageru si SELECT optimalizují už při vytváření po svém. Velice jsem se divil, kdy po přidání tabulky a vazeb do Query Builderu se výsledný SELECT úplně změnil k nepoznání.
- vytvořil jsem si knihovnu, které tento soubor SQL příkazů převede do pascalu, ve kterém programuji, jejímž výsledkem jsou procedury a funkce. Toto jsem navíc udělal zvlášť pro mySQL i pg, tudíž mojí aplikaci moc nezajímá, kterou db zrovna používám.
- jak už jsem psal výše, administrační klikátka, mají různé "rádobyfíčurky", někdy pomohou, někdy uškodí. Napadá mě můj pokus o cizí klíč pro zamezení DELETE (ON DELETE RESTRICT), kdy vše po naklikání fungovalo. Až do doby první změny. Z neznámého důvodu totiž EMS pg Manager neumí vytvořit vazbu na cizí klíč pouze pro DELETE, ale zároveň ji vytvoří i pro UPDATE. Ručně napsaný SQL příkaz pro vytvoření tabulky Vám to však neudělá.
Proto doporučuji, když už použít nějaké klikátko, tak jen pro definici kostry na testovacícm schematu a posleze vzit DDL, přečíst, upravit a následně spustit nad skutečným schematem.
Jména objektů v DB
Důležité upozornění pro uživatele přecházející z mySQL na pg je taktéž pojmenovávání objektů v databázi. Zatímco mySQL je case-insensitive a tudíž je jedno jak si kterou tabulku, sloupeček apod pojmenujete, pg má pár zákonitostí, které Vám může připravit pár perných hodin/dní/měsíců/let :-) - (pozn. PostgreSQL je také case-insensitive, až na identifikátory zapsané v uvozovkách, viz dále)
Sice to tady Pavel má, ale raději to zmíním ještě na tomto místě.
Pokud definujete objekt v databázi a jeho jméno v definici uvedete do " je od té chvíle nutnost psát tyto " všude, kde s daným objektem pracujete. Další možností je nepsat " při vytváření těchto objektů, případně si zvyknout na psaní jmen objektů pouze malými písmeny. Bohužel, jak jsem již psal v předchozí části, různá klikátka Vám ty uvozovky v mnoha případech napíšou samy. V mnou používaném EMS pg Lite Manageru jsem asi 4 hodiny hledal, jestli se to nedá nějak vypnout, ale nenašel jsem tuto možnost.
Tipy a triky
Porovnávání řetězců co se podobnosti týče
Narazil jsem na problém, jak poznat zákazníky e-shopu podle jmen (ne vždy zákazník použije svůj login, ale zašle objednávku pod "novým účtem"). Byl jsem upozorněn na trigramy. Copak je to zajímavého ? Jelikož nejsem teoretik, řeknu na rovinu, že do hloubky netuším. Jelikož však samotný trigram mi přijde ne moc šikovný, je dobré nejprve řetězce zbavit balastu, to jest, mezer, českých znaků, a velkých písmen. Zde je výsledná funkce is_similar :
CREATE OR REPLACE FUNCTION "_global_"."is_similar" (ppar1 varchar, ppar2 varchar) RETURNS boolean AS $body$ DECLARE lpar1 varchar; lpar2 varchar; res boolean; BEGIN res := false; lpar1 := lower(replace(to_ascii(encode(convert_to(ppar1, 'latin2'),'escape'),'latin2'),' ','')); lpar2 := lower(replace(to_ascii(encode(convert_to(ppar2, 'latin2'),'escape'),'latin2'),' ','')); IF lpar1=lpar2 THEN res := true; ELSE res := similarity(lpar1,lpar2) >= 0.3; END IF; IF res IS NULL then res := false; END IF; return res; END; $body$ LANGUAGE 'plpgsql' VOLATILE CALLED ON NULL INPUT SECURITY DEFINER;
Pascalisté a funkce v pg
Jako letitý delphista a začínající uživatel databáze pgSQL mám dost často chybu v uložených procedurách. V pgSQL se uložené procedury a funkce píší sice velmi obdobně (což právě může uživatele zmást), nicméně je zde par rozdílů.
Podmínky
Při psaní podmínek IF-THEN-ELSE-END je na rozdíl od pascalu potřeba psát i ; na konci vykonávaných řádků, stejně tak, jako se nevyužívá uvození begin-end.
Pascal: pg: if <podminka> then IF <podminka> THEN prikaz prikaz; else ELSE prikaz; prikaz; END IF; if (<podminka>) AND (<podminka>) then IF (<podminka>) AND (<podminka>) THEN begin prikaz1; prikaz1; prikaz2; prikaz2; end else ELSE begin prikaz3; prikaz3; prikaz4; prikaz4; end; END IF;
Deklarace proměnných
Dalším rozdílem je deklarace proměnných. Zatímco v pascalu máte možnost deklarovat více proměnných stejného typu najednou - oddělené čárkami, v pg tato možnost není a je nutno deklarovat každou proměnnou zvlášť. Taktéž se v pg na rozdíl od pascalu nepoužívá : pro oddělení typu proměnné.
Pascal: pg: var prom1, prom2: String; DECLARE prom1 VARCHAR; i1: Integer; prom2 VARCHAR; i1 INTEGER:
Pozor na RETURN
U příkazu RETURN je potřeba dát si pozor na dvě věci :
- Na rozdíl od pascalu a jeho proměnné result je RETURN příkazem, který nastaví návratovou hodnotu a UKONČÍ běh funkce.
- U funkce nesmí dojít k tomu, že RETURN nebude (z důvodu složitějších podmínek např) proveden.
Osvědčil se mi následující postup :
DECLARE res VARCHAR; BEGIN res := 'nejaka navratova hodnota pro standartni chovani'; .... jadro funkce, misto RETURN zde staci nastavit res := 'neco'; RETURN res; END;