Php 使用PDO内部循环插入

Php 使用PDO内部循环插入,php,pdo,Php,Pdo,很抱歉问了一些基本的问题,但我对这个错误感到很沮丧。请检查是否需要更正某些内容。如图所示,我试图将数据保存到表A中,从表B中获取数据。保存前,它会检查表B中的数据是否不在表A中,并将其插入 这是我的代码: $sql1="select * from B where status=2"; $q1=$this->pdo->query($sql1); $q1->execute(); $result1=$q1->fetchAll(PDO::FETCH_ASSOC); foreac

很抱歉问了一些基本的问题,但我对这个错误感到很沮丧。请检查是否需要更正某些内容。如图所示,我试图将数据保存到表A中,从表B中获取数据。保存前,它会检查表B中的数据是否不在表A中,并将其插入

这是我的代码:

$sql1="select * from B where status=2";
$q1=$this->pdo->query($sql1);
$q1->execute();
$result1=$q1->fetchAll(PDO::FETCH_ASSOC);

foreach ($result1 as $row) {
  $sql2="select * from A where idB='".$row['idB']."'";
  $q2=$this->pdo->query($sql2);
  $q2->execute();
  $result2=$q2->fetchAll();

  if(empty($result2)){
    $data = ['idB' => $row['idB'],'name' => $row['name'];
    $s_inreg="insert into A(idB,name) values(:idB,:name)";
    $stmt=$this->pdo->prepare($s_inreg);
    $ret=$stmt->execute($data);
  }
}

假设有100个数据,只有10个数据存储成功,其余的数据保存失败。

假设您使用的是MySQL数据库,您可以使用以下语法通过一个查询完成此操作

在“idB”中插入“名称”` 从B中选择'idB','name' 其中B.status=2 而且不存在 从列表中选择1 其中A.idB=B.idB
在这里,我缩小了你的代码,或者至少是那些真正做事情的代码

$result1 = $this->pdo->query('
SELECT
    B.idB,
    B.name
FROM
    B
LEFT JOIN
    A ON A.idB=B.idB
WHERE
    B.status=2 AND IS NULL A.ibB
')->fetchAll(PDO::FETCH_ASSOC);

$stmt = $this->pdo->prepare('
INSERT INTO
    A(idB,name) VALUES (:idB,:name)'
);  

foreach ($result1 as $row) $stmt->execute($row);
假设您所做的是正确的,让我们看看连接

select * from B where status=2
select * from A where idB='".$row['idB']."'
 //and the results of A are $row
 $row['name'] //<-- dont forget this field
当我们加入他们时:

select 
    B.idB,B.name
from 
    B
LEFT JOIN  #left JOIN
    A ON A.idB=B.idB
WHERE
       B.status=2
   AND
       IS NULL A.ibB #records from B where no A.idB exists.
正如评论中指出的那样:

您基本上需要B中的所有记录,这些记录没有与a中的记录匹配的记录

为此,我们可以使用左连接。如果联接表B的左侧有联接记录,则将返回联接表B左侧的所有记录

然后我们只需要保留左侧B中A.ibB值为null的记录,我们可以使用null A.ibB

这些缺失的记录是我们希望在末尾插入的记录:

然后让我们看看PDO代码:

$q1=$this->pdo->query($sql1);
/// $q1->execute(); <--------------------- no need for this
$result1=$q1->fetchAll(PDO::FETCH_ASSOC);
如果您将PDO设置为抛出异常,那么您就不必担心if失败时返回FALSE,因为它只会抛出异常

就像我们只使用一次SQL字符串一样,我们可以直接将其放入,然后去掉$sql1。插入查询也是如此:

$stmt = $this->pdo->prepare('INSERT INTO A(idB,name) VALUES (:idB,:name)');  

foreach ($result1 as $row) $stmt->execute($row);
但是有一两个,注意到。在这里,因为我们将从第一个查询中提取的内容缩减为只需要的内容,并且所有内容的名称都相同,所以我们可以将$row直接放入execute。另一件需要注意的事情是在循环之外准备查询。我们可以根据需要多次重复使用PDO语句,DB只需要第一次解释SQL,这为我们节省了一点性能

萨默里

如果便于阅读,请保留局部变量。我喜欢摆脱它们,因为我不太喜欢打字,因为我写了很多代码,所以我尽量少写,以完成这项工作。但是,我已经做了很长时间了,所以我可以相当容易地阅读更复杂的代码

我只是想用这种方式来展示它,因为我认为它在许多例子中都没有得到很好的体现,比如你可以在多大程度上减少你的代码,并且仍然让它做同样的事情。要看的代码越少,调试的代码就越少


干杯。

既然$result2从未使用过,那么$result2有什么意义呢?请准备好您的查询,因为它在PDO中非常简单。@ArtisticPhoenix$result2用于if empty$result2您使用的是什么数据库?MySQL或其他什么?我认为您的连接逻辑与OP想要的相反。你的查询将选择所有在a中有匹配idB的B记录。哈哈,你的右边@Phil-我把我的阅读障碍归咎于此。我需要一个带isnull的左连接,至少我认为是这样,在我的头脑中弄清楚了。感谢伟大的分析,这就是我需要的。顺便说一句,正如您已经演示的,当表位于同一数据库中时,确实可以使用JOIN。但在相同的情况下,如果两个表(如A和B)位于不同的数据库中,该怎么办?当然,JOIN对我们来说相当困难。Mysql实际上可以在不同数据库中的两个表之间进行连接。并非所有数据库都能做到这一点,因此通常不鼓励这样做。您只需要包括数据库,从database1.table中选择a.*,b.*作为联接database2.table作为b。。。。不要告诉任何人,但实际上我一直都这么做。但这是因为我们集成了3个不同的系统,2个是第三方产品,1个是我创建的,因此我无法修改第三方应用程序的数据库,而将其放入我的应用程序需要不必要的维护。是的,在此之前,感谢@ArtisticPhoenix为您提供的帮助。
 $result1 = $this->pdo->query($sql1)->fetchAll(PDO::FETCH_ASSOC);
$stmt = $this->pdo->prepare('INSERT INTO A(idB,name) VALUES (:idB,:name)');  

foreach ($result1 as $row) $stmt->execute($row);