重学Node.js及其框架(Express, Koa, egg.js) 之 MySQL及Nodejs中使用MySQL

756 阅读17分钟

数据库的下载和安装自行google。

总结自 Coderwhy的nodejs课程。

终端连接数据库

我们如果想要操作数据,需要先和数据建立一个连接,最直接的方式就是通过终端来连接;

两种方式的区别在于输入密码是直接输入,还是另起一行以密文的形式输入;

  • mysql -uroot -p密码
  • mysql -uroot -p。敲回车,然后输入密码。

MySQL默认的数据库

  • infomation_schema:信息数据库,其中包括MySQL在维护的其他数据库、表、列、访问权限等信息;
  • performance_schema:性能数据库,记录着MySQL Server数据库引擎在运行过程中的一些资源消耗相关的信息;
  • mysql:用于存储数据库管理者的用户信息、权限信息以及一些日志信息等;
  • sys:相当于是一个简易版的performance_schema,将性能数据库中的数据汇总成更容易理解的形式;

GUI工具选择

我建议选择navicat premium。因为。。。他收费,如果想免费,自己找资源吧。 下载地址www.navicat.com/en/products…

认识SQL语句

我们希望操作数据库(特别是在程序中),就需要有和数据库沟通的语言,这个语言就是SQL:

  • SQL是Structured Query Language,称之为结构化查询语言,简称SQL;
  • 使用SQL编写出来的语句,就称之为SQL语句;
  • SQL语句可以用于对数据库进行操作; 事实上,常见的关系型数据库SQL语句都是比较相似的,所以你学会了MySQL中的SQL语句,之后去操作比如Oracle或者其他关系型数据库,也是非常方便的。

SQL语句的常用规范:

  • 通常关键字是大写的,比如CREATE、TABLE、SHOW等等;
  • 一条语句结束后,需要以;结尾
  • 如果遇到关键字作为表名或者字段名称,可以使用``包裹;

SQL语句的分类

  • DDL(Data Definition Language):数据定义语言。可以通过DDL语句对数据库或者表进行:创建、删除、修改等操作;
  • DML(Data Manipulation Language):数据操作语言。可以通过DML语句对进行:添加、删除、修改等操作;
  • DQL(Data Query Language):数据查询语言。可以通过DQL从数据库中查询记录;(重点)
  • DCL(Data Control Language):数据控制语言。对数据库、表格的权限进行相关访问控制操作;

SQL的数据类型

我们知道不同的数据会划分为不同的数据类型,在数据库中也是一样。

MySQL支持的数据类型有:数字类型,日期和时间类型,字符串(字符和字节)类型,空间类型和 JSON数据类型

  • 数字类型
    • 整数数字类型:INTEGER,INT,SMALLINT,TINYINT,MEDIUMINT,BIGINT。
    • 浮点数字类型:FLOAT,DOUBLE(FLOAT是4个字节,DOUBLE是8个字节)。
    • 精确数字类型:DECIMAL,NUMERIC(DECIMAL是NUMERIC的实现形式)。DECIMAL()方法可传入两个参数,参数一表示多少个数字,参数二表示多少个小数。
  • 日期类型
    • YEAR类型 以YYYY格式显示值。支持的范围 1901到2155,和 0000。
    • DATE类型 用于具有日期部分但没有时间部分的值, 格式为式YYYY-MM-DD。支持的范围是 '1000-01-01' 到 '9999-12-31';
    • DATETIME类型 用于包含日期和时间部分的值, 格式为YYYY-MM-DD hh:mm:ss。支持的范围是'1000-01-01 00:00:00' 到 '9999-12-31 23:59:59';
    • TIMESTAMP数据类型被用于同时包含日期和时间部分的值, 格式为YYYY-MM-DD hh:mm:ss。的范围是UTC的时间范围:'1970-01-01 00:00:01' 到 '2038-01-19 03:14:07'; 另外:DATETIME或TIMESTAMP 值可以包括在高达微秒(6位)精度的后小数秒一部分。DATETIME表示的范围可以是'1000-01-01 00:00:00.000000'到'9999-12-31 23:59:59.999999'
  • 字符串类型
    • CHAR类型在创建表时为固定长度,长度可以是0到255之间的任何值。在被查询时,会删除后面的空格。
    • VARCHAR类型的值是可变长度的字符串,长度可以指定为0到65535之间的值。在被查询时,不会删除后面的空格。
    • BINARY和VARBINARY 类型用于存储二进制字符串,存储的是字节字符串。
    • BLOB用于存储大的二进制类型。
    • TEXT用于存储大的字符串类型。如果varchar依旧不能存储,那么将会使用TEXT类型。

表约束

PRIMARY KEY(主键) 一张表中,我们为了区分每一条记录的唯一性,必须有一个字段是永远不会重复,并且不会为空的,这个字段我们通常会将它设置为主键。

  • 主键是表中唯一的索引。
  • 并且必须是NOT NULL的,如果没有设置 NOT NULL,那么MySQL也会隐式的设置为NOT NULL。
  • 主键也可以是多列索引,PRIMARY KEY(key_part, ...),我们一般称之为联合主键。
  • 建议:开发中主键字段应该是和业务无关的,尽量不要使用业务字段来作为主键。 UNIQUE(唯一) 某些字段在开发中我们希望是唯一的,不会重复的,比如手机号码、身份证号码等,这个字段我们可以使用UNIQUE来约束。
  • 使用UNIQUE约束的字段在表中必须是不同的;
  • 对于所有引擎,UNIQUE 索引允许NULL包含的列具有多个值NULL。就是同一个字段的记录可以同为null。 NOT NULL(不能为空) 某些字段我们要求用户必须插入值,不可以为空,这个时候我们可以使用 NOT NULL 来约束。

DEFAULT(默认值) 某些字段我们希望在没有设置值时给予一个默认值,这个时候我们可以使用 DEFAULT来完成。

AUTO_INCREMENT(自动递增) 某些字段我们希望不设置值时可以进行递增,比如用户的id,这个时候可以使用AUTO_INCREMENT来完成。

FOREIGN KEY (表内字段) REFERENCES 外表(外表的主键) (外键), 某些字段希望引用到其他表的字段来作为值。即将两个表联系起来。

数据库的操作

通过DDL语句对数据库进行操作

  • 查看所有的数据
    SHOW DATABASES;
  • 使用某一个数据
    USE 数据库名;
  • 查看当前正在使用的数据库
    SELECT DATABASE();
  • 创建数据库
    CREATE DATABASE IF NOT EXISTS `数据库名称`
    DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci; // 这些都是数据库的默认编码。utf8mb4_0900_ai_ci这个表示数据库中数据的排序规则。表示不区分轻重音和大小写。
  • 删除数据库
    DROP DATABASE IF EXIT `数据库名`;
  • 修改数据库
    # 修改数据库的字符集和排序规则
    ALTER DATABASE `数据库名` CHARACTER SET = utf8 COLLATE = utf8_unicode_ci;

数据表的操作

通过DDL语句对表进行操作

  • 查看所有的数据表
    SHOW TABLES;
  • 查看某一个表结构
    DESC `表名`;
  • 创建表 一般设置表的时候有时间字段,我们都会给时间字段设置DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP默认值。在我们插入数据的时候,自动添加当前时间给这个字段。
    CREATE TABLE IF NOT EXISTS `表名`(
        # 字段 类型 约束条件
        id INT PRIMARY KEY AUTO_INCREMENT,
        name VARCHAR(20) NOT NULL,
        age INT DEFAULT 0,
        telPhone VARCHAR(20) DEFAULT '' UNIQUE NOT NULL
    );
  • 删除表
    DROP TABLE IF EXISTS `表名`;
  • 修改表 对表结构,字段等做修改。不修改数据内容。
    # 1.修改表名
    ALTER TABLE `原表名` RENAME TO `修改表名`;
    # 2.添加一个新的列
    ALTER TABLE `表名` ADD `字段` 字段类型;
    ALTER TABLE `moment` ADD `updateTime` DATETIME;
    # 3.删除一列数据
    ALTER TABLE `表名` DROP `字段`;
    # 4.修改列的名称
    ALTER TABLE `表名` CHANGE `原字段` `修改字段` 修改后的字段类型;
    # 5.修改列的数据类型
    ALTER TABLE `表名` MODIFY `字段` 字段类型;
    # 6.根据表结构创建另外一张表(不会复制数据)
    CREATE TABLE IF NOT EXISTS `表名` LIKE `参照表名`
    # 7.根据表结构创建另外一张表(并且复制数据)
    CREATE TABLE IF NOT EXISTS `表名` AS (SELECT * FROM `参照表名`);

通过DML语句对表进行操作, 比如插入数据,删除数据,修改数据

  • 向表中插入数据
    #按表中字段的顺序插入数据
    INSERT INTO `表名` VALUES (对应的字段插入的值);
    #指定字段插入数据
    INSERT INTO `表名` (若干字段) VALUES (对应的字段插入的值);
    
    INSERT INTO `products` (`title`, `description`, `price`, `publishTime`) 
    VALUES ('iPhone', 'iPhone12只要998', 998.88, '2020-10-10');
  • 删除表中的数据
    # 会删除表中所有的数据
    DELETE FROM `表名`;
    # 会删除符合条件的数据
    DELETE FROM `表名` WHERE 条件;
    DELETE FROM `products` WHERE `title` = 'iPhone';
  • 修改表中的数据 修改数据内容。
    # 会修改表中所有的数据
    UPDATE `表名` SET 修改内容;
    UPDATE `products` SET `title` = 'iPhone12', `price` = 1299.88;
    # 会修改符合条件的数据
    UPDATE `表名` SET 修改内容 WHERE 条件;
    UPDATE `products` SET `title` = 'iPhone12', `price` = 1299.88 
    WHERE `title` = 'iPhone';

对数据库的查询操作

通过DMQL语句对表进行操作, 查询符合条件的数据。

主要就是通过SELECT用于从一个或者多个表中检索选中的行。

查询格式

    SELECT select_expr [, select_expr]...
    [FROM table_references]
    [WHERE where_condition]
    [ORDER BY expr [ASC | DESC]]
    [LIMIT {[offset,] row_count | row_count OFFSET offset}]
    [GROUP BY expr]
    [HAVING where_condition]

WHERE基本条件查询

逻辑查询

and, &&。 或or, ||。 之间between and 这个也会包括两头的结果。In关键字是取代多个或查询的。

    # 查询品牌是华为,并且小于2000元的手机
    SELECT * FROM `products` WHERE `brand` = '华为' and `price` < 2000;
    SELECT * FROM `products` WHERE `brand` = '华为' && `price` < 2000;

    # 查询10002000的手机(不包含10002000SELECT * FROM `products` WHERE price > 1000 and price < 2000;

    # OR: 符合一个条件即可
    # 查询所有的华为手机或者价格小于1000的手机
    SELECT * FROM `products` WHERE brand = '华为' or price < 1000;

    # 查询10002000的手机(包含10002000SELECT * FROM `products` WHERE price BETWEEN 1000 and 2000;

    # 查看多个结果中的一个
    SELECT * FROM `products` WHERE brand IN ('华为', '小米');
    -- 等价于
    SELECT * FROM `products` WHERE brand = '华为' || brand = '小米';

空值查询

  • IS NULL
  • IS NOT NULL
    SELECT * FROM `products` WHERE name IS NULL;
    SELECT * FROM `products` WHERE name IS NOT NULL;

模糊查询

模糊查询使用LIKE关键字,结合两个特殊的符号:

  • % 表示匹配任意个的任意字符。
  • _ 表示匹配一个的任意字符。
    # 查询所有以v开头的title
    SELECT * FROM `products` WHERE title LIKE 'v%';

    # 查询带M的title
    SELECT * FROM `products` WHERE title LIKE '%M%';

    # 查询带M的title必须是第三个字符
    SELECT * FROM `products` WHERE title LIKE '__M%';

对查询结果排序

ORDER BY有两个常用的值:

  • ASC:升序排列。默认
  • DESC:降序排列。
    SELECT * FROM `products` WHERE brand = '华为' or price < 1000 
    ORDER BY price ASC;

可以添加多个排序。作为辅排序。当主排序相同的时候,我们就可以通过辅排序来进行排序。

    SELECT * FROM `products` WHERE brand = '华为' or price < 1000 
    ORDER BY price ASC, score DESC;

分页查询

当数据库中的数据非常多时,一次性查询到所有的结果进行显示是不太现实的,在真实开发中,我们都会要求用户传入offset、limit或者page等字段。它们的目的是让我们可以在数据库中进行分页查询;

它的用法有[LIMIT {[offset,] row_count | row_count OFFSET offset}]

    SELECT * FROM `products` LIMIT 30 OFFSET 0;
    SELECT * FROM `products` LIMIT 30 OFFSET 30;
    SELECT * FROM `products` LIMIT 30 OFFSET 60;
    
    # 另外一种写法:offset, row_count
    SELECT * FROM `products` LIMIT 90, 30;

分组查询

我们通过GROUP BY来创建分组。通常结合聚合函数使用。

在我们没有分组之前,使用聚合函数,它将整个表看成一个组。即聚合函数相当于默认将所有的数据分成了一组。

我们先对数据进行分组,再对每一组数据,进行聚合函数的计算。并且我们可以通过HAVING来对分组进行约束。注意:WHERE不能在GROUP BY后面使用,我们只能通过HAVING来对分组进行约束。他表示在分完组后进行条件筛选。

    SELECT brand,
    COUNT(*) as count,
    ROUND(AVG(price),2) as avgPrice,
    MAX(price) as maxPrice,
    MIN(price) as minPrice,
    AVG(score) as avgScore
    FROM `products` GROUP BY brand
    HAVING avgPrice < 4000 and avgScore > 7;

常用的聚合函数

注意:COUNT(*)COUNT(字段)的区别。前面是统计该表中有多少记录。或者统计的是非空记录的个数。而且后者还可以通过DISTICT来约束相同记录只记做一次。即COUNT(DISTINCT 字段)

    # 华为手机价格的平均值
    SELECT AVG(price) FROM `products` WHERE brand = '华为';

    # 计算所有手机的平均分
    SELECT AVG(score) FROM `products`;

    # 手机中最低和最高分数
    SELECT MAX(score) FROM `products`;
    SELECT MIN(score) FROM `products`;

    # 计算总投票人数
    SELECT SUM(voteCnt) FROM `products`;

    # 计算所有条目的数量
    SELECT COUNT(*) FROM `products`;

    # 华为手机的个数
    SELECT COUNT(*) FROM `products` WHERE brand = '华为';

多张表

如果我们想要两张表存在联系。我们就需要在一张表中给联系字段设置外键。

现在假设我们有一张products和一张brand表。将两张表联系起来,我们可以将products中的brand_id关联到brand中的id。

    ALTER TABLE `products` ADD FOREIGN KEY (brand_id) REFERENCES brand(id);

我们如何让两个表有关的字段做到联动呢?

当我们更新或者删除外键时,可以设置几个值:

  • RESTRICT(默认属性):当更新或删除某个记录时,会检查该记录是否有关联的外键记录,有的话会报错的,不允许更新或删除;

image.png

  • NO ACTION:和RESTRICT是一致的,是在SQL标准中定义的;
  • CASCADE:当更新或删除某个记录时,会检查该记录是否有关联的外键记录,有的话:
    • 更新:那么会更新对应的记录;
    • 删除:那么关联的记录会被一起删除掉;

image.png

image.png

  • SET NULL:当更新或删除某个记录时,会检查该记录是否有关联的外键记录,有的话,将对应的值设置为NULL;

image.png 注 意:当我们使用外键,并且将类型设置为cascade时,我们删除外表数据,那么将会将内表对应数据也删除。但是删除内表数据,将不会影响外表。

尽量不要使用cascade类型,但是对于一些特殊操作,使用cascade类型很方便。 假如我们删除评论数据,想要恢复的数据也删除,就可以设置cascade类型了。方便操作。

如何通过代码修改外键类型呢?

    -- 查看表结构,找到外键名称
    SHOW CREATE TABLE `表名`;
    
    -- 删除之前的外键,根据外键名称
    ALTER TABLE `表名` DROP FOREIGN KEY 外键名称;
    
    -- 添加新的外键
    ALTER TABLE `表名` ADD FOREIGN KEY (引用的外键字段)
    REFERENCES 外键表(外键字段)
    ON UPDATE 更新时的外键类型 ON DELETE 删除时的外键类型;
    
    
    
    -- 查看表结构,找到外键名称
    SHOW CREATE TABLE `products`;
    -- 删除之前的外键
    ALTER TABLE `products` DROP FOREIGN KEY products_ibfk_1;
    -- 添加新的外键
    ALTER TABLE `products` ADD FOREIGN KEY (brand_id)
    REFERENCES brand(id)
    ON UPDATE CASCADE ON DELETE CASCADE;
    

多表之间的连接查询

如果我们希望查询到产品的同时,显示对应的品牌相关的信息,因为数据是存放在两张表中,所以这个时候就需要进行多表查询。

我们可以使用 SQL JOIN 操作: 左连接 右连接 内连接 全连接 image.png 以下查询的sql语句案例。我们假设有products(id, brand, title, price, score, voteCnt, url, pid, brand_id(外键字段))brand(id(外键引用字段), name, website, phoneRank)两个表

左连接 如果我们希望获取到的是左边所有的数据(以左表为主): image.png

这个时候就表示无论左边的表是否有对应的brand_id的值对应右边表的id,左边的数据都会被查询出来,这个也是开发中使用最多的情况,它的完整写法是LEFT [OUTER] JOIN,但是OUTER可以省略的;

    SELECT * FROM `products` LEFT JOIN `brand` ON `products`.brand_id = `brand`.id;

    SELECT * FROM `products` LEFT JOIN `brand` ON `products`.brand_id= `brand`.id
    WHERE brand.id IS NULL;

右连接 如果我们希望获取到的是右边所有的数据(以由表为主):

image.png 这个时候就表示无论左边的表中的brand_id是否有和右边表中的id对应,右边的数据都会被查询出来,右连接在开发中没有左连接常用,它的完整写法是RIGHT [OUTER] JOIN,但是OUTER可以省略的。

    SELECT * FROM `products` RIGHT JOIN `brand` ON `products`.brand_id = `brand`.id;
    
    SELECT * FROM `products` RIGHT JOIN `brand` ON `products`.brand_id= `brand`.id
    WHERE products.id IS NULL;

内连接 事实上内连接是表示左边的表和右边的表都有对应的数据关联:

image.png 内连接在开发中偶尔也会常见使用,看自己的场景。内连接有其他的写法:CROSS JOIN, INNER JOIN, JOIN都可以。

    SELECT * FROM `products` INNER JOIN `brand` ON `products`.brand_id = `brand`.id;

我们会发现它和之前的下面写法是一样的效果:

    SELECT * FROM `products`, `brand` WHERE `products`.brand_id = `brand`.id;

但是他们代表的含义并不相同:

  • 内连接,代表的是在两张表连接时就会约束数据之间的关系,来决定之后查询的结果。
  • where条件,代表的是先计算出笛卡尔乘积,在笛卡尔乘积的数据基础之上进行where条件的筛选。 全连接 SQL规范中全连接是使用FULL JOIN,但是MySQL中并没有对它的支持,我们需要使用 UNION 来实现:

image.png

(SELECT * FROM `products` LEFT JOIN `brand` ON `products`.brand_id = `brand`.id)
UNION
(SELECT * FROM `products` RIGHT JOIN `brand` ON `products`.brand_id = `brand`.id);

(SELECT * FROM `products` LEFT JOIN `brand` ON `products`.brand_id = `brand`.id 
WHERE `brand`.id IS NULL)
UNION
(SELECT * FROM `products` RIGHT JOIN `brand` ON `products`.brand_id = `brand`.id 
WHERE `products`.id IS NULL);

如何将我们查询到多表字段的数据转化成对象或者数组呢?

我们需要用到JSON_OBJECT(key, value, [...])JSON_ARRAY()方法来将一个表中的字段转化成一个对象或者一个数组。但是如果想把转为的多个对象再放在数组中,我们就需要用到JSON_ARRAYAGG()方法。 一对多

    SELECT products.id as id, 
    products.title as title, 
    products.price as price, 
    products.score as score,
    JSON_OBJECT(
        'id', brand.id, 
        'name', brand.name, 
        'rank', brand.phoneRank, 
        'website', brand.website
    ) as brand
    FROM products LEFT JOIN brand ON products.brand_id = brand.id;

image.png 多对多

    SELECT stu.id, stu.name, stu.age,
    JSON_ARRAYAGG(JSON_OBJECT('id', cs.id, 'name', cs.name)) as courses
    FROM students stu
    LEFT JOIN students_select_courses ssc ON stu.id = ssc.student_id
    LEFT JOIN courses cs ON ssc.course_id= cs.id
    GROUP BY stu.id;

image.png 从上面的查询可以看出,我们如果想要合并通记录的数据,可以使用分组。而且分组后,如果字段是唯一的,那么多可以获取,而不只是只能获取分组字段。

多对多关系查询

如果我们想把两个表建立联系,我们就需要建立一个中间表。这个关系表来记录两张表中的数据关系。然后就是通过多表连接查询语法,来进行查询了。

以下查询的sql语句案例。我们假设有students(id(外键), name, age), courses(id(外键), name, price), 关系表students_select_cources(id, student_id(引用外键字段), course_id(引用外键字段))三个表。 这个关系表用来记录学生id和课程id的对应关系,来确定学生的选课情况。

查询多条数据

    # 查询所有的学生选择的所有课程
    SELECT
    stu.id studentId, stu.name studentName, cs.id
    courseId, cs.name
    courseName, cs.price
    coursePrice
    FROM `students` stu
    JOIN `students_select_courses` ssc
    ON stu.id = ssc.student_id
    JOIN `courses` cs
    ON ssc.course_id = cs.id;


    # 查询所有的学生选课情况
    SELECT
    stu.id studentId, stu.name studentName, cs.id
    courseId, cs.name
    courseName, cs.price
    coursePrice
    FROM `students` stu
    LEFT JOIN `students_select_courses` ssc
    ON stu.id = ssc.student_id
    LEFT JOIN `courses` cs
    ON ssc.course_id = cs.id;

查询单挑数据

    # why同学选择了哪些课程
    SELECT
    stu.id studentId, stu.name studentName, cs.id courseId, cs.name courseName, cs.price
    coursePrice
    FROM `students` stu
    JOIN `students_select_courses` ssc
    ON stu.id = ssc.student_id
    JOIN `courses` cs
    ON ssc.course_id = cs.id
    WHERE stu.id = 1;

    # lily同学选择了哪些课程(注意,这里必须用左连接,事实上上面也应该使用的是左连接)
    SELECT
    stu.id studentId, stu.name studentName, cs.id courseId, cs.name courseName, cs.price
    coursePrice
    FROM `students` stu
    LEFT JOIN `students_select_courses` ssc
    ON stu.id = ssc.student_id
    LEFT JOIN `courses` cs
    ON ssc.course_id = cs.id
    WHERE stu.id = 5;

Nodejs中使用MySQL

如何可以在Node的代码中执行SQL语句来,这里我们可以借助于两个库:

  • mysql:最早的Node连接MySQL的数据库驱动。

  • mysql2:在mysql的基础之上,进行了很多的优化、改进。 目前相对来说,我更偏向于使用mysql2,mysql2兼容mysql的API,并且提供了一些附加功能更快/更好的性能。

  • Prepared Statement(预编译语句):

    • 提高性能:将创建的语句模块发送给MySQL,然后MySQL编译(解析、优化、转换)语句模块,并且存储它但是不执行,之后我们在真正执行时会给?提供实际的参数才会执行;就算多次执行,也只会编译一次,所以性能是更高的;
    • 防止SQL注入:之后传入的值不会像模块引擎那样就编译,那么一些SQL注入的内容不会被执行;or 1 = 1不会被执行;
  • 支持Promise,所以我们可以使用async和await语法。

基本使用

通过调用createConnection()并传入对应数据库连接信息,它将返回一个连接对象。然后通过query执行sql语句。

    const mysql = require('mysql2');

    // 1.创建数据库连接
    const connection = mysql.createConnection({
      host: 'localhost',
      port: 3306,
      database: '数据库名',
      user: 'root',
      password: '数据库密码'
    });

    // 2.执行SQL语句
    const statement = `
      SELECT * FROM products WHERE price > 6000;
    `
    connection.query(statement, (err, results, fields) => {
      console.log(results);
    });

通过预处理语句使用

通过?来占位。然后通过execute传入占位的参数,并执行sql语句。

强调:如果再次执行该语句,它将会从LRU(Least Recently Used) Cache中获取获取,省略了编译statement的时间来提高性能。

    const mysql = require('mysql2');

    // 1.创建数据库连接
        const connection = mysql.createConnection({
          host: 'localhost',
          port: 3306,
          database: '数据库名',
          user: 'root',
          password: '数据库密码'
        });

    // 2.执行SQL语句
    const statement = `
      SELECT * FROM products WHERE price > ? AND score > ?;
    `
    // 参数:sql语句, 传入的参数[], 执行的回调函数
    connection.execute(statement, [6000, 7], (err, results) => {
      console.log(results);
    });

连接池的使用

前面我们是创建了一个连接(connection),但是如果我们有多个请求的话,该连接很有可能正在被占用,那么我们是否需要每次一个请求都去创建一个新的连接呢?

事实上,mysql2给我们提供了连接池(connection pools);

连接池可以在需要的时候自动创建连接,并且创建的连接不会被销毁,会放到连接池中,后续可以继续使用; 我们可以在创建连接池的时候设置LIMIT,也就是最大创建个数;

    const mysql = require('mysql2');

    // 1.创建连接池
    const connections = mysql.createPool({
      host: 'localhost',
      port: 3306,
      database: '数据库名',
      user: 'root',
      password: '数据库密码'
      // 最大连接数
      connectionLimit: 10
    });

    // 2.使用连接池
    const statement = `
      SELECT * FROM products WHERE price > ? AND score > ?;
    `
    connections.execute(statement, [6000, 7], (err, results) => {
      console.log(results);
    });

promise的使用方式

就是连接对象调用promise()方法。

    const mysql = require('mysql2');

    // 1.创建连接池
    const connections = mysql.createPool({
      host: 'localhost',
      port: 3306,
      database: '数据库名',
      user: 'root',
      password: '数据库密码'
      // 最大连接数
      connectionLimit: 10
    });

    // 2.使用连接池
    const statement = `
      SELECT * FROM products WHERE price > ? AND score > ?;
    `
    connections.promise().execute(statement, [6000, 7]).then(([results]) => {
      console.log(results);
    }).catch(err => {
      console.log(err);
    });