Přidat otázku mezi oblíbenéZasílat nové odpovědi e-mailemVyřešeno 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.

Předmět Autor Datum
update nakup set spracovane_skupina='1' where id in ( select nakup.id from nakup inner join zakaznik…
Wikan 09.05.2012 21:59
Wikan
Stále tá istá chybová hláška, ale osobne sa mi to tiež zdá syntakticky správne.
msx. 09.05.2012 22:15
msx.
zkusil bych si pojmenovat tu výslednou tabulku selectu
tomas.kulhanek 09.05.2012 22:19
tomas.kulhanek
update nakup set spracovane_skupina='1' where id in ( select nakup.id from nakup inner join zakaznik…
AZOR 09.05.2012 22:23
AZOR
Jasné, dnes si asi sedím na kábli. Fuguje, ďakujem za pomoc.
msx. 09.05.2012 22:33
msx.
Neviem prečo, ale nenastaví to všetky záznamy, niekde bude chyba. Podmienku pre null tam nemám, pret…
msx. 09.05.2012 22:47
msx.
to je divné (not null jsem čekal že si vyhodíš, ale bez znalosti dat/constrainu to tam při přepisu b…
AZOR 09.05.2012 22:49
AZOR
V tom prvom where som odpísal len "id in" a malo tam byť "zakaznik_id in" preto mi to nešlo. To bolo…
msx. 09.05.2012 22:52
msx.
Opravené: Beriem späť. Zle som to odpísal, tiež to bude fungovať. To jsem rád, imho se to líp čte n…
AZOR 09.05.2012 22:53
AZOR
Práve som to aj otestoval a funguje to.
msx. 09.05.2012 22:55
msx.
Teraz ešte taká otázka, že čo sa vykoná skôr? Tento alebo ten druhý príkaz?
msx. 09.05.2012 22:56
msx.
Spousta lidí to neví, ale pravda je taková, že typicky* nezáleží na tom jak je to napsané, optimaliz…
AZOR 09.05.2012 23:10
AZOR
UPDATE nakup t1 JOIN zakaznik t2 ON t1.id=t2.id SET t1.spracovane_skupina='1' WHERE t2.skupina_id =…
pme 09.05.2012 22:32
pme
Takže toto jediné (* ako som neskôr zistil, nie je to jediné, to horné som len zle odpísal) funguje…
msx. 09.05.2012 22:44
msx.
Nevim jak na MySQL, ale pro MS SQL by to vypadalo takto UPDATE t1 SET t1.spracovane_skupina='1' FRO… poslední
Jan Fiala 10.05.2012 12:54
Jan Fiala

update nakup
set spracovane_skupina='1'
where id in
(
select nakup.id
from nakup
inner join zakaznik on nakup.zakaznik_id=zakaznik.id
where zakaznik.skupina_id='1'
)

Tak to nemusis džjonovat, ne?

update nakup
set spracovane_skupina='1'
where zakaznik_id in
(
select id from zakaznik where skupina_id='1' and id is not null
)

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ší.

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:

UPDATE nakup t1
JOIN zakaznik t2 ON t1.zakaznik_id=t2.id
SET t1.spracovane_skupina='1'
WHERE t2.skupina_id = '1'

Ďakujem za pomoc.

Zpět do poradny Odpovědět na původní otázku Nahoru