【问题标题】:PHP to PostgreSQL insert unnested arrays into multiple rowsPHP 到 PostgreSQL 将未嵌套的数组插入多行
【发布时间】:2013-01-25 19:08:24
【问题描述】:

我有一些 PHP 数组/变量中的数据准备通过 INSERT 语句插入到 PostgreSQL 表中。

举个简单的例子,假设我有以下信息:

$name= 'someName';
$time = array(1,2,3);
$elevation = array(100,200,300);

(在我的实际应用中,这些是双精度,可能有 1000 多个值)

我的 postgresql 表也有列“名称”、“时间”、“海拔”

我想将这些插入到单个 INSERT 语句中,并且已经获得了多种不同的方法来执行此操作。

  1. 循环并一次插入一个数据点(行)。
  2. 在数组上使用 unnest() 并执行一次插入(最快)

我的问题是我可以传递一个变量名和未嵌套的数组,并且每行都重复名称(每个数组元素),还是我需要构造一个重复的数组来命名等效的 count() 作为其他数组?

示例语句:

*cr_query 是我们使用的自定义 PHP pg_query 包装器

cr_query($conn,"INSERT INTO sometable (name,time,elevation) VALUES ({$name},{unnest($time)},{unnest($elevation)}););

这将插入到某个表中:

ID     name      time    elevation
1     someName     1        100
2     someName     2        200
3     someName     3        300

我在这里是对的还是我需要做其他事情?

编辑:

假设我还有另一个变量“表面”。 Surface 可以是双精度值,也可以为 NULL。所以我想插入到表格中,看起来像这样:

ID     name      time    elevation    surface
1     someName     1        100          50
2     someName     2        200         NULL
3     someName     3        300          100

在 PHP 中,在 unnest 语句中使用 klin 规定的方法在表面数组下方将变为 unnest(array[50,,100]);这会引发如下错误:

(来自我的真实数据的错误)

ERROR: syntax error at or near "," LINE 3: ...-6,5.75E-6,5.75E-6,5.75E-6,5.75E-6]),unnest(array[,,,,,,,,,]... ^

编辑 2:

现在所有的“编码”都在工作,出现了一个新问题。假设上面的示例列“表面”是双精度类型。

假设我正在插入一个数组,但是对于这个集合,所有数据都是空的。

最重要的部分是:

unnest(array[null,null,null,null,null,null,null,null,null,null])

但是,这个数组是字符串类型的。向它添加一个值,它就会成为该数值的类型,但我需要能够处理它。

我的问题是:如何将所有空值的未嵌套数组插入双精度列? (我尝试投射 ::double 精度)但这是不可能的。

【问题讨论】:

    标签: php arrays postgresql insert


    【解决方案1】:

    假设你的 cr_query() 函数没有做任何神奇的事情,你的代码将会引发 postgres 语法错误。您可以使用 unnest,但必须准备正确的查询文本。 试试你的代码:

    $name= 'someName';
    $time = array(1,2,3);
    $elevation = array(100,200,300);
    echo "INSERT INTO sometable (name,time,elevation) VALUES ".
        "({$name},{unnest($time)},{unnest($elevation)})"
    
    echo: INSERT INTO sometable (name,time,elevation) VALUES (someName,{unnest(Array)},{unnest(Array)})
    

    显然这不是我们想要发送给 postgres 的。如何修复?

    $name= 'someName';
    $time = array(1,2,3);
    $elevation = array(100,200,300);
    $timestr = 'array['. implode(',', $time). ']';
    $elevstr = 'array['. implode(',', $elevation). ']';
    echo "INSERT INTO sometable (name,time,elevation) ".
        "VALUES ('$name',unnest($timestr),unnest($elevstr));"
    
    echo: INSERT INTO sometable (name,time,elevation) VALUES ('someName',unnest(array[1,2,3]),unnest(array[100,200,300]));
    

    我认为这是正确的查询。请注意,我将文本变量 '$name' 括在单引号中。


    如果您的数组中有空值,则必须在准备好的查询文本中将所有空字符串替换为“空”。 可能最简单的方法是使用 str_replace()。 随着转换变得越来越复杂,为此目的编写一个函数(例如“pgstr()”)会很方便。

    function pgstr($array) {
        $str = 
            str_replace('[,', '[null,', 
            str_replace(',]', ',null]', 
            'array['. implode(',', $array). ']'));
        while (strpos($str, ',,') > 0) $str = str_replace(',,', ',null,', $str);
        return $str;
        }
    
    $name= 'someName';
    $time = array(1,2,3,4);
    $elevation = array(100,null,300,null);
    $surface = array(null,null,3.24,null);
    $timestr = pgstr($time);
    $elevstr = pgstr($elevation);
    $surfstr = pgstr($surface);
    echo 
        "INSERT INTO sometable (name,time,elevation,surface) ".
        "VALUES ('$name',unnest($timestr),unnest($elevstr),unnest($surfstr));";
    

    【讨论】:

    • 我一直认为如何在单个 INSERT 语句中插入多行的唯一方法是使用更多用逗号分隔的 '(value1, value2)' 部分。但我试过了,它有效 - 谢谢!您知道 postgres 文档中描述的这种行为在哪里吗?我没找到。
    • 这是反复试验的知识。前段时间我想从两个数组中生成元素的组合,所以我尝试了select unnest(array[1,2,3]), unnest(array[1,2,3])。结果在某种程度上是合乎逻辑的,但我不知道有关此的任何正式文档。也可以试试select unnest(array[1,2]), unnest(array[1,2,3]) 等等。
    • 我在 Postgres 文档中发现了某种警告:目前,返回集合的函数也可以在查询的选择列表中调用。对于查询自己生成的每一行,调用返回集的函数,并为函数结果集的每个元素生成一个输出行。但请注意,此功能已弃用,可能会在未来的版本中删除。 35.4.8. Functions returning sets.
    • @klin 我会在星期一试一试,看起来正是我想要的。谢谢。
    • @klin 我在问题中添加了一些其他问题。希望得到一些帮助,您的第一个解决方案似乎可以工作(在找出附加错误之后)
    猜你喜欢
    • 2013-01-20
    • 2011-12-05
    • 1970-01-01
    • 1970-01-01
    • 2022-08-19
    • 2019-07-23
    • 2021-01-13
    • 2018-08-21
    • 2017-10-29
    相关资源
    最近更新 更多