PHP PDO - SQL Insert pouze když záznam neexistuje

ZAJDAN

  • *****
  • 2 056
    • Zobrazit profil
    • E-mail
PHP PDO - SQL Insert pouze když záznam neexistuje
« kdy: 17. 03. 2019, 14:37:57 »
Pokouším se v PHP PDO docílit aby se záznam před vložením zkontroloval zda již existuje, ale vkládá se mi i když existuje.
Mám podezdření, že špatně přiřazuji zástupný symbol v sql dotazu. Poradil by někdo?

Kód: [Vybrat]
$InsertArray = $_POST["Insert"];
$InsertDecoded = json_decode($InsertArray, true);

.....shortened
if(isset($_POST['Insert'])){
try     {
        $pdo = new PDO ( $induce, $user, $password, array(
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8",
        ));
//FIRSTLY FIND IF EXIST/////////////////////////////////////////////////////////////
        $prepared = $pdo->prepare(" SELECT * FROM kw112019 WHERE Commission = :Commission ");

                //přiřazení proměných do zástupných symbolů
        $prepared->bindParam(':Commission', $InsertDecoded["Commission"], PDO::PARAM_INT);

// zisk výsledků
        $result = $prepared->fetch(PDO::FETCH_NUM);

if ($result > 0) {
$json_array[] = array("Letter"=>"-", "Commission"=>"JIŽ EXISTUJE", "Status"=>"-", "DeliveryDate"=>"-");
$json = json_encode($json_array);
echo $json;
}

else {
//INSERT//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
$prepared = $pdo->prepare("INSERT INTO kw112019 (Letter, Commission, Status, DeliveryDate)
                                                               VALUES (:Letter, :Commission, :Status, :DeliveryDate)");
$prepared->execute([
      'Commission' => $InsertDecoded["Commission"],
      'Letter' => $InsertDecoded["Letter"],
      'Status' => $InsertDecoded["Status"],
      'DeliveryDate' => $InsertDecoded["DeliveryDate"],
    ]);
      }
Vesele, vesele do továrny dělník běží...vesele, vesele do továrny jde. Vesele se usmívá když mu soustruh zazpívá...vesele, vesele do továrny jde. Vesele si poskočí když se soustruh roztočí ...vesele, vesele do továrny jde.


ZAJDAN

  • *****
  • 2 056
    • Zobrazit profil
    • E-mail
Re:PHP PDO - SQL Insert pouze když záznam neexistuje
« Odpověď #1 kdy: 17. 03. 2019, 16:38:25 »
Vyřešeno,
zapoměl jsem v Selectu provést execute
$prepared->execute();
Vesele, vesele do továrny dělník běží...vesele, vesele do továrny jde. Vesele se usmívá když mu soustruh zazpívá...vesele, vesele do továrny jde. Vesele si poskočí když se soustruh roztočí ...vesele, vesele do továrny jde.

Re:PHP PDO - SQL Insert pouze když záznam neexistuje
« Odpověď #2 kdy: 17. 03. 2019, 18:04:58 »
Pokud člověk neví, co je špatně, stačí to obvykle oddebugovat (xdebug) a podívat se, jaké dotazy se posílají do databáze (server umí dotazy logovat, tuším že to umí i pdo). Chybu pak člověk najde snadno sám... :)

Jinak některé databáze umí UPSERT resp. MERGE, tyto příkazy vloží nový záznam nebo jej aktualizují - podle toho zda, zda záznam už existuje.

Pak bych se ještě zamyslel, co se stane pokud bude ten váš vkládací kód spouštěn paralelně - a mezi ověřením existence a vložením se totožný záznam vloží z jiného requestu. Jinými slovy, chtělo by to synchronizovat aplikačně anebo transakcí. Abyste po nasazení nezjistil, že to vkládá nesmyslné údaje (což při testování jedním uživatelem nezjistíte a projeví se to až když je tam těch lidí víc).

ZAJDAN

  • *****
  • 2 056
    • Zobrazit profil
    • E-mail
Re:PHP PDO - SQL Insert pouze když záznam neexistuje
« Odpověď #3 kdy: 17. 03. 2019, 20:24:08 »
Pak bych se ještě zamyslel, co se stane pokud bude ten váš vkládací kód spouštěn paralelně - a mezi ověřením existence a vložením se totožný záznam vloží z jiného requestu. Jinými slovy, chtělo by to synchronizovat aplikačně anebo transakcí. Abyste po nasazení nezjistil, že to vkládá nesmyslné údaje (což při testování jedním uživatelem nezjistíte a projeví se to až když je tam těch lidí víc).
díky za tip..rád se propracuju až k tomuto, ale zatím laboruju jen na výukové bázi

Ještě by mne zajímalo pokud mám v Ajaxu dataType: "json",
a v php vracím pomocí echa prostý text, jak s takovýmto response v Ajaxu zacházet v success?
Ajax bude i v response očekávat json?
Vesele, vesele do továrny dělník běží...vesele, vesele do továrny jde. Vesele se usmívá když mu soustruh zazpívá...vesele, vesele do továrny jde. Vesele si poskočí když se soustruh roztočí ...vesele, vesele do továrny jde.

Re:PHP PDO - SQL Insert pouze když záznam neexistuje
« Odpověď #4 kdy: 17. 03. 2019, 22:38:52 »
Pokud máte datatype json tak z PHP posílejte taky json:

Kód: [Vybrat]
print(json_encode(array("text" => "tohle je ten text")));


ZAJDAN

  • *****
  • 2 056
    • Zobrazit profil
    • E-mail
Re:PHP PDO - SQL Insert pouze když záznam neexistuje
« Odpověď #5 kdy: 18. 03. 2019, 15:27:34 »
Pokud máte datatype json tak z PHP posílejte taky json:

Kód: [Vybrat]
print(json_encode(array("text" => "tohle je ten text")));
Díky!
Vesele, vesele do továrny dělník běží...vesele, vesele do továrny jde. Vesele se usmívá když mu soustruh zazpívá...vesele, vesele do továrny jde. Vesele si poskočí když se soustruh roztočí ...vesele, vesele do továrny jde.

BoneFlute

  • *****
  • 1 842
    • Zobrazit profil
Re:PHP PDO - SQL Insert pouze když záznam neexistuje
« Odpověď #6 kdy: 18. 03. 2019, 20:42:49 »
Ještě by mne zajímalo pokud mám v Ajaxu dataType: "json",
a v php vracím pomocí echa prostý text, jak s takovýmto response v Ajaxu zacházet v success?
Ajax bude i v response očekávat json?
Nebude. Pokud se nebude pokoušet o nějakou automagii. A i kdyby ano, tak si třeba na textu vyláme zuby (pokud se zrovna netrefíte na Null, False, True, možná číslo).

Pokud máte datatype json tak z PHP posílejte taky json:

Kód: [Vybrat]
print(json_encode(array("text" => "tohle je ten text")));

Teoreticky by to nemělo stačit. Ještě je důležité posílat hlavičku:
Kód: [Vybrat]
header("Content-Type: application/json");

Re:PHP PDO - SQL Insert pouze když záznam neexistuje
« Odpověď #7 kdy: 18. 03. 2019, 20:58:59 »
Pokud máte datatype json tak z PHP posílejte taky json:

Kód: [Vybrat]
print(json_encode(array("text" => "tohle je ten text")));

Teoreticky by to nemělo stačit. Ještě je důležité posílat hlavičku:
Kód: [Vybrat]
header("Content-Type: application/json");

To je pravda, dík za doplnění. Ono když se to děje v nějakém frameworku automaticky tak na to člověk časem zapomene  :D

Když něco nefunguje je potřeba se stejně podívat v prohlížeči, jaké tam běhají http dotazy a co píše konzole prohlížeče (vývojové nástroje - F12)...

Kit

  • *****
  • 657
    • Zobrazit profil
    • E-mail
Re:PHP PDO - SQL Insert pouze když záznam neexistuje
« Odpověď #8 kdy: 19. 03. 2019, 07:45:41 »
Stačí nastavit v databázi unikátní index a duplicitní záznam se nevloží. Select pak nebude potřebný a atomicita operace bude zajištěna.

ZAJDAN

  • *****
  • 2 056
    • Zobrazit profil
    • E-mail
Re:PHP PDO - SQL Insert pouze když záznam neexistuje
« Odpověď #9 kdy: 19. 03. 2019, 09:18:43 »
moc díky za rady!
ohledně té duplicity, tady jsem se asi špatně vyjádřil. Já chci jen zamezit aby sloupec neobsahoval dva a více řádků se stejnou hodnotou.
Vesele, vesele do továrny dělník běží...vesele, vesele do továrny jde. Vesele se usmívá když mu soustruh zazpívá...vesele, vesele do továrny jde. Vesele si poskočí když se soustruh roztočí ...vesele, vesele do továrny jde.

Re:PHP PDO - SQL Insert pouze když záznam neexistuje
« Odpověď #10 kdy: 19. 03. 2019, 09:31:08 »
Stačí nastavit v databázi unikátní index a duplicitní záznam se nevloží. Select pak nebude potřebný a atomicita operace bude zajištěna.

Tak předpokládám, že tam ten index je. Ale zaprvé tam nebudu cpát duplicitní data a generovat zbytečně chyby v databázi (byť bych si je třeba v php odchytil) a zadruhé chci asi nějak zjistit a zobrazit stav transakce - třeba uživateli nebo to někam zalogovat.

Kit

  • *****
  • 657
    • Zobrazit profil
    • E-mail
Re:PHP PDO - SQL Insert pouze když záznam neexistuje
« Odpověď #11 kdy: 19. 03. 2019, 12:21:34 »
Stačí nastavit v databázi unikátní index a duplicitní záznam se nevloží. Select pak nebude potřebný a atomicita operace bude zajištěna.

Tak předpokládám, že tam ten index je. Ale zaprvé tam nebudu cpát duplicitní data a generovat zbytečně chyby v databázi (byť bych si je třeba v php odchytil) a zadruhé chci asi nějak zjistit a zobrazit stav transakce - třeba uživateli nebo to někam zalogovat.

Unikátní index splňuje vše, co je zmíněno.

ZAJDAN

  • *****
  • 2 056
    • Zobrazit profil
    • E-mail
Re:PHP PDO - SQL Insert pouze když záznam neexistuje
« Odpověď #12 kdy: 19. 03. 2019, 14:34:45 »
Kite...díky..nechám si od zkušených jako Ty rád doporučit správný postup, ale domnívám se, že primární klíč nezajistí aby se do sloupce  nedostal stejný záznam/hodnota. Pokud se mýlím, tak pak nechápu ten princip.

Pravděpodobně máš na mysli, že hodnotu co chci kontrolovat by byla primárním klíčem.
« Poslední změna: 19. 03. 2019, 14:39:05 od ZAJDAN »
Vesele, vesele do továrny dělník běží...vesele, vesele do továrny jde. Vesele se usmívá když mu soustruh zazpívá...vesele, vesele do továrny jde. Vesele si poskočí když se soustruh roztočí ...vesele, vesele do továrny jde.

Kit

  • *****
  • 657
    • Zobrazit profil
    • E-mail
Re:PHP PDO - SQL Insert pouze když záznam neexistuje
« Odpověď #13 kdy: 19. 03. 2019, 15:38:57 »
Kite...díky..nechám si od zkušených jako Ty rád doporučit správný postup, ale domnívám se, že primární klíč nezajistí aby se do sloupce  nedostal stejný záznam/hodnota. Pokud se mýlím, tak pak nechápu ten princip.

Pravděpodobně máš na mysli, že hodnotu co chci kontrolovat by byla primárním klíčem.

Primární klíč je automaticky unikátním podle definice. Mám na mysli sekundární indexy, které můžeš vytvořit ke kterémukoli sloupci nebo skupině sloupců, u kterých potřebuješ zajistit unikátnost. Zároveň pomáhají při vyhledávání záznamů.

BoneFlute

  • *****
  • 1 842
    • Zobrazit profil
Re:PHP PDO - SQL Insert pouze když záznam neexistuje
« Odpověď #14 kdy: 19. 03. 2019, 16:09:41 »
Kite...díky..nechám si od zkušených jako Ty rád doporučit správný postup, ale domnívám se, že primární klíč nezajistí aby se do sloupce  nedostal stejný záznam/hodnota. Pokud se mýlím, tak pak nechápu ten princip.

Pravděpodobně máš na mysli, že hodnotu co chci kontrolovat by byla primárním klíčem.

S oblibou mám složené primární klíče nad více sloupci. Pokud to dává z logiky věci smysl nebo tomu nebrání něco jiného. Pokud to nejde, tak tam přihodím unikátní klíč. Tím mám zajištěno, že mi to bude hlídat databáze - což upřednostňuju.

Například můžu mít PK nad všemi čtyřmi sloupci: Letter, Commission, Status, DeliveryDate. Což ale samozřejmě nebude to co chci, protože pak mi tam vleze stejný Letter + Commission díky tomu, že se to bude lišit třeba Statusem.
Takže se zamyslím nad tím, co chci:
Letter může být duplicitní, když se liší Commission, jinak ne. Takže udělám PK Letter + Commission.
Pak nechci duplicity nad Statusem, takže přidám UQ Letter + Commission + Status a UQ Letter + Commission + Status + DeliveryDate.
- Nebo naopak UQ Letter + Commission + Status a UQ Letter + Commission + DeliveryDate.
- Nebo jen UQ Letter + Commission + Status + DeliveryDate.

Všechno záleží na logice těch dat. Ale mělo by to jít vyjádřit tak jak jsem naznačil.