通过关系检查和可能的错误数据逐行插入大量数据

时间:2017-01-31 09:37:55

标签: c# mysql excel winforms entity-framework

我在这里阅读了许多与此类似的文章和问题,但是他们发现了一些非常接近的文章。

我在10列excel文件中有40,000行。 这里的数据是手工打印的。

有两个主要数字,MO&订单,在我需要先检查的文件中。 由于这些是手动打字,所以可能是错误的。

我有2张桌子 MO表

moID     MO       Order
3409    87234    23845
3410    84562    21342
etc... (38k rows)

printID   moID   user   date   printer
5         3409   Brad   01/24  printer1
34        3409   Brad   01/30  printer1
40        3410   Joe    01/31  printer1
etc... (9k ish and growing)

PROCESS:

我遍历c#app中的每一行,查询以获取moID。然后查询作业是否已存在,然后执行插入操作。如果无法找到moID,我会查询记录可能的MO&订单组合让他们以后修复文件。

LINK QUERYS:

curMOID = dbReports.MoNumbers.Where(r => r.moNumber == moNum && r.moOrder == orderNum).Select(c => c.id_moNumber).FirstOrDefault();
var printJobs = dbReports.PaperPrints.Where(q => q.id_moNumber == curMOID && q.printDate == printDate && q.rowExcelFile == curRow);
if (printJobs.Where(q => q.printSize == null).Count() == 0)

问题:

我的moID查询需要〜250ms(应用程序时间,直接查询为〜.075ms)。与已存在和选项列表相同。因此,每行大约需要0.5秒才能完成。 40k行需要5个多小时。我必须每天与用户这样做。有没有更好的方法来执行此操作或某种方式来加快查询通过应用程序。

3 个答案:

答案 0 :(得分:2)

是的,这是一种痛苦的,非常痛苦的方法。有一种无痛的方式,速度更快,不涉及任何编码。

第1步:将文件导出为CSV

第2步:使用LOAD DATA INFILE
使用它将数据加载到虚拟表

  

LOAD DATA INFILE语句将文本文件中的行读取到   桌子的速度非常快

第3步:创建目标表

使其与虚拟表完全相同,但请确保您不希望重复的列具有唯一索引。

您可以使用CREATE TABLE LIKE声明

执行此操作

第4步:从temp中选择最终
是的,语法是

INSERT IGNORE INTO destination SELECT * FROM tmp_table

第5步:使用multi table delete清理tmp_table

您有一个表格,其中包含无法导入的行。你用一行代码

在一分钟内完成了它

答案 1 :(得分:0)

除非我误以为您使用moID作为确定是否应插入的唯一键,所以:

您最好的选择是开始批量查询。

取5000 moID并先查询它们,然后从你留出的5000中删除任何返回,然后大量插入剩下的内容。冲洗并重复。

答案 2 :(得分:0)

谢谢@ e4c5。找到我需要去的地方。想要清楚地了解我的所作所为。过去需要5个小时,现在需要5秒。我仍在使用C#程序检查文件,csv创建并通过LOAD DATA INFILE发送。

1)创建一个CSV,每行包含所有表格中的信息。

  • 使用EPPLUS打开文件。检查我想要的类型的必填字段,如果出现错误则停止,以便用户修复必填字段。

2)创建了我想要插入

的表格的副本
  • 新表名为StagePrintJob

3)在我的案例中添加了MO和Order值的列。

4)将舞台上的moID字段更改为默认值0

5)使用LOAD DATA INFILE查询

  • 我截断(清除)表格,所以我不必每次都创建它。只需重复使用。

            "TRUNCATE TABLE  `" + table + "`; " +
    
            string.Format("LOAD DATA LOCAL INFILE '{0}' INTO TABLE `" + table + "` ", csvFullName).Replace(@"\", @"\\") +
            "FIELDS TERMINATED BY ',' " +
            "ENCLOSED BY '\"' " +
            "LINES TERMINATED BY '\\r\\n' " +
            "ignore 1 lines " +
            "(@printFix, moClient, moNumber, moOrder, printComment, printPrinter, printStatus, printUser, printIssue, printSolution, printQty, rowExcelFile, excelFile) " +
            "SET printDate = STR_TO_DATE(@printFix, '%m/%d/%Y'); " +
            "Call PaperPrintProcedure('" + printFileName + "')";
    
  • SET printDate是一种将我的日期字符串转换为mySQL理解的字符串的方法

  • 我在LOAD DATA LOCAL INFILE上使用了LOCAL,因此我可以在本地PC上使用文件,而不必先将其发送到mySQL服务器。

6)创建一个存储过程(可以运行命令)。我做了一个更新查询,根据我想要的表检查我的值。

        update StagePrint test inner join MoNumbers mo on test.moNumber = mo.moNumber && test.moOrder = mo.moOrder
        set test.id_moNumber = mo.id_moNumber;

7)我将暂存的行插入到我的实际表格中,只要它现在具有MO的ID。

  • 我删除了与我的文件相同的行,因为excel文件中没有好的ID,因此现在可以使用。

        DELETE FROM  `PaperPrint` WHERE  `excelFile` =  printFileName;
    
        insert into PaperPrint(id_moNumber, printQty, printDate, printSize, printUser, printPrinter, printStatus, printIssue, printSolution, printComment, rowExcelFile, excelFile) 
        select id_moNumber, printQty, printDate, printSize, printUser, printPrinter, printStatus, printIssue, printSolution, printComment, rowExcelFile, excelFile from StagePrint 
        where StagePrint.id_moNumber <> 0;
    

8)在StagedTable中查询您ID = 0的所有记录,并修复或删除它们。