2011-09-28 268 views
2

我需要将一些非常大的文件(数百万条记录)加载到数据库中。它们的形式是:在MySQL中使用LOAD DATA INFILE过滤空或空输入

word1\tblahblahblah 
word2\tblahblah 
word3\tblahblah 
word4 
word5\tblahblah 
... 

我的问题是,我想忽略不具有第二记录(“blahblah的”),像word4行。

我目前使用下面的查询来加载文件:

LOAD DATA LOCAL INFILE 'file' 
IGNORE INTO TABLE tablename 
COLUMNS TERMINATED BY '\t' 
LINES TERMINATED BY '\n' 
(col1, col2); 

这有不同之处在于它仍然接受空值我想要的功能。有没有办法跳过word4类型的行,而不是将它们添加到数据库?

直觉上,我认为使用WHEN或WHERE子句是完美的,但是通过在线查看文档和其他信息,我找不到任何可以工作的示例。我是否被迫先过滤这些记录,或者我可以在这个查询中完成吗?

任何帮助grealy表示赞赏!

回答

1

我会通过使用grepawk过滤文件然后将其管道输入到MySQL(通过/dev/stdin)执行此操作。是这样的:

cat your_file.txt | 
    awk '/\t.+/' | 
    mysql -u your_username -pyour_password \ 
     -e "LOAD DATA LOCAL INFILE '/dev/stdin' \ 
      IGNORE INTO TABLE tablename   \ 
      COLUMNS TERMINATED BY '\t'   \ 
      LINES TERMINATED BY '\n'   \ 
      (col1, col2);" \ 
     your_database_name 

给予awk在第二行中的正则表达式匹配只具有一个制表符之后是一个或多个任意字符的任何行。您可能想调整它以适应您的需求。

编辑:我发生了另一种可能性。您可以使用SET在空白栏上设置一些魔术值,并在表上放置一个BEFORE INSERT触发器,该触发器在看到该值时将保留在一行上。我没有与触发器太多的经验,但我认为这样的事情应该工作:

CREATE TRIGGER skip_magic_rows 
    BEFORE INSERT ON tablename 
    FOR EACH ROW 
    BEGIN 
    IF NEW.col2 = 'IDSPISPOPD4815162342' THEN # Some unlikely magic string 
     # Trigger an error, which will cause the INSERT to fail† 

     # If you have MySQL < 5.5 this is kludgy -- see Note 1 
     DROP TABLE `Skipped row` 

     # OR 

     # In MySQL >= 5.5 you can send a signal--'45000' is a generic error 
     SIGNAL SQLSTATE '45000' SET message_text = 'Skipped row'; # See Note 2 

    END IF 
    END 
; 

†:Per the docs

期间无论是之前或之后失败触发效果的错误整个语句导致触发器调用。

则...

LOAD DATA LOCAL INFILE 'file' 
    IGNORE INTO TABLE tablename 
    COLUMNS TERMINATED BY '\t' 
    LINES TERMINATED BY '\n' 
    (col1, @var2) 
    SET col2 = IF(@var2 IN (NULL, ''), 'IDSPISPOPD4815162342', @var2) 
; 

希望是有帮助!

注1:Relevant blog post and comments
注2:Relevant SO thread

+0

感谢乔丹,这是类似于我结束了使用的解决方案。这就是说,这也是我试图避免的(在将数据提供给LOAD DATA INFILE命令之前过滤数据),我想以某种方式将此过滤器合并到加载程序中。但是,如果在接下来的几天里我没有得到任何其他点击,我会将其标记为正确的,因为据我所知,这是处理此问题的最佳方法。 – Thomp

+0

@Thomp:增加了一个替代解决方案,可以为你解决,看看上面。 –

+0

我唯一担心的是第二种解决方案,那就是时间。它是否减缓了执行这些额外操作的负载?我想知道的最好方法是尝试两种实现方式并计时,但我已经在开发中取得了进展。也许当我得到一些空闲时间。无论如何,谢谢你的解决方案。第一个的变化结束了我的工作。 – Thomp