通过 PDO 查询使用 PHP 数组删除行,NOT IN 带有行构造函数表达式和 IN 条件
Delete rows via PDO query using PHP arrays with NOT IN with row constructor expression and an IN condition
我需要删除 table 中满足 NOT IN
和 IN
条件的行。查询将使用 php 个包含可变数据量的数组。
我已经成功地直接在我的数据库上测试了 SELECT 查询,如下所示:
SELECT *
FROM pivot
WHERE (table_1_id, table_2_id) NOT IN ((5,2),(5,3),(1,1),(3,1),(3,2))
AND table_2_id IN (1,2,3)
AND is_active = 1
关于这个示例数据:
table_1_id
table_2_id
is_active
5
1
1
5
2
1
5
3
1
1
1
1
3
1
1
3
2
1
我得到正确的结果:
table_1_id
table_2_id
is_active
5
1
1
现在我需要使用 $table1Ids
和 $table2Ids
在 php(作为 DELETE)查询中实现此 sql。我尝试调用 array_unique()
和 implode()
将数组值注入查询,但逻辑不正确。
$delete = "
DELETE FROM pivot
WHERE (table_1_id, table_2_id)
NOT IN (
" . implode(',', array_unique($table1Ids)) . ",
" . implode(',', array_unique($table2Ids)) . "
)
AND table_2_id IN (
" . implode(',', array_unique($table2Ids)) . "
)
AND is_active = 1";
$this->pdo->exec($delete);
我不确定如何设置数组并将它们以正确的格式传递给查询。
- "zip-flatten" 您的两个 equal-length 数组,以便它们可用于在您的 sql.[=21= 中制作带括号的 "row constructor" 语法]
- 为 WHERE 子句中的第二个条件隔离第二个数组中的唯一值。
- 对数组进行计数,生成占位符字符串,然后将这些变量插入到您的 sql。
- 合并您的变量并将它们写入
execute()
函数的参数数组。
代码:(Demonstration with SELECT instead of DELETE)
$table1Ids = [5, 5, 1, 3, 3];
$table2Ids = [2, 3, 1, 1, 2]; // assumed to always have identical length as $table1Ids
$zipFlattened = [];
foreach ($table1Ids as $index => $zipFlattened[]) {
$zipFlattened[] = $table2Ids[$index];
}
// $zipFlattened = [5, 2, 5, 3, 1, 1, 3, 1, 3, 2]
$uniqueIds2 = array_unique($table2Ids);
$placeholders1 = implode(',', array_fill(0, count($table1Ids), '(?,?)'));
$placeholders2 = implode(',', array_fill(0, count($uniqueIds2), '?'));
$sql = <<<SQL
DELETE
FROM pivot
WHERE (table_1_id, table_2_id) NOT IN ($placeholders1)
AND table_2_id IN ($placeholders2)
AND is_active = 1
SQL;
$stmt = $pdo->prepare($sql);
$stmt->execute(array_merge($zipFlattened, $uniqueIds2));
我需要删除 table 中满足 NOT IN
和 IN
条件的行。查询将使用 php 个包含可变数据量的数组。
我已经成功地直接在我的数据库上测试了 SELECT 查询,如下所示:
SELECT *
FROM pivot
WHERE (table_1_id, table_2_id) NOT IN ((5,2),(5,3),(1,1),(3,1),(3,2))
AND table_2_id IN (1,2,3)
AND is_active = 1
关于这个示例数据:
table_1_id | table_2_id | is_active |
---|---|---|
5 | 1 | 1 |
5 | 2 | 1 |
5 | 3 | 1 |
1 | 1 | 1 |
3 | 1 | 1 |
3 | 2 | 1 |
我得到正确的结果:
table_1_id | table_2_id | is_active |
---|---|---|
5 | 1 | 1 |
现在我需要使用 $table1Ids
和 $table2Ids
在 php(作为 DELETE)查询中实现此 sql。我尝试调用 array_unique()
和 implode()
将数组值注入查询,但逻辑不正确。
$delete = "
DELETE FROM pivot
WHERE (table_1_id, table_2_id)
NOT IN (
" . implode(',', array_unique($table1Ids)) . ",
" . implode(',', array_unique($table2Ids)) . "
)
AND table_2_id IN (
" . implode(',', array_unique($table2Ids)) . "
)
AND is_active = 1";
$this->pdo->exec($delete);
我不确定如何设置数组并将它们以正确的格式传递给查询。
- "zip-flatten" 您的两个 equal-length 数组,以便它们可用于在您的 sql.[=21= 中制作带括号的 "row constructor" 语法]
- 为 WHERE 子句中的第二个条件隔离第二个数组中的唯一值。
- 对数组进行计数,生成占位符字符串,然后将这些变量插入到您的 sql。
- 合并您的变量并将它们写入
execute()
函数的参数数组。
代码:(Demonstration with SELECT instead of DELETE)
$table1Ids = [5, 5, 1, 3, 3];
$table2Ids = [2, 3, 1, 1, 2]; // assumed to always have identical length as $table1Ids
$zipFlattened = [];
foreach ($table1Ids as $index => $zipFlattened[]) {
$zipFlattened[] = $table2Ids[$index];
}
// $zipFlattened = [5, 2, 5, 3, 1, 1, 3, 1, 3, 2]
$uniqueIds2 = array_unique($table2Ids);
$placeholders1 = implode(',', array_fill(0, count($table1Ids), '(?,?)'));
$placeholders2 = implode(',', array_fill(0, count($uniqueIds2), '?'));
$sql = <<<SQL
DELETE
FROM pivot
WHERE (table_1_id, table_2_id) NOT IN ($placeholders1)
AND table_2_id IN ($placeholders2)
AND is_active = 1
SQL;
$stmt = $pdo->prepare($sql);
$stmt->execute(array_merge($zipFlattened, $uniqueIds2));