在循环内使用PDO插入

时间:2018-11-02 04:42:57

标签: 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);

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个,其​​余存储失败。

2 个答案:

答案 0 :(得分:1)

假设您使用的是MySQL数据库,则可以使用INSERT ... SELECT语法对一个查询执行此操作...

INSERT INTO A (`idB`, `name`)
SELECT `idB`, `name` FROM B
WHERE B.status = 2
AND NOT EXISTS (
  SELECT 1 FROM A
  WHERE A.idB = B.idB
)

答案 1 :(得分:0)

在这里我缩小了您的代码,或者至少缩小了实际起作用的代码

$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);

假设您输入的内容正确无误,让我们看一下JOIN

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

如果A.idB = B.idB,我们可以参加。然后,您仅使用idBname,因此我们可以使用B中的这两个来代替*(因为$rowB的)。

我们可以将其显示为一半:

select B.idB,B.name from B where status=2
select * from A where A.idB=B.idB

何时加入他们:

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.

AS在注释中指出:

您基本上希望B的所有记录都没有与A匹配的记录。

为此,我们可以使用LEFT JOIN。如果它们在右侧的B中有JOINED记录,它将从JOIN的LEFT端(表A)返回所有记录,而这些记录将毫无保留。

然后,我们只需要保留左侧B中具有nullA.ibB的记录,就可以使用IS NULL A.ibB来完成。

这些丢失的记录是我们想要在末尾插入的记录:


然后让我们看一下PDO代码:

$q1=$this->pdo->query($sql1);
/// $q1->execute(); <--------------------- no need for this
$result1=$q1->fetchAll(PDO::FETCH_ASSOC);

现在$this->pdo->query()返回false或PDOStatement对象,并且[PDOSTatement]->fetchAll()可以通过返回值联接。

因此我们可以删除所有这些局部变量,并以这种方式编写。

 $result1 = $this->pdo->query($sql1)->fetchAll(PDO::FETCH_ASSOC);

如果您已将PDO设置为抛出异常,则此方法效果最佳,那么您不必担心如果失败则返回FALSE,因为它只会抛出一个异常。

与只使用一次SQL字符串的方式相同,我们可以直接将其放入,并摆脱$sql1。插入查询也是如此:

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

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

但是要注意一两个。在这里,因为我们将从第一个查询中提取的内容缩减为仅我们需要的内容,并且所有内容的名称都相同,所以我们可以将$row放到execute中。要注意的另一件事是在循环外准备查询。我们可以根据需要重复使用PDOStatement多次,而DB仅在第一次解释SQL时使用,这为我们节省了一些性能。

摘要

如果您更容易阅读,请保留局部变量。我喜欢摆脱它们,因为在编写大量代码时我不喜欢打字,所以我尽力而为地完成了工作。但是,我已经做了很长时间了,所以我可以很容易地阅读更复杂的代码。

我只是想以这种方式展示它,因为,我认为在很多示例中它不能很好地体现出您可以减少代码的数量,并且仍然让它做同样的事情。更少的代码可以查看,更少的代码可以调试(在一定程度上)。

干杯。