SQL里Values不只是插入,还能这样玩,挺有意思的用法分享
- 问答
- 2026-01-21 23:19:42
- 3
说到SQL里的VALUES,大多数人第一个想到的就是和INSERT INTO搭配,往表里插入新数据,这确实是它最基本、最广为人知的职责,但如果你认为VALUES只能干这一件事,那可真是小看它了,今天我们就来分享几个VALUES关键字的“非常规”玩法,你会发现它其实是个挺灵活、挺有意思的工具。
临时充当虚拟表,快速生成测试数据
我们只是想快速测试一个查询语句,或者需要一个简单的数据集来做计算,但手头并没有现成的表,这时候,VALUES就派上用场了,你可以直接把它当作一个“虚拟表”来使用。
我想看看几个特定数字(比如100, 200, 300)的平均值是多少,按照传统思路,你可能得先创建一张临时表,把数据插进去,再用SELECT AVG来计算,但现在,一行查询就能搞定:
SELECT AVG(num) FROM (VALUES (100), (200), (300)) AS temp_table(num);
这句SQL的意思是:VALUES (100), (200), (300) 创建了一个有三行一列的临时结果集,我们用 AS temp_table(num) 给这个临时表起了个名字叫temp_table,并且给这一列命名为num,然后外层的SELECT语句就可以像查询普通表一样,对这个临时表进行求平均值的操作了。
这个用法在数据库管理工具(如DBeaver、Navicat)或一些支持标准SQL的数据库(如PostgreSQL、较新版本的MySQL)中很常见,它非常适合用来做快速验证,省去了创建和清理临时表的麻烦。
与INSERT结合,实现“不存在则插入”
这招在需要避免插入重复数据时特别有用,虽然不同数据库的语法略有差异,但核心思想都利用了VALUES来提供数据,并结合ON CONFLICT或MERGE等子句。
在PostgreSQL或SQLite中,我们想往用户表(user)里插入数据,但如果用户名已存在,就不插入,可以这么写:
INSERT INTO user (id, name, email) VALUES (1, '张三', 'zhangsan@example.com') ON CONFLICT (id) DO NOTHING;
或者更复杂点,如果冲突了则更新部分字段:
INSERT INTO user (id, name, email) VALUES (1, '张三', 'zhangsan@example.com') ON CONFLICT (id) DO UPDATE SET email = EXCLUDED.email;
这里,VALUES子句提供了想要插入(或更新)的数据源,当发生冲突(比如id重复)时,ON CONFLICT子句会触发,决定是忽略(DO NOTHING)还是用VALUES提供的新数据去更新旧记录(DO UPDATE)。EXCLUDED是一个特殊的表,代表的就是这次因冲突而未能成功插入的那行数据,这个用法在数据同步或初始化脚本里非常高效。

在复杂查询中作为数据源,简化CASE WHEN逻辑
我们会遇到一些映射关系,比如将状态码转换成可读的文字,通常我们会用一长串的CASE WHEN ... THEN ... END语句,但如果映射关系很多,SQL语句会变得又长又难维护。
这时,可以用VALUES创建一个“内联”的映射表,然后通过JOIN连接来查询,让逻辑更清晰。
假设我们有一个订单状态码(1,2,3),需要转换成中文('待支付','已发货','已完成'),可以这样写:
SELECT o.order_id, o.amount, status_map.status_name
FROM orders o
JOIN (
VALUES
(1, '待支付'),
(2, '已发货'),
(3, '已完成')
) AS status_map(status_code, status_name)
ON o.status = status_map.status_code;
我们通过VALUES在查询内部直接定义了一个微型的映射表status_map,它包含status_code和status_name两列,主查询只需要简单地与这个虚拟表进行JOIN,就能获得状态名称,这种方式比写一堆CASE WHEN更模块化,尤其是当映射关系需要频繁修改或项数很多时,优势更明显。
在UPDATE语句中,一次性更新多条记录

这是一个稍微进阶但非常实用的技巧,通常我们更新多条记录,如果更新的值不同,需要执行多条UPDATE语句,但通过将VALUES和FROM子句(在标准SQL中常通过JOIN实现)结合,可以一条语句搞定。
比如在PostgreSQL中,我们想根据ID批量更新用户积分:
UPDATE user
SET score = new_data.new_score
FROM (
VALUES
(1, 100),
(2, 150),
(3, 200)
) AS new_data(user_id, new_score)
WHERE user.id = new_data.user_id;
这条语句的意思是:VALUES子句创建了一个临时表new_data,里面包含了要更新的用户ID和对应的新积分,UPDATE语句将主表user与这个临时表通过ID关联起来,然后将主表的score字段设置为临时表中的new_score,这样就实现了一次性、有针对性地更新多条记录,效率比循环执行单条UPDATE高得多。
总结一下
你看,VALUES这个关键字,远不止是INSERT的“小跟班”,它本质上是一个强大的行构造器,能够随时随地生成一个内存中的临时数据集,这个数据集可以当作表来查询,可以作为数据源用于插入或更新逻辑,还能帮助我们把复杂的判断条件简化。
下次当你写SQL时,如果遇到需要临时数据、简单映射或者批量操作的情况,不妨想想VALUES能不能帮上忙,灵活运用它,不仅能减少代码量,还能让查询逻辑变得更加清晰和优雅,这或许就是SQL语言的魅力所在,看似简单的关键字,背后往往隐藏着意想不到的用法。
(注:上述示例语法主要基于PostgreSQL等对标准SQL支持较好的数据库,具体到MySQL、SQL Server等数据库时,部分语法可能有所不同,但核心思想是相通的,使用时请查阅相应数据库的文档。)
本文由钊智敏于2026-01-21发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:http://www.haoid.cn/wenda/84249.html
