2008-11-19 5 views

Répondre

49

je travaillais pour Zend et travaillé spécifiquement sur Zend_Db un peu.

Non, il n'y a pas de support API pour la syntaxe ON DUPLICATE KEY UPDATE. Dans ce cas, vous devez simplement utiliser query() et créer vous-même l'instruction SQL complète.

Je ne recommande pas d'interpoler des valeurs dans le SQL comme le montre harvejs. Utilisez les paramètres de requête. Editer: Vous pouvez éviter de répéter les paramètres en utilisant VALUES() expressions.

$sql = "INSERT INTO sometable (id, col2, col3) VALUES (:id, :col2, :col3) 
    ON DUPLICATE KEY UPDATE col2 = VALUES(col2), col3 = VALUES(col3)"; 

$values = array("id"=>1, "col2"=>327, "col3"=>"active"); 
+0

Oui, c'est ce que je l'avais fait aussi bien, je me demandais s'il y avait une méthode de Zend_Db _... qui fournit cette fonctionnalité alors peut-être à la place d'utiliser $ db-> insert() nous pouvons utiliser $ db-> insertOrUpdate() ... juste une idée. – danielrsmith

+1

Non, il n'y a pas de telle méthode dans Zend_Db. Le but du produit ZF était toujours de fournir des solutions simples aux 80% des cas les plus courants. –

+1

Vous pouvez l'étendre et ajouter cette fonctionnalité facilement;) –

5

@Bill Karwin: des solutions géniales! Mais il serait préférable d'utiliser des espaces réservés nommés (": id", ": col1", ...) au lieu des signes de questions. Que vous n'auriez pas besoin de dupliquer les valeurs par array_marge. Aussi, si pour utiliser la syntaxe "SET" de "INSERT" au lieu de "VALUES", le code devient plus simple à générer automatiquement pour n'importe quel ensemble de champs.

$sql = 'INSERT INTO sometable SET id = :id, col2 = :col2, col3 = :col3 
    ON DUPLICATE KEY UPDATE id = :id, col2 = :col2, col3 = :col3'; 
+0

Je crois que cela dépend de l'adaptateur que vous utilisez –

6

une barre latérale Comme, vous pouvez simplifier la clause ON DUPLICATE KEY UPDATE et réduire la quantité de traitement de votre script doit faire en utilisant VALUES():

$sql = 'INSERT INTO ... ON DUPLICATE KEY UPDATE id = VALUES(id), col2 = VALUES(col2), col3 = VALUES(col3)'; 

Voir http://dev.mysql.com/doc/refman/5.1/en/insert-on-duplicate.html pour plus d'informations.

-6

vous pouvez tout simplement faire quelque chose comme ceci:

Définir un index unique sur votre identifiant

puis

try { 
    do insert here 
} catch (Exception $e) { 
    do update here 
} 
1

Utilisez ce lieu:

REPLACE INTO sometable SET field ='value'..... 

Cela mettra à jour si existe ou simplement insérer si non. C'est une partie de l'API standard mysql.

+4

Non, ce ne sera pas. Remplacer supprime toute ligne correspondante existante et en insère une nouvelle. Cela entraînera un comportement indésirable si vous n'insérez pas toutes les valeurs. Exemple: vous avez une table avec un 'time_created'. Si vous utilisez la mise à jour sans définir la valeur, elle restera la même que lorsque vous avez créé la ligne. Si vous utilisez 'REPLACE', la ligne sera supprimée, une nouvelle sera insérée et' time_created' sera réglé à l'heure actuelle. – apfelbox

3
$arrayData = array('column1' => value1, 'column2' => value2, ...) 

class Model_Db_Abstract extends Zend_Db_Table_Abstract 
{ 
    protected $_name; 
    protected $_primaryKey; 

    public function insertOrUpdate($arrayData) 
    { 
     $query = 'INSERT INTO `'. $this->_name.'` ('.implode(',',array_keys($arrayData)).') VALUES ('.implode(',',array_fill(1, count($arrayData), '?')).') ON DUPLICATE KEY UPDATE '.implode(' = ?,',array_keys($arrayData)).' = ?'; 
     return $this->getAdapter()->query($query,array_merge(array_values($arrayData),array_values($arrayData))); 
    } 

} 

USAGES:

par exemple. Model_Db_Contractors.php

class Model_Db_Contractors extends Model_Db_Abstract 
{ 

    protected $_name = 'contractors'; 
    protected $_primaryKey = 'contractor_id'; 

    ... 
} 

IndexController.php

class IndexController extends Zend_Controller_Action 
{ 
public function saveAction() 
{ 
    $contractorModel = new Model_Db_Contractors(); 
    $aPost = $this->getRequest()->getPost(); 

    /* some filtering, checking, etc */ 

    $contractorModel->insertOrUpdate($aPost); 
} 
} 
+1

pas sûr pourquoi 'array_merge (array_values ​​($ arrayData), array_values ​​($ arrayData))' mais 'array_values ​​($ arrayData)' suffira – Patrioticcow

+0

Bonne question, je ne me souviens pas pourquoi je l'ai mis là. – Pawel

+0

Une requête SQL correcte est requise pour lier la deuxième partie de la requête (ON DUPLICATE KEY UPDATE ... =?) Aux valeurs de tableau. – Pawel

Questions connexes