Autor Zpráva
peto50
Profil
Mám tabuľku v databáze. Má stĺpce: name1, name2, number, pid. Number označuje poradie riadku a normálne má jedinečnú hodnotu.

Potom mám HTML formuláre pre každý riadok tabuľky, ktoré umožňujú jednotlivé riadky zmazať.

Pred zmazaním mám napr. tabuľku, ktorá má v stĺpci number hodnoty: 1,2,3,4,5,6.
Po zmazaní napr. 3. riadku má hodnoty: 1,2,4,5,6.
To chcem práve opraviť, aby mala: 1,2,3,4,5.

Kód, ktorý používam, však nefunguje správne.

$last=$pdo->query("SELECT number FROM tabulka ORDER BY number DESC LIMIT 1")->fetch();
$last=(int)$last['number']; //získam najväčšiu hodnotu number

if (isset($_POST["zmaz"]))
{
    $pdo->prepare("DELETE FROM tabulka WHERE name1=? LIMIT 1")->execute(array($_POST["zmaz"])); //zmaznie daného riadku
    
    $lastnew=0; //pomocná premenná pre menenie hodnôt number
    for($i=1;$i<=$last;$i++) //cyklus postupne prechádza všetky riadky a nastavuje nové hodnoty number od 1 vyššie
        if(!($exec=$pdo->exec("UPDATE tabulka SET number=".++$lastnew." WHERE number=".$i." LIMIT 1"))===1)
        //tu je problém - exec nevracia správne hodnoty
            $lastnew--; //ak riadok s hodnotou number=$i neexistuje $lastnew sa vráti na mninulú hodnotu
}

alternatíva s inak nastaveným $lastnew:
if (isset($_POST["zmaz"]))
{
    $pdo->prepare("DELETE FROM tabulka WHERE name1=? LIMIT 1")->execute(array($_POST["zmaz"])); //zmaznie daného riadku
    
    $lastnew=1; //pomocná premenná pre menenie hodnôt number
    for($i=1;$i<=$last;$i++) //cyklus postupne prechádza všetky riadky a nastavuje nové hodnoty number od 1 vyššie
        if(($exec=$pdo->exec("UPDATE tabulka SET number=".$lastnew." WHERE number=".$i." LIMIT 1"))===1)
        //tu je problém - exec nevracia správne hodnoty
            $lastnew++; //ak riadok s hodnotou number=$i existuje $lastnew sa zvýši
}

Obidva kódy fungujú až na menenie hodnôt stĺpca number.


ešte iný kód, ktorý fungoval, ale nie je v PDO:
if (isset($_POST["zmaz"]))
{
    mysqli_query($con,"DELETE FROM tabulka WHERE name1='".mysqli_real_escape_string($con, $_POST["zmaz"])."' LIMIT 1");
    $lastnew=0;
    for($i=1;$i<=$last;$i++)
        if(mysqli_fetch_array(mysqli_query($con,"SELECT pid FROM tabulka WHERE number='".$i."' LIMIT 1")))
            mysqli_query($con,"UPDATE tabulka SET number=".++$lastnew." WHERE number=".$i);
}
lionel messi
Profil
peto50:
Po zmazaní napr. 3. riadku má hodnoty: 1,2,4,5,6.
To chcem práve opraviť, aby mala: 1,2,3,4,5.


Recyklácia primárnych kľúčov obvykle nie je dobrý nápad.
peto50
Profil
lionel messi:
Stlpec number nie je primárny kľúč.
juriad
Profil
Stačí odečíst jedničku od všech záznamů, které mají číslo větší než bylo číslo toho odstraněného. Jediným dotazem a ne nějakým zběsilým cyklem.

Pokud byl nějaký řadek odstraněn DELETEm (tu kontrolu si musíš doprogramovat pomocí rowCount), provedeš:
$pdo->exec("UPDATE tabulka SET number = number - 1 WHERE number > " . (int) $_POST["zmaz"]);

lionel messi:
Pokud by tím třeba chtěl simulovat pořadí něčeho, co může uživatel měnit, pak to smysl má. Třeba pořadí fotek.
mimochodec
Profil
peto50:
Jestli tam chceš nějaké rostoucí číslo, počítej si v php a jen vypisuj, do databáze ho nemusíš ukládat.
peto50
Profil
juriad:
dik :)

môj nový kód:
if (isset($_POST["zmaz"]) && $del=$pdo->prepare("SELECT number FROM tabulka WHERE name1=?"))
    if ($del->execute(array($_POST["zmaz"])) && $del=$del->fetch())
    {
        $pdo->prepare("DELETE FROM tabulka WHERE name1=? LIMIT 1")->execute(array($_POST["zmaz"]));
        $pdo->exec("UPDATE tabulka SET number=number-1 WHERE number>".$del['number']);
    }

len sa mi nepáči, že nemôžem mať všetky podmienky spolu. ak sú spolu, dáva mi to chybu, že $del nie je definovaný...
Tomáš123
Profil
peto50:
Tak ho definuj pred podmienkami: $del = "";.
juriad
Profil
peto50, Tomáš123:
Problém je jinde. A totiž s prioritou operátorů: && má přednost před =.

Pokud name1 není unikátní nebo klíč, tak to docela smrdí. To bys mazal víceméně náhodný záznam.
Máš, doufám, unikátnost nad number. Co znamená, že normálně má jedinečnou hodnotu? On snad nemusí mít?

Asi bych to napsal takto (super bezpečně). Ještě by bylo potřeba zajímat se o návratové hodnoty funkcí commit a rollBack.
if (isset($_POST["zmaz"])) {
  $pdo->beginTransaction();
  # vrátí náhodný jeden záznam s takovým name1 a počet všech takových (může být i 0)
  $sels = $pdo->prepare("SELECT number, COUNT(*) AS cnt FROM tabulka WHERE name1 = ?");
  $selb = $sels->execute(array($_POST["zmaz"]));
  $selrow = $sels->fetch();
  if ($selb && $selrow && $selrow['cnt'] == 1) {
    $dels = $pdo->prepare("DELETE FROM tabulka WHERE name1 = ?");
    $delb = $dels->execute(array($_POST["zmaz"]));
    if ($delb && $dels->rowCount() == 1) {
      $upds = $pdo->prepare("UPDATE tabulka SET number = number - 1 WHERE number > ?");
      $updb = $pdo->execute(array($selrow['number']));
      if ($updb) {
        $pdo->commit();
      } else {
        $pdo->rollBack(); # update failed
      }
    } else {
        $pdo->rollBack(); # delete failed or not exactly one row deleted
    }
  } else {
    $pdo->rollBack(); # select failed or fetch failed or not exactly one row with such name1
  }
}

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: