【发布时间】:2017-10-26 07:56:21
【问题描述】:
我正在验证几个数据库的电子邮件。 我们的验证提供商为我们创建了一个电子邮件列表,其中包含要放置的状态(已检查、未响应等......)
但对于某些地址,我们也进行了修复(例如 foo@gail.com => foo@gmail.com)
我需要输入正确的状态 (20),并且只有时修复电子邮件。我也可能不得不在状态已经正确时修复邮件。
我当前的 PDO 更新请求如下:
$req_fix_mail_and_update_status = "
UPDATE {$user_table_name}
SET status = :mail_status1
, {$mail_column_name} = :mail_fixed1
WHERE (({$mail_column_name} LIKE :mail_address) OR ({$mail_column_name} LIKE :mail_fixed2))
AND ((status != :mail_status2) OR ({$mail_column_name} NOT LIKE :mail_fixed3))
";
现在,棘手的部分来了:
其中一个数据库存储有关多个网站的数据,并且可能包含邮件重复项。
我对 (fk_site, email) 之类的东西有一个组合的唯一约束
...还有一个极端情况,一些电子邮件同时具有“固定”和“非固定”值条目
例如:
Login FK_Site Mail Status
Alice 01 foo@gmail.com 0
Alice 01 foo@gmal.com 0
Bob 02 foo@gmal.com 0
当然,尝试修复错误的地址会使重复无效,因为 (fk_site, email) 唯一约束在 Alice 上会失败 => 请求失败 (#$%§@&!)。
但是 Bob 仍然需要修复他的邮件,并且线路也需要更新它们的状态!
我正在寻找解决此问题的方法,但无法使用 SQL 找到任何东西。 当我失败时再提出一个(比如说,最多两个)请求可能是可以的,但这似乎是一种狡猾的方式,我不想把任务变成肮脏和不可读的东西,因为这样的边缘 cas
通常,UPDATE [...] with a "ON DUPLICATE KEY <just update status>" 子句是我需要的,但看到它不存在我并不感到惊讶。
我的 worker 是用 PHP 编写的,并且使用 PDO
有什么想法吗?
【问题讨论】:
-
我会捕获异常,看看它是否在重复键上,然后触发更新查询。
-
@Your Common Sense 我想到了,但是如果我考虑我的示例案例,我不仅要执行新的状态请求,还需要更新 Bob 的错误电子邮件没有尝试更新爱丽丝的。第二次更新将需要修复 only 没有与引发约束违规的其他值等效的行。我尝试使用子选择,但对我来说似乎不可能进行更新。也许带有
WHERE NOT EXISTS子句?我会再挖一遍。 -
等等,您的源数据没有站点 ID?
-
@Your Common Sense 我当然知道,但我不知道如何在我的请求中利用它。我刚刚测试了以下内容,但由于“无法在 from 子句中指定目标表 p1”而失败。
UPDATE prospect p1 SET firstname='UPDATED', status = 20 WHERE email="<wrong_value>" AND NOT EXISTS ( SELECT id FROM prospect p2 WHERE email = "<right_value>" AND p1.site_id = p2.site_id AND p1.origin = p2.origin )请注意,我的唯一约束中有第三列 -
看起来我找到了一种方法,将
WHERE NOT EXISTS与子选择结合使用。UPDATE prospect p1 SET email="<fixed_value>", status = 20 WHERE p1.email="<wrong_value>" AND NOT EXISTS ( SELECT id FROM (SELECT * FROM prospect cpy) as p2 WHERE email = "<fixed_value>" AND p1.site_id = p2.site_id AND p1.origin = p2.origin )我对表演有一些疑问,但由于涉及的台词很少,应该问题不大。
标签: php mysql pdo on-duplicate-key