Mysql - 需要像UPDATE [...]在DUPLICATE KEY [...]

时间:2017-10-26 07:56:22

标签: php mysql pdo on-duplicate-key

我正在验证几个数据库的电子邮件。 我们的验证提供商为我们创建了一个电子邮件列表,其中包含要放置的状态(已检查,未响应等等)

但是对于一些地址,我们也得到了修复(例如foo@gail.com => foo @ g m ail.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)这样的东西有一个独特的约束
...和一个边缘案例,一些电子邮件同时具有“固定”和“非固定”值条目

e.g。 :

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 stil需要修复他的邮件,并且线路也需要更新状态!

我正在寻找一种方法来解决这个问题,但是找不到SQL的任何东西。 当我失败时发出一个(比如说,最多两个)更多的请求可能没问题,但这似乎是一种滑稽的方式,而且我不想把任务变成一些肮脏而且难以理解的边缘cas

通常情况下,UPDATE [...] with a "ON DUPLICATE KEY <just update status>"条款是我需要的,但我并不惊讶地发现它不存在。
我的工作人员用PHP编写,并使用PDO

有什么想法吗?

1 个答案:

答案 0 :(得分:0)

好的,所以这里是替代品&#34;回答&#34;我的问题。 请注意,一个更简单的解决方案(如果它存在...)将是受欢迎的。

它在技术上解决了我的需求,但非常难看,并且花了我3个额外的请求而不是一个。

  • 一个更新邮件&amp;具有错误邮件的行的状态,一旦邮件被修复就不会创建重复
  • 仅更新具有正确电子邮件的行的状态
  • 仅更新具有由于约束而无法修复的邮件的行的状态

这有点重,但性能在这里不是问题。我的错误在于它使代码的可读性降低,需要详细解释才能理解为什么需要3个请求。

这是我的(PDO)请求,只更新不会创建副本的行:

UPDATE prospect p1
    SET email = :mail_fixed1
    ,status = :mail_status1
WHERE 
    p1.email = :mail_address
    AND NOT EXISTS (
        SELECT site_id FROM (SELECT site_id, email, origin  FROM  prospect cpy) as p2
        WHERE 
            email = :mail_fixed2
            AND p1.site_id = p2.site_id
            AND p1.origin = p2.origin
        )
  • unicity约束在三元组上( site_id, email, origin
  • :mail_fixed1:mail_fixed2等占位符具有相同的值绑定。我必须使用不同的脚本的原因是因为我的脚本也连接到SQL-Server数据库,当多次使用占位符时,驱动程序崩溃时出现难以理解的错误。
  • 我的第3个请求,只更新邮件修复程序WOULD创建副本的行是相同的,除了&#34; NOT EXISTS&#34;被替换为&#34; EXISTS&#34; (此外,邮件未被修改,状态已修复,但这些是详细信息

中间的第2个请求没什么特别的,但为了完整起见我把它放在这里:

UPDATE {$user_table_name}
    SET status = :mail_status1
WHERE ({$mail_column_name} LIKE :mail_address)
    AND ((status IS NULL)  OR  (status != :mail_status2))

我忘了提到另一个小缺点:我的脚本用于计算更新行的精确数量,但现在可能会多次计算几行,因为同一行可以通过2个请求更新。这是一个小细节,但仍然很烦人。

无论如何,我希望这篇文章能帮助别人!