我正在尝试为此找到最佳解决方案,我知道ON DUPLICATE KEY UPDATE是处理类似问题的理想方法,但是被检查的字段可能会多次出现,这是userId和productId字段之间的关系,是唯一的,而不是字段本身。作为1的userId可以喜欢多个产品。
基本上,我想完成的事情(最好不要删除并重新插入现有字段)是,如果用户喜欢特定产品,则isActive等于1,如果他们在喜欢之前不喜欢该产品,则将isActive设置为0。如果他们再次喜欢同一产品,并且满足了userId和productId条件,则他们的userId会重选过去已经喜欢的产品(现有的行),然后将isActive设置为1。
我基本上想使用isActive作为切换来防止Id的碎片化,据我了解,与删除和重新插入相比,这更有效且更可取?
我将如何编写MySQL查询来完成此任务?
这是表模式
最佳答案
如果(userId, productId)
的组合是唯一的,则可以在该元组上创建UNIQUE约束,例如
CREATE UNIQUE INDEX mytable_UX1 ON mytable (userId, productId)
然后可以使用单个
INSERT ... ON DUPLICATE KEY
语法。 (请注意,即使由于“重复键”异常而未插入行,插入尝试也将消耗AUTO_INCREMENT值。)如果没有
UNIQUE
约束,则需要INSERT
和UPDATE
语句的组合。尝试更新,然后从MySQL检查“找到的行”计数。在您的情况下,将isActive定义为整数类型且不设置为NULL,并为赋值
isActive = !isActive
,“受影响的行”计数将与“找到的行”计数匹配;N.B.对于将来的读者,在更一般的情况下,我们不能保证找到的行实际上需要更新,当“找到的行”计数不为零时,“受影响的行”计数可以为零。 mysqli和PDO都具有(可以在连接上)覆盖默认行为的设置,并指定“受影响的行”将返回“找到的行”。
通过检查UPDATE语句“匹配”的行数,可以知道
INSERT
语句是否需要运行。MySQL不支持ANSI“
MERGE
”语法。因此,除了
INSERT ... ON DUPLICATE KEY
语句外,MySQL将要求(至少)发出两个单独的SQL语句。这两个单独的语句可以捆绑到一个存储过程中,因此您可以获得一个数据库调用来执行“ upsert”类型的功能。但是,这在您的应用程序和数据库之间传播了逻辑,并需要另一个需要维护的数据库对象。您可能会决定存储过程方法的额外复杂性超过了潜在的性能提升;并且您在性能改善方面的努力可能会更好地瞄准其他地方。
关于php - MySql如何插入或更新2个字段的重复项?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24375145/