AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 302217
Accepted
outis
outis
Asked: 2021-11-06 19:11:54 +0800 CST2021-11-06 19:11:54 +0800 CST 2021-11-06 19:11:54 +0800 CST

如何将 MySQL Shell 的 (JSON) 格式化结果保存到文件中?

  • 772

在官方 MySQL 应用程序中有点独特,MySQL Shell 提供(简单的)JSON 输出。在 MySQL shell 提示符下,键入以下内容将获得 JavaScript 对象数组的结果(每行一个):

\option resultFormat json/array
\use information_schema
SELECT table_catalog, table_schema, table_name, engine, create_time, table_collation
  FROM tables 
  WHERE table_schema='INFORMATION_SCHEMA' AND table_name LIKE 'T%';

然后将其传递给寻呼机以在屏幕上显示。如何将输出重定向或以其他方式保存到文件(例如名为 results.json)?

(注意:查询可以是任何东西。以上内容是作为一个简单但不重要的测试用例提供的,应该可以针对任何 MySQL 安装运行。)

由于 MySQL Shell 可在各种平台上使用,因此首选平台无关解决方案,但特定平台的解决方案也很受关注。

mysql mysql-shell
  • 1 1 个回答
  • 751 Views

1 个回答

  • Voted
  1. Best Answer
    outis
    2021-11-06T19:11:54+08:002021-11-06T19:11:54+08:00

    简单的解决方案

    据我所知,有两种简单的方法。一种是从非交互模式下的登录 shell 命令行,另一种是(ab)使用 MySQL Shell 的\pager命令。

    登录外壳

    登录 shell 方式是捕获任何命令输出以及mysqlsh运行查询的特定参数的方法。对于 Unix shell:

    sql="SELECT table_catalog, table_schema, table_name, engine, create_time, table_collation
        FROM tables
        WHERE table_schema='INFORMATION_SCHEMA' AND table_name LIKE 'T%';"
    mysqlsh -u user --sql --result-format=json/array --schema=INFORMATION_SCHEMA --execute "$sql" > results.json
    

    对于 PowerShell,变量设置不同(即使用sv sql "..."),但其余部分相同。

    \pager 诡计

    旧的 mysql 客户端有一个可以将输出发送到文件的tee 命令。虽然 MySQL Shell 没有类似的命令,\pager但可以设置为(登录 shell)命令,将结果输出到文件。如果您还想查看结果,请使用tee系统具有的任何命令。

    \option resultFormat json/array
    \pager tee results.json
    \use information_schema
    SELECT table_catalog, table_schema, table_name, engine, create_time, table_collation
        FROM tables
        WHERE table_schema='INFORMATION_SCHEMA' AND table_name LIKE 'T%';
    

    如果您不想看到结果,请使用不产生任何输出的登录 shell 命令,例如\pager cat >results.jsonor \pager type >results.json。

    请注意,每个查询结果都将替换前一个查询结果(有点诡计,您可能会创建一个命令来选择每次运行时都不存在的文件名)。

    另请注意,输出将在末尾包含结果摘要(“ <N>行中的集合(<时间>秒)”)。如果你不想要这个,要么从文件中删除它,要么通过一个命令在输出到文件之前将结果删除(例如grep -E -v '^[0-9]+ rows in set \([.0-9]+ sec\)$' | tee results.json,或Select -SkipLast 1 | Tee-Object results.json;参见“尾的相反:除了最后 n 行之外的所有行”更多 Unix 选项)。

    如果您想查看分页结果,您仍然可以通过寻呼机传送结果。例如:

    \pager sed '$d' | tee results.json | less
    

    复杂的解决方案

    Python

    可以交互地使用 Python,但只能使用适当定义的助手。由于此解决方案依赖于编码,因此它可能与 DBA.SE 无关,更适合 SO。但是,为此解决方案创建有关 SO 的相关问题的替代方法接近交叉发布并分裂答案,因此此处提供了解决方案。

    Result在编程模式(JS或Python)中,查询结果是ClassicResult对象。MySQL Shell 在显示它们时会对其进行格式化,但结果本身没有格式。这意味着在任何编程模式下,结果都必须在输出之前以编程方式格式化。

    Python 引擎有open,并且该json模块可用。在这两者之间,可以定义合适的函数来将结果格式化为 JSON 并将它们输出到文件中。json.JSONEncoder不支持Resultand ClassicResult,因此要么需要定义合适的 JSONEncoder,要么需要将它们转换为内置类型,任何不是内置类型的字段(例如Date列)也一样。后者可以相当简洁地完成。

    首先,领域。判断是否json可以对字段进行编码的一个简单方法是尝试它并通过将值转换为字符串来处理失败。此外,该字段将按名称从使用的行中获取get_field。

    def row_field(row, name):
        """Get a field by name from a row, converting it to a built-in type if necessary."""
        field = row.get_field(name)
        try:
            json.dump(row.get_field(name))
        except:
            field = str(field)
        return field
    

    转换为内置类型非常简单:必须获取结果,然后列表和字典推导将行数据组装成内置类型,使用上述row_field()方法来获取和转换字段。

    def nativize(results):
        """Convert SQL query results to built-in types."""
        rows = results.fetch_all()
        return [{name:row_field(row, name) for name in results.column_names} for row in rows]
    

    json.dump()将支持的对象转换为 JSON 并输出到给定的文件对象。要将所有内容联系在一起,这里有一个函数可以转换结果、打开文件并将它们传递给json.dump().

    def dump_json(results, file=None, **kwargs):
        """Dump (or return) results as JSON to a file.
        
        If no `file` is given, returns JSON results as string.
        """
        data = nativize(results)
        if file:
            fp = open(file, 'w')
            json.dump(data, fp, **kwargs)
            fp.close()
        else:
            return json.dumps(data, **kwargs)
    

    上述功能可以添加到从 8.0.17 版本开始的插件中。在您平台上的“插件”目录中,将上述函数(和一条import json语句)放入插件文件夹(例如“dump_json/init.py”)中的初始化脚本中,以及以下内容以创建扩展并添加文件输出函数(改编自示例插件):

    if 'ext' not in globals():
        ext = shell.create_extension_object()
        shell.register_global("ext", ext, {"brief":"MySQL Shell extension plugins."})
    
    try:
        shell.add_extension_object_member(ext, "dump_json", dump_json, {
            'brief': 'Writes or returns the JSON representation of results to a given file.',
            'parameters': [
                {
                    'name': 'results',
                    'type': 'object',
                    'brief': 'Query results.',
                },
                {
                    'name': 'file',
                    'type': 'string',
                    'brief': 'output pathname',
                    'required': False,
                },
            ]
        })
    except Exception as e:
        shell.log("ERROR", f'Failed to register util.dump_json: {e}.')
    

    dump_json然后可以通过extMySQL Shell 中的全局访问该函数:

    \py
    query="""SELECT table_catalog, table_schema, table_name, engine, create_time, table_collation
        FROM tables
        WHERE table_schema='INFORMATION_SCHEMA' AND table_name LIKE 'T%';
    """
    \use information_schema
    results = session.run_sql(query)
    ext.dump_json(results, 'path/to/results.json')
    

    如果使用早于 8.0.17 的版本,请改为使用辅助函数创建 Python 模块(创建扩展ext并添加dump_json到它的代码应该省略),以及import来自 MySQL shell 的模块。

    死胡同

    在交互式 shell 中,INTO OUTFILE由服务器处理,因此没有机会被 MySQL Shell 格式化。更一般地说,SQL 是在服务器端解释的,没有办法指导客户端将结果保存到文件中,因此 MySQL Shell 中的交互式 SQL 模式本身无法提供解决方案。

    JavaScript 没有访问文件的标准方式(内置的或来自库的)。MySQL JS API提供了一些自己的方法,例如通过os和util的各种文件 I/O 方法读取文本文件,但不提供通用文件输出。util在两个方面未达标:虽然它有一些文件输出方法,但它们只能转储数据库和表(不是任意查询结果)并且只能以标准转储格式转储。(不过,一种普遍感兴趣的方法是util.importJSON,它支持将 JSON 文件导入文档存储。)

    此外,JavaScript 模式似乎没有标准 JSON 对象来生成 JSON 输出。

    • 2

相关问题

  • 是否有任何 MySQL 基准测试工具?[关闭]

  • 我在哪里可以找到mysql慢日志?

  • 如何优化大型数据库的 mysqldump?

  • 什么时候是使用 MariaDB 而不是 MySQL 的合适时机,为什么?

  • 组如何跟踪数据库架构更改?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目

    • 12 个回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Jin 连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve