【问题标题】:PostgreSQL PDO insert into array typePostgreSQL PDO 插入数组类型
【发布时间】:2013-06-19 03:20:57
【问题描述】:

我正在尝试使用 PHP PDO 将值插入 PostgreSQL 数据库,但遇到以下错误消息:

SQLSTATE[22P02]: Invalid text representation: 7 ERROR: array value must start with "{" or dimension information

字段类型是PostgreSQL Array

这是我的代码(简化):

try {
  $sql='INSERT INTO table (fieldName, foo) VALUES (?, ?)';
  $fieldName=array('1','2');
  $data=array($fieldName, 'bar'); # fieldName is array type in PostgreSQL
  $STH = $conn->prepare($sql);          
  $STH->execute($data);
catch(PDOException $e) {
  # Handle exception
}

谢谢!

【问题讨论】:

  • 为什么是$data=array(array('1','2')); 而不是$data=array('1','2');
  • 我更新了问题。 fieldname 变量在 PostgreSQL 中存储为数组。

标签: php sql arrays postgresql pdo


【解决方案1】:

我最近接到电话要求实现类似的目标。我会使用 json_encode 将 PHP 数组转换为 json 并绑定参数或值,以便它转义所有值 - 从而消除 SQL 注入的机会。

$st->bindValue(':arr',json_encode(["jam sandwich","ham sandwich","cheese sandwich"]),\PDO::PARAM_STR);

然后在 PDO 语句中使用数组聚合函数从 json 函数构建数组。

例如

SELECT array_agg(ar) FROM 
jsonb_array_elements_text('["jam sandwich","ham sandwich","cheese sandwich"]') ar;

您可以在 CTE(通用表表达式)中使用它来在单个查询中执行插入、更新或其他操作,同时确保所有值都被转义,从而确保安全。

【讨论】:

    【解决方案2】:

    我知道这是一个旧线程,但它是“php Postgres PDO 数组”的第一个谷歌点击,所以我将添加我的答案。马特的答案的问题在于,内爆没有固有的消毒作用。因此,如果 $fieldname 包含引号、逗号、小胡子括号等,它将创建一个无效值。请参阅下面的示例,了解如何使用适当的 PDO 处理数组数据:

    // Connect to PostgreSQL database and create test table /////
    $dsn = "pgsql:host=$host;dbname=$db;user=$user;password=$pwd";
    $psql = new PDO($dsn);
    
    if($psql == null){throw new Exception("Error, db connection returned null.");}
    // Set errormode to exceptions
    $psql->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    
    $sql_table = "
        CREATE TABLE IF NOT EXISTS testarray (
            id         SERIAL PRIMARY KEY,
            something  TEXT,
            test1      TEXT[]
        )";
    $q_table = $psql->prepare($sql_table);
    $q_table->execute();
    /////////////////////////////////////////////////////////////
    
    // Create a new row and get it's ID
    $sql_new = "INSERT INTO testarray (something) VALUES ('stuff') RETURNING id";
    $q_new = $psql->prepare($sql_new);
    $q_new->execute();
    $r_new = $q_new->fetchAll(PDO::FETCH_ASSOC);
    $id = $r_new[0]['id'];
    
    $myarray = array("Test1", "Test2", "test3", "testing4", "TEST5");
    
    // Use a PDO for efficiency and ease of use
    // Use the ARRAY_APPEND SQL function to use PDO to add to an array
    $sql_up = "UPDATE testarray SET test1 = ARRAY_APPEND(test1, :arr) WHERE id = :id";
    $q_up = $psql->prepare($sql_up);
    $q_up->bindParam(":id", $id);
    
    // Loop through each element, binding it to the PDO and executing again
    foreach($myarray as $elem){
        $q_up->bindParam(":arr", $elem);
        $q_up->execute();
    }
    

    现在在您的数据库中:

    testing=# SELECT * FROM testarray;
     id | something |               test1                
    ----+-----------+------------------------------------
      1 | stuff     | {Test1,Test2,test3,testing4,TEST5}
    (1 row)
    
    testing=# 
    

    【讨论】:

    • 看起来相当老套,但至少看起来它可以按预期可靠地放入数据而不会出错。
    【解决方案3】:

    以防万一有人遇到这种情况,解决方案是内爆数组并添加 {}。

    $fieldName='{'.implode(",",$fieldName).'}';
    

    【讨论】:

    • 用户可以提供数据,这些数据要么使您的数据库生成错误,要么作为与数据库客户端所拥有的数组不同的数组进行处理:php 中的 ['hello \\','world'] 将变为PostgreSQL 中的“{hello world}”,它应该是“{hello \\,world}”。当然,我从未使用过 PgSQL,所以我可能是错的,但根据我在文档中阅读的内容,这似乎是正确的。 postgresql.org/docs/current/static/arrays.html
    • 我对这个答案投了反对票,因为它不会转义值。如果$fieldName 包含逗号和其他特殊字符,则不会按预期解释!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-13
    • 2016-09-29
    • 1970-01-01
    • 2015-08-16
    相关资源
    最近更新 更多