【问题标题】:How to export a MySQL database to JSON?如何将 MySQL 数据库导出为 JSON?
【发布时间】:2011-06-29 12:38:13
【问题描述】:

我有兴趣将 MySQL 数据库中的值子集导出到磁盘上的 JSON 格式文件中。

我找到了一个链接,讨论了一种可能的方法:http://www.thomasfrank.se/mysql_to_json.html

...但是当我使用该页面中的方法时,它似乎可以工作,但有两个问题:

1) 它只返回大约 15 个结果,最后一个被突然切断(不完整)。当我以SELECT name, email FROM students WHERE enrolled IS NULL 运行它时,我的标准查询返回大约 4000 个结果 但是当我运行它时:

SELECT 
     CONCAT("[",
          GROUP_CONCAT(
               CONCAT("{name:'",name,"'"),
               CONCAT(",email:'",email,"'}")
          )
     ,"]") 
AS json FROM students WHERE enrolled IS NULL;

... 如链接中所述,它仅返回(如我所述)15 个结果。 (fwiw,我根据我应该得到的 4000 检查了这些结果,这 15 个与 4000 的前 15 个相同)

2) 当我将INTO OUTFILE '/path/to/jsonoutput.txt' FIELDS TERMINATED BY ',' 添加到该查询的末尾时,实际文件中似乎包含“转义”字符。所以逗号最终看起来像 '\,' 显然我只想让逗号没有 \。

关于如何从 MySQL 获取正确的 JSON 输出的任何想法? (使用这种方法,还是其他方法)?

谢谢!

【问题讨论】:

  • 对于基于 shell 的解决方案,您可以使用 jo 运行查询并输出 json,或者您可以将查询输出通过管道传输到 export-mysql-to-json

标签: sql mysql json


【解决方案1】:

期望 MySQL 直接从查询中生成格式良好的 json 可能对 MySQL 提出了太多要求。相反,请考虑生成更方便的东西,例如 CSV(使用您已经知道的 INTO OUTFILE '/path/to/output.csv' FIELDS TERMINATED BY ','sn-p),然后将结果转换为具有内置支持的语言的 json,例如 python 或 php。

编辑 python示例,使用精细的SQLAlchemy:

class Student(object):
    '''The model, a plain, ol python class'''
    def __init__(self, name, email, enrolled):
        self.name = name
        self.email = email
        self.enrolled = enrolled

    def __repr__(self):
        return "<Student(%r, %r)>" % (self.name, self.email)

    def make_dict(self):
        return {'name': self.name, 'email': self.email}



import sqlalchemy
metadata = sqlalchemy.MetaData()
students_table = sqlalchemy.Table('students', metadata,
        sqlalchemy.Column('id', sqlalchemy.Integer, primary_key=True),
        sqlalchemy.Column('name', sqlalchemy.String(100)),
        sqlalchemy.Column('email', sqlalchemy.String(100)),
        sqlalchemy.Column('enrolled', sqlalchemy.Date)
    )

# connect the database.  substitute the needed values.
engine = sqlalchemy.create_engine('mysql://user:pass@host/database')

# if needed, create the table:
metadata.create_all(engine)

# map the model to the table
import sqlalchemy.orm
sqlalchemy.orm.mapper(Student, students_table)

# now you can issue queries against the database using the mapping:
non_students = engine.query(Student).filter_by(enrolled=None)

# and lets make some json out of it:
import json
non_students_dicts = ( student.make_dict() for student in non_students)
students_json = json.dumps(non_students_dicts)

【讨论】:

  • 太棒了,非常感谢!我最终在编辑之前遵循了你的建议,并且我有一个工作 python 脚本,它可以读取 CSV 并转换为 JSON,正如你所建议的那样:) 但我肯定是想检查 SQLAlchemy,所以这个编辑也是一个很大的帮助!谢谢!!!
【解决方案2】:

这是应该在应用层完成的事情。

例如,在php中它很简单

编辑添加了数据库连接的东西。无需外部任何东西。

$sql = "select ...";
$db = new PDO ( "mysql:$dbname", $user, $password) ;
$stmt = $db->prepare($sql);
$stmt->execute();
$result = $stmt->fetchAll();

file_put_contents("output.txt", json_encode($result));

【讨论】:

  • 我从来没有真正使用过 php,但这看起来很棒——我首先需要创建与数据库的连接吗?这需要外部库吗?我花了很多时间试图让 MySQLdb 为 python 工作......(最终没有工作:\)
  • +1 我认为你在fetchAll()之前也需要$stmt -&gt; execute();
  • 无法让它工作,考虑到它被宣传为“像..一样简单”我希望它可以正常工作,但它没有。也许需要更多的解释。我发现关注其他关于使用 ruby​​ 和 mysql2xxxx 的帖子要容易得多 - 这确实有效!
  • 如果更新了连接字符串,这个脚本会很棒。它不会像现在这样工作,即使它很容易修复,没有 PHP 经验的人也不知道如何使用它。我提出了修改建议。
  • 这里很危险,如果有 很多 数据被导出,这可能会爆炸,因为由于“fetchAll()”,它会先将所有数据提取到 RAM 中,然后再写入一下子出来。这里考虑一下 SQL 数据库的千兆字节顺序。
【解决方案3】:

如果你有 Ruby,你可以安装 mysql2xxxx gem(不是 mysql2json gem,它是一个不同的 gem):

$ gem install mysql2xxxx

然后运行命令

$ mysql2json --user=root --password=password --database=database_name --execute "select * from mytable" >mytable.json

gem 还提供mysql2csvmysql2xml。它不如 mysqldump 快,但也没有 mysqldump 的一些怪异之处(比如只能从与 MySQL 服务器本身相同的计算机转储 CSV)

【讨论】:

  • 在新版本中看起来 --username=root 现在是 --user=root 并且您可能需要使用 --database=somedatabase 提供数据库名称
  • mysqldump 不必在同一台服务器上运行 afaik ...除非这是特定于 CSV 输出的?
【解决方案4】:

如链接中所述,它仅返回(如我所述)15 个结果。 (fwiw,我根据我应该得到的 4000 检查了这些结果,这 15 个与 4000 的前 15 个相同)

这是因为 mysql 将 group concat 返回的数据长度限制为在@@group_concat_max_len 中设置的值,只要它达到它截断的数量并返回它到目前为止所获得的值。

您可以通过几种不同的方式设置@@group_concat_max_len。参考The mysql documentation...

【讨论】:

    【解决方案5】:

    另外,如果您在应用层导出,请不要忘记限制结果。 例如,如果您有 10M 行,则应该逐部分获取结果。

    【讨论】:

      【解决方案6】:

      如果您使用 Ruby,另一种解决方案是使用 ActiveRecord 编写与数据库的连接脚本。您需要先安装它

      gem 安装活动记录

      # ruby ./export-mysql.rb
      require 'rubygems'
      require 'active_record'
      
      ActiveRecord::Base.establish_connection(
        :adapter => "mysql",
        :database => "database_name",
        :username => "root",
        :password => "",
        :host => "localhost"
      )
      
      class Event < ActiveRecord::Base; end
      class Person < ActiveRecord::Base; end
      
      File.open("events.json", "w") { |f| f.write Event.all.to_json }
      File.open("people.json", "w") { |f| f.write Person.all.to_json }
      

      如果您想首先操作数据或包含或排除某些列,您还可以向 ActiveRecord 类添加方法。

      Person.all.to_json(:only => [ :id, :name ])
      

      使用 ActiveRecord,您不仅限于 JSON。您可以像 XML 或 YAML 一样轻松导出

      Person.all.to_xml
      Person.all.to_yaml
      

      您不仅限于 MySQL。 ActiveRecord 支持的任何数据库(Postgres、SQLite3、Oracle...等)。

      值得一提的是,您可以打开另一个数据库句柄

      require 'active_record'
      
      ActiveRecord::Base.configurations["mysql"] = {
        :adapter  => 'mysql',
        :database => 'database_name',
        :username => 'root',
        :password => '',
        :host     => 'localhost'
      }
      
      
      ActiveRecord::Base.configurations["sqlite3"] = {
        :adapter  => 'sqlite3',
        :database => 'db/development.sqlite3'
      }
      
      class PersonMySQL < ActiveRecord::Base
        establish_connection "mysql"
      end
      
      class PersonSQLite < ActiveRecord::Base
        establish_connection "sqlite3"
      end
      
      
      PersonMySQL.all.each do |person|
          PersonSQLite.create(person.attributes.except("id"))
      end
      

      这是一篇关于它的简短博客文章http://www.seanbehan.com/how-to-export-a-mysql-database-to-json-csv-and-xml-with-ruby-and-the-activerecord-gem

      【讨论】:

      • 好人!很好的解释,我喜欢连接到多个数据库的技术。
      • 在处理数百万条记录时,对象实例化会增加很多开销。
      【解决方案7】:

      您可以直接从 PHPMyAdmin 将任何 SQL 查询导出为 JSON

      【讨论】:

      • 请详细说明!我在任何地方都找不到这个选项。
      【解决方案8】:

      我知道这是旧的,但为了有人寻找答案......

      There's a JSON library for MYSQL that can be found here您需要对您的服务器具有 root 访问权限并且能够轻松安装插件(这很简单)。

      1) 将 lib_mysqludf_json.so 上传到你安装的 mysql 的 plugins 目录中

      2) 运行 lib_mysqludf_json.sql 文件(它几乎可以为您完成所有工作。如果遇到问题,只需删除以 'DROP FUNCTION...' 开头的所有内容)

      3) 将您的查询编码为:

      SELECT json_array(
               group_concat(json_object( name, email))
      FROM ....
      WHERE ...
      

      它会返回类似的东西

      [ 
         { 
           "name": "something",
           "email": "someone@somewhere.net"
          }, 
         { 
           "name": "someone",
           "email": "something@someplace.com"
          }
      
      ]
      

      【讨论】:

        【解决方案9】:

        使用以下 ruby​​ 代码

        require 'mysql2'
        
        client = Mysql2::Client.new(
          :host => 'your_host', `enter code here`
          :database => 'your_database',
          :username => 'your_username', 
          :password => 'your_password')
        table_sql = "show tables"
        tables = client.query(table_sql, :as => :array)
        
        open('_output.json', 'a') { |f|       
            tables.each do |table|
                sql = "select * from `#{table.first}`"
                res = client.query(sql, :as => :json)
                f.puts res.to_a.join(",") + "\n"
            end
        }
        

        【讨论】:

          【解决方案10】:

          另一种可能性是使用 MySQL Workbench。

          在对象浏览器上下文菜单和结果网格菜单中有一个 JSON 导出选项。

          更多关于MySQL documentation: Data export and import的信息。

          【讨论】:

            【解决方案11】:

            HeidiSQL 也允许您这样做。

            突出显示“数据”选项卡或查询结果集中的任何数据...然后右键单击并选择“导出网格行”选项。 然后,此选项允许您将任何数据导出为 JSON,直接导出到剪贴板或直接导出到文件:

            【讨论】:

            • 我喜欢这种方式。
            • 当我尝试导出一个包含 270 万行和 53 列的表时,这会失败,range check error
            【解决方案12】:

            对于任何想要使用 Python 执行此操作,并且能够在不预先定义字段名称等的情况下导出所有表的人,我前几天为此编写了一个简短的 Python 脚本,希望有人觉得它有用:

            from contextlib import closing
            from datetime import datetime
            import json
            
            import MySQLdb
            
            DB_NAME = 'x'
            DB_USER = 'y'
            DB_PASS = 'z'
            
            def get_tables(cursor):
                cursor.execute('SHOW tables')
                return [r[0] for r in cursor.fetchall()] 
            
            def get_rows_as_dicts(cursor, table):
                cursor.execute('select * from {}'.format(table))
                columns = [d[0] for d in cursor.description]
                return [dict(zip(columns, row)) for row in cursor.fetchall()]
             
            def dump_date(thing):
                if isinstance(thing, datetime):
                    return thing.isoformat()
                return str(thing)
            
            
            with closing(MySQLdb.connect(user=DB_USER, passwd=DB_PASS, db=DB_NAME)) as conn, closing(conn.cursor()) as cursor:
                dump = {}
                for table in get_tables(cursor):
                    dump[table] = get_rows_as_dicts(cursor, table)
                print(json.dumps(dump, default=dump_date, indent=2))
            

            【讨论】:

              【解决方案13】:

              这可能是一个更小众的答案,但如果您使用的是 Windows 和 MYSQL Workbench,您只需选择所需的表,然后单击结果网格中的导出/导入。这将为您提供多种格式选项,包括 .json

              【讨论】:

                【解决方案14】:

                使用 MySQL Shell,您可以只使用终端直接输出到 JSON

                echo "Your SQL query" | mysqlsh --sql --result-format=json --uri=[username]@localhost/[schema_name]
                

                【讨论】:

                • 如果您对mysqlsh 感到困惑,以及它与我们使用了十多年的mysql (cli) 命令有何不同,请注意它们是完全不同的工具。 mysql (cli) 不支持这种 JSON 格式——您必须单独安装 mysqlsh。更多信息:mysqlserverteam.com/…
                【解决方案15】:

                我找到的最简单的解决方案是将mysqljq 命令与JSON_OBJECT 查询结合使用。实际上,如果 JSON Lines 格式足够好,则不需要 jq

                从远程服务器转储到本地文件示例。

                ssh remote_server \
                    "mysql \
                        --silent \
                        --raw \
                        --host "" --port 3306 \
                        --user "" --password="" \
                        table \
                        -e \"SELECT JSON_OBJECT('key', value) FROM table\" |
                    jq --slurp --ascii-output ." \
                > dump.json
                

                books 表格示例

                +----+-------+
                | id | book  | 
                +----+-------+
                | 1  | book1 | 
                | 2  | book2 | 
                | 3  | book3 | 
                +----+-------+
                

                查询看起来像:

                SELECT JSON_OBJECT('id', id, 'book', book) FROM books;
                

                dump.json 输出

                [
                    {
                        "id": "1",
                        "book": "book1"
                    },
                    {
                        "id": "2",
                        "book": "book2"
                    },
                    {
                        "id": "3",
                        "book": "book3"
                    }
                ]
                

                【讨论】:

                  【解决方案16】:

                  如果有人在 2021 年来到这里寻找答案,这就是使用 MySql Shell 的方法。

                  https://dev.mysql.com/doc/mysql-shell/8.0/en/mysql-shell-json-output.html

                  这是一个从控制台连接和使用mysql的JS引擎,很不错但是11年前还不存在

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 2013-09-19
                    • 2018-06-20
                    • 1970-01-01
                    • 2017-09-03
                    • 2016-10-16
                    • 2014-04-08
                    • 2022-10-17
                    相关资源
                    最近更新 更多