作者:杨涛涛
资深数据库专家,专研 MySQL 十余年。擅长 MySQL、PostgreSQL、MongoDB 等开源数据库相关的备份恢复、SQL 调优、监控运维、高可用架构设计等。目前任职于爱可生,为各大运营商及银行金融企业提供 MySQL 相关技术支持、MySQL 相关课程培训等工作。
本文来源:原创投稿
*爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。
MySQL Shell 是兼容 MySQL 传统命令行客户端的超级替代版,支持 SQL 、JavaScript 、Python 三种语言环境。工具自身包含了很多组件,使得 DBA 们管理 MySQL 更加便捷高效。
今天我们来介绍 MySQL Shell 的组件:MYSQLX 组件的两个检索函数在具体使用上的一些区别。
MYSQLX 组件包含很多预置的类库, 其中与MySQL 交互最直接的就是 Session 类库。Session 类库里又包含一系列内置函数来处理数据:其中函数 run_sql 和 sql 都可以直接和 MySQL 服务端交互来运行 SQL 语句。那到底有什么区别呢? 我们接下来具体介绍这两个。(Python 环境写法:run_sql、sql;JavaScript环境下:runSQL、sql)
第一、函数run_sql 如何使用:
先连上 X 端口 33060,替代默认语言环境为 Python ,变量 c1 即为 Session 对象(Session:root@localhost:33060)。
root@ytt-pc-cheap:/home/ytt# mysqlsh mysqlx:/root@localhost:33060/ytt --py MySQL Shell 8.0.30 ... Creating an X protocol session to 'root@localhost:33060/ytt' Fetching schema names for autocompletion... Press ^C to stop. Your MySQL connection id is 9 (X protocol) Server version: 8.0.30 MySQL Community Server - GPL Default schema `ytt` accessible through db. MySQL localhost:33060+ ssl ytt Py > c1=db.get_session() MySQL localhost:33060+ ssl ytt Py > c1 <Session:root@localhost:33060>
执行 run_sql 创建表t1: run_sql 可以运行任何 MySQL 兼容的 SQL 语句。
MySQL localhost:33060+ ssl ytt Py > c1.run_sql("create table t1(id int auto_increment primary key, r1 int)") Query OK, 0 rows affected (0.0656 sec) MySQL localhost:33060+ ssl ytt Py > c1.run_sql("desc t1") +-------+------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+------+------+-----+---------+----------------+ | id | int | NO | PRI | NULL | auto_increment | | r1 | int | YES | | NULL | | +-------+------+------+-----+---------+----------------+ 2 rows in set (0.0017 sec)
插入几条样例数据:
MySQL localhost:33060+ ssl ytt Py > c1.run_sql("insert into t1(r1) values (10),(20),(30)") Query OK, 3 rows affected (0.0114 sec) Records: 3 Duplicates: 0 Warnings: 0
用 run_sql 来执行 查询语句:
MySQL localhost:33060+ ssl ytt Py > c1.run_sql("table t1") +----+----+ | id | r1 | +----+----+ | 1 | 10 | | 2 | 20 | | 3 | 30 | +----+----+ 3 rows in set (0.0008 sec)
以上都是直接运行 run_sql 函数的结果。
其实 run_sql 函数执行后会返回一个 SqlResult 对象,SqlResult 对象包含很多函数:获取语句执行时间,一次性获取一行或者多行数据,判断是否有数据等等。 既然是 SqlResult ,那就是一个结果集,不支持多次获取,类似 MySQL 的游标。
接下来把 run_sql 函数执行结果赋予一个变量 r1 ,后续操作都通过 r1 来进行:r1 被赋予 SqlResult 对象。
MySQL localhost:33060+ ssl ytt Py > r1=c1.run_sql("table t1") MySQL localhost:33060+ ssl ytt Py > r1.has_data() true MySQL localhost:33060+ ssl ytt Py > r1.get_execution_time() 0.0010 sec MySQL localhost:33060+ ssl ytt Py > r1.fetch_one() [ 1, 10 ] MySQL localhost:33060+ ssl ytt Py > r1.fetch_one() [ 2, 20 ] MySQL localhost:33060+ ssl ytt Py > r1.fetch_one() [ 3, 30 ] MySQL localhost:33060+ ssl ytt Py > r1.fetch_one() MySQL localhost:33060+ ssl ytt Py >
run_sql 函数也可以绑定变量执行:
MySQL localhost:33060+ ssl ytt Py > c1.run_sql("select * from t1 where r1 in (?,?,?)",[10,20,30]) +----+----+ | id | r1 | +----+----+ | 1 | 10 | | 2 | 20 | | 3 | 30 | +----+----+ 3 rows in set (0.0004 sec)
第二、函数 sql 如何使用:
sql 函数和 run_sql 函数不一样,它返回的不是 SqlResult 对象,而是一个 SqlExecute 对象,是 SqlResult 对象产生之前的阶段。举个例子:把 sql 函数执行结果赋予变量 r2 ,这样每调用一次 r2 ,相当于重新执行一次原请求。
MySQL localhost:33060+ ssl ytt Py > r2=c1.sql("table t1") MySQL localhost:33060+ ssl ytt Py > r2 +----+----+ | id | r1 | +----+----+ | 1 | 10 | | 2 | 20 | | 3 | 30 | +----+----+ 3 rows in set (0.0004 sec) MySQL localhost:33060+ ssl ytt Py > r2 +----+----+ | id | r1 | +----+----+ | 1 | 10 | | 2 | 20 | | 3 | 30 | +----+----+ 3 rows in set (0.0002 sec)
如果把变量 r2 的执行结果赋予变量 r3 ,那 r3 就变成一个 SqlResult 对象,只支持获取一次,又回退到 run_sql 函数的结果:
MySQL localhost:33060+ ssl ytt Py > r3=r2.execute() MySQL localhost:33060+ ssl ytt Py > r3.fetch_all() [ [ 1, 10 ], [ 2, 20 ], [ 3, 30 ] ] MySQL localhost:33060+ ssl ytt Py > r3.fetch_all() [] MySQL localhost:33060+ ssl ytt Py > r3 Empty set (0.0004 sec)
sql 函数同样支持执行绑定变量的请求: 一次绑定一个数组。
MySQL localhost:33060+ ssl ytt Py > r2=c1.sql("select * from t1 where r1 in (?,?,?)") MySQL localhost:33060+ ssl ytt Py > r2.bind([10,20,30]) +----+----+ | id | r1 | +----+----+ | 1 | 10 | | 2 | 20 | | 3 | 30 | +----+----+ 3 rows in set (0.0006 sec) MySQL localhost:33060+ ssl ytt Py > r2.bind([40,50,30]) +----+----+ | id | r1 | +----+----+ | 3 | 30 | +----+----+ 1 row in set (0.0002 sec)
结论:
对于函数 run_sql 和 sql 来讲,可以参考对象 SqlResult 和 SqlExecute 的差异来选择自己最合适的使用场景。