Nechtěný SQL insert při POST/GET.

Při programování vstupu do databáze a přidávání údajů do tabulky narazí každý na jev nežádoucího přidání údajů do tabulky. Dochází k tomu třeba při osvěžení (refresh) obsahu stránky, obsahující formulářové prvky. Pokud jsou údaje vložené do formulářových prvků předávány na webový server pomocí metody POST, budeme vyzváni k opakování zaslání údajů, nebo odmítnutí zaslání, avšak při použití metody GET budou údaje automaticky zopakovány, neboť veškeré předávané parametry se nachází v příkazové řádce prohlížeče, připojeny k příslušnému URL.
Následující tabulka obsahuje čtyři naposledy vložené údaje. Údaje by měly být vloženy pouze při stisknutí tlačítka 'Uložit'. Pokud toto tlačítko jednou stisknete, připojí se údaj z textového pole jako poslední údaj k tabulce, což lehce zjistíme pozorováním čísla ve sloupci ID, které je automaticky generováno SQL databází a je zaručeně jedinečné. Nadále již nepoužijeme tlačítko 'Uložit', ale obsah stránky osvěžíme, třeba přes nabídku vyvolanou pravým tlačítkem myši. Zjistíme, že obsah textového pole bude opět přidán jako poslední řádek tabulky. To je ovšem nežádoucí.

IDText
311Podatak će biti pohranjen u tablici nakon pritisnuća tipke 'Spremiti'.
312Podatak će biti pohranjen u tablici nakon pritisnuća tipke 'Spremiti'.
313Podatak će biti pohranjen u tablici nakon pritisnuća tipke 'Spremiti'.
314Podatak će biti pohranjen u tablici nakon pritisnuća tipke 'Spremiti'.

Jak si sami můžete ověřit, pokud pro vložení údaje do tabulky použijete následující tlačítko 'Uložit', bude údaj do tabulky vložen pouze po jeho stisknutí a nikoliv při vyvolaném osvěžení obsahu této stránky.


Dále bude uvedeno řešení, které zamezuje nechtěnému opakovanému vložení údajů do tabulky. Popsáno bude s použitím skriptovacího jazyka PHP4, ovšem podobně lze problém řešit i s použitím Javy, či jiných programovacích prostředků.
Jak bylo tohoto cíle dosaženo? Nejdříve byla vyhodnocena přítomnost proměnné, vyskytující se v těle formuláře, nejlépe samotného tlačítka 'Uložit'. Protože veškeré proměnné jsou v podstatě přítomny i při následném osvěžení obsahu stránky jako parametry v URL, je nutné je odstranit, zde tak, že bezprostředně po uložení údajů do tabulky je webovému serveru zaslán opětovný požadavek na tuto stránku, ovšem bez názvu a hodnoty proměnné, jejíž přítomnost vyhodnocujeme. Zde jsou fragmenty zdrojového kódu v PHP4:

<?php

// vyhodnocení přítomnosti proměnné z těla formuláře
if (isset($save2)) {
 $udaj2 = addslashes(trim($udaj2));
 $db->query("INSERT INTO manuals1 (txt) VALUES('$udaj2')");
 // opětovaný požadavek na překreslení stránky bez parametrů
 header("Location: ../cz/cz_dbInsert.php");
}

.
.
.

<center>
<table border="0" cellspacing="1" cellpadding="0">
<tr>
<td class="tabid">ID</td>
<td class="tabtxt">Text</td>
</tr>
<?

$db->query("SELECT * FROM manuals1 ORDER BY Id");

while ($db->next_record()) {

?>
<tr>
<td class="tabid"><? echo $db->f("Id"); ?></td>
<td class="tabtxt"><? echo stripslashes($db->f("txt")); ?></td>
</tr>
<?

}

?>
</table>
<form method="GET" action="../cz/cz_dbInsert.php" target="body">
<!-- proměnná $save2 v těle formuláře -->
<input type="submit" name="save2" value="Uložit" id="submit">
<input type="text" name="udaj2" value="Tento údaj .... tlačítka 'Uložit'.">
</form>
</center>

?>
Jak je zřejmé, ukládání údajů do tabulky předchází jejich vykreslení na stránce. Vhodné je také umístit testování na přítomnost proměnné z těla formuláře na začátek skriptu, ještě před samotné vykreslení stránky. Tím jistě zkrátíme potřebné časy a celý jev se nám bude zdát jednolitý. Pozor ovšem na skutečnost, abychom při opětovném odeslání požadavku na server vyloučili z předávaných parametrů název proměnné, kterou testujeme. V příkladu žádné parametry nejsou v URL na server zasílány! Jinak pouze dosáhneme nekonrolovatelný počet opakovaného volání serveru a tím i nedokončení činnosti skriptu, nehledě na přetížení webového serveru, prohlížeče a sítě!
© 2005 Djordje Zurovac, všechna práva vyhrazena.