提问人:Radium Chris 提问时间:11/2/2023 最后编辑:mickmackusaRadium Chris 更新时间:11/13/2023 访问量:96
使用 PDO 预准备语句将 2d json 数据中的行插入数据库表中 [已关闭]
Insert rows into database table from 2d json data using a PDO prepared statement [closed]
问:
我做了很多从一个站点到另一个站点的数据传输,主要是数据库数据。最新的是一个简单的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);
一切看起来都是正确的,但没有发生插入。我尝试先用一次插入插入多行,但现在循环但仍然不起作用......
两边的桌子结构相同。
答:
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 和$data
prepare
$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很高兴听到。我以为我会添加单个执行代码仅供将来参考,即使现在不适用。
评论
$a
$sql