[PHP] on duplicate key update wrapper

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • kvaruni
  • Registratie: Oktober 2002
  • Laatst online: 14-09 15:45
Ik heb een wrapper geschreven voor de nieuwe ON DUPLICATE KEY functie die in MySQL 4.1 zit, omdat ik thuis hier graag gebruik van maak, terwijl ik op de server waar mijn code draait, geen toegang heb tot MYSQL 4.1

Ik post deze code om twee redenen:
- Ik hoop dat er mensen zijn die hetzelfde probleem hebben en dat ze hiermee geholpen worden.
- En ik vraag mij af of deze code niet nog wat geöptimaliseerd kan worden.

Alvast bedankt voor mogelijkse optimalisaties!

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
if (preg_match("/INSERT INTO(.+?)\((.+?)\)[ ]*VALUES[ ]*\((.+?)\)[ ]*ON[ ]+DUPLICATE[ ]+KEY[ ]+UPDATE[ ]+(.+)/i", $query, $Matches)) {
  preg_match("/(.*)[ ]+ON[ ]+DUPLICATE[ ]+KEY[ ]+UPDATE[ ]+(.*)/i", $Matches[0], $MatchInsert);
  $insert = $MatchInsert[1] . ";";
  if (!(mysql_query($insert))) {
   if (stristr(mysql_error(),"DUPLICATE")) {
    $update = "UPDATE " . $Matches[1] . " SET " . $MatchInsert[2] . ";";
    mysql_query($update) or trigger_error("Unable to execute the provided query!<br />The query to execute was: . " . $query . ".<br />The error that was generated is: " . mysql_error() . ".",E_USER_ERROR);
    } else {
    trigger_error("Unable to execute the provided query!<br />The query to execute was: . " . $query . ".<br />The error that was generated is: " . mysql_error() . ".",E_USER_ERROR);
    }
   }
  }

[ Voor 8% gewijzigd door kvaruni op 11-11-2003 20:34 ]


Acties:
  • 0 Henk 'm!

  • kvaruni
  • Registratie: Oktober 2002
  • Laatst online: 14-09 15:45
Ik heb mijn wrapper voor ON DUPLICATE KEY een hoop bijgeschaafd met onder andere de volgende dingen:

- Mogelijkheid om de gegenereerde key van het primaire veld terug te vinden, zowel bij een insert als een update. Anders retourneert hij -1.

- Betere aanpassing van de query indien deze al bestaat. Zal nu enkel kijken naar de velden die daadwerkelijk keys zijn (wat een hoop problemen gaf bij de vorige versie).

Ditmaal dus: deze code werkt (voor zover getest) 100%, maar moet nog verder getest worden en ook wat optimalisaties zouden geen kwaad kunnen dunkt me :)

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
 if (preg_match("/INSERT INTO(.+?)\((.+?)\)[ ]*VALUES[ ]*\((.+?)\)[ ]*ON[ ]+DUPLICATE[ ]+KEY[ ]+UPDATE[ ]+(.+)/i", $query, $Matches)) {
  # Apparently, we have na INSERT INTO...ON DUPLICATE KEY UPDATE query.
  preg_match("/(.*)[ ]+ON[ ]+DUPLICATE[ ]+KEY[ ]+UPDATE[ ]+(.*)/i", $Matches[0], $MatchInsert);
  # We can now create the INSERT query.
  $insert = $MatchInsert[1] . ";";
  # If this insert query fails, we may have to deal with a row that is already present.
  if (!(mysql_query($insert))) {
   # if the error description contains duplicate, then we know for sure.
   if (stristr(mysql_error(),"DUPLICATE")) {
    # We then buidl the update query
    $update = "UPDATE " . $Matches[1] . " SET " . $MatchInsert[2] . " WHERE ";
    $selectID = "SELECT ";
    $FieldNames = explode(",", $Matches[2]);
    $FieldValues = explode(",", $Matches[3]);
    # We then run through every single filed as to be able to further assemble
    # our select query.
    $Result = mysql_query("SHOW KEYS FROM " . $Matches[1]);
    while($Row = mysql_fetch_row ($Result)) {
     $Keys[] = $Row[4]; # needed to determine the name of the key field
     $KeyName[] = $Row[2]; # needed to determine if this is an autoincrement.
     }
    $check = 0;
    for ($a = 0; $a < count($FieldNames); $a++) {
     $passed = 0;
     foreach ($Keys as $value) {
      if (strpos($FieldNames[$a], $value)) {
       $passed = 1;
       break;
       }
      }
     if ($passed == 1) {
      if ($check == 0) { 
       $addString = $FieldNames[$a] . " = " . $FieldValues[$a];
       $check = 1;
       } else {
       $addString .= " AND " . $FieldNames[$a] . " = " . $FieldValues[$a]; 
       }
      }# End passed
     }
    @$update .= $addString . ";";
    # And execute it.
    mysql_query($update) or trigger_error("Unable to execute the provided query!<br />The query to execute was . " . $query . ".<br />The error that was generated is: " . mysql_error() . ".",E_USER_ERROR);
    $passed = 0;
    for ($counter = 0; count($KeyName) > $counter; $counter++) {
     if ($KeyName[$counter] == "PRIMARY") {
      $passed = 1;
      $selectID .= $Keys[$counter] . " FROM " . $Matches[1] . " WHERE " . $addString . " LIMIT 1;"; 
      break; 
      }
     }
    if ($passed == 1) {
     $Result = mysql_query($selectID);
     $Row = mysql_fetch_row ($Result);
     return $Row[0];
     } else {
     return -1;
     }
    } else {
    # However, if duplicate was not in the error string, this means there was another error. Let's see it.
    trigger_error("Unable to execute the provided query!<br />The query to execute was: . " . $query . ".<br />The error that was generated is: " . mysql_error() . ".",E_USER_ERROR);
    }
   } else {
   # If the INSERT query was performed succesfully, we return the newly generated ID key.
   return mysql_insert_id();
   }

Acties:
  • 0 Henk 'm!

  • Spider.007
  • Registratie: December 2000
  • Niet online

Spider.007

* Tetragrammaton

Ik denk dat je beter af bent met wat webspace voor jezelf om daar dit soort spullen op te promoten :) Iedereen kan wel handige scripts gaan posten maar dat kan dan beter in een centraal topic; in plaats van allemaal losse topics? Verder zie ik het grote voordeel van deze wrapper niet; of ben je ervan overtuigd dat het iets heel bijzonders is? Een paar entertjes tussendoor zou ook niet verkeerd zijn voor de mensen met een resolutie < 1600x1200 :)

---
Prozium - The great nepenthe. Opiate of our masses. Glue of our great society. Salve and salvation, it has delivered us from pathos, from sorrow, the deepest chasms of melancholy and hate