根据两列检查重复项

时间:2013-03-04 23:53:35

标签: php sql-server

所以我有一张员工表如下:

empid | companyid | empnum | ...
  1   |     1     |    1   | ...
  2   |     1     |    2   | ...
  3   |     1     |    3   | ...
  4   |     2     |    1   | ...
  5   |     2     |    2   | ...

表上的每个员工条目都会获得由MSSQL自动生成的唯一ID(empid)。我有一个PHP应用程序,它将CSV文件作为输入,带有员工的“主列表”。但是,该CSV文件只有右侧的“empnum”列(它不包含companyid,或者显然是employeeid)。当我遍历CSV文件的每一行时添加了companyid。 CSV 仅包含尚未在数据库中的员工,但无法保证,因此我需要检查以确保员工在插入之前不在那里。验证方法是确保对于这个特定的companyid(假设我们为companyid = 1插入),表中没有匹配的empnum。因此,如果我有一个包含此数据的CSV文件,它将是有效的:

empnum, ...
4, ...

但是,如果我有一个包含此数据的CSV文件,则该文件无效:

empnum, ...
3, ...

由于3已作为companyid = 1的empnum存在,因此ENTIRE导入将失败。在PHP应用程序中,我有:

try {
   db->beginTransaction();
   while (($data = fgetcsv($handle, 5000, ",")) !== FALSE) {
      //SQL TO INSERT ROW   
   }
   db->commit();
} catch (PDO Exception) {
   db->rollBack();
}

我应该使用什么SQL来插入行,以便在该companyid已存在empnum时会导致异常?我需要做哪些数据库更改?我最初的想法是:

选项1 - 插入临时表,然后运行一个select查询,该查询将两个表连接到companyid / empnum中的匹配值,如果它返回行> 0,抛出异常。 PRO:只有1个选择。 CON:所有东西都被插入到临时表中,然后转入真实表中如果它通过select =大量浪费时间,如果它失败

选项2-根据当前行执行select语句,如果它返回行> 0,抛出异常,否则插入真实表。专业:你一发现就会发现失败,这样你就可以节省时间。 CON:你的查询现在增加了(2x-1),所以如果你成功了,你会有很多额外的开销!

所以我的问题是: - 什么是最好的选择(1,2或完全不同的东西)? - 我可以以某种方式让MSSQL在插入时抛出异常吗?

1 个答案:

答案 0 :(得分:1)

选项1是加载数据的“标准”方式(当然在我的世界中)。您的临时表实际上称为“临时”表。这比逐行检查要快得多(查找RBAR)。

事实上,总是花费最多时间的是逐行做事。

泥地图性能比较:

选项1:

  1. 按行(慢)
  2. 逐行插入表格
  3. 使用单个SELECT查询(快速)在表之间捕获重复项
  4. 如果成功,请将分段复制到实时表格(快速)
  5. 选项2:

    1. 逐行(中)将数据从CSV中加载出来
    2. 执行此操作时,Capture会逐行选择(慢速)
    3. 逐行复制

      当您在选项2中找到重复内容时,您会怎么做?是否要回滚所有其他记录,或者是否要通知用户并继续?