Autor Zpráva
quatzael
Profil
Mám v databázi dvě tabulky s úplně stejnou strukturou a potřeboval bych jeden řádek z jedné tabulky přepsat daty z řádku z jiné tabulky.
Existuje na to prosím nějaké jednoduché řešení nebo to musím udělat složitě přes select a update?
Tori
Profil
Vyberte si:
INSERT INTO t1 (sloupce) SELECT sloupce FROM t2 WHERE id = 123 ON DUPLICATE KEY UPDATE
(s využitím unikátního klíče v cílové tabulce)

UPDATE t1, t2 SET t1.col = t2.col WHERE t1.id = t2.id AND t2.id = 123  -- tohle mi chybělo, pardon
(tabulky se můžou spojit jakkoli chcete, tj. i podle sloupce, kde není unik.klíč)
quatzael
Profil
Tori:

UPDATE t1, t2 SET t1.col = t2.col WHERE t1.id = t2.id
Opravdu tam má být za tím UPDATE i ta tabulka (t2), ze který jenom čtu data?? Updatuju přeci jenom t1.

Kdybych tam zadal jenom tohle, tak by to nefungovalo?
UPDATE t1 SET t1.col = t2.col WHERE t1.id = t2.id

Tomu prvnímu řádku moc nerozumím, proč je tam to INSERT když chci hodnoty přepsat?? A co mám zadat místo těch teček??

Mám tam asi stovku sloupců, takže i když je ten druhej řádek s UPDATE docela srozumitelnej tak by asi bylo stejně rychlejší to udělat v PHP přes foreach..
Tori
Profil
quatzael:
Opravdu tam má být za tím UPDATE i ta tabulka (t2), ze který jenom čtu data?
Ano, je to víceméně zkopírovaný příklad z manuálu. Zkusil jste to a hlásí to chybu, či co?

Tomu prvnímu řádku moc nerozumím, proč je tam to INSERT když chci hodnoty přepsat?
Přepsání obstarává ta poslední část (ON DUPLICATE KEY UPDATE) v případě, že vkládám duplicitní hodnotu do sloupce s unikátním klíčem. Např.pokud vkládám ID + nějaká data, tak "insert .. on duplicate.." buď vloží nový řádek (pokud takové ID ještě v tabulce není), nebo updatuje existující.

Nicméně jestli chcete prostě přepsat všechny sloupce v tom řádku, tak bude asi jednodušší použít REPLACE. Pokud máte v obou tabulkách sloupce ve stejném pořadí, tak to bude i nejkratší zápis z těch tří možných:
REPLACE INTO cilovaTabulka SELECT * FROM zdrojovaTabulka WHERE id = 123
Ještě jsem opravila ten předchozí příspěvek, snad to je srozumitelnější.
quatzael
Profil
Tori:
Supr, díky. Takhle to vypadá, že by to mělo být ok.

Jenom trošku upřesnění.. Potřebuju to podle nějakého konkrétního sloupce a ne podle id, takže by to mělo vypadat takto:

REPLACE INTO cilovaTabulka SELECT * FROM zdrojovaTabulka WHERE sloupec = 123

Zatím jsou ty tabulky shodné i pokud jde o počet řádků, takže i ta hodnota z mého vybraného sloupce (má charakter také určitého duplicitního id) jedné tabulce je stejná jako hodnota ze sloupce z druhé tabulky v rámci jednoho shodného id. Ale pokud v jedné tabulce vymažu nějaký řádek, tak se dvojice hodnot id a toho sloupce (duplicitního id) bude u těchto dvou tabulek lišit.

Jak tedy ten příkaz přesně funguje? Přepisuje i hodnotu id nebo to funguje tak (a takhle bych to potřeboval), že vybere ze zdrojové tabulky řádek, který obsahuje v určeném sloupci zadanou hodnotu (např. 123) a všechny hodnoty (mimo id) nakopíruje do řádku v cílové tabulce, ve kterém v určeném sloupci je také stejná hodnota (např. 123)?
Tori
Profil
REPLACE funguje podobně jako INSERT, ale s tím rozdílem, že pokud by vkládaná data vytvořila duplicitní hodnotu ve sloupci, na kterém je unikátní/primární klíč, tak se původní kolidující řádek nejdřív smaže, a až pak se vloží nová data. Oproti tomu INSERT ... ON DUPLICATE KEY UPDATE se nejdřív pokusí vložit data a pokud tento pokus selže kvůli kolizi ve sloupci s unikátním klíčem, tak v tom kolidujícím řádku updatuje zadané sloupce - nemaže ho. (Nevím co se stane, pokud vkládaná data kolidují s hodnotami v různých řádcích - jestli se updatují všechny nebo co.

Ale pokud v jedné tabulce vymažu nějaký řádek, tak se dvojice hodnot id a toho sloupce (duplicitního id) bude u těchto dvou tabulek lišit.
Recyklujete použitá ID? A podle čeho najdete ty řádky (ve zdrojové i cílové tabulce) - nějaký jedinečný identifikátor tam být musí, ne? Asi přecijen bude lepší ten UPDATE, jestli vyhledáváte podle něčeho jiného než podle sloupce s prim.klíčem: UPDATE t1, t2 SET t1.col1 = t2.col1 WHERE t1.col3 = 'neco' AND t2.col123456789 = 'necoJineho'
quatzael
Profil
Tori:
Prostě potřebuju, aby se to přepsání týkalo jenom těch řádků, kde je ta společná hodnota v konkrétním sloupci určená tou podmínkou za WHERE:

WHERE sloupec = 123

tzn. najde podle této podmínky řádek ze zdrojové tabulky, zkopíruje všechna data (mimo id), najde ve druhé tabulce stejný řádek (zase podle stejné podmínky: WHERE sloupec = 123) a nakopíruje tam tato data.

Tedy tak, aby to id bylo úplně ignorováno a nijak se nezměnilo..
Tori
Profil
Tak asi to, co jsem psala:
UPDATE t1, t2 SET t1.col1 = t2.col1, t1.col2 = t2.col2 ..a další sloupce.. 
WHERE t1.sloupec = 123 AND t2.sloupec = 123
quatzael
Profil
Tori:
no tak to ale budu muset vyřešit nějak pomocí toho foreach, protože je tam fakt snad víc než sto sloupců..
Tori
Profil
quatzael:
Jestli přepisujete všechny sloupce v tom řádku, včetně ID, tak to už ho můžete rovnou vymazat a pak zkopírovat pomocí insert into select. ↓ ano.
quatzael
Profil
Tori:
Ne, vždyť jsem přeci několikrát zdůrazňoval, že chci, aby se přepsalo všechno, jen to samotné id bylo ignorováno...
I když je pravda, že to samotné id vlastně vůbec nepotřebuju, i když by asi bylo lepší aby zůstávalo shodné s tím id v původní tabulce..

Měla jste asi namysli INSERT INTO SELECT, ne??

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: