SQL 入门到精通:从基础到高级的完整指南

297 阅读5分钟

嘿,数据爱好者们!今天我们将踏上一段 SQL 的奇幻旅程,从基础到高级功能,全面解锁 SQL 的强大之处。无论你是刚入门的新手,还是想提升技能的老手,这篇文章都将为你提供宝贵的知识。准备好你的数据背包,咱们出发吧!


一、SQL 简介

SQL(结构化查询语言)是一种用于管理和操作关系数据库的语言。它是数据世界的基石,广泛应用于数据存储、查询和分析。通过 SQL,你可以执行创建、读取、更新和删除(CRUD)操作,管理数据库中的数据。


二、SQL 基础知识

1. SQL 的基本结构

一个 SQL 查询的基本结构如下:

SELECT column1, column2, ...
FROM tablename
WHERE condition;
  • SELECT: 指定要查询的列。
  • FROM: 指定数据来源的表。
  • WHERE: 过滤条件,筛选出符合条件的行。

2. 数据类型

在 SQL 中,常见的数据类型包括:

  • 整数类型INT, BIGINT, SMALLINT, TINYINT
  • 字符串类型VARCHAR, CHAR, TEXT
  • 日期时间类型DATE, TIME, DATETIME
  • 数值类型DECIMAL, FLOAT, DOUBLE
  • 布尔类型BIT, BOOLEAN

三、数据查询(DQL)

数据查询是 SQL 的核心功能之一。通过 SELECT 语句,你可以从数据库中检索数据。

1. 基本查询

SELECT *
FROM customers;
  • * 表示选择所有列。
  • FROM customers 指定数据来源的表。

2. 条件查询

SELECT customer_name, email
FROM customers
WHERE country='USA'
  AND age > 18;
  • WHERE 子句用于过滤数据。
  • ANDORNOT 用于组合条件。

3. 分组和聚合

SELECT product_category, AVG(price) AS average_price
FROM products
GROUP BY product_category
HAVING AVG(price) > 100;
  • GROUP BY 将数据按指定列分组。
  • HAVING 过滤分组后的结果。

四、数据操作(DML)

1. 插入数据

INSERT INTO customers (customer_id, name, email)
VALUES ('C001', 'John Doe', 'john@example.com');
  • INSERT INTO 指定要插入数据的表和列。
  • VALUES 提供要插入的数据。

2. 更新数据

UPDATE customers
SET email = 'jane@example.com'
WHERE customer_id = 'C001';
  • SET 指定要更新的列和新值。
  • WHERE 确定要更新的行。

3. 删除数据

DELETE FROM customers
WHERE customer_id = 'C001';
  • DELETE FROM 指定要删除数据的表。
  • WHERE 过滤要删除的行。

五、数据定义(DDL)

1. 创建表

CREATE TABLE orders (
    order_id INT PRIMARY KEY,
    customer_id INT,
    order_date DATE,
    total_amount DECIMAL(10, 2)
);
  • CREATE TABLE 创建新表。
  • PRIMARY KEY 定义主键,确保唯一性和非空性。

2. 修改表

ALTER TABLE orders
ADD COLUMN order_status VARCHAR(50);
  • ALTER TABLE 修改表结构。
  • ADD COLUMN 添加新列。

3. 删除表

DROP TABLE orders;
  • DROP TABLE 删除整个表。

六、数据控制(DCL)

1. 用户权限管理

GRANT SELECT, INSERT ON customers TO 'user1'@'%';
REVOKE DELETE ON customers FROM 'user1'@'%';
  • GRANT 授予用户权限。
  • REVOKE 撤销用户权限。

七、表连接(JOIN)

1. 内连接(INNER JOIN)

SELECT orders.order_id, customers.customer_name
FROM orders
INNER JOIN customers
ON orders.customer_id = customers.customer_id;
  • INNER JOIN 只返回两个表中有匹配记录的行。

2. 左连接(LEFT JOIN)

SELECT orders.order_id, customers.customer_name
FROM customers
LEFT JOIN orders
ON customers.customer_id = orders.customer_id;
  • LEFT JOIN 返回左表的所有记录,右表无匹配时为 NULL。

3. 右连接(RIGHT JOIN)

SELECT orders.order_id, customers.customer_name
FROM customers
RIGHT JOIN orders
ON customers.customer_id = orders.customer_id;
  • RIGHT JOIN 返回右表的所有记录,左表无匹配时为 NULL。

4. 全连接(FULL OUTER JOIN)

SELECT orders.order_id, customers.customer_name
FROM customers
FULL OUTER JOIN orders
ON customers.customer_id = orders.customer_id;
  • FULL OUTER JOIN 返回两个表中所有记录,任一表无匹配时为 NULL。

八、子查询和 CTE

1. 子查询

SELECT *
FROM customers
WHERE customer_id IN (
    SELECT customer_id
    FROM orders
    WHERE order_date > '2023-01-01'
);
  • 子查询用于在主查询中获取满足条件的数据。

2. 公共表表达式(CTE)

WITH sales AS (
    SELECT customer_id, SUM(amount) AS total_sales
    FROM orders
    GROUP BY customer_id
)
SELECT *
FROM sales
WHERE total_sales > 1000;
  • CTE 允许在查询中定义一个临时的结果集,可以被引用多次。

九、窗口函数

窗口函数用于在分组数据中计算排名、累计值等。

1. ROW_NUMBER()

SELECT order_id, customer_id, order_date,
       ROW_NUMBER() OVER (ORDER BY order_date) AS row_num
FROM orders;
  • 为每一行分配一个唯一的编号。

2. RANK()

SELECT product_id, sales,
       RANK() OVER (ORDER BY sales DESC) AS sales_rank
FROM products;
  • 根据 sales 列降序排列,计算每行的排名。

3. DENSE_RANK()

SELECT product_id, sales,
       DENSE_RANK() OVER (ORDER BY sales DESC) AS dense_rank
FROM products;
  • 与 RANK() 类似,但没有空隙。

4. NTILE()

SELECT product_id, sales,
       NTILE(4) OVER (ORDER BY sales DESC) AS quartile
FROM products;
  • 将数据分成 4 个桶,显示每个产品的分位数。

5. LAG() 和 LEAD()

SELECT order_id, order_date,
       LAG(order_date, 1) OVER (ORDER BY order_date) AS prev_order_date,
       LEAD(order_date, 1) OVER (ORDER BY order_date) AS next_order_date
FROM orders;
  • LAG() 获取前一行的值。
  • LEAD() 获取后一行的值。

十、正则表达式和过滤

1. LIKE

SELECT *
FROM customers
WHERE customer_name LIKE '%John%';
  • % 匹配任意数量的字符。
  • _ 匹配单个字符。

2. REGEXP

SELECT *
FROM customers
WHERE customer_name REGEXP '^J.*n$';
  • ^ 匹配字符串开始。
  • .* 匹配任意数量的字符。
  • $ 匹配字符串结束。

3. 过滤条件

SELECT *
FROM customers
WHERE country = 'USA'
  AND age > 18
  AND email IS NOT NULL;
  • IS NULL 检查值是否为 NULL。
  • IN 检查值是否在列表中。

十一、视图

视图是基于一个 SELECT 语句的虚拟表。

1. 创建视图

CREATE VIEW customer_orders AS
SELECT c.customer_name, o.order_id, o.order_date
FROM customers c
JOIN orders o ON c.customer_id = o.customer_id;

2. 查询视图

SELECT *
FROM customer_orders
WHERE order_date > '2023-01-01';

十二、存储过程和函数

1. 存储过程

DELIMITER $$

CREATE PROCEDURE GetCustomerOrders(IN customer_id INT)
BEGIN
    SELECT *
    FROM orders
    WHERE customer_id = customer_id;
END$$

DELIMITER ;

CALL GetCustomerOrders(123);
  • 存储过程封装了复杂的逻辑,提高代码重用性。

2. 用户定义函数

DELIMITER $$

CREATE FUNCTION CalculateDiscount(price DECIMAL(10, 2))
RETURNS DECIMAL(10, 2)
DETERMINISTIC
BEGIN
    DECLARE discount DECIMAL(10, 2);
    IF price >= 100 THEN
        discount = price * 0.1;
    ELSE
        discount = 0;
    END IF;
    RETURN discount;
END$$

DELIMITER ;

SELECT CalculateDiscount(120.00) AS discount_amount;
  • 用户定义函数可以在 SQL 中封装复杂的计算逻辑。

十三、事务管理

事务确保数据库操作的原子性、一致性、隔离性和持久性。

BEGIN TRANSACTION;

-- 执行一系列操作

COMMIT;

-- 或者在异常情况下
ROLLBACK;

十四、索引和优化

索引可以提高查询性能。

1. 创建索引

CREATE INDEX idx_customer_name
ON customers (customer_name);

2. 删除索引

DROP INDEX idx_customer_name ON customers;

十五、备份和恢复

1. 数据库备份

mysqldump -u username -p database_name > backup.sql

2. 数据库恢复

mysql -u username -p database_name < backup.sql

十六、常见错误和解决方法

  1. 语法错误:确保 SQL 语句的语法正确,注意大小写和符号。
  2. 权限问题:检查用户是否有足够的权限执行操作。
  3. 性能问题:优化查询,使用索引,避免过多的子查询。

十七、总结

SQL 是一个强大的工具,掌握它可以帮助你高效地管理和分析数据。从基础的 CRUD 操作到高级的窗口函数和存储过程,SQL 为你提供了丰富的功能。通过不断的实践和学习,你可以逐步提升自己的 SQL技能,成为数据处理的高手。

祝你在 SQL 的学习和应用中一帆风顺,数据分析的世界等你来探索!