【MySQL数据库基础】(七)删库跑路?先学会怎么“存”和“取”吧!MySQL 基础查询全攻略(上)

【MySQL数据库基础】(七)删库跑路?先学会怎么“存”和“取”吧!MySQL 基础查询全攻略(上)

前言

        如果说算法是灵魂,那么数据库就是肉体。无论你的架构多么牛叉,最终都要落地到数据的增删改查(CRUD)上。

        很多初学者觉得 SQL 简单,不就是 SELECT *吗?但真正到了高并发、大数据量的场景,基础不牢地动山摇。今天,咱们就带你深入浅出地剖析 MySQL 的“创建(Create)”与“查询(Retrieve)”,从零开始,拒绝死板!下面就让我们正式开始吧!

在开始写代码前,咱们先统一一下黑话。C (Create):创建/插入。R (Retrieve):读取/查询。U (Update):更新/修改。D (Delete):删除。

        简单来说,这就是数据的生命周期。本文我们将重点攻克前两个:如何优雅地把数据存进去,以及如何精准地把数据搜出来。

一、Create:给数据库注入灵魂

        要存数据,得先有表。咱们先在 Bash 终端里操作一把,创建一个名为 students 的学生表:

-- 这里是在 MySQL 命令行执行的 SQL CREATE TABLE students ( id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT, -- 自增主键,防止乱码 ID [cite: 14] sn INT NOT NULL UNIQUE COMMENT '学号', -- 唯一学号,不能重复 [cite: 15] name VARCHAR(20) NOT NULL, -- 姓名,不能为空 [cite: 16] qq VARCHAR(20) -- QQ 号 [cite: 17] ); [cite: 13] 

1.1 插入数据的“姿势”

        有了表,接下来就是插入数据了。

姿势一:全列插入

        如果你懒得写列名,可以直接全列插入。但注意,VALUES 后面的参数必须和表定义的列顺序、数量一字不差!

-- 这里的 id 如果填 NULL,由于我们设置了 AUTO_INCREMENT,MySQL 会自动帮我们数数 [cite: 20] INSERT INTO students VALUES (100, 10000, '唐三藏', NULL); [cite: 21] INSERT INTO students VALUES (101, 10001, '孙悟空', '11111'); [cite: 23] 

姿势二:指定列插入

        这是最推荐的方式。只插入你关心的列,不仅安全,还能减少数据传输。

INSERT INTO students (id, sn, name) VALUES (102, 20001, '曹孟德'), (103, 20002, '孙仲谋'); [cite: 41, 42, 43] 

1.2 进阶操作:当“撞衫”时怎么办?

        在插入数据时,经常会遇到主键冲突唯一键冲突。 例如,你再次插入 id=100 的数据,MySQL 会报错:Duplicate entry '100' for key 'PRIMARY'

方案 A:发生冲突就更新(ON DUPLICATE KEY UPDATE)

        这种做法像极了现实生活中的“覆盖式安装”。如果主键冲突了,就按照我后面写的规则改一下。

INSERT INTO students (id, sn, name) VALUES (100, 10010, '唐大师') ON DUPLICATE KEY UPDATE sn = 10010, name = '唐大师'; [cite: 79, 80] 
注意:MySQL 返回的affected rows很有意思。如果是 0,说明没改;如果是 1,说明直接插入成功;如果是 2,说明发生了冲突并进行了更新。

方案 B:简单粗暴的替换(REPLACE)

    REPLACE 的逻辑是:没冲突就正常插;有冲突就先把你删了,我重新插一条!

REPLACE INTO students (sn, name) VALUES (20001, '曹阿瞒'); [cite: 100]

二、Retrieve:大海捞针的艺术

        存数据是为了用数据。SELECT语句是 SQL 的灵魂,它的语法极其丰富。

        我们先搞一个考试成绩表 exam_result作为演示:

CREATE TABLE exam_result ( id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT, name VARCHAR(20) NOT NULL, chinese float DEFAULT 0.0, math float DEFAULT 0.0, english float DEFAULT 0.0 ); [cite: 118] -- 批量插入一些英雄好汉的数据 [cite: 121] INSERT INTO exam_result (name, chinese, math, english) VALUES ('唐三藏', 67, 98, 56), ('孙悟空', 87, 78, 77), ('猪悟能', 88, 98, 90), ('曹孟德', 82, 84, 67), ('刘玄德', 55, 85, 45), ('孙权', 70, 73, 78), ('宋公明', 75, 65, 30); [cite: 121, 122, 124, 127, 131, 134, 137, 138] 

2.1 SELECT 的基础变幻

1. 全列查询(不推荐!)

SELECT * FROM exam_result; [cite: 146] 

        在生产环境中,千万别乱用*。首先,传输大量数据费带宽;其次,可能无法利用索引优化,导致查询变慢。

2. 指定列查询

        只拿你想要的那一列,简单明了。

SELECT id, name, english FROM exam_result; [cite: 192] 

3. 给查询结果“整整容”——别名

觉得列名太生硬?可以换个好听的名字展示。甚至可以对列进行计算。

-- 这里将三门成绩相加,并起个外号叫“总分” [cite: 311] SELECT id, name, chinese + math + english AS 总分 FROM exam_result; [cite: 310, 311] 

4. 去重(DISTINCT)

        如果只想看有哪些数学分数存在(不要重复的),就用 DISTINCT

SELECT DISTINCT math FROM exam_result; [cite: 356] 

2.2 WHERE 子句:数据的过滤器

        如果没有 WHERE,数据库就是个垃圾堆。我们要筛选出有价值的信息,就需要各种运算符。

常见比较运算符

>>=<<=:最基础的大小比较。BETWEEN a0 AND a1:范围查询(闭区间)。IN (option, ...):离散集合匹配。IS NULL / IS NOT NULL:专门对付 NULL。LIKE:模糊匹配。% 匹配任意个字符,_ 匹配一个。

案例实战

Q1:找出语文成绩在 [80, 90] 的同学?

SELECT name, chinese FROM exam_result WHERE chinese BETWEEN 80 AND 90; [cite: 406] 

Q2:姓孙的同学有哪些?

SELECT name FROM exam_result WHERE name LIKE '孙%'; [cite: 439] 

Q3:总分在 200 以下的同学?

陷阱警告:在 WHERE 条件中,不能使用你在 SELECT 里起的别名!
-- 错误写法:WHERE 总分 < 200 (会报错) SELECT name, chinese + math + english AS 总分 FROM exam_result WHERE chinese + math + english < 200; [cite: 475, 476, 477] 

2.3 ORDER BY:让数据“排排坐”

        排序是查询的最后一道工序。

ASC:升序(默认)。DESC:降序。多字段排序:我们可以先按数学降序,数学一样的再按英语升序。
SELECT name, math, english FROM exam_result ORDER BY math DESC, english ASC; [cite: 651] 
冷知识:在 ORDER BY中,是可以使用别名的!这和 WHERE刚好相反。

2.4 LIMIT:分页查询的救星

        如果你有 100 万条数据,一次性显示出来肯定卡死。这时就需要分页。

-- 从第 0 条开始,取 3 条(第一页) [cite: 725, 726, 733, 735] SELECT * FROM exam_result LIMIT 3 OFFSET 0; [cite: 735] -- 从第 3 条开始,取 3 条(第二页) [cite: 729, 758, 760] SELECT * FROM exam_result LIMIT 3 OFFSET 3; [cite: 760] 

        在对陌生的大表进行查询时,养成随手加LIMIT 1的习惯,这是后端开发的一种修养,防止因全表扫描导致的数据库卡死。


总结

        本篇我们聊了“增”和“查”的最基础部分。在下一篇,我们将深入探讨“聚合函数”、“分组查询”以及让人头疼的“表连接”。

        想要精通数据库,不仅要会写代码,更要懂它的心。 我们下期再见!

Read more

别再做“调包侠”!AI模型的底层逻辑,全靠这门“数学语言”撑着

别再做“调包侠”!AI模型的底层逻辑,全靠这门“数学语言”撑着

做AI、搞数据这么久,你有没有过这样的时刻? 跟着教程敲代码,能轻松跑通CNN、Transformer,甚至能调参调出不错的效果,但被人问起“模型前向传播到底在算什么”“特征降维的核心逻辑是什么”,却支支吾吾说不出个所以然; 面试时,HR随口一问“奇异值分解在推荐系统里怎么落地”“梯度下降的线性代数本质是什么”,瞬间大脑空白,明明学过无数次,却怎么也说不明白; 工作中,模型出现过拟合、收敛太慢,只能盲目调整学习率、增减网络层数,却找不到问题根源——其实你心里清楚,自己只是“会用AI”,并没有真正“懂AI”。 很多人都陷入了一个误区:学AI只追算法、练代码,却忽略了支撑所有模型的“底层骨架”——线性代数。就像狗熊会一直强调的,AI的本质是数学,而线性代数,就是AI能“思考”“运算”的核心语言。 我们不妨拆解一下,那些你天天在用的AI模型,底层全是线性代数的身影,只是你没意识到而已。 AI模型的底层逻辑,本质是线性代数的“花式运算” 很多人觉得线性代数“

By Ne0inhk
【Linux】网络基础(一)

【Linux】网络基础(一)

文章目录 * 网络发展 * 认识协议 * 🚩网络协议 * 🚩协议分层 * OSI七层协议 * 🚩TCP/IP五层(四层)协议 * 🚩网络传输基本流程 * 🚩数据包的封装和解包 * MAC地址 网络发展 起初计算机是用在军事上的 独立模式: 计算机之间相互独立 网络互联:多台计算机连接在一起实现网络互联 局域网LAN:计算机数量越来越多了,通过交换机和路由器连接在一起 广域网WAN:将远隔千里之外的的计算机连接在一起 所谓局域网广域网是相对概念,我们家庭路由器就可以看作局域网,把家家户户连接的社区就是广域网。社区看作局域网,把社区连接的就是广域网,中国网络看作局域网,连接世界就是广域网 认识协议 协议是一种约定 计算机之间通过光信号电信号交流,通过频率强弱来代表0和1,要想传递不同信息,就要约定好数据格式,比如000代表什么信息 要想多台计算机之间相互通信,就要约定共同的标准,这就是网络协议 🚩网络协议 🚩协议分层 打电话的例子,语言层汉语有协议,通信设备层也有协议 英语之间交流

By Ne0inhk
Flutter 组件 ansi_styles 的鸿蒙化适配实战 - 驾驭极致终端交互艺术、实现 OpenHarmony 开发链路、日志系统与控制台的工业级色彩分级方案

Flutter 组件 ansi_styles 的鸿蒙化适配实战 - 驾驭极致终端交互艺术、实现 OpenHarmony 开发链路、日志系统与控制台的工业级色彩分级方案

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 组件 ansi_styles 的鸿蒙化适配实战 - 驾驭极致终端交互艺术、实现 OpenHarmony 开发链路、日志系统与控制台的工业级色彩分级方案 前言 在鸿蒙(OpenHarmony)生态的底座开发、高性能服务端侧逻辑构建、或者是对命令行交互(CLI)有极其严苛要求的自动化工程流水线中。“终端日志的可视化分级与视觉重心引导维度”是衡量整个底层调试链路效能的最终质量门禁。面对包含数万行内核日志、海量网络请求报文、甚至是 0308 批次重型打包过程产生的满屏文字流。如果仅仅依靠终端中苍白的一串 White 和 Black 或者是毫无温标感的 txt 控制台。不仅会导致在定位历史回退(Regression)时让开发工程师如同在字符废墟中盲人摸象。更会因为缺乏大局观的报错优先级呈现。令技术高层在跨终端指挥调度时陷入严重的信息盲区。 我们需要一种“色彩生动、警示分明”的终端资产汇报艺术。 ansi_styles 是一套专注于无缝整合全球公认顶级

By Ne0inhk

Ubuntu下系统服务(Service)管理详解

1.核心概念:什么是服务? 在Ubuntu操作系统中,服务通常指的是在系统后台持续运行的守护进程。它们为操作系统或其他应用程序提供特定的功能支持,例如网络连接(SSH)、Web服务(Nginx/Apache)、数据库(MySQL)或计划任务等。 2.服务管理方式的演进 Ubuntu系统管理服务的方式主要经历了两种体系,其核心区别在于初始化管理系统: -传统方式(SystemVinit):在Ubuntu14.10及更早版本中作为默认系统。 -现代方式(systemd):自Ubuntu15.04起成为所有后续版本的默认初始化系统。 重要提示:您当前使用的任何主流现代Ubuntu版本(如18.04LTS,20.04LTS,22.04LTS等)均默认采用systemd。 3.两种管理方式的对比 以下表格清晰地列出了两种管理方式的关键区别: SystemVinit(传统方式) -服务脚本位置:/etc/init.d/目录下 -核心管理命令示例:sudo /etc/init.d/

By Ne0inhk