Autor Zpráva
Ladiscz
Profil
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
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
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 *
Mrkněte na
insert into ... on duplicate key update
Ladiscz
Profil
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

echo "<center>";
echo "
<form method=\"post\">
<table align=\"center\" border=\"0\" width=\"300\">
<tr>
<td colspan=\"2\"><b>Přidat raid</b></td>
</tr>
<tr>
<td>Datum</td>
</tr>
<tr>
<td>
<select style=\"background-color: white\" name=\"denvtydnu\">
<option style=\"background-color: white\" value=\"Pondělí\">Pondělí</option>
<option style=\"background-color: white\" value=\"Úterý\">Úterý</option>
<option style=\"background-color: white\" value=\"Středa\">Středa</option>
<option style=\"background-color: white\" value=\"Čtvrtek\">Čtvrtek</option>
<option style=\"background-color: white\" value=\"Pátek\">Pátek</option>
<option style=\"background-color: white\" value=\"Sobota\">Sobota</option>
<option style=\"background-color: white\" value=\"Neděle\">Neděle</option>
</select>
<select style=\"background-color: white\" name=\"den\">
<option style=\"background-color: white\" value=\"01\">1.</option>
<option style=\"background-color: white\" value=\"02\">2.</option>
<option style=\"background-color: white\" value=\"03\">3.</option>
<option style=\"background-color: white\" value=\"04\">4.</option>
<option style=\"background-color: white\" value=\"05\">5.</option>
<option style=\"background-color: white\" value=\"06\">6.</option>
<option style=\"background-color: white\" value=\"07\">7.</option>
<option style=\"background-color: white\" value=\"08\">8.</option>
<option style=\"background-color: white\" value=\"09\">9.</option>
<option style=\"background-color: white\" value=\"10\">10.</option>
<option style=\"background-color: white\" value=\"11\">11.</option>
<option style=\"background-color: white\" value=\"12\">12.</option>
<option style=\"background-color: white\" value=\"13\">13.</option>
<option style=\"background-color: white\" value=\"14\">14.</option>
<option style=\"background-color: white\" value=\"15\">15.</option>
<option style=\"background-color: white\" value=\"16\">16.</option>
<option style=\"background-color: white\" value=\"17\">17.</option>
<option style=\"background-color: white\" value=\"18\">18.</option>
<option style=\"background-color: white\" value=\"19\">19.</option>
<option style=\"background-color: white\" value=\"20\">20.</option>
<option style=\"background-color: white\" value=\"21\">21.</option>
<option style=\"background-color: white\" value=\"22\">22.</option>
<option style=\"background-color: white\" value=\"23\">23.</option>
<option style=\"background-color: white\" value=\"24\">24.</option>
<option style=\"background-color: white\" value=\"25\">25.</option>
<option style=\"background-color: white\" value=\"26\">26.</option>
<option style=\"background-color: white\" value=\"27\">27.</option>
<option style=\"background-color: white\" value=\"28\">28.</option>
<option style=\"background-color: white\" value=\"29\">29.</option>
<option style=\"background-color: white\" value=\"30\">30.</option>
<option style=\"background-color: white\" value=\"31\">31.</option>
</select>
<select style=\"background-color: white\" name=\"mesic\">
<option style=\"background-color: white\" value=\"01\">1.</option>
<option style=\"background-color: white\" value=\"02\">2.</option>
<option style=\"background-color: white\" value=\"03\">3.</option>
<option style=\"background-color: white\" value=\"04\">4.</option>
<option style=\"background-color: white\" value=\"05\">5.</option>
<option style=\"background-color: white\" value=\"06\">6.</option>
<option style=\"background-color: white\" value=\"07\">7.</option>
<option style=\"background-color: white\" value=\"08\">8.</option>
<option style=\"background-color: white\" value=\"09\">9.</option>
<option style=\"background-color: white\" value=\"10\">10.</option>
<option style=\"background-color: white\" value=\"11\">11.</option>
<option style=\"background-color: white\" value=\"12\">12.</option>
</select>
<select style=\"background-color: white\" name=\"rok\">
<option style=\"background-color: white\" value=\"2011\">2011</option>
<option style=\"background-color: white\" value=\"2012\">2012</option>
<option style=\"background-color: white\" value=\"2013\">2013</option>
</select>
</td>
</tr><tr>
<td>Čas</td>
</tr>
<tr>
<td>
</select><select style=\"background-color: white\" name=\"hod\">
<option style=\"background-color: white\" value=\"10\">10</option>
<option style=\"background-color: white\" value=\"11\">11</option>
<option style=\"background-color: white\" value=\"12\">12</option>
<option style=\"background-color: white\" value=\"13\">13</option>
<option style=\"background-color: white\" value=\"14\">14</option>
<option style=\"background-color: white\" value=\"15\">15</option>
<option style=\"background-color: white\" value=\"16\">16</option>
<option style=\"background-color: white\" value=\"17\">17</option>
<option style=\"background-color: white\" value=\"18\">18</option>
<option style=\"background-color: white\" value=\"19\">19</option>
<option style=\"background-color: white\" value=\"20\">20</option>
<option style=\"background-color: white\" value=\"21\">21</option>
<option style=\"background-color: white\" value=\"22\">22</option>
</select>
:
<select style=\"background-color: white\" name=\"min\">
<option style=\"background-color: white\" value=\"00\">00</option>
<option style=\"background-color: white\" value=\"15\">15</option>
<option style=\"background-color: white\" value=\"30\">30</option>
<option style=\"background-color: white\" value=\"45\"
Tori
Profil
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 *
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()
, skôr než ich použiješ v databáze (SQL injection)
PS 2: Prečo máš celý formulár v echo()? Môžeš predsa ukončiť php blok. ?>
Ján K.
Profil *
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
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
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
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 *
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 *
Ladiscz:
Máte nastavený ten UNIQUE index?
ALTER TABLE `ucast` ADD UNIQUE (`guid`, `name`);
Ladiscz
Profil
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
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 *
Á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
Aha, děkuji, zkusím to
Ladiscz
Profil
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
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
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
[#19] Tori
Děkuju, teď už to UNIQUE dát jde, nicméně pořád se tam nic nezapisuje...
Tori
Profil
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
$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
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. :)

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:

0