doufei7464 2012-02-16 19:58 采纳率: 0%
浏览 56
已采纳

具有k / v对和未知数的PDO?

I have a question about PDO for talking to databases, the example I am familiar with is:

$data = array('Cathy', '9 Dark and Twisty Road', 'Cardiff');  

$STH = $DBH->("INSERT INTO folks (name, addr, city) values (?, ?, ?);  
$STH->execute($data); 

But, if we had a k/v pair, would it be the same? ala

$data = array('one'=>'Cathy', 'two'=>'9 Dark and Twisty Road', 'three'=>'Cardiff');  

$STH = $DBH->("INSERT INTO folks (?, ?, ?) values (?, ?, ?);  
$STH->execute($data); 

And what if we had a none ascertainable amount of values?

$data = array(range(0, rand(1,99));  

$STH = $DBH->("INSERT INTO folks (/* how would you put stuff here? */) values (/* how would you put stuff here? */);  
$STH->execute($data);  

It leaves me more confused than not....

Could someone show me how the above two would work with k/v pairs and unknown counts?

Much thanks

  • 写回答

2条回答 默认 最新

  • dslfq06464 2012-02-16 20:35
    关注

    Prepared statements only work with literals, not with identifiers. So you need to construct the SQL statement with the identifiers filled in (and properly escaped).

    Properly escaping literals is tricky, though. PDO doesn't provide a method for doing literal-escaping, and MySQL's method of escaping literals (using `) is completely different from every other database and from the ANSI SQL standard. See this question for more detail and for workarounds.

    If we simplify the issue of escaping the identifiers, you can use a solution like this:

    // assuming mysql semantics
    function escape_sql_identifier($ident) {
        if (preg_match('/[\x00`\\]/', $ident)) {
            throw UnexpectedValueException("SQL identifier cannot have backticks, nulls, or backslashes: {$ident}");
        }
        return '`'.$ident.'`';
    }
    
    // returns a prepared statement and the positional parameter values
    function prepareinsert(PDO $pdo, $table, $assoc) {
        $params = array_values($assoc);
        $literals = array_map('escape_sql_identifier', array_keys($assoc));
        $sqltmpl = "INSERT INTO %s (%s) VALUES (%s)";
        $sql = sprintf($sqltmpl, escape_sql_identifier($table), implode(',',$literals), implode(',', array_fill(0,count($literals),'?'));
        return array($pdo->prepare($sql), $params);
    }
    
    function prefixkeys($arr) {
        $prefixed = array();
        for ($arr as $k=>$v) {
            $prefixed[':'.$k] = $v;
        }
        return $prefixed;
    }
    
    // returns a prepared statement with named parameters
    // this is less safe because the parameter names (keys) may be vulnerable to sql injection
    // In both circumstances make sure you do not trust column names given through user input!
    function prepareinsert_named(PDO $pdo, $table, $assoc) {
        $params = prefixkeys($assoc);
        $literals = array_map('escape_sql_identifier', array_keys($assoc));
        $sqltmpl = "INSERT INTO %s (%s) VALUES (%s)";
        $sql = sprintf($sqltmpl, escape_sql_identifier($table), implode(',',$literals), implode(', ', array_keys($params)));
        return array($pdo->prepare($sql), $params);
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 对于相关问题的求解与代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 信号傅里叶变换在matlab上遇到的小问题请求帮助
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作
  • ¥15 求NPF226060磁芯的详细资料