【问题标题】:How do I import CSV file into a MySQL table?如何将 CSV 文件导入 MySQL 表?
【发布时间】:2011-04-07 19:15:54
【问题描述】:

我有一个来自客户端的非规范化事件日志 CSV,我正在尝试将其加载到 MySQL 表中,以便我可以重构为合理的格式。我创建了一个名为“CSVImport”的表,其中 CSV 文件的每一列都有一个字段。 CSV 包含 99 列,因此这本身就是一项艰巨的任务:

CREATE TABLE 'CSVImport' (id INT);
ALTER TABLE CSVImport ADD COLUMN Title VARCHAR(256);
ALTER TABLE CSVImport ADD COLUMN Company VARCHAR(256);
ALTER TABLE CSVImport ADD COLUMN NumTickets VARCHAR(256);
...
ALTER TABLE CSVImport Date49 ADD COLUMN Date49 VARCHAR(256);
ALTER TABLE CSVImport Date50 ADD COLUMN Date50 VARCHAR(256);

表上没有约束,所有字段都包含 VARCHAR(256) 值,除了包含计数(由 INT 表示)、是/否(由 BIT 表示)、价格(由 DECIMAL 表示)和文字简介(由 TEXT 表示)。

我尝试将数据加载到文件中:

LOAD DATA INFILE '/home/paul/clientdata.csv' INTO TABLE CSVImport;
Query OK, 2023 rows affected, 65535 warnings (0.08 sec)
Records: 2023  Deleted: 0  Skipped: 0  Warnings: 198256
SELECT * FROM CSVImport;
| NULL             | NULL        | NULL           | NULL | NULL               | 
...

整个表格都填满了NULL

我认为问题在于文本简介包含多行,并且 MySQL 正在解析文件,好像每一新行都对应一个数据库行。我可以毫无问题地将文件加载到 OpenOffice。

clientdata.csv 文件包含 2593 行和 570 条记录。第一行包含列名。我认为它是逗号分隔的,文本显然是用双引号分隔的。

更新:

如有疑问,请阅读手册:http://dev.mysql.com/doc/refman/5.0/en/load-data.html

我在LOAD DATA 语句中添加了一些信息,表明 OpenOffice 足够聪明地进行推断,现在它加载了正确数量的记录:

LOAD DATA INFILE "/home/paul/clientdata.csv"
INTO TABLE CSVImport
COLUMNS TERMINATED BY ','
OPTIONALLY ENCLOSED BY '"'
ESCAPED BY '"'
LINES TERMINATED BY '\n'
IGNORE 1 LINES;

但是仍然有很多完整的NULL 记录,并且加载的数据似乎都没有放在正确的位置。

【问题讨论】:

  • 如果你在 OSX 上,Sequel Pro 有一个很棒的导入工具,而且它是 免费 ;-)
  • 令我惊讶的是,原发帖人比任何人都更好地回答了他自己的问题……我不知道为什么有这么多人愿意在现有 SQL 命令的情况下提供软件推荐,它可以是programmatic而不是基于UI的。我不了解其他人,但程序化对我来说意味着我可以设置脚本以在时间戳上自动导入文件,而基于 UI 的纯粹是手动的。
  • @ChrisCirefice:我认为接受的答案很好地解释了这一点。他需要一些帮助,手动创建“加载数据”命令,图形程序可以提供帮助。一旦图形程序创建了“加载数据”命令,他就可以以编程方式重用它。
  • @Merrick 这对 osx 很有效
  • @ChrisCirefice 脚本非常适合重复事件;但是 GUI 更适合一次性的事情,因为您不必为了一次做一件事而弄清楚所有的秘密

标签: mysql csv load-data-infile


【解决方案1】:

您的问题的核心似乎是将 CSV 文件中的列与表中的列匹配。

许多图形化的 mySQL 客户端都为这类事情提供了非常好的导入对话框。

我最喜欢这份工作是基于 Windows 的HeidiSQL。它为您提供了一个图形界面来构建LOAD DATA 命令;您可以稍后以编程方式重复使用它。

Screenshot: "Import textfile" dialog

要打开“导入文本文件”对话框,请转到Tools > Import CSV file

【讨论】:

  • 对于 Mac OSX,请使用 Sequel Pro。
  • 我刚试过,它要求我先创建表...而不是使用列名。
  • 您必须先选择一张桌子,然后才能继续...因为重点是不必制作桌子...
  • 请注意,在 Linux 中,HeidiSQL 在 Wine 下运行良好。
  • @Paul 答案的最是 GUI 工具可以更轻松地将导入列与表列匹配。
【解决方案2】:

mysql命令行在导入时容易出现太多问题。以下是你的做法:

  • 使用 excel 编辑表头名称不带空格
  • 另存为 .csv
  • 使用免费的 Navicat Lite Sql Browser 导入并自动创建一个新表(给它一个名字)
  • 打开新表,为 ID 插入主自动编号列
  • 根据需要更改列的类型。
  • 完成!

【讨论】:

    【解决方案3】:

    使用mysqlimport 将表加载到数据库中:

    mysqlimport --ignore-lines=1 \
                --fields-terminated-by=, \
                --local -u root \
                -p Database \
                 TableName.csv
    

    我在http://chriseiffel.com/everything-linux/how-to-import-a-large-csv-file-to-mysql/找到它

    要将分隔符设为制表符,请使用--fields-terminated-by='\t'

    【讨论】:

    • mysqlimport 在幕后使用LOAD DATA INFILE...,所以几乎是一回事。
    • LOAD DATA INFILE一样,需要先创建表才能使用mysqlimport
    • @MladenJablanović,这绝对不是一回事。尝试导入 10 亿行。您会惊讶于它在性能方面的巨大差异
    • 还需要--fields-optionally-enclosed-by=\"和`--fields-escaped-by=\`
    • 应该是正确答案。谈论 CLI,就像问题在讨论,而不是 GUI。
    【解决方案4】:

    phpMyAdmin 可以处理 CSV 导入。步骤如下:

    1. 准备 CSV 文件以使字段的顺序与 MySQL 表字段的顺序相同。

    2. 从 CSV(如果有)中删除标题行,以便文件中只有数据。

    3. 进入phpMyAdmin界面。

    4. 在左侧菜单中选择表格。

    5. 点击顶部的导入按钮。

    6. 浏览到 CSV 文件。

    7. 选择“CSV using LOAD DATA”选项。

    8. 在“终止于”的字段中输入“,”。

    9. 按照与数据库表中相同的顺序输入列名。

    10. 点击开始按钮就完成了。

    这是我为将来使用而准备的笔记,如果其他人可以受益,请在此处分享。

    【讨论】:

    • 这很好也很简单。我更喜欢通过 SQL 创建表和列(因此我跳过步骤 #9)并通过导入 CSV 插入数据。不要忘记在 CSV 中为任何自动递增的字段/列设置 NULL
    • 请注意,当 CSV 文件中包含西里尔字符时,phpMyAdmin 会惨遭失败,无论您告诉它使用 utf-8。
    • 如果您要导入大型 CSV 文件,请不要忘记更改导入大小。顺便说一句,它不是大型 CSV 文件的好选择。
    • 这需要先将 .csv 文件下载到 Web 客户端,因为您无法浏览到本地 csv 文件。
    • 是的,您可以,您需要选中标记为“本地关键字”的复选框,您可以使用本地 csv 文件
    【解决方案5】:

    我已导入 200 多行的最简单方法是在 phpmyadmin sql 窗口中的命令下方

    我有一个包含两列的简单国家/地区表 CountryId,CountryName

    这里是 .csv 数据

    这里是命令:

    LOAD DATA INFILE 'c:/country.csv' 
    INTO TABLE country 
    FIELDS TERMINATED BY ',' 
    ENCLOSED BY '"'
    LINES TERMINATED BY '\n'
    IGNORE 1 ROWS
    

    记住一件事,永远不要出现在第二列,否则你的导入将停止

    【讨论】:

    • ',' -> '\t', '"' -> '' 在 TSV 文件的情况下,如果没有标题则删除最后一行。(希望搜索爬虫对此进行索引)。
    • 如果是本地文件,可能需要LOAD DATA LOCAL INFILE。如果这会引发错误 1148 "used command is not allowed",您可以通过在命令行上使用--local-infile 运行 mysql 来启用它。
    • 我得到了错误:ERROR 1045 (28000): Access denied for user 'user'@'%' (using password: YES)
    • 我收到此错误:MySQL 服务器正在使用 --secure-file-priv 选项运行,因此无法执行此语句
    • 完美答案只需使用LOAD DATA LOCAL INFILE 运行它,一切都很好
    【解决方案6】:

    如果您使用的是加载了 Excel 电子表格的 Windows 机器,那么 Excel 的新 mySql 插件非常出色。甲骨文的人在那个软件上确实做得很好。您可以直接从 Excel 建立数据库连接。该插件将分析您的数据,并以与数据一致的格式为您设置表格。我有一些巨大的 csv 数据文件要转换。这个工具可以节省大量时间。

    http://dev.mysql.com/downloads/windows/excel/

    您可以在 Excel 中进行更新,这些更新将在线填充到数据库中。这对于在超便宜的 GoDaddy 共享主机上创建的 mySql 文件非常有效。 (请注意,当您在 GoDaddy 上创建表时,您必须选择一些非标准设置才能启用数据库的异地访问...)

    使用此插件,您可以在 XL 电子表格和在线 mySql 数据存储之间实现纯交互。

    【讨论】:

      【解决方案7】:

      您可以通过列出 LOAD DATA 语句中的列来解决此问题。来自manual

      LOAD DATA INFILE 'persondata.txt' INTO TABLE persondata (col1,col2,...);
      

      ...所以在您的情况下,您需要按照它们在 csv 文件中出现的顺序列出 99 列。

      【讨论】:

        【解决方案8】:

        将csv文件导入mysql数据库的PHP查询

        $query = <<<EOF
                    LOAD DATA LOCAL INFILE '$file'
                     INTO TABLE users
                     FIELDS TERMINATED BY ','
                     LINES TERMINATED BY '\n'
                     IGNORE 1 LINES
                    (name,mobile,email)
            EOF;
        if (!$result = mysqli_query($this->db, $query))
           {
                exit(mysqli_error($this->db));
           }
        

        **CSV 文件数据示例**

        name,mobile,email
        Christopher Gritton,570-686-3439,ChristopherKGritton@inbound.plus
        Brandon Wilson,541-309-5149,BrandonMWilson@inbound.plus
        Craig White,516-795-8065,CraigJWhite@inbound.plus
        David Whitney,713-214-3966,DavidCWhitney@inbound.plus
        

        【讨论】:

          【解决方案9】:

          我知道问题很老,但我想分享这个

          我用这种方法在 0.046sec 内导入了超过 10 万条记录 (~5MB)

          这是你的做法:

          LOAD DATA LOCAL INFILE  
          'c:/temp/some-file.csv'
          INTO TABLE your_awesome_table  
          FIELDS TERMINATED BY ',' 
          ENCLOSED BY '"'
          LINES TERMINATED BY '\n'
          (field_1,field_2 , field_3);
          

          包含最后一行非常重要,如果您有多个字段,即通常它会跳过最后一个字段(MySQL 5.6.17)

          LINES TERMINATED BY '\n'
          (field_1,field_2 , field_3);
          

          然后,假设您有 第一行作为您的字段的标题,您可能还想包含这一行

          IGNORE 1 ROWS
          

          如果您的文件有标题行,这就是它的样子。

          LOAD DATA LOCAL INFILE  
          'c:/temp/some-file.csv'
          INTO TABLE your_awesome_table  
          FIELDS TERMINATED BY ',' 
          ENCLOSED BY '"'
          LINES TERMINATED BY '\n'
          IGNORE 1 ROWS
          (field_1,field_2 , field_3);
          

          【讨论】:

          • 我导入了 16k 行和 48 列。谢谢你,伙计。
          • 这是最好的解决方案。对于任何好奇这有多快的人:我在一个 20 美元/月的 AWS Lightsail 实例上在 14 秒内导入了 320 万行,并带有板载 MySQL 服务器(不是高性能 RDS)。太棒了!
          • 在这一行中,(field_1,field_2 , field_3); 是指 .csv 文件还是表格中的列列表?即,这些字段是什么?
          • @tera_789 csv 文件中可能与您的表匹配的那些
          【解决方案10】:

          这是示例 excel 文件屏幕截图:

          另存为并选择 .csv。

          如果您使用notepad++或任何其他记事本打开,您将获得如下所示的.csv数据屏幕截图。

          确保删除标题并在 .csv 中进行列对齐,就像在 mysql 表中一样。 将文件夹名称替换为您的文件夹名称

          加载数据本地INFILE
          'D:/folder_name/myfilename.csv' INTO TABLE 邮件 以“,”结尾的字段 (fname,lname,email, phone);

          如果是大数据,你可以喝咖啡然后加载!

          这就是你所需要的。

          【讨论】:

            【解决方案11】:

            更改服务器名、用户名、密码、数据库名、文件路径、表名和要插入的数据库中的字段

            <?php
                $servername = "localhost";
                $username = "root";
                $password = "";
                $dbname = "bd_dashboard";
                //For create connection
                $conn = new mysqli($servername, $username, $password, $dbname);
            
                $query = "LOAD DATA LOCAL INFILE 
                            'C:/Users/lenovo/Desktop/my_data.csv'
                            INTO TABLE test_tab
                            FIELDS TERMINATED BY ','
                            LINES TERMINATED BY '\n'
                            IGNORE 1 LINES
                            (name,mob)";
                if (!$result = mysqli_query($conn, $query)){
                    echo '<script>alert("Oops... Some Error occured.");</script>';
                    exit();
                        //exit(mysqli_error());
                   }else{
                    echo '<script>alert("Data Inserted Successfully.");</script>'
                   }
                ?>
            

            【讨论】:

              【解决方案12】:

              试试这个,它对我有用

                  LOAD DATA LOCAL INFILE 'filename.csv' INTO TABLE table_name FIELDS TERMINATED BY ',' ENCLOSED BY '"' IGNORE 1 ROWS;
              

              IGNORE 1 ROWS 忽略包含字段名的第一行。请注意,对于文件名,您必须输入文件的绝对路径。

              【讨论】:

              • 这是最好的答案。为什么要使用 另一个 工具,而单个 SQL 命令就可以了?
              • 当您尝试将文件加载到在服务器上运行的 mysql 中时,您知道如何进行这项工作吗?它要求我拒绝访问文件(密码)。 csv文件位置的密码在哪里输入?
              【解决方案13】:

              如果您使用的是 MySQL Workbench(当前为 6.3 版本),您可以通过以下方式执行此操作:

              1. 右键单击“表格”;
              2. 选择表数据导入向导;
              3. 选择您的 csv 文件并按照说明进行操作(也可以使用 JSON); 好处是您可以根据要导入的 csv 文件创建新表或将数据加载到现有表中

              【讨论】:

              • +1。我使用这个是因为 mysql 一直给我LOAD DATA INFILEmysqlimport 的错误(“这个版本的 mysql 不支持这个”)
              • 这个方法有效,但是有点慢。我原以为使用此功能会构建大量 INSERT 查询并尝试一次完成所有操作,但看起来这样做实际上每行运行一次 INSERT
              • 这个方法救了我。我在加载数据时遇到了很多错误,但需要快点。如果有读者遇到 LOAD DATA 问题,我强烈推荐。
              • 使用 Workbench 8.0.22 这个功能还很不稳定。不断崩溃,导入 0 行或只是冻结。尝试使用 Our World in Data 的 COVID-19 CSV:github.com/owid/covid-19-data/tree/master/public/data
              【解决方案14】:

              另一个解决方案是使用惊人的csvkit 套件中的csvsql 工具。

              使用示例:

              csvsql --db mysql://$user:$password@localhost/$database --insert --tables $tablename  $file
              

              此工具可以自动推断数据类型(默认行为)、创建表并将数据插入到创建的表中。 --overwrite 选项可用于删除已存在的表。 --insert 选项 — 从文件中填充表格。

              安装套件

              pip install csvkit
              

              先决条件: python-devlibmysqlclient-devMySQL-python

              apt-get install python-dev libmysqlclient-dev
              pip install MySQL-python
              

              【讨论】:

                【解决方案15】:

                【讨论】:

                  【解决方案16】:

                  我看到了一些奇怪的东西。您用于转义的字符与用于 ENCLOSING 的字符相同。因此,当引擎发现“”时,它不知道该怎么做,我认为这就是为什么似乎没有任何东西在正确的位置。 我认为如果你去掉 ESCAPING 的行,应该会运行得很好。喜欢:

                  LOAD DATA INFILE "/home/paul/clientdata.csv"
                  INTO TABLE CSVImport
                  COLUMNS TERMINATED BY ','
                  OPTIONALLY ENCLOSED BY '"'
                  LINES TERMINATED BY '\n'
                  IGNORE 1 LINES;
                  

                  除非您分析(手动、视觉、...)您的 CSV 并找出哪个字符用于转义。有时是'\'。但如果你没有它,就不要使用它。

                  【讨论】:

                    【解决方案17】:

                    我使用 mysql 工作台来做同样的工作。

                    1. 创建新架构
                    2. 打开新创建的架构
                    3. 右键单击“表格”并选择“表格数据导入向导”
                    4. 提供 csv 文件路径和表名,最后配置列类型,因为向导会根据它们的值设置默认列类型。

                    注意:使用“tail -f [mysqlworkbenchpath]/log/wb*.log”查看 mysql 工作台的日志文件是否有任何错误

                    【讨论】:

                    • 非常感谢您的回答 - 作为 MySQL 新手,我对此一无所知 - 它对我使用 CSV 有帮助。现在,我还需要从 Access 导入 10 个表 - 你认为最简单的方法是将这些表导出到 Excel,从 Excel 导出到 CSV,然后使用这些步骤吗?
                    • 我发现这个方法并没有导入所有行:(在 5,342 行中它只为我导入了 2,485 行。为什么会这样?
                    • 嘿 Naomi,如果你检查 mysqlworkbench 日志,它会告诉你为什么它停止导入数据。您的 DB 和 CSV 文件中可能有一些空值或不匹配类型。但我强烈建议遵循胡安的回答(就在我之后)。他的解决方案比我更好更干净。
                    【解决方案18】:

                    如何将csv文件导入sql表

                    示例文件:Overseas_trade_index 数据 CSV 文件

                    步骤:

                    1. 需要为overseas_trade_index创建表。

                    2. 需要创建与csv文件相关的列。

                      SQL 查询:

                      ( id int not null primary key auto_increment,
                      series_reference varchar (60),
                      period varchar (60),
                      data_value decimal(60,0),
                      status varchar (60),
                      units varchar (60),
                      magnitude int(60),
                      subject text(60),
                      group text(60),
                      series_title_1 varchar (60),
                      series_title_2 varchar (60),
                      series_title_3 varchar (60),
                      series_title_4 varchar (60),
                      series_title_5 varchar (60),
                       );
                      
                    3. 需要在终端连接mysql数据库。

                      =>show databases;
                      =>use database;
                      =>show tables;
                      
                    4. 请输入此命令将csv数据导入mysql表。

                      load data infile '/home/desktop/Documents/overseas.csv' into table trade_index fields terminated by ',' lines terminated by '\n' (series_reference,period,data_value,status,units,magnitude,subject,series_title1,series_title_2,series_title_3,series_title_4,series_title_5);
                      
                    5. 在sqldatabase上找到这个海外贸易指数数据:

                      select * from trade_index;
                      

                    【讨论】:

                      【解决方案19】:

                      我使用 phpmyadmin 以简单的方式完成了它。我按照@Farhan 的步骤操作,但所有数据都在单列​​中。 我是怎么做到的:

                      1. 创建了一个 CSV 文件并删除了带有列名的标题行。只保留数据。
                      2. 我创建了一个表,其列名与 csv 列匹配。
                      3. 记得为每一列分配适当的类型。
                      4. 我刚刚选择了导入并转到导入选项卡。
                      5. 在浏览中,我选择了 CSV 文件并保持所有选项不变。
                      6. 令我惊讶的是,所有数据都成功导入到了相应的列中。

                      【讨论】:

                        【解决方案20】:

                        我知道我的回答迟了,但我想提一些其他的方法来做到这一点。 最简单的一种是使用命令行。步骤如下:

                        1. 通过输入以下命令访问 MySQL CLI:

                        mysql -u my_user_name -p

                        1. 在数据库中创建表
                        use new_schema;
                        
                        CREATE TABLE employee_details (
                        id INTEGER,
                        employee_name VARCHAR(100),
                        employee_age INTEGER,
                        PRIMARY KEY (id)
                        );
                        
                        1. 将 CSV 文件导入表中。我们可以提及文件路径,也可以将文件存储在 MySQL 服务器的默认目录中。
                        LOAD DATA INFILE 'Path to the exported csv file'
                        INTO TABLE employee_details
                        FIELDS TERMINATED BY ','
                        IGNORE 1 ROWS;
                        

                        这是众多解决方案中唯一的一个,我在tutorial 中找到了它 如果将 CSV 文件加载到 MySQL 数据库中是您的日常任务,那么自动化这个过程会更好。在这种情况下,您可以使用一些允许您按计划加载数据的第三方工具。

                        【讨论】:

                          猜你喜欢
                          • 2012-06-20
                          • 2016-06-05
                          • 1970-01-01
                          • 1970-01-01
                          • 2012-05-15
                          • 1970-01-01
                          相关资源
                          最近更新 更多