很抱歉,我提出了一些基本问题,但对此错误我感到非常沮丧。请检查是否需要更正。插图,我试图将数据保存到表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个,其余存储失败。
答案 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
,我们可以参加。然后,您仅使用idB
和name
,因此我们可以使用B中的这两个来代替*
(因为$row
是B
的)。
我们可以将其显示为一半:
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
中具有null
值A.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时使用,这为我们节省了一些性能。
摘要
如果您更容易阅读,请保留局部变量。我喜欢摆脱它们,因为在编写大量代码时我不喜欢打字,所以我尽力而为地完成了工作。但是,我已经做了很长时间了,所以我可以很容易地阅读更复杂的代码。
我只是想以这种方式展示它,因为,我认为在很多示例中它不能很好地体现出您可以减少代码的数量,并且仍然让它做同样的事情。更少的代码可以查看,更少的代码可以调试(在一定程度上)。
干杯。