2013-04-14 2 views
3

Я хотел бы вставить данные с помощью Zend \ Db \ Sql \ Вставить с опцией дублирование KEY UPDATEZF2 + Zend Db Sql Insert + дублирование KEY UPDATE

На самом деле я использую этот вид запроса:

INSERT INTO `user_data` (`user_id`, `category`, `value`) 
VALUES (12, 'cat2', 'my category value') 
ON DUPLICATE KEY UPDATE `user_id`=VALUES(`user_id`), `category`=VALUES(`category`), `value`=VALUES(`value`); 

с

$this->dbAdapter->query($sql, Adapter::QUERY_MODE_EXECUTE); 

Но как я могу генерировать этот выше запрос с Zend \ Db \ Sql \ Вставить?

спасибо за любое предложение. Приветствия

+1

не уверен, что вы можете, вы можете сделать это с сырым запроса, хотя. Я расширил Insert, чтобы разрешить это в одном проекте. Я выкопаю код. – Andrew

+1

. Я только что просмотрел текущие документы ZF2 (v 2.1), и похоже, что у него нет поддержки UPDATE DUPLICATE KEY UPDATE. Однако, что вы, возможно, захотите рассмотреть, это расширение класса Insert в ваш собственный класс InsertUpdate. –

+0

ОК спасибо. Я буду расширять класс Insert для его обработки. Скоро я отправлю код. –

ответ

2

Я сделал этот код: расширенный класс Sql \ Insert

Это работает, но я думаю, что нужно, чтобы зажечь ее. Потому что я просто обновляю последние строки «prepareStatement» и «getSqlString» из базы Zend \ Db \ Sql \ Insert.

Вы можете найти мой плагин здесь https://github.com/remithomas/rt-extends

Что вы думаете?

<?php 

namespace RtExtends\Sql; 

use Zend\Db\Adapter\AdapterInterface; 
use Zend\Db\Adapter\StatementContainerInterface; 
use Zend\Db\Adapter\ParameterContainer; 
use Zend\Db\Adapter\Platform\PlatformInterface; 
use Zend\Db\Adapter\Platform\Sql92; 

use Zend\Db\Sql\Insert as ZendInsert; 

class Insert extends ZendInsert{ 

    /** 
    * Constants 
    */ 
    const SPECIFICATION_INSERTDUPLICATEKEY = 'insert'; 
    const VALUES_DUPLICATEKEY = "duplicatekey"; 

    /** 
    * @var array Specification array 
    */ 
    protected $duplicatespecifications = array(
     self::SPECIFICATION_INSERTDUPLICATEKEY => 'INSERT INTO %1$s (%2$s) VALUES (%3$s) ON DUPLICATE KEY UPDATE %4$s' 
    ); 

    /** 
    * Constructor 
    * 
    * @param null|string|TableIdentifier $table 
    */ 
    public function __construct($table = null) 
    { 
     parent::__construct($table); 
    } 

    /** 
    * Prepare statement 
    * 
    * @param AdapterInterface $adapter 
    * @param StatementContainerInterface $statementContainer 
    * @return void 
    */ 
    public function prepareStatement(AdapterInterface $adapter, StatementContainerInterface $statementContainer) 
    { 
     $driver = $adapter->getDriver(); 
     $platform = $adapter->getPlatform(); 
     $parameterContainer = $statementContainer->getParameterContainer(); 

     if (!$parameterContainer instanceof ParameterContainer) { 
      $parameterContainer = new ParameterContainer(); 
      $statementContainer->setParameterContainer($parameterContainer); 
     } 

     $table = $this->table; 
     $schema = null; 

     // create quoted table name to use in insert processing 
     if ($table instanceof TableIdentifier) { 
      list($table, $schema) = $table->getTableAndSchema(); 
     } 

     $table = $platform->quoteIdentifier($table); 

     if ($schema) { 
      $table = $platform->quoteIdentifier($schema) . $platform->getIdentifierSeparator() . $table; 
     } 

     $columns = array(); 
     $values = array(); 

     foreach ($this->columns as $cIndex => $column) { 
      $columns[$cIndex] = $platform->quoteIdentifier($column); 
      if (isset($this->values[$cIndex]) && $this->values[$cIndex] instanceof Expression) { 
       $exprData = $this->processExpression($this->values[$cIndex], $platform, $driver); 
       $values[$cIndex] = $exprData->getSql(); 
       $parameterContainer->merge($exprData->getParameterContainer()); 
      } else { 
       $values[$cIndex] = $driver->formatParameterName($column); 
       if (isset($this->values[$cIndex])) { 
        $parameterContainer->offsetSet($column, $this->values[$cIndex]); 
       } else { 
        $parameterContainer->offsetSet($column, null); 
       } 
      } 
     } 

     $sql = sprintf(
      $this->duplicatespecifications[self::SPECIFICATION_INSERTDUPLICATEKEY], 
      $table, 
      implode(', ', $columns), 
      implode(', ', $values), 
      implode(",", array_map(array($this, "mapValue"), $columns)) 
     ); 

     $statementContainer->setSql($sql); 
    } 

    /** 
    * Get SQL string for this statement 
    * 
    * @param null|PlatformInterface $adapterPlatform Defaults to Sql92 if none provided 
    * @return string 
    */ 
    public function getSqlString(PlatformInterface $adapterPlatform = null) 
    { 
     $adapterPlatform = ($adapterPlatform) ?: new Sql92; 
     $table = $this->table; 
     $schema = null; 

     // create quoted table name to use in insert processing 
     if ($table instanceof TableIdentifier) { 
      list($table, $schema) = $table->getTableAndSchema(); 
     } 

     $table = $adapterPlatform->quoteIdentifier($table); 

     if ($schema) { 
      $table = $adapterPlatform->quoteIdentifier($schema) . $adapterPlatform->getIdentifierSeparator() . $table; 
     } 

     $columns = array_map(array($adapterPlatform, 'quoteIdentifier'), $this->columns); 
     $columns = implode(', ', $columns); 

     $values = array(); 
     foreach ($this->values as $value) { 
      if ($value instanceof Expression) { 
       $exprData = $this->processExpression($value, $adapterPlatform); 
       $values[] = $exprData->getSql(); 
      } elseif ($value === null) { 
       $values[] = 'NULL'; 
      } else { 
       $values[] = $adapterPlatform->quoteValue($value); 
      } 
     } 

     $values = implode(', ', $values); 
     $valuesDuplicate = implode(",", array_map(array($this, "mapValue"), $columns)); 

     return sprintf($this->duplicatespecifications[self::SPECIFICATION_INSERTDUPLICATEKEY], $table, $columns, $values, $valuesDuplicate); 
    } 

    private function mapValue($columns){ 
     return $columns."=VALUES(".$columns.")"; 
    } 
} 

?> 
3

Возможно, это решение поможет вам.

https://gist.github.com/newage/227d7c3fb8202e473a76

/** 
* Use INSERT ... ON DUPLICATE KEY UPDATE Syntax 
* @since mysql 5.1 
* @param array $insertData For insert array('field_name' => 'field_value') 
* @param array $updateData For update array('field_name' => 'field_value_new') 
* @return bool 
*/ 
public function insertOrUpdate(array $insertData, array $updateData) 
{ 
$sqlStringTemplate = 'INSERT INTO %s (%s) VALUES (%s) ON DUPLICATE KEY UPDATE %s'; 
$adapter = $this->tableGateway->adapter; /* Get adapter from tableGateway */ 
$driver = $adapter->getDriver(); 
$platform = $adapter->getPlatform(); 

$tableName = $platform->quoteIdentifier('table_name'); 
$parameterContainer = new ParameterContainer(); 
$statementContainer = $adapter->createStatement(); 
$statementContainer->setParameterContainer($parameterContainer); 

/* Preparation insert data */ 
$insertQuotedValue = []; 
$insertQuotedColumns = []; 
foreach ($insertData as $column => $value) { 
$insertQuotedValue[] = $driver->formatParameterName($column); 
$insertQuotedColumns[] = $platform->quoteIdentifier($column); 
$parameterContainer->offsetSet($column, $value); 
} 

/* Preparation update data */ 
$updateQuotedValue = []; 
foreach ($updateData as $column => $value) { 
$updateQuotedValue[] = $platform->quoteIdentifier($column) . '=' . $driver->formatParameterName('update_' . $column); 
$parameterContainer->offsetSet('update_'.$column, $value); 
} 

/* Preparation sql query */ 
$query = sprintf(
$sqlStringTemplate, 
$tableName, 
implode(',', $insertQuotedColumns), 
implode(',', array_values($insertQuotedValue)), 
implode(',', $updateQuotedValue) 
); 

$statementContainer->setSql($query); 
return $statementContainer->execute(); 
} 
+1

Я разработал код, чтобы использовать истинное «обновление по дублированию». Sql https://github.com/remithomas/rt-extends –

Смежные вопросы