Autor | Zpráva | ||
---|---|---|---|
martin1 Profil * |
#1 · Zasláno: 25. 8. 2013, 04:21:21
Ahoj,
nejsem zrovna velky expert na SQL, tak bych se rad poradil ohledne ulozeneych procedur. (Pouzivam MySQL databazi). Jak moc je vhodne pouzivat ulozene procedury? Nezpomaly se tim DB? Je rozumne mit procedury "skoro na vsechno"? Zda se mi lepsi napsat proceduru, nez pak vsechno resit v koncove aplikaci. Kouknete prosim na nasledujici kod (jenom priklad): CREATE TABLE adresa ( id INTEGER NOT NULL AUTO_INCREMENT, ulice VARCHAR(50), cp CHAR(5), mesto VARCHAR(25) NOT NULL, psc CHAR(5), PRIMARY KEY (id) ) DEFAULT CHARSET=utf8 COLLATE=utf8_czech_ci ; CREATE TABLE uzivatel ( id INTEGER NOT NULL AUTO_INCREMENT, login VARCHAR(20) NOT NULL, telefon CHAR(14), heslo CHAR(128) NOT NULL, adresa_id INTEGER NOT NULL, PRIMARY KEY (id), UNIQUE UQ_uzivatel_login(login), KEY (adresa_id) ) DEFAULT CHARSET=utf8 COLLATE=utf8_czech_ci ; ALTER TABLE uzivatel ADD CONSTRAINT FK_uzivatel_adresa FOREIGN KEY (adresa_id) REFERENCES adresa (id); delimiter $$ create procedure SP_vlozUzivateleSAdresou ( login VARCHAR(20), heslo CHAR(20), ulice VARCHAR(50), cp CHAR(5), mesto VARCHAR(25), psc CHAR(5) ) begin if exists(SELECT id FROM adresa WHERE `ulice`=ulice AND `cp`=cp AND `mesto`=mesto AND `psc`=psc) then INSERT INTO uzivatel (`login`, `heslo`, `adresa_id`) VALUES (login, SHA2(heslo,512), (SELECT id FROM adresa WHERE `ulice`=ulice AND `cp`=cp AND `mesto`=mesto AND `psc`=psc) ); else INSERT INTO adresa (`ulice`, `cp`, `mesto`, `psc`) VALUES (ulice, cp, mesto, psc); INSERT INTO uzivatel (`login`, `heslo`, `adresa_id`) VALUES (login, SHA2(heslo,512), (SELECT id FROM adresa WHERE `ulice`=ulice AND `cp`=cp AND `mesto`=mesto AND `psc`=psc) ); end if; end $$ delimiter ; call SP_vlozUzivateleSAdresou ("martin", "abc123", "Ulice", "1024", "Město", "12345"); call SP_vlozUzivateleSAdresou ("pepa", "456def", "Ulice", "1024", "Město", "12345"); Pridavam uzivatele a k nemu adresu. Normalne musim vytvorit nejdriv zaznam v tabulce adresa a pote uzivatele. Jeste musim ve sve aplikaci hledat, jestli uz adresa existuje. Takhle jenom zavolam ulozenou proceduru a mam po starostech :-) Jaky na to mate nazor? Dekuji za vase nazory! |
||
Joker Profil |
#2 · Zasláno: 25. 8. 2013, 09:26:22
Podle mě to není problém a je to tak správně. Teda až na slovo „nezpomalý“.
|
||
Alphard Profil |
#3 · Zasláno: 25. 8. 2013, 10:32:14
S výkonem problém nevidím, spíš naopak, bude to rychlejší, ale uvedený případ se mi na obvyklých webech zdá moc náročný na psaní a údržbu. Inserty běžně nechávám sestavovat z položek polí, představa, že bych měl udělat hromady podobných jednoduchých procedur a při přidání nějakého sloupce vše upravovat, mě zrovna neláká.
Situace se výrazně změní ve chvíli, kdy k db přistupuje více aplikací. Čím složitější systém, tím výhodnější to bude. Pro velké aplikace jsou uložený procedury/funkce/pohledy někdy jediný přístupový bod k db. |
||
Camo Profil |
#4 · Zasláno: 25. 8. 2013, 14:22:11
Alphard:
Ale ak pridáš nejaký stĺpec, tak máš jedno či ti to urobí bordel v php kóde, alebo v procedúre, nie? Ja tiež rozmýšľam, že by som to zaviedol u seba. Mne to vychádza ako efektívnejšie. Všetky tie testy a opakovanie kódu ti vypadnú. Len nevieš, čo to presne robí. Jedine to okomentovať. |
||
martin1 Profil * |
#5 · Zasláno: 25. 8. 2013, 15:17:18
Alphard:
>> ale uvedený případ se mi na obvyklých webech zdá moc náročný na psaní a údržbu Mas pravdu, dal jsem to jen jako ukazku. Napada me jiny pripad. Existujici uzivatel si bude chtit zmenit adresu. Zada mi novou adresu a ja musim najit jestli uz exituje. Kdyz ano, tak adresa_id nastavim na spravne id. Pokud pouziju ulozenou proceduru, tak do db jenom poslu nove udaje a vic neresim. Jaky na to mas nazor? A jeste jedna vec. jaky mas nazor na pouzivani pohledu? Kdyz vyse uvedeny kod rozsirim o tabulku stat a budu chtit vypsat login vsech uzivatelu z ceska, je dobry napad si udelat pohled a ten pak volat z aplikace, nebo je lepsi z aplikace volat select s joinem? CREATE TABLE stat ( id INTEGER NOT NULL AUTO_INCREMENT, nazev VARCHAR(50) NOT NULL, PRIMARY KEY (id) ) DEFAULT CHARSET=utf8 COLLATE=utf8_czech_ci ; CREATE TABLE adresa ( id INTEGER NOT NULL AUTO_INCREMENT, ulice VARCHAR(50), cp CHAR(5), mesto VARCHAR(25) NOT NULL, psc CHAR(5), stat_id INTEGER NOT NULL, KEY (stat_id), PRIMARY KEY (id) ) DEFAULT CHARSET=utf8 COLLATE=utf8_czech_ci ; CREATE TABLE uzivatel ( id INTEGER NOT NULL AUTO_INCREMENT, login VARCHAR(20) NOT NULL, telefon CHAR(14), heslo CHAR(128) NOT NULL, adresa_id INTEGER NOT NULL, PRIMARY KEY (id), UNIQUE UQ_uzivatel_login(login), KEY (adresa_id) ) DEFAULT CHARSET=utf8 COLLATE=utf8_czech_ci ; ALTER TABLE uzivatel ADD CONSTRAINT FK_uzivatel_adresa FOREIGN KEY (adresa_id) REFERENCES adresa (id); ALTER TABLE adresa ADD CONSTRAINT FK_adresa_stat FOREIGN KEY (stat_id) REFERENCES stat (id); INSERT INTO `stat` (`id`, `nazev`) VALUES (1, 'Česká Republika'), (2, 'USA'); CREATE VIEW vwUzivateleCZ AS SELECT stat.nazev, uzivatel.login FROM uzivatel INNER JOIN adresa ON uzivatel.adresa_id = adresa.id INNER JOIN stat ON adresa.stat_id = stat.id; -------- SELECT stat.nazev, uzivatel.login FROM uzivatel INNER JOIN adresa ON uzivatel.adresa_id = adresa.id INNER JOIN stat ON adresa.stat_id = stat.id -------- SELECT * FROM vwUzivateleCZ |
||
Jan Tvrdík Profil |
#6 · Zasláno: 25. 8. 2013, 16:07:37
martin1:
Doporučuji ti zvážit přechod na PostgreSQL, které je přeci jenom na tento styl vývoje (psaní pohledů a procedur) vhodnější. |
||
Alphard Profil |
#7 · Zasláno: 25. 8. 2013, 17:40:49
Camo [#4]:
Já nemluvím o bordelu, já mluvím o nutnosti změny. PHP musím změnit v každém případě, přinejmenším předat další parametr (pokud nechci přímo expandovat pole, což by možná taky šlo). Čím více míst, kde bude nutná změna, tím hůře. Dělat jen obálku nad insertem se mi nezdá užitečné. Pokud by se ale insert prováděl z více různých aplikací, je to úplně jiná situace, to jsem psal hned na začátku. martin1 [#5]: Já nechci bez znalosti kontextu odhadovat nějakou hranici, když ještě ne a kdy už ano. Sám uložené procedury používám v místech, kde se provádí složitější práce s daty a je tedy výhodné být k těm datům co nejblíže. Občas jsem měl také určité snahy přenést víc aplikační logiky na databázi, ale narazil jsem na velkou složitost při programování. Jak píše [#6] Jan Tvrdík, MySQL má v této oblasti oproti konkurenci rezervy. Pak vznikají konstrukce jako declare curs cursor for select ...; declare continue handler for not found set bDone = 1; open curs; drop temporary table if exists __tmp; create temporary table ... Pohledy používám, ale taky to s nimi nepřeháním. Pro opakující se joiny, které nemám v pohledech, mám pomocí dibi sestavený základní dotaz a ten potom rozvíjím do konkrétních případů. |
||
Časová prodleva: 11 let
|
0