【问题标题】:MySQL - SELECT * INTO OUTFILE LOCAL ?MySQL-SELECT * INTO OUTFILE LOCAL?
【发布时间】:2011-02-21 11:53:24
【问题描述】:

MySQL 太棒了!我目前参与了一次主要的服务器迁移,以前,我们的小型数据库曾经与客户端托管在同一台服务器上。
所以我们曾经这样做过:SELECT * INTO OUTFILE .... LOAD DATA INFILE ....

现在,我们将数据库移至另一台服务器,SELECT * INTO OUTFILE .... 不再有效,这是可以理解的——我相信是出于安全原因。 但是,有趣的是,LOAD DATA INFILE .... 可以更改为 LOAD DATA LOCAL INFILE ....,然后 bam 就可以了。

我没有抱怨,也没有表达对 MySQL 的厌恶。替代方案添加了 2 行额外代码和一个系统调用,形成一个 .sql 脚本。我只想知道为什么LOAD DATA LOCAL INFILE 有效,为什么没有SELECT INTO OUTFILE LOCAL 这样的东西?

我做了功课,找不到上述问题的直接答案。我也找不到@ MySQL 的功能请求。如果有人能澄清这一点,那就太棒了!

MariaDB 有能力处理这个问题吗?

【问题讨论】:

  • 还有一种替代方法,它涉及使用 tee 命令,该命令允许您将 mysql 的输入和输出记录到客户端的单独文件中,但是这会记录整个 mysql 会话,而不是输出 select查询内容,并且没有格式选项,例如输出为 CSV 样式。

标签: mysql sql mariadb into-outfile


【解决方案1】:

回复:SELECT * INTO OUTFILE

检查 MySQL 是否有权限将文件写入服务器上的 OUTFILE 目录。

【讨论】:

  • OUTFILE 是写入与数据库所在服务器不同的客户端服务器。
  • MySQL 文档 (dev.mysql.com/doc/refman/5.0/en/select.html) 定义了 OUTFILE 的位置。它指出:“该文件是在服务器主机上创建的,因此您必须具有 FILE 权限才能使用此语法。file_name 不能是现有文件,这可以防止 /etc/passwd 和数据库表等文件被破坏. " 所以,我会检查 MySQL 是否有权限将文件写入服务器上的 OUTFILE 目录。我不知道为什么没有“LOCAL OUTFILE”版本。如果您需要在本地导出,许多人使用的一个选项是 phpMyAdmin。
【解决方案2】:

您提供给LOAD DATA INFILE 的路径是针对运行服务器的机器上的文件系统,而不是您连接的机器。 LOAD DATA LOCAL INFILE 用于客户端的机器,但它要求服务器以正确的设置启动,否则不允许。您可以在这里阅读所有相关信息:http://dev.mysql.com/doc/refman/5.0/en/load-data-local.html

至于SELECT INTO OUTFILE,我不确定为什么没有本地版本,除了通过连接可能很棘手。您可以通过mysqldump 工具获得相同的功能,但不能通过向服务器发送 SQL。

【讨论】:

  • LOAD DATA 工作正常,但在数据库托管的服务器上转储文件时,不可能将文件转储到不同服务器上的客户端。
  • mysqldump 和 mysql -e swtich 选项都达不到预期的结果。 mysqldump 转储整个数据库/表,我们不能根据条件只转储几列。 mysql -e swtich 将文件转储为.txt格式,无法实现管道输出。
【解决方案3】:

来自手册:The SELECT ... INTO OUTFILE 语句的主要目的是让您非常快速地将表转储到服务器计算机上的文本文件中。如果要在服务器主机以外的某个客户端主机上创建结果文件,则不能使用SELECT ... INTO OUTFILE。在这种情况下,您应该改用 mysql -e "SELECT ..." > file_name 之类的命令在客户端主机上生成文件。”

http://dev.mysql.com/doc/refman/5.0/en/select.html

一个例子:

mysql -h my.db.com -u usrname--password=pass db_name -e 'SELECT foo FROM bar' > /tmp/myfile.txt

【讨论】:

  • 如何添加分隔符?没有INTO OUTFILE 我得到一个错误
  • 分隔符是指'FIELDS TERMINATED BY',' `?如果是这样,我不确定您将如何完成,也许使用 CONCAT()?
【解决方案4】:

你可以通过传入 -s (--silent) 选项的 mysql 控制台实现你想要的。

同时传递 -r (--raw) 选项可能是个好主意,这样特殊字符就不会被转义。您可以使用它来传递您想要的查询。

mysql -u 用户名 -h 主机名 -p -s -r -e "select concat('this',' ','works')"

编辑:另外,如果您想从输出中删除列名,只需添加另一个 -s(mysql -ss -r 等)

【讨论】:

    【解决方案5】:

    按照 Waverly360 的建议,使用带有 -e 选项的 mysql CLI 是一个不错的选择,但这可能会耗尽内存并在大型结果中被杀死。 (还没有找到背后的原因)。 如果是这种情况,并且您需要所有记录,我的解决方案是:mysqldump + mysqldump2csv:

    wget https://raw.githubusercontent.com/jamesmishra/mysqldump-to-csv/master/mysqldump_to_csv.py
    mysqldump -u username -p --host=hostname database table | python mysqldump_to_csv.py > table.csv
    

    【讨论】:

      【解决方案6】:

      由于我发现自己经常寻找这个确切的问题(希望我之前错过了一些东西......),我最终决定花时间写一个small gist to export MySQL queries as CSV files,有点像https://stackoverflow.com/a/28168869,但基于PHP 以及更多选项。这对我的用例很重要,因为我需要能够微调 CSV 参数(分隔符、NULL 值处理)并且文件需要是实际有效的 CSV,因此简单的 CONCAT 是不够的,因为它如果值包含换行符或 CSV 分隔符,则不会生成有效的 CSV 文件。

      注意:需要在服务器上安装 PHP! (可通过php -v查看)

      通过“安装”mysql2csv

      wget https://gist.githubusercontent.com/paslandau/37bf787eab1b84fc7ae679d1823cf401/raw/29a48bb0a43f6750858e1ddec054d3552f3cbc45/mysql2csv -O mysql2csv -q && (sha256sum mysql2csv | cmp <(echo "b109535b29733bd596ecc8608e008732e617e97906f119c66dd7cf6ab2865a65  mysql2csv") || (echo "ERROR comparing hash, Found:" ;sha256sum mysql2csv) ) && chmod +x mysql2csv
      

      (下载 gist 的内容,检查校验和并使其可执行)

      使用示例

      ./mysql2csv --file="/tmp/result.csv" --query='SELECT 1 as foo, 2 as bar;' --user="username" --password="password"
      

      生成带有内容的文件/tmp/result.csv

      foo,bar
      1,2
      

      参考帮助

      ./mysql2csv --help
      Helper command to export data for an arbitrary mysql query into a CSV file.
      Especially helpful if the use of "SELECT ... INTO OUTFILE" is not an option, e.g.
      because the mysql server is running on a remote host.
      
      Usage example:
      ./mysql2csv --file="/tmp/result.csv" --query='SELECT 1 as foo, 2 as bar;' --user="username" --password="password"
      
      cat /tmp/result.csv
      
      Options:
              -q,--query=name [required]
                      The query string to extract data from mysql.
              -h,--host=name
                      (Default: 127.0.0.1) The hostname of the mysql server.
              -D,--database=name
                      The default database.
              -P,--port=name
                      (Default: 3306) The port of the mysql server.
              -u,--user=name
                      The username to connect to the mysql server.
              -p,--password=name
                      The password to connect to the mysql server.
              -F,--file=name
                      (Default: php://stdout) The filename to export the query result to ('php://stdout' prints to console).
              -L,--delimiter=name
                      (Default: ,) The CSV delimiter.
              -C,--enclosure=name
                      (Default: ") The CSV enclosure (that is used to enclose values that contain special characters).
              -E,--escape=name
                      (Default: \) The CSV escape character.
              -N,--null=name
                      (Default: \N) The value that is used to replace NULL values in the CSV file.
              -H,--header=name
                      (Default: 1) If '0', the resulting CSV file does not contain headers.
              --help
                      Prints the help for this command.
      

      【讨论】:

      • PHP 7 是必需的,因为第 81 行: $actualOption = $actualOptions[$option] ?? $actualOptions[$longopt] ?? $默认值;
      【解决方案7】:

      尝试将路径设置为/var/lib/mysql-files/filename.csv (MySQL 8)。通过在 mysql 客户端命令行中键入 SHOW VARIABLES LIKE "secure_file_priv"; 来确定您的文件目录。

      在此处查看答案:(...) --secure-file-priv in MySQLvhu user 于 2015 年回答

      【讨论】:

        猜你喜欢
        • 2012-02-26
        • 2010-11-05
        • 2013-03-24
        • 1970-01-01
        • 2011-02-17
        • 2020-02-24
        • 2018-07-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多