MySQL - update + join
Toto je zoznam záznamov, ktoré chcem upraviť:
select nakup.id
from nakup
inner join zakaznik on nakup.zakaznik_id=zakaznik.id
where zakaznik.skupina_id='1'
Potrebujem pri týchto záznamoch upraviť toto:
update nakup
set spracovane_skupina=1
Toto je výsledok:
update nakup
set spracovane_skupina='1'
where
(
select nakup.id
from nakup
inner join zakaznik on nakup.zakaznik_id=zakaznik.id
where zakaznik.skupina_id='1'
)
Dostávam chybovú hlášku:
SQL Error (1093): You can't specify target table 'nakup' for update in FROM clause
Doplňujúce informácie:
- MySQL 5.5.8
- motor tabuľky "nakup" je InnoDB
- motor tabuľky "zakaznik" je MyISAM
Toto som mal ako inšpiráciu:
339622-sql-update
Dúfam, že som dodal všetky potrebné informácie. Chcel by som vás poprosiť o pomoc s týmto SQL príkazom. Tabuľky som pre prehľadnosť premenoval na slovenské, takže, ak tam nájdete nejaký preklep, je to len prepisom na poradňu. V originále mám anglické názvy.
Stále tá istá chybová hláška, ale osobne sa mi to tiež zdá syntakticky správne.
zkusil bych si pojmenovat tu výslednou tabulku selectu
Tak to nemusis džjonovat, ne?
Jasné, dnes si asi sedím na kábli. Fuguje, ďakujem za pomoc.
Neviem prečo, ale nenastaví to všetky záznamy, niekde bude chyba. Podmienku pre null tam nemám, pretože záznam s null nemám.
Opravené: Beriem späť. Zle som to odpísal, tiež to bude fungovať.
to je divné (not null jsem čekal že si vyhodíš, ale bez znalosti dat/constrainu to tam při přepisu být mělo)
V tom prvom where som odpísal len "id in" a malo tam byť "zakaznik_id in" preto mi to nešlo. To bolo tým, že úplne prvý príspevok to má chybne a to som odpísal.
Opravené: Beriem späť. Zle som to odpísal, tiež to bude fungovať.
To jsem rád, imho se to líp čte než ten inner join..
Práve som to aj otestoval a funguje to.
Teraz ešte taká otázka, že čo sa vykoná skôr? Tento alebo ten druhý príkaz?
Spousta lidí to neví, ale pravda je taková, že typicky* nezáleží na tom jak je to napsané, optimalizátor to udělá pořád stejně. Existují sice lidé, kteří na přepisy věří - ale typický přepis implicitně přidá/odstraní nějakou novou informaci pro optimalizátor (například když neudělam join ale dam to do projection jako skalární select muže to vracet stejný výsledek ale dal jsem sql enginu navíc informaci, že pro každý řádek z jedné tabulky muže být jen jeden z druhé, kterou při joinu mít nemusel = tzn stejný výsledek ale nejsou to stejné selecty).
Pokud tam máš primární klíče na id, a zakaznik_id a tedy i (heh dnes jsem na to zrovna narazil s JaFim a myslim ze v tvem postu) not null/unique constraint pak by měli být exekuční plány naprosto stejné. Nezávisle na tom jak jsi to napsal, pokud tam například nemáš ten not null constraint pak jsou to dva uplně jiné příkazy (ačkoliv vzhledem k datum dávají stejný výsledek) a tedy i jiné prováděcí plány a muj odhad (vzhledem k většímu množství informací) by byl že to s tim joinem pak poběží rychleji, jinak imho stejný plán a tedy stejně rychle.
* typicky = sql stroj nemůže při větším počtu tabulek projít všechny kombinace (pro příklad Oracle 10g - 60 000 kombinací, Oracle 11g - jíná strategie 2000 po fragmentech) a tedy pokud to napíšeš jinak při větším počtu tabulek tak budou jinak i exekuční plány, ale to pouze tim že neprohledal celý stavový prostor a tam je pak doslova náhoda, co bude lepší.
UPDATE nakup t1
JOIN zakaznik t2 ON t1.id=t2.id
SET t1.spracovane_skupina='1'
WHERE t2.skupina_id = '1'
Takže toto jediné (* ako som neskôr zistil, nie je to jediné, to horné som len zle odpísal) funguje správne. Akurát je tam malá chybička:
Ďakujem za pomoc.
Nevim jak na MySQL, ale pro MS SQL by to vypadalo takto