当前位置: 首页>后端>正文

nodejs全栈入门开发教程

前言

1、nodej是什么?what

2、为什么用? why

3、怎么用?how

一、Nodejs介绍和特色

1、nodejs是什么?

Node.js 不是一门语言,而是一个开发平台(有对应的语言和实现特定功能的api),是一个用C++开发的 ,事件驱动 I/O 服务端 JavaScript 环境,是一个基于 Chrome V8 引擎的 JavaScript 运行环境,V8 引擎执行 Javascript 的速度非常快,性能非常好,

用于方便地搭建响应速度快、易于扩展的网络应用,它有非阻塞、事件驱动模型的特性,有轻量高效的特点,适用于分布式设备上运行数据密集型的实时应用

Node.js是一个用C++开发的 、服务器端、单阻塞式I/O、事件驱动模型、基于 Chrome V8 引擎的 JaveScript运行环境( 即Javascript 语言解释器)

2、安装配置

2.1、node下载地址

https://nodejs.org/en/download/

LTS版本:长期支持版,即稳定版(建议) Current版本:最新版 安装node后在cmd下运行node -v即可查看安装的node.js版本
nodejs全栈入门开发教程,第1张
node版本png

如果安装成功却提示node不是内部或者外部的命令。则需要手动配置环境变量

2.2、配置环境变量

为什么要配置环境变量:一般情况下,cmd环境想要运行一个文件,例如node.exe,那么对应的路径下必须有node.exe这个文件才能启动,否则就会提示命令不存在。 配置环境变量就是告诉电脑,如果我们输入的命令在当前路径下没有对应的执行文件,那么就去其他路径下查看,配置环境变量也就是添加一个可供查找的绝对路径 如何配置环境变量: 右键计算机>属性>系统高级设置>高级>环境变量

nodejs全栈入门开发教程,第2张
环境变量png

选择Path这个变量名,对应的变量值是有若干的路径组成的每个路径用";"隔开,添加时也记得加 分号 ,这里node.js安装是已经自动添加了环境变量,所以里面已经有node.js的路径了,如果没有,就要手动添加

2.3、node的版本管理工具(nvm)

1.安装nvm(Node Version Manager )
nodejs全栈入门开发教程,第3张
nvm安装版png

2.常用命令:cmd窗口输入命令

  • nvm v:显示nvm版本,如果有则表示安装成功。
  • nvm list: 列出已经安装的node.js版本
  • nvm uninstall 版本号:卸载指定版本的nodejs。
  • nvm install latest:安装最新版node.js
  • nvm install 版本号:安装指定的node.js版本
  • nvm ues 版本号:使用指定的node.js版本

2.4、自动重启服务器(node-dev/nodemon/supervisor)

2.4.1、node-dev

1、node-dev是一个node.js开发工具,当文件被修改时,它会自动重新启动node进程

// 全局安装
npm install -g node-dev
// 运行服务
node-dev index.js

2、Node-dev 可以当有js文件修改后自动去重启nodejs进程, 这样就不用每次ctrl+c 终止在重启了,而且不仅支持js文件, .json .node .coffee 文件格式都支持

2.4.2、nodemon

1、 Nodemon是一个使用工具,它将会见监视源文件中任何的更改并自动重启服务器

// 全局安装
npm install -g nodemon
// 运行服务
nodemon index.js

2、实际项目中可在package.json中配置

{
  "name": "nodejs",
  "version": "1.0.0",
  "description": "nodejs测试",
  "main": "index.js",
  "dependencies": {},
  "devDependencies": {},
  "scripts": {
    "start": "nodemon index.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}
2.4.3、npm

1、npm是Node Package Manage的缩写,意思是node的包管理系统

  • NPM提供了很多命令,例如installpublish,使用npm help可查看所有命令。
  • 使用npm help <command>可查看某条命令的详细帮助,例如npm help install
  • package.json所在目录下使用npm install . -g可先在本地安装当前命令行程序,可用于发布前的本地测试。
  • 使用npm update <package>可以把当前目录下node_modules子目录里边的对应模块更新至最新版本。
  • 使用npm update <package> -g可以把全局安装的对应命令行程序更新至最新版。
  • 使用npm cache clear可以清空NPM本地缓存,用于对付使用相同版本号发布新版本代码的人。
  • 使用npm unpublish <package>@<version>可以撤销发布自己发布过的某个版本代码。

2、使用淘宝镜像

// 使用淘宝镜像
npm install -g cnpm --registry=https://registry.npmmirror.com
// 使用cnpm 命令来安装模块
cnpm install [name]

3、yarn

3、Nodejs三大特色

故事背景:

高级餐厅(传统服务器语言):(给每一个用户分配一个服务员(多个服务员,多线程)—>用户看菜单->等待I/O操作->要点的菜告诉服务员-> I/O 操作结束后线程继续执行->看菜单,服务员闲置到你点完( I/O 操作结束) -->阻塞式 I/O

小餐馆(nodejs):所有用户共享一个服务员(一个服务员,单线程)-->用户看菜单(等待I/O操作)-->您先看着菜单,点好了叫我(回调函数)-->顾客点完后会主动叫服务员(执行回调函数)

3.1. 单线程

3.1.1、和其他后台语言不一样,Node.js 不会为每一个客户建立一个新的线程。而仅仅使用一个线程。当有用户链接了,就会出发一个内部事件,经过非阻塞I/O、事件驱动机制,让Node.js程序在宏观上也是并行的。

服务器单线程带来的好处,操作系统彻底再也不用有线程建立、销毁的时间开销。

3.1.2、相对于php、java后端语言的多线程,nodej采用异步单线程优势

节约服务器内存(线程越多占用的内存越多) 节约上下文切换的时间(由于多线程实现原理是通过切换时间片来实现的 所以线程越多 需要切换的次数就越多 耗费的时间越长) 不存在锁的问题 (java通常会通过给进程加锁来解决多个线程访问同一资源的问题 而单线程就不存在这个问题)

固然它的优点也是它的劣势,一个用户形成了线程的崩溃,整个服务也会崩溃。

3.1.3、浏览器线程(了解)

JS引擎线程 .GUI渲染线程(和JS引擎线程互斥 两者只有一者正在执行 不会同时进行) 事件触发线程 定时器触发线程 异步http请求线程

3.2. 非阻塞 I/O(no-blocking I/O)

3.2.1、正常来讲,I/O 阻塞了代码的执行,极大地下降了程序的执行效率。因为 Node.js 采用了非阻塞 I/O 机制,在执行了访问数据库的代码以后,将当即转而执行其后面的代码,把数据库返回的处理代码放到回调函数中,从而提升了程序的执行效率

3.2.2 理解非阻塞和同步异步

同步和异步起决于被调用者 阻塞和非阻塞起决于调用者

阻塞是按顺序执行的,而非阻塞是不需要按顺序的

3.3. 事件驱动(event-driven)

在 Node 中,客户端请求创建链接,提交数据等行为,会触发相应的事件,在一个时刻,只能执行一个事件回调函数,可是在执行一个事件回调的中途,能够转而处理其余事件,而后继续执行原事件的回调函数,这种处理机制,称为“事件环”机制。

Node.js 使用事件驱动模型,当web server接收到请求,就把它关闭然后进行处理,然后去服务下一个web请求。当这个请求完成,它被放回处理队列,当到达队列开头,这个结果被返回给用户。这个模型非常高效可扩展性非常强,因为 webserver 一直接受请求而不等待任何读写操作。(这也称之为非阻塞式IO或者事件驱动IO)在事件驱动模型中,会生成一个主循环来监听事件,当检测到事件时触发回调函数。
[图片上传失败...(image-64461e-1678162204288)]

整个事件驱动的流程就是这么实现的,非常简洁。有点类似于观察者模式,事件相当于一个主题(Subject),而所有注册到这个事件上的处理函数相当于观察者

Node.js 有多个内置的事件,我们可以通过引入 events 模块,并通过实例化 EventEmitter 类来绑定和监听事件,如下实例:

[图片上传失败...(image-effb9d-1678159779170)]

Node.js中所有的I/O都是异步的,回调函数,套回调函数

4、为什么要用Nodejs,优势

  1. 它是一个Javascript运行环境(简单容易上手)

  2. 依赖于Chrome V8引擎进行代码解释(号称世界上最快的解释器)

  3. 事件驱动(高并发处理速度优势)

  4. 非阻塞I/O(创建新的线程去执行,不会阻塞主线程。动作并行执行,速度更快)--->适合I/O密集型应用

  5. 轻量、可伸缩,适于实时数据交互应用(由高并发特性决定)

  6. 单进程,单线程(不会占用大量的内存)

  7. 处理高并发场景性能更佳

  8. node 最大的优势就是性能强,同样的服务器性能使用 node 可以比传统的服务器语言多容纳一百倍的用户(对于不同的任务有不同的差别, I/O 操作越多,node优势越明显)(每个线程2M,理论8g内存,就是4000用户,nodejs就是4万)

5、Nodejs劣势

1、不适合CPU密集型应用;CPU密集型应用给Node带来的挑战主要是:由于JavaScript单线程的原因,如果有长时间运行的计算(比如大循环),将会导致CPU时间片不能释放,使得后续I/O无法发起; 解决方案:分解大型运算任务为多个小任务,使得运算能够适时释放,不阻塞I/O调用的发起;

2、只支持单核CPU,不能充分利用CPU;

3、可靠性低,一旦代码某个环节崩溃,整个系统都崩溃 原因:单进程,单线程 解决方案: (1)Nnigx反向代理,负载均衡,开多个进程,绑定多个端口; (2)开多个进程监听同一个端口,使用cluster模块;

4、开源组件库质量参差不齐,更新快,向下不兼容

5、Debug不方便,错误没有stack trace

总结:nodejs本就是极客追求性能极致的产物,缺少了很多服务器的健壮性考量,所以不适用于银行、证券、电信等需要极高可靠性的业务中

6、应用场景

nodeJs 善于I/O,不善于计算,因为nodejs最擅长的就是任务调度,如果你的业务有巨量的CPU计算(同步代码),实际上也相当于这个计算阻塞了整个线程,即巨量的计算不适合NodeJS开发。 当应用程序需要处理大量高并发的I/O,而在向客户端发出响应之前,应用程序内部并不需要复杂的处理的时候,NodeJs非常适合。 适合与 web socket 配合,开发长连接的实时交互应用程序。

  1. RESTful API

这是NodeJS最理想的应用场景,可以处理数万条连接,本身没有太多的逻辑,只需要请求API,组织数据进行返回即可。它本质上只是从某个数据库中查找一些值并将它们组成一个响应。由于响应是少量文本,入站请求也是少量的文本,因此流量不高,一台机器甚至也可以处理最繁忙的公司的API需求。

  1. 统一Web应用的UI层

目前MVC的架构,在某种意义上来说,Web开发有两个UI层,一个是在浏览器里面我们最终看到的,另一个在server端,负责生成和拼接页面。

不讨论这种架构是好是坏,但是有另外一种实践,面向服务的架构,更好的做前后端的依赖分离。如果所有的关键业务逻辑都封装成REST调用,就意味着在上层只需要考虑如何用这些REST接口构建具体的应用。那些后端程序员们根本不操心具体数据是如何从一个页面传递到另一个页面的,他们也不用管用户数据更新是通过Ajax异步获取的还是通过刷新页面。

  1. 大量Ajax请求的应用

例如个性化应用,每个用户看到的页面都不一样,缓存失效,需要在页面加载的时候发起Ajax请求,NodeJS能响应大量的并发请求。  总而言之,NodeJS适合运用在高并发、I/O密集、少量业务逻辑的场景。

4、具体场景可以表现为如下:

  1. Web服务 API 如:REST
  2. 基于web、canvas等多人联网游戏
  3. 后端的web服务,如:跨域、服务器端的请求;
  4. 基于web的多人实时聊天客户端、聊天室、图文直播
  5. 高并发量的web应用程序 如:用户表单收集系统、实时交互系统、考试系统、联网软件
  6. 单页面浏览器应用程序

二、Nodejs

1、 REPL(交互式解释器)

Node.js REPL(Read Eval Print Loop:交互式解释器) 表示一个电脑的环境,类似 Windows 系统的终端或 Unix/Linux shell,我们可以在终端中输入命令,并接收系统的响应

//启动 Node 的终端
node
  • ctrl + c - 退出当前终端。
  • ctrl + c 按下两次 - 退出 Node REPL。
  • ctrl + d - 退出 Node REPL.
  • 向上/向下 键 - 查看输入的历史命令
  • tab 键 - 列出当前命令
  • .help - 列出使用命令
  • .break - 退出多行表达式
  • .clear - 退出多行表达式
  • .save filename - 保存当前的 Node REPL 会话到指定文件
  • .load filename - 载入当前 Node REPL 会话的文件内容。

2、Node.js 全局对象

2.1、有唯一的全局对象 global 2.2、process = global.process process也是Node.js提供的一个对象,它代表当前Node.js进程

2.3、判断JavaScript执行环境

if (typeof(window) === 'undefined') {
    console.log('node.js');
} else {
    console.log('browser');
}

3、事件循环

ode.js 使用事件驱动模型,当web server接收到请求,就把它关闭然后进行处理,然后去服务下一个web请求。

当这个请求完成,它被放回处理队列,当到达队列开头,这个结果被返回给用户。

这个模型非常高效可扩展性非常强,因为 webserver 一直接受请求而不等待任何读写操作。(这也称之为非阻塞式IO或者事件驱动IO)

在事件驱动模型中,会生成一个主循环来监听事件,当检测到事件时触发回调函数

// 引入 events 模块
var events = require('events');
// 创建 eventEmitter 对象
var eventEmitter = new events.EventEmitter();

// 创建事件处理程序
var connectHandler = function connected() {
   console.log('连接成功。');

   // 触发 data_received 事件 
   eventEmitter.emit('data_received');
}

// 绑定 connection 事件处理程序
eventEmitter.on('connection', connectHandler);

// 使用匿名函数绑定 data_received 事件
eventEmitter.on('data_received', function(){
   console.log('数据接收成功。');
});

// 触发 connection 事件 
eventEmitter.emit('connection');

console.log("程序执行完毕。");

大多数时候我们不会直接使用 EventEmitter,而是在对象中继承它。包括 fs、net、 http 在内的,只要是支持事件响应的核心模块都是 EventEmitter 的子类

4、模块(ES6 模块、CommonJS 模块)

1、语法上面,CommonJS 模块使用require()加载和module.exports输出,ES6 模块使用importexport

// package.json 文件中,指定type 字段
{
   "type": "module"
}

.mjs文件总是以 ES6 模块加载,.cjs文件总是以 CommonJS 模块加载,.js文件的加载取决于package.json里面type字段的设置

4、fs

Node.js内置的fs模块就是文件系统模块,负责读写文件。

和所有其它JavaScript模块不同的是,fs模块同时提供了异步和同步的方法

// 异步读取文件
'use strict';
var fs = require('fs');
fs.readFile('sample.txt', 'utf-8', function (err, data) {
    if (err) {
        console.log(err);
    } else {
        console.log(data);
    }
});

// 同步读取文件
'use strict';
var fs = require('fs');
var data = fs.readFileSync('sample.txt', 'utf-8');
console.log(data)

5、Stream(流)

stream是Node.js提供的又一个仅在服务区端可用的模块,目的是支持“流”这种数据结构

Node.js,Stream 有四种流类型:

  • Readable - 可读操作。
  • Writable - 可写操作。
  • Duplex - 可读可写操作.
  • Transform - 操作被写入数据,然后读出结果。

所有的 Stream 对象都是 EventEmitter 的实例。常用的事件有:

  • data - 当有数据可读时触发。

  • end - 没有更多的数据可读时触发。

  • error - 在接收和写入过程中发生错误时触发。

  • finish - 所有数据已被写入到底层系统时触发。

    文件流读取文本内容的示例

'use strict';

var fs = require('fs');

// 打开一个流:
var rs = fs.createReadStream('sample.txt', 'utf-8');

rs.on('data', function (chunk) {
    console.log('DATA:')
    console.log(chunk);
});

rs.on('end', function () {
    console.log('END');
});

rs.on('error', function (err) {
    console.log('ERROR: ' + err);
});

6、http模块

request对象封装了HTTP请求,我们调用request对象的属性和方法就可以拿到所有HTTP请求的信息;

response对象封装了HTTP响应,我们操作response对象的方法,就可以把HTTP响应返回给浏览器。

'use strict';

// 导入http模块:
var http = require('http');

// 创建http server,并传入回调函数:
var server = http.createServer(function (request, response) {
    // 回调函数接收request和response对象,
    // 获得HTTP请求的method和url:
    console.log(request.method + ': ' + request.url);
    // 将HTTP响应200写入response, 同时设置Content-Type: text/html:
    response.writeHead(200, {'Content-Type': 'text/html'});
    // 将HTTP响应的HTML内容写入response:
    response.end('<h1>Hello world!</h1>');
});

// 让服务器监听8080端口:
server.listen(8080);

console.log('Server is running at http://127.0.0.1:8080/');

7、crypto

crypto模块的目的是为了提供通用的加密和哈希算法

7.1MD5

MD5是一种常用的哈希算法,用于给任意数据一个“签名”。这个签名通常用一个十六进制的字符串表示:

const crypto = require('crypto');

const hash = crypto.createHash('md5');

// 可任意多次调用update():
hash.update('Hello, world!');
hash.update('Hello, nodejs!');

console.log(hash.digest('hex')); // 7e1977739c748beac0c0fd14fd26a544

7.2、其他加密算法

Hmac算法也是一种哈希算法,它可以利用MD5或SHA1等哈希算法。不同的是,Hmac还需要一个密钥,Hmac理解为用随机数“增强”的哈希算法

AES是一种常用的对称加密算法,加解密都用同一个密钥

DH算法是一种密钥交换协议,它可以让双方在不泄漏密钥的情况下协商出一个密钥来

RSA算法是一种非对称加密算法,即由一个私钥和一个公钥构成的密钥对,通过私钥加密,公钥解密,或者通过公钥加密,私钥解密。其中,公钥可以公开,私钥必须保密。

8、路由(url)

我们要为路由提供请求的 URL 和其他需要的 GET 及 POST 参数,随后路由需要根据这些数据来执行相应的代码

https://www.runoob.com/nodejs/nodejs-router.html

9、GET/POST请求

https://www.runoob.com/nodejs/node-js-get-post.html

9、nodejs连接 MySQL

9.1、安装mysql

cnpm install mysql

连接数据库,并执行查询语句

var mysql  = require('mysql');  

var connection = mysql.createConnection({     
  host     : 'localhost',       
  user     : 'root',              
  password : '123456',       
  port: '3306',                   
  database: 'test' 
}); 

connection.connect();

var  sql = 'SELECT * FROM websites';
//查
connection.query(sql,function (err, result) {
        if(err){
          console.log('[SELECT ERROR] - ',err.message);
          return;
        }

       console.log('--------------------------SELECT----------------------------');
       console.log(result);
       console.log('------------------------------------------------------------\n\n');  
});

connection.end();

9.2、connection.query查询方式

第一个参数是一个SQL语句,可以是任意的数据库语句,而第二个参数是一个回调函数,查询结果通过回调参数的方式返回。

connection.query('select * from book where author = "xyf" and country = "china"',function(err, result) {
    console.log(result);
    }
);

第二种 占位符注入查询

第二种查询方式是采用了占位符的形式connection.query(sqlString, values, callback) ,这样就不需要进行恶心的字符串的拼接了。

connection.query('select * from book where author = and country = ?',
['xyf', 'china'],function(err, result) {
    console.log(result);

    }
);

第三种 使用对象查询方式

第三种查询方式我们将查询语句和查询值组合成一个对象来进行查询。它的形式是这样的:connection.query(object, callback)

connection.query(
    {
    sql:'select * from book where author = and country = ?',

    values: ['xyf', 'china'], //作为对象的属性

    timeout: 40000,},function(err, result) { console.log(result);}
);

10、REST

REST就是一种设计API的模式,最常用的数据格式是JSON

1、REST即表述性状态传递(英文:Representational State Transfer,简称REST)是Roy Fielding博士在2000年他的博士论文中提出来的一种软件架构风格

2、HTTP 方法

以下为 REST 基本架构的四个方法:

  • GET - 用于获取数据。
  • PUT - 用于更新或添加数据。
  • DELETE - 用于删除数据。
  • POST - 用于添加数据。

拓展内容

1、Express(提供了最简单而强大的方式来创建 Web 服务器。它的极简主义方法、没有偏见、专注于服务器的核心功能,是其成功的关键)

2、Koa2(Koa 是一个新的 web 框架,由 Express 幕后的原班人马打造, 致力于成为 web 应用和 API 开发领域中的一个更小、更富有表现力、更健壮的基石)

3、Egg.js(使用 Node.js 和 Koa 构建更好的企业级框架和应用程序的框架)

4、NestJs(基于 TypeScript 的渐进式 Node.js 框架,用于构建企业级的高效、可靠和可扩展的服务器端应用程序)

5、Socket.io (构建网络应用的实时通信引擎)

6、js模板引擎(EJS、Nunjucks)

7、MySql (关系型数据库管理系统)/ MongoDB(非关系型数据库)

7.1、数据库CRUD

# 插入数据
INSERT INTO table_name ( field1, field2,...fieldN )
                       VALUES
                       ( value1, value2,...valueN )
# 查询数据
SELECT column_name,column_name
FROM table_name
[WHERE Clause]
[LIMIT N][ OFFSET M]

# 修改数据
UPDATE table_name SET field1=new-value1, field2=new-value2
[WHERE Clause]

# 删除数据
DELETE FROM table_name [WHERE Clause]

# 多表查询
# tcount_tbl
mysql> SELECT * FROM tcount_tbl;
+---------------+--------------+
| runoob_author | runoob_count |
+---------------+--------------+
| 菜鸟教程  | 10           |
| RUNOOB.COM    | 20           |
| Google        | 22           |
+---------------+--------------+
# runoob_tbl
mysql> SELECT * from runoob_tbl;
+-----------+---------------+---------------+-----------------+
| runoob_id | runoob_title  | runoob_author | submission_date |
+-----------+---------------+---------------+-----------------+
| 1         | 学习 PHP    | 菜鸟教程  | 2017-04-12      |
| 2         | 学习 MySQL  | 菜鸟教程  | 2017-04-12      |
| 3         | 学习 Java   | RUNOOB.COM    | 2015-05-01      |
| 4         | 学习 Python | RUNOOB.COM    | 2016-03-06      |
| 5         | 学习 C      | FK            | 2017-04-05      |
+-----------+---------------+---------------+-----------------+

INNER JOIN(内连接,或等值连接):获取两个表中字段匹配关系的记录。 INNER JOIN  中 INNER可以省略
mysql> SELECT a.runoob_id, a.runoob_author, b.runoob_count FROM runoob_tbl a INNER JOIN tcount_tbl b ON a.runoob_author = b.runoob_author;
+-------------+-----------------+----------------+
| a.runoob_id | a.runoob_author | b.runoob_count |
+-------------+-----------------+----------------+
| 1           | 菜鸟教程    | 10             |
| 2           | 菜鸟教程    | 10             |
| 3           | RUNOOB.COM      | 20             |
| 4           | RUNOOB.COM      | 20             |
+-------------+-----------------+----------------+

LEFT JOIN(左连接):获取左表所有记录,即使右表没有对应匹配的记录。
mysql> SELECT a.runoob_id, a.runoob_author, b.runoob_count FROM runoob_tbl a LEFT JOIN tcount_tbl b ON a.runoob_author = b.runoob_author;
+-------------+-----------------+----------------+
| a.runoob_id | a.runoob_author | b.runoob_count |
+-------------+-----------------+----------------+
| 1           | 菜鸟教程    | 10             |
| 2           | 菜鸟教程    | 10             |
| 3           | RUNOOB.COM      | 20             |
| 4           | RUNOOB.COM      | 20             |
| 5           | FK              | NULL           |
+-------------+-----------------+----------------+
RIGHT JOIN(右连接): 与 LEFT JOIN 相反,用于获取右表所有记录,即使左表没有对应匹配的记录

mysql> SELECT a.runoob_id, a.runoob_author, b.runoob_count FROM runoob_tbl a RIGHT JOIN tcount_tbl b ON a.runoob_author = b.runoob_author;
+-------------+-----------------+----------------+
| a.runoob_id | a.runoob_author | b.runoob_count |
+-------------+-----------------+----------------+
| 1           | 菜鸟教程    | 10             |
| 2           | 菜鸟教程    | 10             |
| 3           | RUNOOB.COM      | 20             |
| 4           | RUNOOB.COM      | 20             |
| NULL        | NULL            | 22             |
+-------------+-----------------+----------------+

# 子查询(相关子查询和非相关子查询)
嵌套在其他查询中的查询即子查询,子查询也叫内部查询,子查询总是从内向外处理。
SELECT * FROM tab1 WHERE size IN (
    SELECT size FROM tab2
)
相关子查询:指查询结果依赖于外部查询的子查询,外部查询每执行一次,内部子查询也会执行一次
非相关子查询:指独立于外部查询的子查询,内部子查询仅执行一次,执行完毕后将查询结果作为外部查询的条件使用
不依赖与外部的查询
非相关子查询一般可以分为:
    返回单值的子查询
    返回一个列表的子查询

# MySQL中数据的基本查询方式

1.查询所有列

  select * from 表名称;

2.查询指定列

  select 字段名,字段名,字段名 from 表名称;

3.查询时添加常量列(临时备注)

  select 字段名,字段名,字段名,字段名 as 备注 from 表名称;

4.查询时合并列(合并列只能合并数值类型的字段)

  select 字段名,(字段名+字段名) from 表名称;

5.查询时去除重复记录

  select distinct 字段名 from 表名称;

6.条件查询(where)

  (1)逻辑条件:and(并)  or(或)

  select * from 表名称 where 字段名=值 and 字段名=值;

  select * from 表名称 where 字段名=值 or 字段名=值;

  (2)比较条件:>  <  >=  <=  =  <>(不等于)  between and(等价于>=且<=)

  (3)判空条件(null空字符串):is null  /  is not null  /  =  '  '  /<>  '  '

  null:表示没有值   /   空字符串:有值,但是值是空字符串

  判断null

  select * from 表名称 where 字段名 is null;

  判断空字符串

  select * from 表名称 where 字段名='  ';

  判断null和空字符串

  select * from 表名称 where 字段名 is null or 字段名='  ';

  查询不包括null和空字符串的字段

  select * from 表名称 where 字段名 is not null and 字段名<> '  ';

  (4)模糊条件:like

  通常用一下替换标记:

  %:表示任意个字符

  _:表示一个字符

  select * from 表名称 where 字段名 like '部分值%';

7.聚合查询(使用聚合函数的查询)

  常用的聚合函数:sum()求和   avg()求平均值   max()求最大值   min()求最小值   count()计数

  用法:select 聚合函数(字段名) from 表名称;

  注意:count()函数统计的数量不包含null的数据,使用count统计表的记录数,要使用不包含null值的字段。

8. 分页查询(limit起始行,查询几行)

  起始行从0开始

  分页:当前页  每页显示多少条

  分页查询当前页的数据的sql:select * from 表名称 limit(当前页-1) 每页显示多少条,每页显示多少条;

例如:查询第1,2条记录(第一页的数据)

  select * from 表名称 limit 0,2;(当前页-1再乘以2,显示几条数据)

  查询第3,4条记录(第二页的数据)

  select * from 表名称 limit 2,2;

  查询第5,6条记录(第三页的数据)

  select * from 表名称 limit 4,2;

  查询第7,8条记录

  select * from 表名称 limit 6,2; 

9. 查询排序(order by)

  语法:order by 字段 asc/desc

  asc:顺序,正序。数值:递增,字母:自然顺序(a-z)

  desc:倒序,反序。数值:递减,字母:自然反序(z-a)

  默认情况下,按照插入记录顺序排序

  select * from 表名称 order by 字段名 asc/desc;

  注意:多个排序条件

  select * from 表名称 order by 字段名 asc,字段名 desc;

10. 分组查询(group by)

  select 字段名(同一个) from 表名称 group by 字段名(同一个);

11. 分组查询后筛选

  注意:分组之前条件使用where关键字,分组之后条件使用having关键字,如分组后找出大于或者小于n的字段

  select 字段名,count(*) from 表名称 group by 字段名 having count(*) 比较条件 n;

8、Mocha(一个功能丰富的javascript测试框架,运行在node.js和浏览器中,使异步测试变得简单有趣)

9、Sequelize(Node的ORM框架Sequelize来操作数据库)

10、Nunjucks(模板引擎就是基于模板配合数据构造出字符串输出的一个组件)

11、EJS(高效的嵌入式 JavaScript 模板引擎)


https://www.xamrdz.com/backend/3c31938215.html

相关文章: