我有一个表,每隔几秒钟就会获取新数据。考虑我的表产品:
+----+-------------+--------+--------------------------------+-------+--------+---------------------+
| id | business_id | name | description | link | status | created_at |
+----+-------------+--------+--------------------------------+-------+--------+---------------------+
| 1 | 12 | qwerty | Description for product qwerty | zxcvb | 1 | 2015-12-07 23:49:33 |
+----+-------------+--------+--------------------------------+-------+--------+---------------------+
| 2 | 12 | abcde | Description for product abcde | mnopq | 0 | 2015-12-07 23:49:33 |
+----+-------------+--------+--------------------------------+-------+--------+---------------------+
列名称和描述中的值是唯一的(我不确定这是否正确)。
我想要的条件:如果新数据与上次插入的数据相同,但时间戳大于 5 分钟,则执行更新或在表中插入新行。即使名称和描述是唯一的。
我试过的查询:
INSERT INTO product(business_id, name, description, link)
VALUES ('$business_id' ,'$product_name','$product_description', '$short')
ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id)
我应该改变哪种条件?我应该删除唯一键吗?
在重复的名称和说明值的时间戳不比上次插入的记录晚 5 分钟时插入这些值。
有了这个要求,你有效地说名称和描述不是唯一的。因此,实际上,您必须删除这些字段上的unique
键/索引才能实现这一点。
其次,您假设如果表中已存在新值,则它必须位于最后插入的记录中,但似乎无法保证这一点。您还应该处理以下可能性:首先插入值 A,然后在一分钟后插入值 B,然后在 10 分钟后再次插入值 A。
在您提供的逻辑中,最后一个操作将被检测为重复,并会转换为上次插入记录的更新。但这不是值 A 的记录。实际上,在这种情况下,您建议的ON DUPLICATE
子句会产生自己的重复错误(id上重复)。
所以这是我建议做的:
删除名称和描述上的UNIQUE
键/索引,但您仍然可以从使用非唯一索引中受益;
使用以下 INSERT 语句:
INSERT INTO product(business_id, name, description, link)
SELECT :business_id, :name, :description, :link
FROM product
WHERE NOT ( name = :name
AND description = :description
AND created_on < DATE_ADD(NOW(), INTERVAL -5 MINUTE)
)
:
表示预准备语句中参数的占位符。您不应该像以前那样在 SQL 语句中插入字符串,因为这样您就容易受到 SQL 注入的攻击。阅读有关将代码转换为使用预准备语句的信息。
如果之前已经注册了名称和描述值组合,并且发生在 5 分钟前,则上述 INSERT
语句将不执行任何操作。
在这种情况下,您可以在 PHP 中测试没有使用 num_rows
方法插入任何记录。如果返回 0,则您将执行第二个 SQL 来执行更新:
UPDATE product
SET link = :link
WHERE name = :name
AND description = :description
AND created_on < DATE_ADD(NOW(), INTERVAL -5 MINUTE)
同样,您应该使用准备好的语句来执行此操作。
如果使用唯一描述,则无法插入具有相同描述的新记录。唯一应该在"id"处使用,所以是的,你应该在描述上删除唯一。
您可以使用if子句检查是否business_id是否相同并且create_at大于5分钟,然后更新或插入新行。