[PHP/MySQL] Importeren mits controle reeds bestaand

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Blue_man
  • Registratie: Maart 2003
  • Laatst online: 21-05-2024
Ik wil gebruikers een bestand laten importeren in MySQL dmv PHP.
Het bestand uitlezen lukt, alles wordt in variabele gestoken en de variabelen worden goed weggeschreven in de database.

Tijd om het script dus uit te breiden:

Bestaat deze lijn nog niet in MySQL
-> insert de gegevens
-> anders update de gegevens

Code die ik nu heb is

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//we controleren of er een lijn in de database zit met de inhoud van vorige variabelen
$check = "SELECT * FROM $tabelnaam WHERE voorwaarde1 = '$var1' AND voorwaarde2 = '$var2'"; 
$resultcheck = mysql_query($check) or die (mysql_error());
$row = mysql_fetch_array($resultcheck);
$row = $row['kolomindex'];
if(!isset($row))
{ //code wanneer de regel nog niet in de database zit.
$insert = "INSERT INTO $tabelnaam (aanslagjaar) VALUES ('$inhoudcookie')";
$resultinsert = mysql_query($insert) or die (mysql_error());
}
else
{ //code wanneer de regel wel al in de database zit.
$update = "UPDATE $tabelnaam SET Statusid = '$status' WHERE aanslagjaar = '$inhoudcookie'";
$resultupdate = mysql_query($update) or die(mysql_error()); 
}
//en we kunnen helemaal opnieuw beginnen


Ik hoop dat ik nergens een haakje of een ' teveel weggedaan heb, in mijn origineel script heb ik er een aantal echo's tussenstaan om tussentijds te controleren of alle variabelen wel nog goed zijn en de insert en update query's zijn ook langer.

Jullie snappen het plaatje wel dat ik bedoel: ik lees de lijn uit, steek de index in een variabele: is de variabele blanco dan zitten de gegevens nog niet in de database...

Of hebben jullie een ander voorstel om ofwel insert ofwel voor update te kiezen.

le·vens·moe (bn.)
1.genoeg van het leven hebbend, het leven als een last beschouwend.


Acties:
  • 0 Henk 'm!

  • Tharulerz
  • Registratie: April 2009
  • Laatst online: 10-04 05:16
Je kan beter gebruiken maken van mysql_num_rows($result)

Als die gelijk is aan 0 dan heb je 0 rijen teruggekregen (en bestaat het dus nog niet).

Als het nu nog niet bestaat ga je een error krijgen op mysql_fetch_array($resultcheck), iets in de aard van: $resultcheck is not a valid Mysql resource ofzo.

Acties:
  • 0 Henk 'm!

  • hostname
  • Registratie: April 2009
  • Laatst online: 20:16
MySQL kent hier de INSERT ... ON DUPLICATE KEY UPDATE ... syntax voor. Dan moet je wel je keys op de goede velden hebben liggen. Hoe ranzig het is mag je verder zelf beoordelen ;)

Acties:
  • 0 Henk 'm!

  • cariolive23
  • Registratie: Januari 2007
  • Laatst online: 18-10-2024
Je kunt ook gewoon een UPDATE doen en mocht die niet lukken omdat er geen bestaand record is (zie mysql_affected_rows()), dan doe je de INSERT.

Wanneer je de UNIQUE-constraint goed hebt aangemaakt, zou je ook eerst een INSERT kunnen doen en bij het mislukken een UPDATE.

Ligt een beetje aan de hoeveelheid dubbele data welke aanpak het beste is, dan kan na verloop van tijd zelfs veranderen.

Acties:
  • 0 Henk 'm!

  • Gomez12
  • Registratie: Maart 2001
  • Laatst online: 17-10-2023
Alternatieve aanpak ( als het om vrij veel data gaat ) :
- Maak een temp-tabel aan, dump hier alles blind in.
- Doe dan 1 insert query voor een join
- Doe daarna 1 update query voor de updates

Scheelt je een zooi query's en bij grotere indexen scheelt het massa's index update tijd.

Acties:
  • 0 Henk 'm!

  • Blue_man
  • Registratie: Maart 2003
  • Laatst online: 21-05-2024
Gomez12 schreef op zaterdag 06 maart 2010 @ 18:37:
Alternatieve aanpak ( als het om vrij veel data gaat ) :
- Maak een temp-tabel aan, dump hier alles blind in.
- Doe dan 1 insert query voor een join
- Doe daarna 1 update query voor de updates

Scheelt je een zooi query's en bij grotere indexen scheelt het massa's index update tijd.
Dit was een idee waar ik ook mee rondliep. Maar het betreft hier geen massa gegevens (een duizendtal zal al een mooi gemiddelde zijn). Ik kijk vandaag/morgen naar de voorgestelde alternatieven en laat iets weten.

le·vens·moe (bn.)
1.genoeg van het leven hebbend, het leven als een last beschouwend.


Acties:
  • 0 Henk 'm!

  • _eXistenZ_
  • Registratie: Februari 2004
  • Laatst online: 19-09 01:03
Nog even een algemene tip voor de TS: indenting

Je code wordt dan een stuk leesbaarder:

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//we controleren of er een lijn in de database zit met de inhoud van vorige variabelen
$check = "SELECT * FROM $tabelnaam WHERE voorwaarde1 = '$var1' AND voorwaarde2 = '$var2'"; 
$resultcheck = mysql_query($check) or die (mysql_error());
$row = mysql_fetch_array($resultcheck);
$row = $row['kolomindex'];

if(!isset($row)) { //code wanneer de regel nog niet in de database zit.
    $insert = "INSERT INTO $tabelnaam (aanslagjaar) VALUES ('$inhoudcookie')";
    $resultinsert = mysql_query($insert) or die (mysql_error());
} else { //code wanneer de regel wel al in de database zit.
    $update = "UPDATE $tabelnaam SET Statusid = '$status' WHERE aanslagjaar = '$inhoudcookie'";
    $resultupdate = mysql_query($update) or die(mysql_error()); 
}
//en we kunnen helemaal opnieuw beginnen


Overigens vind MySQL het geloof ik best als je alleen een UPDATE draait, de row zal geinsert worden als deze nog niet bestaat afaik. Maargoed, dat kan je even testen.

[ Voor 88% gewijzigd door _eXistenZ_ op 07-03-2010 15:18 ]

There is no replacement for displacement!


Acties:
  • 0 Henk 'm!

  • Gomez12
  • Registratie: Maart 2001
  • Laatst online: 17-10-2023
_eXistenZ_ schreef op zondag 07 maart 2010 @ 14:06:
Overigens vind MySQL het geloof ik best als je alleen een UPDATE draait, de row zal geinsert worden als deze nog niet bestaat afaik. Maargoed, dat kan je even testen.
Ik wist dat MySQL krom was, maar zo krom dat geloof zelfs ik nog niet eens...

Het is technisch onmogelijk om van een update een insert te maken, een update kan 1 veld updaten waardoor je de rest van de row niet hoeft aan te leveren, wat moet er dan in de andere velden geinsert worden???

Acties:
  • 0 Henk 'm!

Verwijderd

Gomez12 schreef op zondag 07 maart 2010 @ 15:43:
[...]

Ik wist dat MySQL krom was, maar zo krom dat geloof zelfs ik nog niet eens...

Het is technisch onmogelijk om van een update een insert te maken, een update kan 1 veld updaten waardoor je de rest van de row niet hoeft aan te leveren, wat moet er dan in de andere velden geinsert worden???
NULL of de default waarde, zolang natuurlijk de primary key velden acceptabele waarden hebben.

Maar je hebt gelukkig gelijk. Dit gaat niet vanzelf. Er is wel de speciale REPLACE INTO, maar ook die doet niet wat de topicstarter wil.

Wil je het echt in een enkele query, dan moet het via de ON DUPLICATE KEY UPDATE syntax.

Acties:
  • 0 Henk 'm!

  • Blue_man
  • Registratie: Maart 2003
  • Laatst online: 21-05-2024
Wordt nog lastiger dan gedacht. Ik heb momenteel de volgende code uitgewerkt:

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$update = "UPDATE $tabelnaam SET Lastmodifiedby = '$lastmod' WHERE nnaangever = '$nn1'";
$updatemysql = mysql_query($update) or die(mysql_error()); 
$num_rows = mysql_affected_rows();
//hoeveel rijen zijn er beïnvloed?
echo "Aantal bewerkte rijen: ".$num_rows."<br>";
    //indien geen, dan een insert, anders zie boven.
    if($num_rows != "1")
    { //code wanneer de aangifte nog niet in de database zit.
        $insert = "INSERT INTO $tabelnaam (velden)
            VALUES ('$waarden')";
        $insertinsert = mysql_query($insert) or die (mysql_error());
        echo "De volgende gegevens zijn toegevoegd aan de database:<br>";
        echo $waarden."<br>";
    }
    else
    { //code wanneer de aangifte wel al in de database zit.
        echo "De volgende gegevens zijn geupdate in de database:<br>";
        echo $waarden."<br>";
    }


Het volgende doet zich nu voor: wanneer de waarde in de database gelijk is aan de waarde van de UPDATE, overschrijft hij de waarden niet waardoor mijn $num_rows verschillen van 1 waardoor evengoed een INSERT gebeurd. Wat gek is want hiervan kan ik niets terugvinden dat dit effectief zo zou zijn (op de website van mysql.com en via Google.

De andere alternatieven:
+ mysql_num_rows($result): is niet van toepassing bij UPDATE;
+ INSERT ... ON DUPLICATE KEY UPDATE: de primaire sleutel is slechts op één veld van toepassing: de id (auto increment), op alle andere velden is het mogelijk om dezelfde gegevens te krijgen. Niet volledig dezelfde lijn, maar de gegevens kunnen wel op verschillende lijnen terugkomen.

@_eXistenZ_: ik pas tabs toe in mijn code, maar was hier op GoT iets te ijverig in spaties te verwijderen, ik hoop dat het nu wat leesbaarder is :)

le·vens·moe (bn.)
1.genoeg van het leven hebbend, het leven als een last beschouwend.


Acties:
  • 0 Henk 'm!

  • Gomez12
  • Registratie: Maart 2001
  • Laatst online: 17-10-2023
Staat gewoon vermeld op http://php.net/manual/en/function.mysql-affected-rows.php

Alternatief wat je anders kan doen is gewoon eerst een select query op nnaangever and Lastmodifiedby en dan naargelang het aantal rows daaruit een actie uitvoeren. 1 = UPDATE query, 0 = INSERT Query

Kost je alleen wel een bepaald percentage meer query's.

Of gewoon een nieuwe key aanmaken zodat insert on duplicate key update werkt. Wmb af te raden omdat je 1 onnodige unique key genereert en omdat je wmb dan vreemde error-afhandeling doet

Acties:
  • 0 Henk 'm!

  • Blue_man
  • Registratie: Maart 2003
  • Laatst online: 21-05-2024
Gomez12 schreef op zondag 07 maart 2010 @ 20:25:
Staat gewoon vermeld op http://php.net/manual/en/function.mysql-affected-rows.php

Alternatief wat je anders kan doen is gewoon eerst een select query op nnaangever and Lastmodifiedby en dan naargelang het aantal rows daaruit een actie uitvoeren. 1 = UPDATE query, 0 = INSERT Query

Kost je alleen wel een bepaald percentage meer query's.

Of gewoon een nieuwe key aanmaken zodat insert on duplicate key update werkt. Wmb af te raden omdat je 1 onnodige unique key genereert en omdat je wmb dan vreemde error-afhandeling doet
Op php.net had ik nog niet gekeken voor deze MySQL query 8)7 . Toch nog bedankt voor de link, nu weet ik tenminste dat dit normaal is.

Zoals je zegt heb ik een SELECT query gedaan, daarna een mysql_affected_rows(); (http://dev.mysql.com/doc/.../mysql-affected-rows.html zegt dat ik ook affected_rows kan gebruiken bij een SELECT), daar waar ik eerder
PHP:
1
2
$row = $row['kolomindex']; 
if(!isset($row))
gebruikte.

Probleem opgelost, bedankt voor de hulp!

le·vens·moe (bn.)
1.genoeg van het leven hebbend, het leven als een last beschouwend.


Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 10:15

Janoz

Moderator Devschuur®

!litemod

Blue_man schreef op maandag 08 maart 2010 @ 09:14:
....nu weet ik tenminste dat dit normaal is.
Nou, eigenlijk is het niet normaal. Het probleem ligt echter niet bij jou, maar bij een abnormale implementatie van mysql (again).

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'

Pagina: 1