5、SQL语言基础(DML):增删改查实战
各位同学,今天我们来聊聊DML——也就是数据操作语言。说白了,这就是我们跟数据库打交道的四个基本动作:插入、更新、删除和查询。我在项目里几乎每天都在用这些语句,它们就像数据库世界的“四则运算”,简单但极其重要。
核心知识点一览:
- INSERT:往表里塞数据
- UPDATE:修改已有数据
- DELETE:删除不需要的数据
- SELECT:查询数据(最常用)
- WHERE:给操作加条件过滤
5.1 INSERT:往表里插入数据
INSERT 语句,说白了就是往表里加一行数据。我刚开始学的时候总觉得这玩意儿太简单,直到有一次在生产环境里插错了字段顺序……嗯,从那以后我再也不敢不看表结构就写 INSERT 了。
基本语法有两种写法:
-- 写法一:指定所有字段(推荐)
INSERT INTO 表名 (字段1, 字段2, 字段3) VALUES (值1, 值2, 值3);
-- 写法二:省略字段名(不推荐,容易出错)
INSERT INTO 表名 VALUES (值1, 值2, 值3);
我个人习惯用第一种写法。你想想看,如果表结构变了,第二种写法直接就崩了。我在项目里见过太多这种坑了。
举个例子,假设我们有个用户表:
CREATE TABLE users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
age INTEGER,
email TEXT
);
-- 插入一条完整数据
INSERT INTO users (name, age, email) VALUES ('张三', 28, 'zhangsan@example.com');
-- 插入部分字段(age 和 email 可以为 NULL)
INSERT INTO users (name) VALUES ('李四');
小技巧:在 Android 的 SQLite 中,如果你用 ContentValues 来插入数据,记得字段名一定要跟表定义完全一致,大小写也要注意。我踩过这个坑,查了半天才发现是字段名写错了。
5.2 UPDATE:更新已有数据
UPDATE 用来修改表中已有的数据。这里有个关键点——一定要加 WHERE 条件,否则会更新整张表!
我曾经在测试环境里干过这种事,还好不是生产环境,不然就等着被老板骂吧。
-- 基本语法
UPDATE 表名 SET 字段1 = 新值1, 字段2 = 新值2 WHERE 条件;
-- 示例:把张三的年龄改成30
UPDATE users SET age = 30 WHERE name = '张三';
-- 更新多个字段
UPDATE users SET age = 30, email = 'newemail@example.com' WHERE name = '张三';
警告:永远不要在生产环境直接执行不带 WHERE 的 UPDATE!如果你真的需要更新全表,先 SELECT 出来看看数据,确认无误再操作。我个人的习惯是:先写 SELECT 看结果,再改成 UPDATE。
5.3 DELETE:删除数据
DELETE 用来删除表中的行。跟 UPDATE 一样,WHERE 条件是你的救命稻草。
-- 基本语法
DELETE FROM 表名 WHERE 条件;
-- 示例:删除张三这条记录
DELETE FROM users WHERE name = '张三';
-- 删除所有年龄小于18的用户
DELETE FROM users WHERE age < 18;
嗯,这里要注意:DELETE 删除的是行,不是表。如果你想清空整张表,可以用 DELETE FROM 表名(不加 WHERE),但 SQLite 里更推荐用 TRUNCATE 的替代方案——直接 DROP 表再重建,或者用 DELETE FROM 表名 后执行 VACUUM 回收空间。
避坑指南:我曾经在项目里写了一个 DELETE 语句,忘了加 WHERE,结果把整个用户表清空了。还好有备份,不然就凉了。所以我的建议是:DELETE 之前先 SELECT 一下,确认你要删的是哪些数据。
5.4 SELECT:查询基础
SELECT 是 DML 里最核心、最常用的语句。说白了,前面那些操作都是为了给查询服务的——你存数据是为了以后能查出来用。
-- 查询所有字段
SELECT * FROM users;
-- 查询指定字段
SELECT name, age FROM users;
-- 查询并给字段起别名
SELECT name AS 姓名, age AS 年龄 FROM users;
-- 去重查询
SELECT DISTINCT age FROM users;
-- 限制返回行数
SELECT * FROM users LIMIT 10;
我个人习惯:永远不要在生产环境用 SELECT *。你想想看,如果表有50个字段,你只需要3个,查出来50个字段不仅浪费网络带宽,还浪费内存。在 Android 里尤其要注意,Cursor 对象会占用不少资源。
5.5 WHERE:条件过滤
WHERE 是 DML 的灵魂。没有 WHERE 的 UPDATE 和 DELETE 是灾难,没有 WHERE 的 SELECT 是低效。
WHERE 支持的操作符:
| 操作符 | 说明 | 示例 |
|---|---|---|
| = | 等于 | WHERE name = '张三' |
| <> 或 != | 不等于 | WHERE age <> 18 |
| > < >= <= | 比较运算符 | WHERE age >= 18 |
| BETWEEN | 范围查询 | WHERE age BETWEEN 18 AND 30 |
| LIKE | 模糊匹配 | WHERE name LIKE '张%' |
| IN | 集合匹配 | WHERE age IN (18, 20, 25) |
| AND / OR | 逻辑组合 | WHERE age > 18 AND name LIKE '张%' |
| IS NULL / IS NOT NULL | 空值判断 | WHERE email IS NULL |
-- 综合示例:查询年龄在18到30之间、姓张的用户
SELECT name, age, email
FROM users
WHERE age BETWEEN 18 AND 30
AND name LIKE '张%'
ORDER BY age DESC
LIMIT 20;
经验之谈:在 Android 的 SQLite 中,LIKE 查询默认是大小写不敏感的,这点跟其他数据库不太一样。另外,如果你要查询大量数据,记得给 WHERE 条件里的字段建索引,不然数据量一上来,查询速度会慢到你怀疑人生。
5.6 综合实战:一个完整的增删改查示例
好了,理论讲完了,我们来个完整的例子。假设我们要做一个简单的通讯录管理:
-- 1. 创建表
CREATE TABLE contacts (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
phone TEXT,
group_name TEXT DEFAULT '默认分组'
);
-- 2. 插入数据
INSERT INTO contacts (name, phone, group_name) VALUES ('张三', '13800138001', '家人');
INSERT INTO contacts (name, phone, group_name) VALUES ('李四', '13800138002', '同事');
INSERT INTO contacts (name, phone) VALUES ('王五', '13800138003');
-- 3. 查询所有数据
SELECT * FROM contacts;
-- 4. 查询某个分组的数据
SELECT * FROM contacts WHERE group_name = '家人';
-- 5. 更新数据:把王五的分组改成'朋友'
UPDATE contacts SET group_name = '朋友' WHERE name = '王五';
-- 6. 删除数据:删除没有分组的联系人(其实都有默认分组了,这里只是演示)
DELETE FROM contacts WHERE group_name IS NULL;
-- 7. 查询最终结果
SELECT id, name, phone, group_name FROM contacts ORDER BY group_name;
这个例子涵盖了 DML 的四个核心操作。你在实际开发中,基本上就是围绕这四个操作来写代码的。我个人建议你把这个例子在 SQLite 命令行或者 Android 的 Room 数据库里跑一遍,感受一下数据的变化过程。
总结一下:
- INSERT 加数据,UPDATE 改数据,DELETE 删数据,SELECT 查数据
- WHERE 是安全阀,UPDATE 和 DELETE 必须带 WHERE
- SELECT 尽量指定字段,别用
* - 操作之前先 SELECT 确认,这是保命技巧
好了,DML 的基础就讲到这里。这些语句你会在后面的每一章里反复用到,所以一定要亲手敲一遍代码。记住:看十遍不如写一遍,写十遍不如踩一次坑。
公众号:蓝海资料掘金营,微信deep3321