0

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

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)。companyid 在我遍历 CSV 文件的每一行时添加。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 - 插入临时表,然后运行一个选择查询,将两个表连接到 companyid/empnum 中的匹配值上,如果它返回行 > 0,则抛出异常。PRO:只有 1 个选择。CON:所有内容都插入临时表然后转储到真实表如果它通过选择=如果失败则浪费大量时间

选项2-根据当前行执行选择语句,如果返回行> 0,则抛出异常,否则插入到真实表中。PRO:一旦发生故障,您就可以立即发现它们,这样您就可以节省自己的时间。缺点:您的查询现在增加了 (2x-1),因此如果您成功,您将有很多额外的开销!

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

4

1 回答 1

1

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

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

泥图性能比较:

选项1:

  1. 将您的初始插入逐行插入表中(慢)
  2. 使用单个 SELECT 查询捕获表之间的重复项(快速)
  3. 如果成功,将 staging 复制到实时表中(快速)

选项 2:

  1. 逐行从 CSV 中加载数据(中)
  2. 在执行此操作时,通过每次选择捕获逐行重复(慢)

不清楚的是,当您在选项 2 中找到重复项时您会怎么做?您要回滚所有其他记录还是要通知用户并继续?

于 2013-03-05T01:05:10.420 回答