Autor | Zpráva | ||
---|---|---|---|
Ladiscz Profil |
#1 · Zasláno: 21. 6. 2011, 00:04:56
Dobrý den,
snažím se vytvořit vlastní plánovač akcí a řeším teď zapisování jednotlivých účastníků na akci. Vše jde vpořádku, ovšem vůbec nevím, jak to mám udělat, aby mohl účastník případně změnit svoji účast v neúčast... Bohužel se nějak moc nevyznám v názvech tagů, ale myslím si, že by tam mělo být něco jako: Pokud `guid`='".$_POST['guid']."' AND `name`='".$_POST['name']."' AND `ucast`<>'".$_POST['ucast']."' potom UPDATE `tabulka_ucast`SET `ucast`='".$_POST['ucast']."'; Pokud `guid`='".$_POST['guid']."' AND `name`<>'".$_POST['name']."' potom INSERT INTO `tabulka_ucast` (`guid`, `ucast`, `name`, `role`, `class`) VALUES ('".$_POST['guid']."', '".$_POST['ucast']."', '".$_POST['name']."', '".$_POST['role']."', '".$_POST['class']."'); Vůbec ale nevím, jak to správně reprodukovat... Můj původní skript pro zapisování do databáze vypadá následovně if (isset($_POST["add"])) { $db->select_db($Config['Database']['Database']); $result = $db->query("INSERT INTO `tabulka_ucast` (`guid`, `ucast`, `name`, `role`, `class`) VALUES ('".$_POST['guid']."', '".$_POST['ucast']."', '".$_POST['name']."', '".$_POST['role']."', '".$_POST['class']."');"); } Děkuji předem za radu |
||
Tori Profil |
#2 · Zasláno: 21. 6. 2011, 00:23:04 · Upravil/a: Tori
Existuje příkaz REPLACE. Na odkázané stránce je hned nahoře popsaný rozdíl mezi REPLACE vs. INSERT... ON DUPLICATE KEY UPDATE, to by mohla být taky možnost.
|
||
Ladiscz Profil |
#3 · Zasláno: 21. 6. 2011, 00:41:34
Děkuju...
A mohl bych ještě poprosit o radu, jak to tedy praktikovat? Protože pokud teď jen vyměním INSERT INTO za REPLACE, dělá to stále totéž co předtím a neřeší to bohužel problém toho, že by někdo mohl chtít změnit svoji účast... |
||
Kajman_ Profil * |
#4 · Zasláno: 21. 6. 2011, 00:48:58
Mrkněte na
insert into ... on duplicate key update |
||
Časová prodleva: 3 dny
|
|||
Ladiscz Profil |
#5 · Zasláno: 23. 6. 2011, 20:16:06
Omlouvám se, ale vůbec tomu odkazu nerozumím.. Nevím, co mám dát jako c+1, respektive jak to vůbec zakomponovat do mého skriptu.
<?php |
||
Tori Profil |
#6 · Zasláno: 23. 6. 2011, 20:38:39
Něco takovéhoto:
$guid = intval($_POST['guid']); // předpokládám, že jen tenhle sloupec má číselný typ. Pokud i jiný, nahraďte mysql_real_es... funkcí intval(). $ucast = mysql_real_escape_string($_POST['ucast']); $name = mysql_real_escape_string($_POST['name']); $role = mysql_real_escape_string($_POST['role']); $class = mysql_real_escape_string($_POST['class']); $query = "INSERT INTO `tabulka_ucast` (`guid`, `ucast`, `name`, `role`, `class`) VALUES ($guid, '$ucast', '$name', '$role', '$class') ON DUPLICATE KEY UPDATE `ucast` = '$ucast', `role` = '$role', `class` = '$class'"; Předpokládám, že každá kombinace guid-name se může vyskytnout jen jednou, takže by asi měl být UNIQUE index přes oba sloupce. Do části UPDATE patří sloupce, které uživatelé mohou měnit. |
||
Ján K. Profil * |
#7 · Zasláno: 23. 6. 2011, 20:43:44
Ten kód formulára je irelevantný. Avšak ak to chápem správne, tak ty máš v tabuľke stĺpec `guid`, ktorý je poradové číslo udalosti, a `name`, čo je asi meno používateľa. V tom prípade sa INSERT ... ON DUPLICATE KEY UPDATE použiť nedá, skôr by som to riešil SELECT-om, a ak vráti aspoň jeden riadok, tak potom pomocou REPLACE, s použitím primary key ktorý ti vrátil ten SELECT.
Pseudo-kód: $q = mysql_query("SELECT id FROM `tabulka_ucast` WHERE `guid` = $guid AND `name` = $name"); if(mysql_num_rows($q) == 0) { mysql_query("INSERT ..."); } else { $row = mysql_fetch_assoc($q); $id = $row['id']; mysql_query("REPLACE ... WHERE `id` = $id"); } PS: nezabudni dáta z $_POST ošetriť pomocou mysql_real_escape_string() PS 2: Prečo máš celý formulár v echo()? Môžeš predsa ukončiť php blok. ?> |
||
Ján K. Profil * |
#8 · Zasláno: 23. 6. 2011, 20:47:16
Tori:
Mám pocit, že ak je unique nad dvoma stĺpcami, OBOJE musia mať unikátne dáta, a ON DUPLICATE KEY UPDATE zmení viac riadkov. Citujem z MYSQL manuálu: If column b is also unique, the INSERT is equivalent to this UPDATE statement instead: UPDATE table SET c=c+1 WHERE a=1 OR b=2 LIMIT 1; |
||
Ladiscz Profil |
#9 · Zasláno: 23. 6. 2011, 20:59:50
Omlouvám se, nevšiml jsem si, že se skript neposlal celý (?)..
Konec skriptu vypadá u mě zatím takto: if (isset($_POST["add"])) { $db->select_db($Config['Database']['Database']); $result = $db->query("INSERT INTO `ucast` (`guid`, `ucast`, `name`, `role`, `class`) VALUES ('".$_POST['guid']."', '".$_POST['ucast']."', '".$_POST['name']."', '".$_POST['role']."', '".$_POST['class']."') ON DUPLICATE KEY UPDATE `name`='".$_POST['nick']."' AND `guid`='".$_POST['guid']."'; UPDATE `ucast` SET `ucast`='".$_POST['ucast']."' WHERE `guid`='".$_POST['guid']."' AND `nick`='".$_POST['name']."';"); echo "Přidáno!"; } A vůbec nevím, jak přesně to tedy změnit |
||
Tori Profil |
#10 · Zasláno: 23. 6. 2011, 21:08:15
Ján K.:
Jednak změní jen jeden řádek (viz LIMIT 1 ve vaší ukázce), a taky se hned pod tím píše: „Ve všeobecnosti se pokud možno vyhýbejte použití klauzule ON DUPLICATE KEY UPDATE u tabulek s několika unikátními indexy.“. Zkoušela jsem to teď v tabulce s jediným indexem přes dva sloupce (typy int a char(20)) a fungovalo to správně. Ladiscz: Do té části ....UPDATE dejte jen ty sloupce, které se mohou změnit. Prostě to samé, jako kdybyste nejdřív SELECTem zjistil, jestli už ten člověk je na akci napsaný, a pak updatoval jeho účast - nick i guid by také zůstaly stejné, ne? |
||
Ladiscz Profil |
#11 · Zasláno: 23. 6. 2011, 21:14:44
No v části UPDATE mám
UPDATE `ucast` SET `ucast`='".$_POST['ucast']."' WHERE `guid`='".$_POST['guid']."' AND `name`='".$_POST['name']."';"); takže by to mělo měnit účast na ANO/NE/MOŽNÁ dle výběru.. Ale nedělá to nic, jen to přidá další řádek do tabulky, takže tam je tentýž člověk dvakrát. |
||
Ján K. Profil * |
#12 · Zasláno: 23. 6. 2011, 21:15:58
Tori:
Jednak změní jen jeden řádek (viz LIMIT 1 ve vaší ukázce) - Áno, máte pravdu, nevšimol som si to... |
||
Ján K. Profil * |
#13 · Zasláno: 23. 6. 2011, 21:38:29
Ladiscz:
Máte nastavený ten UNIQUE index? ALTER TABLE `ucast` ADD UNIQUE (`guid`, `name`); |
||
Ladiscz Profil |
#14 · Zasláno: 23. 6. 2011, 21:47:32 · Upravil/a: Ladiscz
Nemám, ale jde o to, že těch GUID tam může být víc.. Více jmen může být přiřazeno k jednomu guidu události, takže si myslím, že UNIQUE by se tam dávat nemělo...
EDIT: Mám ten systém dělaný tak, že má každá událost své unikátní ID a podle toho se pak jednotliví uživatelé přihlašují k dané události. Takže např. mám události ID 1, 2, 3 a uživatele Pes, Kočka, Slepice. Pes se účastní událostí 1 a 2, tedy GUIDy budou k jeho jménu 1 a 2. Kočka se účastní pouze události 3, tedy GUID u ní bude 3. Slon se účastní všech událostí, takže GUID bude mít 1, 2, 3... |
||
Tori Profil |
#15 · Zasláno: 23. 6. 2011, 21:48:26 · Upravil/a: Tori
Ladiscz:
Když používáte INSERT ... ON DUPLICATE KEY UPDATE, tak už tam nedávejte tu část WHERE, je zbytečná. Tímhle dotazem se nejdřív zkusí vložit data, a pokud to kvůli duplicitním hodnotám selže (proto ten unikátní index přes 2 sloupce), tak se najde ten kolidující řádek a updatuje se. Ad [#14] - může se více než jednou vyskytnout stejná kombinace guid + name? (=jeden člověk by byl několikrát přihlášen na stejnou akci??) |
||
Ján K. Profil * |
#16 · Zasláno: 23. 6. 2011, 21:50:30
Áno, to zmiatlo aj mňa. Ale je rozdiel medzi
UNIQUE(`guid`); UNIQUE(`name`) a UNIQUE(`guid`, `name`) Prvá varianta vraví, že unikátne majú byť hodnoty v stĺpci guid aj v stĺpci name. Druhá vraví, že kombinácia guid-name má byť unikátna. |
||
Ladiscz Profil |
#17 · Zasláno: 23. 6. 2011, 21:51:17
Aha, děkuji, zkusím to
|
||
Ladiscz Profil |
#18 · Zasláno: 23. 6. 2011, 22:06:23 · Upravil/a: Ladiscz
Když zkouším ten skript
ALTER TABLE `ucast` ADD UNIQUE (`guid`, `nick`); vyhodí mi to chybu 1170 - BLOB/TEXT column 'nick' used in key specification without a key length |
||
Tori Profil |
#19 · Zasláno: 23. 6. 2011, 22:26:10
Ladiscz:
Pro každé pole by se měly používat nejmenší nutné typy, tzn. nick bych dala na max.255 znaků (varchar). |
||
Ladiscz Profil |
#20 · Zasláno: 23. 6. 2011, 22:26:51
Momentálně ten můj skript vypadá takto a nefunguje:
$result = $db->query("INSERT INTO `ucast` (`guid`, `ucast`, `nick`, `role`, `class`, `poznamka`) VALUES ('".$_POST['guid']."', '".$_POST['ucast']."', '".$_POST['nick']."', '".$_POST['role']."', '".$_POST['class']."', '-') ON DUPLICATE KEY UPDATE `nick`='".$_POST['nick']."' AND `guid`='".$_POST['guid']."'; UPDATE `ucast` SET `ucast`.`ucast`='".$_POST['ucast']."';"); Vůbec nic se do databáze nezapíše ani neupraví. |
||
Ladiscz Profil |
#21 · Zasláno: 23. 6. 2011, 22:29:52
[#19] Tori
Děkuju, teď už to UNIQUE dát jde, nicméně pořád se tam nic nezapisuje... |
||
Tori Profil |
#22 · Zasláno: 23. 6. 2011, 23:27:00
Pořád je to nějak smíchané se syntaxí obyčejného update. Za "ON DUPLICATE KEY UPDATE" dejte jen sloupce, které chcete změnit, žádné jiné. A vyhoďte všechno za prvním středníkem.
|
||
Ladiscz Profil |
#23 · Zasláno: 23. 6. 2011, 23:33:15 · Upravil/a: Ladiscz
$result = $db->query("INSERT INTO `ucast` (`guid`, `ucast`, `nick`, `role`, `class`, `poznamka`) VALUES ('".$_POST['guid']."', '".$_POST['ucast']."', '".$_POST['nick']."', '".$_POST['role']."', '".$_POST['class']."', '-') ON DUPLICATE KEY UPDATE `ucast`.`ucast`; UPDATE `ucast` SET `ucast`.`ucast`='".$_POST['ucast']."';"); Takhle? A jak to myslíte "vyhodit všechno za prvním středníkem"? Jako smazat? EDIT: Už to mám, děkuji mnohokrát za vaši trpělivost, omlouvám se, že jsem vás zdržoval. |
||
Tori Profil |
#24 · Zasláno: 23. 6. 2011, 23:45:24 · Upravil/a: Tori
Ladiscz:
„Jako smazat?“ Jo. Jednak to tam nepatří, druhak se to stejně neprovede, protože středník ukončuje SQL dotaz a přes mysql_query se nedá provést několik dotazů naráz. S trochou ochrany proti SQL-injection: $db->query("INSERT INTO `ucast` (`guid`, `ucast`, `nick`, `role`, `class`, `poznamka`) VALUES (".(int) $_POST['guid'].", '".mysql_real_escape_string($_POST['ucast'])."', '".mysql_real_escape_string($_POST['nick']) ."', '".mysql_real_escape_string($_POST['role'])."', '".mysql_real_escape_string($_POST['class'])."', '-') ON DUPLICATE KEY UPDATE `ucast`.`ucast`= VALUES(ucast)"); Ten označený kousek je pomocná funkce MySQL - abyste nemusel znova vypisovat + escapovat tu hodnotu, když už byla použitá v části INSERT ... VALUES. (viz Odkaz) edit: Ok, příště nebudu odpovídat tak rychle. :) |
||
Časová prodleva: 13 let
|
0