使用 PDO 预准备语句将 2d json 数据中的行插入数据库表中 [已关闭]

Insert rows into database table from 2d json data using a PDO prepared statement [closed]

提问人:Radium Chris 提问时间:11/2/2023 最后编辑:mickmackusaRadium Chris 更新时间:11/13/2023 访问量:96

问:


编辑问题以包括所需的行为、特定问题或错误以及重现问题所需的最短代码。这将帮助其他人回答这个问题。

7天前关闭。

我做了很多从一个站点到另一个站点的数据传输,主要是数据库数据。最新的是一个简单的pdo DB查询,fetchall,然后Jason对数据进行编码,发送到远程站点并用数据填充数据库,相同的数据库结构。

我想我可以简化这一点,我用最后一条记录作为凝视点。我向源服务器发送请求,其起始值为接收数据库的最后一个 ID,然后在源上运行它。

if ($_GET['start']){
    $startId = $_GET['start'];
    $q = $db->query("SELECT * FROM `table` where `id` > $startId  LIMIT 0,5 ");
    $r= $q->fetchall(PDO::FETCH_ASSOC);
    $out = json_encode($r);
    print $out;
}

这按预期生成了 jason 数据,我在接收端将其转换为数组,然后使用 pdo 进行更新,但在 24 小时未插入后我放弃了!

有什么想法吗?或更好的数据传输方式

接收端代码

    $a = json_decode($html,true);
    print '<pre>';
    print_r($a);
    print '</pre>';
}


foreach ($a as $data){
    if(!$valc){
        $valc = '(';
        foreach($data as $val){
            $valc = $valc.'?,';
        }
        $valc = rtrim($valc, ",");
        $valc = $valc.")";
    }
    $sql = "INSERT INTO table (".implode(', ', array_keys($data)).") VALUES ".$valc." ";
    print '<h4>'.$sql.'</h4>';
    $stmt = $dbo->prepare( $sql );
    $stmt->execute($data);

一切看起来都是正确的,但没有发生插入。我尝试先用一次插入插入多行,但现在循环但仍然不起作用......

两边的桌子结构相同。

php mysql json pdo 插入

评论

1赞 Nick 11/2/2023
始终使用适当的语言标签标记您的问题,以确保它们被最多的受众看到。
1赞 Nick 11/2/2023
源服务器查询容易受到 SQL 注入的攻击。请改用准备好的查询。请参阅 stackoverflow.com/questions/60174/...
0赞 Nick 11/2/2023
里面有什么和?$a$sql
0赞 mickmackusa 11/13/2023
相关新闻:JSON 数据的动态 SQL 插入JSON 中的 INSERT INTO 动态列
0赞 mickmackusa 11/13/2023
以及将包含多维数据的 json 中的多行插入数据库

答:

1赞 Nekkanti Chakradhar 11/2/2023 #1

您似乎正在尝试使用 PHP 和 PDO 将数据从源数据库传输到远程数据库。您使用的方法包括查询源数据库中 ID 大于给定值的记录,然后将此数据插入到远程数据库中。

你可以试试这段代码

$a = json_decode($html, true);

foreach ($a as $data) {
    $columns = implode(', ', array_keys($data));
    $values = rtrim(str_repeat('?, ', count($data)), ', '); // Prepare the placeholder values

    $sql = "INSERT INTO table ($columns) VALUES ($values)";
    $stmt = $dbo->prepare($sql);

    $stmt->execute(array_values($data));
}

评论

0赞 Radium Chris 11/2/2023
我看到我忽略了使用array_values,谢谢你的干净代码运行良好。@Nick ty 也用于更新 php 标签。从我所读到的内容来看,尝试将所有输入作为一个执行而不是遍历数组并没有真正的收益。我用它来一次插入 5000 个,实际上没有延迟。
1赞 Nick 11/3/2023
@RadiumChris假设所有数组键都具有相同的数组键集,则可以通过将 out 移出循环来大大加快此代码的速度。在循环之外,您将使用而不是在表达式中使用 for 和$dataprepare$a[0]$data$columns$values
0赞 Radium Chris 11/13/2023
@Nick是的,数据我都一样,你是说我可以一次执行所有事情吗?也许没有看到如何做到这一点。
1赞 Nick 11/13/2023 #2

@Nekkanti的答案会奏效,但效率低下。如果所有数组键都具有相同的数组键集,则可以将 prepare 移出循环,并在循环中执行:$data

$a = json_decode($html, true);

$columns = implode(', ', array_keys($a[0]));
$values = implode(', ', array_fill(0, count($a[0]), '?')); // Prepare the placeholder values

$sql = "INSERT INTO table ($columns) VALUES ($values)";
$stmt = $dbo->prepare($sql);

foreach ($a as $data) {
    $stmt->execute(array_values($data));
}

您也可以在一个查询中执行整个插入操作,尽管在准备好的查询中可能会遇到参数数量的限制:

$columns = implode(', ', array_keys($a[0]));
$values = implode('), (', array_fill(0, count($a), implode(', ', array_fill(0, count($a[0]), '?'))));

$sql = "INSERT INTO table ($columns) VALUES ($values)";
$stmt = $dbo->prepare($sql);

// flatten array
$data = array_merge(...array_map('array_values', $a));
$stmt->execute($data);

评论

0赞 Radium Chris 11/13/2023
好的,我明白了,我以为可能有一种方法可以在一次执行中插入所有数据,但我看到这也会更有效。再次感谢你
0赞 Nick 11/13/2023
@RadiumChris,如果数据足够小,语句可以适应查询长度限制,则可以构建一个大型子句来一次插入所有数据。不过,我不认为这样做会节省那么多。VALUES
0赞 Nick 11/13/2023
@RadiumChris请看我的编辑,我添加了可以在一次插入中完成所有操作的代码。
0赞 Radium Chris 11/13/2023
有些数据集会非常大,所以循环正常,现在实际上非常有效。我将以相同的方式更新其他传输,对于我的项目来说,循环是完全可以接受的。
1赞 Nick 11/13/2023
@RadiumChris很高兴听到。我以为我会添加单个执行代码仅供将来参考,即使现在不适用。