ZF2 + Zend \ Db \ Sql \ Insert + ON DUPLICATE KEY UPDATE

时间:2013-04-14 20:40:33

标签: php zend-framework2 zend-db sql-insert

我想使用Zend \ Db \ Sql \ Insert插入一些数据,选项 ON DUPLICATE 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 \ Insert 生成上述查询?

感谢任何建议。 干杯

2 个答案:

答案 0 :(得分: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 :(得分:2)

我做了这段代码: Sql \ Insert

的扩展类

它正在工作,但我想我需要点亮它。因为我只是从Zend \ Db \ Sql \ Insert base更新“prepareStatement”和“getSqlString”的最新行。

您可以在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.")";
    }
}

?>