2016-05-12 5 views
0

Ich habe die folgende MySQL-Tabelle:Neuen Datensatz einfügen, wenn er vorher nicht existierte, andernfalls aktualisieren Sie ihn. Auch legen Sie nicht mehr als N-Datensätze für eine bestimmte Bedingung

CREATE TABLE `tblUsg` (
`id` INT(11) UNSIGNED AUTO_INCREMENT PRIMARY KEY, 
`ip` VARCHAR(46) NOT NULL, 
`dtm` DATETIME NOT NULL, 
`huid` BINARY(32) NOT NULL, 
`licnm` VARCHAR(20) NOT NULL, 
`lichld` VARCHAR(256) NOT NULL, 
`flgs` INT NOT NULL, 
`agnt` VARCHAR(256), 

INDEX `ix_huid` (`huid`), 
INDEX `ix_licnm` (`licnm`), 
UNIQUE KEY `ix_lichuid` (`huid`, `licnm`) 
) AUTO_INCREMENT=0 CHARACTER SET utf8 COLLATE utf8_unicode_ci; 

Dann ist das Ziel der folgenden PHP-Skript ist, einen neuen Datensatz einfügen, nur wenn ein Datensatz mit den beiden huid und licnm existieren nicht bereits in dieser Tabelle Ist dies der Fall, Update statt:

if(@mysql_query(
    "INSERT INTO `$tblUsage` (`ip`, `dtm`, `huid`, `licnm`, `lichld`, `flgs`, `agnt`)\n". 
    "VALUES ('$strIP', '$strDate', UNHEX('$strHUID'), '$strLicNm', '$strLicHld', '$strFlgs', '$strAgnt')\n". 
    "ON DUPLICATE KEY UPDATE `ip`='$strIP', `dtm`='$strDate', `lichld`='$strLicHld', `flgs`='$strFlgs', `agnt`='$strAgnt'" 
    , $link) !== false) 
{ 
    //See how many rows did we insert 
    $iRows = @mysql_affected_rows($link); 

    if($iRows === 1) 
    { 
     //Added new record 
     ... 
    } 
    else if($iRows === 0 || $iRows === 2) 
    { 
     //Updated existing record 
     ... 
    } 
    else 
    { 
     //Error 
     ... 
    } 
} 
else 
{ 
    //Error 
    ... 
} 

Aber jetzt brauche ich eine weitere Bedingung hinzufügen - einfügen nicht mehr als N Datensätze mit (ix_lichuid eindeutigen Schlüssel Einschränkung.) das gleiche licnm. (Damit meine ich Gesamtdatensätze mit dem übereinstimmenden Feld licnm in der Tabelle.)

Haben Sie eine Idee, wie Sie das obige SQL ändern, um das zu tun? Ich kann nicht scheinen, es herauszufinden ...

PS. Ich benutze PHP 5.3

+0

Warum verwenden Sie 'mysql_' Funktionen? Sie sind seit langer Zeit veraltet und werden in den neuesten PHP-Versionen nicht mehr unterstützt. Auch Ihr Code scheint anfällig für SQL-Injection zu sein. Verwenden Sie stattdessen vorbereitete Anweisungen. – trincot

+0

@trincot: Dies ist für einen alten Code. Es ist auch nicht das, was ich frage, bitte nimm es nicht in die falsche Richtung. PS. Ich benutze 'mysql_real_escape_string' vor dem Einfügen dieser Variablen. – c00000fd

+0

So sei es, ich ziehe dann weiter. Viel Glück. – trincot

Antwort

0

Sie möchten vielleicht den Ansatz unten versuchen. Dies verwendet PDO stattdessen wie @trincot vorgeschlagen. Es ist auch kommentiert genug, um Sie zu beginnen ...

<?php 

     // LIKE ONE OF THE MASTERS HERE IN SO JUST COMMENTED, USE PDO INSTEAD OF mysql FUNCTIONS 

     // DATABASE CONNECTION CONFIGURATION: 
     defined("HOST")  or define("HOST", "localhost");   //REPLACE WITH YOUR DB-HOST 
     defined("DBASE") or define("DBASE", "database");   //REPLACE WITH YOUR DB NAME 
     defined("USER")  or define("USER", "root");    //REPLACE WITH YOUR DB-USER 
     defined("PASS")  or define("PASS", "root");    //REPLACE WITH YOUR DB-PASS 


     // CREATE A FLAG TO HOLD THE STATUS MESSAGE... WHETHER WE HAVE AN ERROR OR SUCCESS OR WHATEVER: 
     $status  = ""; 

     // CREATE A FUNCTION TO FETCH YOUR DATABASE RESOURCE... 
     // THIS WOULD BE BETTER IF ABSTRACTED INTO A SEPARATE FILE OR CLASS 
     // AND INCLUDED IN SCRIPTS THAT NEED IT LIKE THIS ONE... 
     /**@return PDO */ 
     function getDBConnectionHandle() { 
      try { 
       $db = new PDO('mysql:host='.DB_HOST.';dbname='. DB_NAMES,DB_ADMIN,DB_PWORD); 
       $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
       return $db; 
      } catch (PDOException $e) { 
       // IF THERE WAS AN ANY KIND OF CONNECTION ERROR, "DIE IT OUT" TO THE OUTPUT STREAM: 
       die($e->getMessage()); 
      } 
     } 


     // OBTAIN A DATABASE CONNECTION HANDLE USING THE "getDBConnectionHandle()" FUNCTION 
     $db   = getDBConnectionHandle(); 

     // SO THE 1ST GOAL HERE IS TO CHECK WHETHER A RECORD WITH A GIVEN "huid" AND "licnm" ALREADY EXISTS IN THE DATABASE TABLE. 
     // THAT MEANS WE FIRST RUN A SELECT QUERY TO CHECK IF IT'S THERE OR NOT 
     $stmt1  = $db->prepare('SELECT * FROM `' . $tblUsage . '` WHERE huid=:HD AND licnm=:LM'); 
     $stmt1->bindParam(":HD", hex2bin($strHUID)); 
     $stmt1->bindParam(":LM", $strLicNm); 
     $arrResult = $stmt->fetchAll(PDO::FETCH_ASSOC); 

     // NOW CHECK IF THE WE GOT SOMETHING BACK. IF WE DO, WE UPDATE THE TABLE; OTHERWISE WE INSERT A NEW ROW 
     if($arrResult && !empty($arrResult)){ 
      // WE GOT SOMETHING SO WE GO AHEAD AND UPDATE THE TABLE INSTEAD... 
      $stmt1 = $db->prepare('UPDATE `' . $tblUsage . '` SET `ip`=:IP, `dtm`=:DT, `huid`=:HD, `licnm`=:LM, `lichld`=:LD, `flgs`=:FG, `agnt`=:AT WHERE `huid`=:HD2 AND `licnm`=:LM2 '); 
      $rData1 = array(
       "IP" => $strIP, 
       "DT" => $strDate, 
       "HD" => hex2bin($strHUID), 
       "LM" => $strLicNm, 
       "LD" => $strLicHld, 
       "FG" => $strFlgs, 
       "AT" => $strAgnt, 
       "HD2" => hex2bin($strHUID), 
       "LM2" => $strLicNm, 
      ); 

      $isOK = $stmt1->execute($rData1); 
      $status = ($isOK) ? "The Record with licm: {$strLicNm} was successfully updated." : "There was an Error updating the record with licm: {$strLicNm}."; 
     }else{ 
      // WE ARE CLEAR TO PROCEED WITH INSERT: NOTHING CAME BACK!!! 
      $stmt2 = $db->prepare('INSERT INTO `' . $tblUsage . '` (`ip`, `dtm`, `huid`, `licnm`, `lichld`, `flgs`, `agnt`) VALUES(:IP, :DT, :HD, :LM, :LD, :FG, :AT)'); 
      $rData2 = array(
       "IP" => $strIP, 
       "DT" => $strDate, 
       "HD" => hex2bin($strHUID), 
       "LM" => $strLicNm, 
       "LD" => $strLicHld, 
       "FG" => $strFlgs, 
       "AT" => $strAgnt, 
      ); 

      $isOK = $stmt2->execute($rData2); 
      $status = ($isOK) ? "A new Record with was successfully created." : "There was an Error creating new Record."; 
     } 
     echo $status; 
+0

Danke. Obwohl ich wieder nicht nach dem PHP-Teil frage. Ich könnte es auch in separate MySql-Anfragen aufgeteilt haben. Mein Ziel war es, es aus Gründen der Parallelität unter einem MySql-Aufruf zu halten. Das habe ich gefragt? Außerdem sehe ich nicht wirklich, wie du nicht mehr als N-Inserts-Bedingung implementiert hast? – c00000fd

+0

Großartig dann ... folge einfach der Logik und ersetze alle PDO-Methoden durch ihre MySql-Entsprechungen ... ;-) Prost. – Poiz

+0

Nein. Mein Ziel war es, einen einzigen MySql-Aufruf dafür zu machen. – c00000fd