NodeJS 与第三方模块 mysql(基本操作)

news2024/11/28 5:45:32

文章目录

  • 参考
  • 描述
  • mysql 模块
  • 连接数据库
      • 检测
  • 基本操作
      • 查询
          • 数据与代码分离原则
          • 占位符
      • 插入
          • 另一种姿态
      • 修改
          • 另一种姿态
      • 删除
          • 标记删除

参考

项目描述
哔哩哔哩黑马程序员
搜索引擎Bing

描述

项目描述
NodeJSv18.13.0
nodemon2.0.20
MySQL5.7.40
mysql2.18.1

mysql 模块

npm(NodeJS Package Manager) 包管理器提供了第三方模块 mysql,该模块可用于实现 NodeJS 与 MySQL 数据库的连接。

在终端中使用如下命令开始对第三方模块 mysql 的安装:

npm install mysql

在安装该模块后,你可以在 NodeJS 中使用如下代码将该模块进行导入:

const mysql = require('mysql');

连接数据库

提醒:

在实践本示例中的代码时请确保你已经安装了 MySQL 并已经开启了 mysql 服务。

我们可以使用 mysql.createPool() 函数来创建一个与 MySQL 的连接,你需要向该函数传递一个对象,该对象描述了 MySQL 数据库管理系统的相关信息。

const mysql = require('mysql');

// 建立 NodeJS 与 MySQL 的连接
const db = mysql.createPool({
    // MySQL 所在的计算机的 IP 地址
    host: '127.0.0.1',
    // 用户名称
    user: 'root',
    // 登录密码
    password: '123456', 
    // 需要使用的数据库
    database: 'db_test',
    // MySQL 监听的端口号
    port: 3360
})

注:

  1. 提交给 mysql.createPool() 函数的对象中的 password 属性不能是数值类型。如果将属性 password 的值 ‘123456’ 中的单引号去掉,那么在正式连接数据库时(此时只是提供连接需要使用到的信息,并没有开始连接)终端将抛出如下错误信息:

TypeError [ERR_INVALID_ARG_TYPE]: The first argument must be of type string or an instance of Buffer, ArrayBuffer, or Array or an Array-like Object. Received type number (123456)

  1. 如果你需要连接的 MySQL 的位于当前计算机中,则你可以省略 host 属性;如果 MySQL 监听的端口为默认端口 3306 时,你可以将 port 属性省略。

检测

你可以在原代码的基础上添加如下代码来检测 NodeJS 与 MySQL 的连接是否成功。

// 对数据库进行查询操作
db.query('select 999', (err, result) => {
    if(err){
        console.log('{ Lose }');
        // 打印在查询过程中遇到的错误的信息
        console.log(err.message); 
    }else{
        console.log('{ Win }');
    }
})

执行该程序,如果终端输出 { Win } ,则表明数据库已经成功连接;如果终端中输出 { Lose },请检查连接 MySQL 所需要用到的相关信息是否正确。

注:

在 NodeJS 对数据库进行查询等操作时 NodeJS 将正式向 MySQL 发起连接,所以通过此法可以检查数据库是否可以正常连接。

基本操作

查询

db.query()

使用 db.query() 函数可以对数据库进行查询操作,该函数可以接收两个参数,第一个参数是对数据库进行查询操作时所需要使用的 SQL 查询语句,第二个参数则是查询操作完成后需要执行的回调函数。

你可以向回调函数提交两个参数,其中第一个参数用以接收查询操作过程中可能产生的错误对象,第二个参数用以接收查询成功后数据库返回的查询结果。

举个栗子:

先瞅瞅我的 users 表中有些什么东西:
东西

我们可以通过 NodeJS 查询该表中 id1 的数据:

const mysql = require('mysql');

// 建立 NodeJS 与 MySQL 的连接
const db = mysql.createPool({
    // MySQL 所在的计算机的 IP 地址
    host: '127.0.0.1',
    // 用户名称
    user: 'root',
    // 登录密码
    password: '123456', 
    // 需要使用的数据库
    database: 'db_test',
    // MySQL 监听的端口号
    port: 3360
})

// 对数据库进行查询操作
db.query('select * from users where id = 1', (err, result) => {
    if(err){
        console.log('{ Lose }');
        // 打印在查询过程中遇到的错误的信息
        console.log(err.message);
    }else{
        console.log(result[0]);
    }
})

执行结果:

在执行上述示例中的代码后,终端将输出如下内容:

[ RowDataPacket { id: 1, username: ‘RedHeart’, password: ‘TwoMoons’ } ]

注:

  1. 在使用 mysql 模块的 db.query() 函数数据库中的内容进行查询时将得到一个包含一个或多个对象的数组。
  2. 在上述示例中,我们在查询过程中使用了 console.log(err.message); 来打印错误信息,这有助于我们在发现错误时能够快速的解决错误。
数据与代码分离原则

在编写后端代码时,一定要注意数据与代码分离的原则。

注入攻击是 Web 安全领域中一种最为常见的攻击方式。
注入攻击的本质,是把用户输入的数据当作代码执行。这里有两个关键条件,第一个是用户能够控制输入;第二个是原本程序要执行的代码,拼接了用户的输入。


上述内容引用自吴瀚清的 《白帽子讲Web安全》

当你需要用到用户提供的数据时,一定要小心,恶意的用户会构造特定的数据对你的应用进行攻击。

占位符

为了遵循数据与代码分离的原则,避免网页被 SQL 注入 攻击,mysql 模块为我们提供了占位符这一特性。

mysql 模块中,你可以使用 ? 来代替某个数据。在使用占位符代替数据后,请不要忘记向 mysql 模块提供需要被替代的数据。
向 mysql 模块提供被代替的数据的方式依照需要被替代的数据而定,具体如下:

  1. 当被替代的数据有多个时,你可以通过向 db.query() 函数提供三个实参(其中两个实参我们前面已经见过),第二个实参需要为一个数组,数组中的内容与 SQL 语句中的占位符按从左到右的顺序一一对应。例如:
db.query('select * from users where id = ? and username = ?', [1, 'RedHeart'], (err, result) => {})
  1. 当被替代的数据仅有一个时,你可以通过你可以通过向 db.query() 函数提供三个实参(其中两个实参我们前面已经见过),第二个实参可以为一个仅包含一个元素的数组也可以为被替代的数据。例如:
db.query('select * from users where id = ?', 1, (err, result) => {})

或:

db.query('select * from users where id = ?', [1], (err, result) => {})

注:

并不是 SQL 语句中的所有内容都可以被替换,例如:

db.query('select * from users where ? = 1', 'id', (err, result) => {
    if(err){
        console.log('{ Lose }');
        // 打印在查询过程中遇到的错误的信息
        console.log(err.message);
    }else{
        console.log(result);
    }
})

终端中的输出将为(一个空数组):

[]

在使用占位符时,仅 SQL 语句中的数据部分可以被替换

插入

const mysql = require('mysql');

// 建立 NodeJS 与 MySQL 的连接
const db = mysql.createPool({
    // MySQL 所在的计算机的 IP 地址
    host: '127.0.0.1',
    // 用户名称
    user: 'root',
    // 登录密码
    password: '123456', 
    // 需要使用的数据库
    database: 'db_test',
    // MySQL 监听的端口号
    port: 3360
})

// 定义需要插入表中的数据
data = {id: 2, username: 'YJH', password: 'RedHeart'}

// 尝试将数据插入表中
db.query('insert into users values(?, ?, ?)', [data.id, data.username, data.password], (err, result) => {
    if(err){
        console.log('{ Lose }');
        // 打印在查询过程中遇到的错误的信息
        console.log(err.message);
    }else{
        console.log(result);
    }
})

执行结果:

在执行上述代码后,终端将输出如下内容:

OkPacket {
  fieldCount: 0,
  affectedRows: 1,
  insertId: 2,
  serverStatus: 2,
  warningCount: 0,
  message: '',
  protocol41: true,
  changedRows: 0
}

注:

在执行插入操作后,mysql 模块将返回一个对象。我们可以通过这个对象中的 affectedRows 来判断插入操作是否成功。affectedRows 表示该操作所影响的行数。

所以我们可以都上述代码做一些适当的修改:

db.query('insert into users values(?, ?, ?)', [data.id, data.username, data.password], (err, result) => {
    if(err){
        console.log('{ Lose }');
        // 打印在查询过程中遇到的错误的信息
        console.log(err.message);
    }else if(result.affectedRows === 1){
        console.log('{ Win }');
    }
})
另一种姿态

你可以通过向提交给 db.query() 函数的 SQL 查询语句中添加关键字 set (不区分大小写)及占位符 ? 来简化语句。

const mysql = require('mysql');

// 建立 NodeJS 与 MySQL 的连接
const db = mysql.createPool({
    // MySQL 所在的计算机的 IP 地址
    host: '127.0.0.1',
    // 用户名称
    user: 'root',
    // 登录密码
    password: '123456', 
    // 需要使用的数据库
    database: 'db_test',
    // MySQL 监听的端口号
    port: 3360
})

data = {id: 3, username: 'CYH', password: 'RedHeart'}

db.query('insert into users sEt ?', data, (err, result) => {
    if(err){
        console.log('{ Lose }');
        // 打印在查询过程中遇到的错误的信息
        console.log(err.message);
    }else if(result.affectedRows === 1){
        console.log('{ Win }');
    }
})

执行结果:

在执行上述代码后,终端将输出如下内容:

{ Win }

注:

使用上述方式对数据库进行操作需要注意一点,即提交给 db.query() 函数的第二个参数需要为一个对象且该对象中的属性的个数与表中字段的个数一样且属性名与表中的字段名一一对应。

错误示范:

db.query('insert into users sEt ?', [4, 'XJL', 'RedHeart'], (err, result) => {
    if(err){
        console.log('{ Lose }');
        // 打印在查询过程中遇到的错误的信息
        console.log(err.message);
    }else if(result.affectedRows === 1){
        console.log('{ Win }');
    }
})

上述示例中,我们传递的并不是一个对象而是一个数组。数组中的元素的个数虽能够与字段一一对应,但由于不是对象,mysql 模块将抛出错误。执行该示例代码,你将得到如下内容:

{ Lose }
ER_PARSE_ERROR: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘4’ at line 1

修改

const mysql = require('mysql');

// 建立 NodeJS 与 MySQL 的连接
const db = mysql.createPool({
    // MySQL 所在的计算机的 IP 地址
    host: '127.0.0.1',
    // 用户名称
    user: 'root',
    // 登录密码
    password: '123456', 
    // 需要使用的数据库
    database: 'db_test',
    // MySQL 监听的端口号
    port: 3360
})

db.query('update users set password = ? where id = ?', ['Other', 3], (err, result) => {
    if(err){
        console.log('{ Lose }');
        // 打印在查询过程中遇到的错误的信息
        console.log(err.message);
    }else if(result.affectedRows === 1){
        console.log('{ Win }');
        console.log(result)
    }
})

执行结果:

{ Win }
OkPacket {
  fieldCount: 0,
  affectedRows: 1,
  insertId: 0,
  serverStatus: 2,
  warningCount: 0,
  message: '(Rows matched: 1  Changed: 1  Warnings: 0',
  protocol41: true,
  changedRows: 1
}

可以看到,使用 mysql 模块对数据库进行修改操作,返回的结果仍是一个对象,我们依旧可以通过 affectedRows 来判断修改操作是否成功。

另一种姿态

与插入一样,我们可以使用 set 关键字来简化语句,但同样的,我们需要向 db.query() 函数传递一个对象作为第二个实参,且该对象中的属性需要为被修改的字段,而属性值则需要为字段修改后的结果值。

const mysql = require('mysql');

// 建立 NodeJS 与 MySQL 的连接
const db = mysql.createPool({
    // MySQL 所在的计算机的 IP 地址
    host: '127.0.0.1',
    // 用户名称
    user: 'root',
    // 登录密码
    password: '123456', 
    // 需要使用的数据库
    database: 'db_test',
    // MySQL 监听的端口号
    port: 3360
})

data = {password: 'Other'}

db.query('update users set ? where id = ?', [data, 3], (err, result) => {
    if(err){
        console.log('{ Lose }');
        // 打印在查询过程中遇到的错误的信息
        console.log(err.message);
    }else if(result.affectedRows === 1){
        console.log('{ Win }');
        console.log(result)
    }
})

执行结果:

{ Win }
OkPacket {
  fieldCount: 0,
  affectedRows: 1,
  insertId: 0,
  serverStatus: 2,
  warningCount: 0,
  message: '(Rows matched: 1  Changed: 1  Warnings: 0',
  protocol41: true,
  changedRows: 1
}

注:

在这里我们向 db.query() 的第二个参数传递了一个数组,这似乎违背了我们前面的推断,使用这种方式对表进行插入或是修改操作时,第二个参数也可以是一个数组。但这个数组中的元素需要有一个元素为对象,且这个对象在数组中的排位与 set 关键字右边第一个占位符在该语句中所有占位符的排位相对应。

删除

const mysql = require('mysql');

// 建立 NodeJS 与 MySQL 的连接
const db = mysql.createPool({
    // MySQL 所在的计算机的 IP 地址
    host: '127.0.0.1',
    // 用户名称
    user: 'root',
    // 登录密码
    password: '123456', 
    // 需要使用的数据库
    database: 'db_test',
    // MySQL 监听的端口号
    port: 3360
})

db.query('delete from users where id = ?', 3, (err, result) => {
    if(err){
        console.log('{ Lose }');
        // 打印在查询过程中遇到的错误的信息
        console.log(err.message);
    }else if(result.affectedRows === 1){
        console.log('{ Win }');
        console.log(result)
    }
})

执行结果:

{ Win }
OkPacket {
  fieldCount: 0,
  affectedRows: 1,
  insertId: 0,
  serverStatus: 2,
  warningCount: 0,
  message: '',
  protocol41: true,
  changedRows: 0
}
标记删除

使用 DELETE 语句,会把真正的把数据从表中删除掉。为了保险起见,推荐使用标记删除的形式,来模拟删除的动作。所谓的标记删除,就是在表中设置类似于 status 这样的状态字段,来标记当前这条数据是否被删除。
当用户执行了删除的动作时,我们并没有执行 DELETE 语句把数据删除掉,而是执行了 UPDATE 语句,将这条数据对应的 status 字段标记为删除即可

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/180336.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux——进程

目录 冯诺依曼体系结构 操作系统(Operator System) 概念 设计OS的目的 定位 如何理解 "管理" 总结 系统调用和库函数概念 承上启下 进程 基本概念 描述进程-PCB task_struct-PCB的一种 task_ struct内容分类 组织进程 查看进程 通过系统调用获取进程…

Pycharm使用Git进行版本控制(自建远端Git仓库)

目录本地Git安装远端Git仓库搭建在Pycharm中使用Git进行版本控制设置Git可执行文件路径创建本地Git仓库设置远端Git仓库提交及推送本地Git安装 安装本地Git用于被Pycharm调用,安装方法参考以下博客: Git 的下载与安装_作者:fengzhx0820 远端…

四轮两驱小车(四):STM32驱动5路灰度传感器PID循迹

目录 前言: 小车效果展示: 5路数字灰度传感器: 巡线思路: 加入PID调节的代码: 前言: 之前买了一批5路灰度传感器,想用这传感器进行循迹,无奈网上和官方的资料提供的还是比较少&a…

ARM X210 官方 uboot 配置编译实践

一、X210官方uboot配置编译实践1 1. 找到官方移植好的 uboot(BSP 概念) (1) 源头的源代码是 uboot 官网下载的。这个下载的源代码可能没有你当前使用的开发板的移植,甚至找不到当前开发板使用的 SoC 对应的移植版本。 (2) SoC 厂商在推出一…

分享145个ASP源码,总有一款适合您

ASP源码 分享145个ASP源码,总有一款适合您 下面是文件的名字,我放了一些图片,文章里不是所有的图主要是放不下..., 145个ASP源码下载链接:https://pan.baidu.com/s/1gxm3rFFLu8pUhVncQga6-g?pwd7n85 提取码&#x…

HJ56、HJ58、JZ4、JZ6、JZ15、JZ17几道题

文章目录HJ56 完全数计算题目描述:具体实现:HJ58 输入n个整数,输出其中最小的k个题目描述:具体实现:JZ4 二维数组中的查找题目描述:具体实现:JZ6 从尾到头打印链表题目描述:具体实现…

springboot文件上传,单文件上传和多文件上传,以及数据遍历和回显

springboot文件上传&#xff0c;单文件上传和多文件上传项目结构及pom.xml创建文件表单页面编写javabean编写controller映射MultipartFile类RequestPart注解controller代码application.properties中的文件上传配置遍历数据显示页面运行显示项目结构及pom.xml pom.xml: <dep…

SQL用法详解补充

本文是对上次“SQL用法详解”的一些补充&#xff0c;一些基本操作可以点击链接查看 目录 一.对表结构的常用操作 查看表结构格式 修改表结构格式 1.修改列名和类型 2.修改添加列 3.修改表删除列 4.修改表名 5.数据删除 二.总结 三.实例 解决 完整代码 一.对表结构的常用操…

TIA博途中启用或禁用DP从站或PROFINET IO设备的具体方法

TIA博途中启用或禁用DP从站或PROFINET IO设备的具体方法 在实际项目中我们会遇到这样的问题, 例如:硬件组态中配置了一个控制器和3个 PN IO设备,但是最后只用到了2个PN IO设备,这样控制器一侧无法连接到第3个PN IO设备时,CPU会产生报警,PLC的Error指示灯会一直闪烁。 那么…

蓝桥杯2021省赛Python

蓝桥杯2021省赛Python 不得不说2021的比2020的难 1.卡片 很明显&#xff0c;最先没的肯定是1或者0&#xff0c;我们只要统计到谁会消耗2022个1或者0就好了 if __name__ __main__:res1 0res0 0for i in range(1,100000):i str(i)res1 i.count(1)res0 i.count(0)if res1…

[Rust笔记] 规则宏的“卫生保健”

规则宏代码的“卫生保健”规则宏mbe即是由macro_rules!宏所定义的宏。它的英文全称是Macro By Example。相比近乎“徒手攀岩”的Cpp模板元编程&#xff0c;rustc提供了有限的编译时宏代码检查功能&#xff08;名曰&#xff1a;Mixed Hygiene宏的混合保健&#xff09;。因为rust…

pointcovn 阅读笔记

各种点云采样算法 https://blog.csdn.net/weixin_41485242/article/details/107150963 Inverse Density 1.2 Inverse Density Importance Sampling (IDIS): 这个也比较好理解&#xff0c;简而言之就是根据每个点的密度来对其重新进行排序&#xff0c;尽可能地保留密度比较低的地…

python第九章 异常笔记

和Java类似程序运行有异常的时候&#xff0c;服务器会采用系统默认的异常处理机制&#xff1a;返回信息&#xff0c;终止程序。异常的类型&#xff1a;常见异常类型&#xff1a;1.NameError&#xff1a;访问了未定义的变量2.IndexError&#xff1a;越界访问3.AttributeError&am…

网络原理-网络发展史和通信基础

目录 1.网络发展史 面向终端的计算机网络 计算机网络阶段(局域网LAN) 组网方式 计算机网络互联阶段(广域网WAN) 2.通信基础 IP地址 端口号 网络协议 协议的作用 知名协议的默认端口 协议分层 分层的作用 OSI七层模型 TCP/IP五层模型 网络设备所在分层 网络分层…

《数据结构》八大排序和拓展的排序(详细教学并提供多种版本、动态图分析)

今天&#xff0c;我将带来数据结构的排序算法&#xff0c;排序算法作为校招中常考知识点之一&#xff0c;我们必须要熟练的掌握它,对自己提出高要求&#xff0c;才能有高回报。 目录排序的概念和应用内部排序和外部排序排序算法需要掌握的知识插入排序1.直接插入排序2.希尔排序…

【教程】Python实时检测CPU和GPU的功耗

目录 前言 GPU功耗检测方法 CPU功耗检测方法 sudo的困扰与解决 完整功耗分析示例代码 转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhang.cn] 前言 相关一些检测工具挺多的&#xff0c;比如powertop、powerstat、s-tui等。但如何通过代码的方式来实时检测&#xf…

Unsafe Fileupload-基础篇(文件上传绕过技巧与upload-labs靶场)

数据来源 本文仅用于信息安全的学习&#xff0c;请遵守相关法律法规&#xff0c;严禁用于非法途径。若观众因此作出任何危害网络安全的行为&#xff0c;后果自负&#xff0c;与本人无关。 文件上传基础 01 什么是文件上传 02 文件上传产生漏洞的原因 03 文件上传漏洞危害 0…

济人药业更新招股书:计划在A股上市,中成药业务收入持续下滑

近日&#xff0c;安徽济人药业股份有限公司&#xff08;下称“济人药业”&#xff09;递交预披露更新招股书&#xff0c;准备在上海证券交易所主板上市。据贝多财经了解&#xff0c;济人药业于2022年7月1日递交上市申请&#xff0c;此次更新了截至2022年6月30日的财务数据等信息…

Android深入系统完全讲解(42)

红色部分 pc 000007cc 代表当前 pc 指向的位置。libnative-lib.so 代表在哪个库里面。于是我 们就需要知道&#xff0c;libnative-lib.so 库的 pc 000007cc 偏移位置&#xff0c;是个什么代码。 我们从 NDK 开发包中找到 D:\android-ndk-r19c\toolchains\arm-linux-androideabi…

远程控制软件

远程控制软件1. 概述2. TeamViewer3. Todesk4. 向日葵5. AnyDesk6. Splashtop结束语1. 概述 出门在外或者工作时突然需要访问家中的电脑拿取文件或者资料时&#xff0c;是直接跑回家拿去、还是委托家里人员帮忙呢&#xff1f; 这时候你就需要一类软件来完成这个任务了&#xf…