2013-03-04 54 views
0

所以,我有一个雇员表如下:检查重复根据两列

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

上表中的每个员工入职获得一个唯一的ID(EMPID)由MSSQL自动生成。我有一个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插入行,以便它会导致异常如果empnum已经存在该companyid?我需要做什么数据库更改?我最初的想法是:

选项1 - 插入到一个临时表中,然后运行一个select查询,该查询在companyid/empnum中的匹配值上连接两个表,如果它返回大于0的行,则抛出异常。 PRO:只有一个选择。 CON:所有内容都被插入到临时表中如果它通过select select =很多浪费时间,则转储到临时表中

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

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

+0

这不是确切的代码,但你可以得到一个想法: $ nextEmpnum =( “SELECT MAX empnum FROM employee_table WHERE companyid =” $ COMPANY_ID)+1 “INSERT INTO employee_table值(” $ nextEmpnum。 “,”。$ company_id – 2013-03-05 00:00:07

+0

对不起,我应该指定更好的,我没有试图为empnum创建一个唯一的id,empnum将由导入数据的公司提供,我只需要看看员工已经在桌子上存在(基于companyid和empnum的组合) – 2013-03-05 00:43:55

+0

另外,不知道为什么这个问题得到了downvote。如果你downvoted,请说明原因! – 2013-03-05 04:15:09

回答

1

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

其实什么将始终以最时间做事逐行。

一个mudmap性能对比:

选项1:

  1. 做你的初始插入到表行由行(慢)表之间
  2. 捕获重复同一个SELECT查询(快)
  3. 如果成功的,复制到举办现场表(快速)

选项2:

  1. 载入你的数据从您的CSV行由行(中)
  2. 虽然这样做,捕获,通过每次选择复制逐行(慢)

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

+0

在这个时候,我有3个“屏幕”他们走过。首先是选择文件并上传它。其次通过阅读CSV显示所有数据的预览。他们打进口,然后我的问题生效。更多地考虑这一点,也许在预览期间,我可以以某种方式标记任何显示为重复的东西并阻止它们导入? – 2013-03-05 01:39:51

+1

对我来说,这会增加一个临时表的权重,因为在将它加载到最终表之前,需要“暂存”它。你可以使用INSERT INTO FinalTable SELECT * FROM StaginTable WHERE Status ='Import'将它传输到最终表中。只要知道你为用户增加了复杂性,他们并不总是那样!上传的文件如何进入数据库 - 是批量加载还是您有一些PHP代码逐行插入并插入?有多少条记录? – 2013-03-05 03:34:30

+1

登台表的另一个原因是当某人在数字字段或格式不正确的日期有txt时。您可以只用文本字段将所有内容加载到临时表中,并添加此数据清理过程。否则,如果您只是尝试将CS​​V数据直接加载到您的目标中,则可能会出现数据转换问题以及重复问题。 – 2013-03-05 03:36:15