0%

SQL 核心操作语法详解:查询、插入、删除与修改

SQL(Structured Query Language)是操作关系型数据库的标准语言,核心操作包括数据查询(SELECT)、插入(INSERT)、删除(DELETE/TRUNCATE)和修改(UPDATE)。本文详细解析这些操作的语法规则、使用场景及注意事项,帮助你快速掌握 SQL 基础操作。

查询操作(SELECT)

SELECT 是 SQL 中最常用的操作,用于从表中检索数据,语法灵活且功能强大。

基本语法

1
2
3
4
5
6
SELECT <字段列表>
FROM <表名>
[WHERE <查询条件>]
[GROUP BY <分组字段>]
[HAVING <分组过滤条件>]
[ORDER BY <排序字段> [ASC|DESC]];
各子句说明:
  • SELECT <字段列表>:指定要查询的字段,* 表示查询所有字段(不推荐,效率低且依赖表结构)。
    示例:SELECT id, name FROM users;(查询 users 表的 idname 字段)。
  • FROM <表名>:指定数据来源的表(可多表联合查询,用 JOIN 连接)。
  • WHERE <查询条件>:过滤行数据,支持比较运算符(=, >, <, >=, <=, !=)、逻辑运算符(AND, OR, NOT)、模糊查询(LIKE)等。
    示例:SELECT * FROM orders WHERE amount > 1000 AND status = 'paid';(查询金额 > 1000 且已支付的订单)。
  • GROUP BY <分组字段>:按指定字段分组,通常与聚合函数(COUNT, SUM, AVG, MAX, MIN)配合使用。
    示例:SELECT user_id, COUNT(*) AS order_count FROM orders GROUP BY user_id;(按用户 ID 分组,统计每个用户的订单数)。
  • HAVING <分组过滤条件>:对分组后的结果进行过滤(WHERE 用于分组前过滤,HAVING 用于分组后过滤)。
    示例:SELECT user_id, COUNT(*) AS order_count FROM orders GROUP BY user_id HAVING order_count >= 5;(筛选出订单数≥5 的用户)。
  • ORDER BY <排序字段>:按指定字段排序,ASC 升序(默认),DESC 降序。
    示例:SELECT * FROM products ORDER BY price DESC;(按价格降序排列商品)。

常用查询技巧

  • 去重查询:用 DISTINCT 去除重复行。
    示例:SELECT DISTINCT category FROM products;(查询所有不重复的商品分类)。
  • 限制结果数量:用 LIMIT(MySQL)或 TOP(SQL Server)限制返回行数。
    示例:SELECT * FROM articles LIMIT 10;(查询前 10 篇文章)。
  • 模糊查询:用 LIKE 匹配字符串,% 表示任意字符(包括空),_ 表示单个字符。
    示例:SELECT * FROM users WHERE name LIKE '张%';(查询姓张的用户)。

插入操作(INSERT)

INSERT 用于向表中添加新数据,支持单行插入、批量插入及从其他表复制数据。

阅读全文 »

算法基本使用:从经典问题看算法思想

算法是解决问题的步骤化策略,不同算法思想适用于不同场景。本文结合具体示例,解析最大公约数、递推、递归、分治、穷举、贪婪、回溯等经典算法的核心思想与实现。

最大公约数(欧几里得算法)

核心思想:利用 “两个数的最大公约数等于其中较小数与两数余数的最大公约数” 这一性质,通过反复取模简化问题,直至余数为 0。

算法步骤

  1. m < n,交换 mn(确保 m ≥ n)。
  2. 计算 m % nm 除以 n 的余数)。
  3. 若余数为 0,则 n 即为最大公约数;否则,令 m = nn = 余数,重复步骤 2。

代码解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public int maxCommonDisvisor(int m, int n) {
int temp;
// 确保 m ≥ n
if (m < n) {
temp = m;
m = n;
n = temp;
}
while (true) {
if (m % n == 0) { // 余数为0,n是最大公约数
return n;
}
// 迭代:m = n,n = 余数
temp = m % n;
m = n;
n = temp;
}
}

扩展

  • 更相减损术:通过反复用大数减小数(而非取模)求最大公约数,适合无法高效取模的场景(如大数运算)。
  • 最小公倍数:两数乘积除以最大公约数,即 lcm(m, n) = m * n / gcd(m, n)

递推算法

核心思想:从已知条件出发,通过迭代计算中间结果,逐步推导出最终答案(分顺推和逆推)。

经典示例:斐波那契数列

斐波那契数列定义为:f(0)=1f(1)=1f(n)=f(n-1)+f(n-2)n ≥ 2)。

代码解析(顺推)

阅读全文 »

Callable接口与异步任务处理:从基础到实战

在 Java 并发编程中,Callable接口与Future框架是处理异步任务的核心组件,它们弥补了Runnable接口在返回值和异常处理上的不足,为多线程任务提供了更灵活的结果获取机制。本文将深入解析CallableFutureFutureTaskCompletionService的设计原理与实战应用。

Callable 接口:超越 Runnable 的异步任务定义

Runnable 的局限性

Runnable是 Java 早期定义线程任务的接口,但其run()方法存在两大缺陷:

  • 无返回值:无法直接获取任务执行结果,需通过共享变量间接传递,代码繁琐;
  • 无异常抛出run()方法声明不允许抛出受检异常,必须在方法内部捕获处理,增加了代码复杂度。

Callable 的改进

Callable接口专为解决上述问题设计,其定义如下:

1
2
3
4
@FunctionalInterface  
public interface Callable<V> {
V call() throws Exception;
}

核心优势

  • 有返回值call()方法返回泛型V,直接承载任务结果;
  • 支持异常:声明抛出Exception,允许任务将异常传递给调用方处理;
  • 函数式接口:可配合 Lambda 表达式简化代码。

Callable 与 Runnable 的对比

特性 Runnable Callable
方法名 run() call()
返回值 void V(泛型)
异常处理 不允许抛出受检异常 允许抛出Exception
线程启动方式 直接通过Thread启动 需配合FutureTask使用

Future 接口:异步结果的生命周期管理

Callable仅定义任务,而Future接口则负责管理任务的执行过程和结果获取,是 “生产者 - 消费者” 模型中的桥梁。

Future 接口的核心方法

阅读全文 »

Java 泛型详解:类型安全的基石

泛型(Generics)是 Java 5 引入的核心特性,它允许在定义类、接口和方法时使用类型参数,从而实现代码的类型安全复用性。在泛型出现之前,集合类只能存储 Object 类型,取出时必须强制转换,容易引发运行时 ClassCastException。泛型的出现将类型检查提前到编译期,从根本上解决了这一问题。

泛型的核心价值

  1. 编译期类型检查:阻止将错误类型的对象放入集合,避免运行时类型转换异常。
  2. 消除强制类型转换:从集合中获取元素时无需手动转换,代码更简洁。
  3. 代码复用:一套泛型代码可适配多种数据类型(如 ArrayList<String>ArrayList<Integer> 共享同一套 ArrayList 实现)。
  4. 提升可读性:通过类型参数明确集合或方法支持的数据类型,代码意图更清晰。

泛型的基本用法

泛型类与泛型接口

泛型类 / 接口在定义时声明类型变量(用 <T> 表示),使用时指定具体类型。

示例:自定义泛型类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// 定义泛型类,T为类型变量(可替换为任意标识符,通常用T、E、K、V等)
public class Box<T> {
private T value; // 使用类型变量作为属性类型

public Box(T value) { // 作为构造器参数类型
this.value = value;
}

public T getValue() { // 作为返回值类型
return value;
}

public void setValue(T value) { // 作为方法参数类型
this.value = value;
}
}

// 使用泛型类:指定具体类型(如String、Integer)
public class BoxDemo {
public static void main(String[] args) {
Box<String> stringBox = new Box<>("Hello");
String str = stringBox.getValue(); // 无需强制转换

Box<Integer> intBox = new Box<>(123);
int num = intBox.getValue(); // 自动拆箱
}
}
示例:泛型接口
阅读全文 »

Java 异常处理详解:从原理到实践

异常是程序运行过程中出现的非预期情况(如空指针、数组越界等)。Java 提供了完善的异常处理机制,通过 try-catch-finallythrowthrows 等关键字,使程序在遇到异常时能够优雅地处理,而非直接崩溃。本文将深入解析 Java 异常体系、处理机制及最佳实践。

异常体系结构

Java 异常体系以 Throwable 为根类,分为两大分支:Error(错误)Exception(异常),二者均继承自 Throwable

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Throwable
├─ Error(错误):JVM 无法处理的严重问题
│ ├─ VirtualMachineError(虚拟机错误)
│ │ ├─ OutOfMemoryError(内存溢出)
│ │ └─ StackOverflowError(栈溢出)
│ └─ NoClassDefFoundError(类定义未找到)

└─ Exception(异常):程序可处理的问题
├─ RuntimeException(运行时异常,非检查型)
│ ├─ NullPointerException(空指针)
│ ├─ ClassCastException(类型转换)
│ ├─ ArithmeticException(算术错误)
│ └─ IndexOutOfBoundsException(下标越界)

└─ 非 RuntimeException(检查型异常)
├─ IOException(I/O 异常)
├─ ClassNotFoundException(类未找到)
└─ SQLException(数据库异常)

1. Error(错误)

Error 表示 JVM 自身无法解决的严重问题,通常由硬件或系统级故障导致,程序无法处理,应避免捕获 Error

  • 常见类型:
    • OutOfMemoryError:内存溢出(如无限创建对象)。
    • StackOverflowError:栈溢出(如无限递归调用)。
    • NoClassDefFoundError:类定义缺失(如编译后删除了 .class 文件)。

2. Exception(异常)

Exception 表示程序运行中可预期的异常,程序可以捕获并处理,分为两类:

阅读全文 »