【问题标题】:PDO binding two array of valuesPDO 绑定两个值数组
【发布时间】:2016-03-30 14:07:10
【问题描述】:

我在INSERT statemnt in foreach 中添加了很多带有参数 ($queryArr) 的值

    public function getClients()
{

    helper::putToLog("\n----- getClients\n", true);

    $managedCustomerService = $this->user->GetService('ManagedCustomerService', ADWORDS_VERSION);

    $selector = new Selector();
    $selector->fields = array("CustomerId", "Name", "CurrencyCode");

    $graph = $managedCustomerService->get($selector);

    if (isset($graph->entries)) {
        $accounts = [];

        foreach ($graph->entries as $account) {
            $accounts[$account->customerId] = $account;            
        }

        helper::putToLog('Clients found: '.count($accounts)."\n", true);

    } else {
        helper::putToLog('Clients not found'."\n", true);
        return false;
    }


    $sth = $this->db->prepare('UPDATE `adwords_clients_google` set status = 2');
    $sth->execute();
    $sth = null;



    $queryClients = "INSERT INTO `adwords_clients_google` (`client_foreign_id`, `status`, `client_name`, `client_currency`) VALUES";

    foreach($accounts as $account) {

        $queryArr[$account->customerId] = "(".$account->customerId.",  1, :".$account->customerId.", :".$account->customerId."_currencyCode)"; 

        $nameArr[$account->customerId] = $account->name;
        $currencyArr[$account->customerId."_currencyCode"] = $account->currencyCode;


    }

    $queryClients .= implode(',', $queryArr) . " ON DUPLICATE KEY UPDATE `status` = VALUES(`status`), `client_name` = VALUES(`client_name`) ";

    $sth = $this->db->prepare($queryClients);

    foreach ($nameArr as $key => $value) {
        $sth->bindValue(":$key", str_replace("'", "\'", $value), PDO::PARAM_STR);
    }

    foreach ($currencyArr as $key => $value) {
        $sth->bindValue(":$key", $value, PDO::PARAM_STR);
    }

    print_r($sth);

    try {
        if ($sth->execute()) {
            helper::putToLog('ok queryCampaignArr, inserted rows: ' . $sth->rowCount());
        } else {
            helper::putToLog('not ok', true);
        }
    } catch (Exception $ex) {
        helper::putToLog($sth->debugDumpParams(), true);
        helper::putToLog("ERROR: ".$ex->getMessage(), true);
    }

    return true;
}

我需要绑定 2 个值数组 $nameArr$currencyArr。我没有收到任何错误,但 client_currency 列是空的,即使数组 $currencyArr 包含所有必要的值。怎么了?

【问题讨论】:

  • 当您使用PDO::PARAM_STR 作为当前值时,当前列的数据类型是什么;

标签: php arrays pdo


【解决方案1】:

您似乎还没有掌握准备+参数化语句的概念。
您只需准备一次,然后使用不同的参数(一次或多次)执行它们。

$sth = $this->db->prepare('
    INSERT INTO
        `adwords_clients_google`
        (`client_foreign_id`, `status`, `client_name`, `client_currency`)
    VALUES
        (:id, 1, :name, :currency)
    ON DUPLICATE KEY UPDATE
        `status` = VALUES(`status`),
        `client_name` = VALUES(`client_name`)
');
$sth->bindParam(':id', $id);
$sth->bindParam(':name', $name);
$sth->bindParam(':currency', $currency);
foreach($accounts as $account) {
    $id = $account->customerId;
    $name = $account->name;
    $currency = $account->currencyCode;
    $sth->execute();
}

如果您没有收到任何错误消息/日志条目,请确保您的 PDO 实例的 error handling mode 确实设置为 PDO::ERRMODE_EXCEPTION。

编辑:为了说明这一点,这里有一个sscce

<?php
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'localonly', 'localonly', array(
    PDO::ATTR_EMULATE_PREPARES=>false,
    PDO::MYSQL_ATTR_DIRECT_QUERY=>false,
    PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION
));

setup($pdo); // creating temporary table + sample data for this example
printTable("before", $pdo);

$sth = $pdo->prepare('
    INSERT INTO
        `soFoo`
        (`client_foreign_id`, `status`, `client_name`, `client_currency`)
    VALUES
        (:id, 1, :name, :currency)
    ON DUPLICATE KEY UPDATE
        `status` = VALUES(`status`),
        `client_name` = VALUES(`client_name`)
');
$sth->bindParam(':id', $id);
$sth->bindParam(':name', $name);
$sth->bindParam(':currency', $currency);
$accounts = data();
foreach($accounts as $account) {
    $id = $account->customerId;
    $name = $account->name;
    $currency = $account->currencyCode;
    $sth->execute();
}
printTable("after", $pdo);

function data() {
    return array_map(function($e) { return (object)$e; }, array(
        array('customerId'=>1, 'name'=>'customerA', 'currencyCode'=>'cA'),
        array('customerId'=>2, 'name'=>'customerB', 'currencyCode'=>'cB'),
    ));
}

function printTable($cap, $pdo) {
    echo $cap, "\r\n";
    foreach( $pdo->query('SELECT * FROM soFoo', PDO::FETCH_ASSOC) as $r ) {
        echo join(', ', $r), "\r\n";
    }
}

function setup($pdo) {
    $pdo->exec('
        CREATE TEMPORARY TABLE soFoo (
            client_foreign_id int,
            `status` int,
            client_name varchar(32),
            client_currency varchar(32),
            unique(client_foreign_id)
        )
    ');

    $pdo->exec("INSERT INTO soFoo (client_foreign_id,status,client_name,client_currency) VALUES (1, 0, 'agent smith', 'kruegerrand')");
}

打印

before
1, 0, agent smith, kruegerrand
after
1, 1, customerA, kruegerrand
2, 1, customerB, cB

【讨论】:

  • 我想创建一个查询并只执行一次,就像我上面的代码一样,您创建了很多查询并执行了多次。
  • 你为什么要这样?特别是。使用 prepare() 时?
  • 因为我需要在长查询的末尾添加ON DUPLICATE KEY UPDATE status` = VALUES(status), client_name = VALUES(client_name) ";`
  • 不是不多次执行该语句的正当理由。不这样做违背了准备好的声明的目的(部分)。
  • 非常感谢您的解释。我不知道有什么问题,但表中的字段client_currency 保持为空。 $account-&gt;currencyCode 有值,所有其他字段都可以正常工作,但不是这个。
猜你喜欢
  • 2012-04-27
  • 1970-01-01
  • 2012-09-02
  • 1970-01-01
  • 2015-01-06
  • 2013-05-26
  • 2017-01-29
  • 2012-12-02
  • 1970-01-01
相关资源
最近更新 更多