【问题标题】:Comparing an array to a table and deleting the difference将数组与表进行比较并删除差异
【发布时间】:2018-01-29 21:28:06
【问题描述】:

我有一个数组:

[1, 2, 3, 5]

我有一张桌子:

+--------+
| number |
+--------+
| 1      |
| 2      |
| 3      |
| 4      |
| 5      |
+--------+

我想要做的是比较两者并从表中删除差异。所以在这种情况下,4。

最好的方法是什么? (我正在使用 MySQL(i) 和 php)

以下方法可行,但也有缺点:

  • 遍历数组并手动将每个项目添加到WHERE 子句的IN 部分:

    DELETE FROM tbl WHERE number NOT IN (1, 2, 3, 5)
    

    问题是这是不安全字符串的潜在风险,并且 sql 查询有大小限制。

  • 使用数组创建一个临时表并使用它进行比较:

    DELETE FROM tbl WHERE number NOT IN (SELECT num FROM tmp)
    

    这非常耗费资源(为每个连接创建和删除一个新表)并且速度很慢。

【问题讨论】:

  • SQL 语句的大小限制是多少?即使有相当大的数组,我也没有遇到过这种情况。并且 - 您不必迭代数组,您可以使用 implode 或者 - 最好使用准备好的语句,例如 this answer - 这将防止您关注的不安全字符串问题。
  • @cale_b 该链接中的答案有点天才。感谢您分享。
  • 除此之外,只要您的临时表不是那么大或不经常创建,您还可以指定 MEMORY 作为存储引擎以加快它们的性能/生命周期。
  • sql参数限制为apparently在50k到60k之间。我的桌子现在不是那么大,但它对未来的证明很好。
  • 定义“最佳”。

标签: php mysql sql arrays


【解决方案1】:

DELETE FROM tbl WHERE number NOT IN (SELECT num FROM tmp)

不是因为创建/删除慢,而是因为

  • 缺少索引
  • NOT IN条件

您可以改为这样做,前提是该数字已编入索引

delete tbl.*
from
  tbl
  left join tmp using (number)
where tmp.number is null

这不是资源密集型,也不受 max_allowed_pa​​cket 限制

【讨论】:

  • 不应该是tbl left join tmp where tmp.number is null吗?
  • 我仍然不喜欢为每个连接创建和删除一个新表的想法。我认为我要做的是设置一个永久的“比较表”并使用连接 ID,以便脚本的多个实例可以在表上操作而不会相互干扰。
  • 这会让你在insert 之前做一些delete 一些带有连接ID 的新行,如果使用MyISAM 还要冒表锁定的风险。可能不会更好
【解决方案2】:

一个简单的方法是:

DELETE FROM tbl WHERE NOT FIND_IN_SET(number, ?)

然后将你的数组绑定为字符串'1,2,3,5'

这不能使用索引,但NOT IN (1,2,3,5)也不能。

如果您的数组太大而无法绑定为字符串,那么我会问这么大的数据量来自哪里。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-07
    • 2013-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多