所以我有一张员工表如下:
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在插入时抛出异常吗?
答案 0 :(得分:1)
选项1是加载数据的“标准”方式(当然在我的世界中)。您的临时表实际上称为“临时”表。这比逐行检查要快得多(查找RBAR)。
事实上,总是花费最多时间的是逐行做事。
泥地图性能比较:
选项1:
选项2:
当您在选项2中找到重复内容时,您会怎么做?是否要回滚所有其他记录,或者是否要通知用户并继续?