【问题标题】:Checking Duplicates before inserting into SQL database在插入 SQL 数据库之前检查重复项
【发布时间】:2013-02-11 23:20:41
【问题描述】:

所以我一直在做一些研究,我需要编写一个INSERT 语句来将唯一的客户端名称插入到我服务器上的表中。然而,数据库的默认标准已经有数千个客户端,在插入新客户端时,我们需要在尝试将其添加到系统之前检查它们是否已经存在。

我的问题是最好/最快的方法是什么?在客户表上运行一个简单的选择查询(按 ASC 排序),然后对结果进行二分搜索或其他操作,或者只执行类似于下面的 SQL 查询会更好吗?

IF NOT EXISTS (SELECT 1 FROM clients AS c WHERE c.clientname = ?)
BEGIN
  INSERT INTO clients (clientname, address, ...)
  VALUES (?, ?, ...)
END

这是一个缓慢的陈述吗?每次提交我可能需要运行数百次插入。

【问题讨论】:

    标签: sql


    【解决方案1】:

    如果您希望给定的列是唯一的,则标准建议是创建一个 UNIQUE 约束。

    ALTER TABLE clients ADD UNIQUE KEY (clientname);
    

    然后尝试进行INSERT,如果没有匹配行则成功,如果有重复则失败。不需要 SELECT。

    【讨论】:

    • +1。如果存在多个同时数据库连接的可能性,这种“比许可更容易请求宽恕”的方法比 OP 描述的“先看再跳跃”方法更安全。
    • 我投了反对票。 Downvoter,你能评论一下你认为这个答案缺少什么吗?也许我可以改进它。
    【解决方案2】:

    在查询中根据磁盘操作计算 SQL 的成本并不少见(通常这意味着读/写一个块(通常 8 KB)是您的成本单位)。 (在 Memory-DB 中应该改变这种思路)。

    如果您有数百、可能数千个项目,并且每个项目...比如说 20 字节,那么您的完整数据库可能适合磁盘上的单个块(400 个项目/块)。也许它需要更多的街区,但万岁:这是一个可以忽略的小数字。使用这么小的数据库,您的数据库可能会在数据库的内存缓存中闲逛,您只需要为写访问付费。 随着数据库的增长,如果您有索引,您需要的块访问数量可以成倍减少。

    如果数据库中已经存在一个项目,那么您的解决方案和比尔的解决方案都不会导致任何写入访问,因此它应该同样快。

    有趣的部分是:

    我可能每次都需要运行数百次插入 提交。

    这意味着您可能会在磁盘上写入同一个块数百次。如果您可以一步完成,那会更快。但是,这确实是一个问题,因为我不知道任何允许这种行为的 SQL 函数。 MySQL 的 INSERT 提供了一种在单个语句中指定多个值的方法。这可能是一个相当大的优势(我不知道 MySQL 是如何处理这种情况的),但它是 MySQL 特有的,并且不可移植。

    另一种加快速度的方法是不要等到您更改的块被写入磁盘。这可能会在没有通知的情况下丢失数据,但可以显着提升性能。同样,这是特定于您使用的 DBMS。例如。如果您将 MySQL 与 InnoDB 一起使用,您可以在 my.ini 中设置选项 innodb_flush_log_at_trx_commit=0 来归档此行为。

    在客户表上运行一个简单的选择查询会更好吗 (由 ASC 排序),并对结果进行二分搜索或其他操作

    这会不必要地将大量数据从您的 DBMS 复制到客户端(可能位于不同的机器上,通过网络协议进行通信)。对于您的小型数据库,这仍然可以,但它不能很好地扩展。只有当它可以帮助您在单个操作中将数据保存到磁盘时,它才有用。

    【讨论】:

    • 感谢您的信息!我想做INSERT INTO clients (...) VALUES (...), (...), etc,但是由于我的IF 声明,它看起来很复杂,但在比尔的建议下,这可能会发生并且会加快我的进程!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-28
    • 1970-01-01
    • 2011-12-04
    相关资源
    最近更新 更多