更新数据

最近更新时间: 2026-03-13 09:03:00

表中插入数据后,可以使用 UPDATE ... SET ... 语句更新表的行记录。
UPDATE 用于更新表数据,可以更新一个字段或者多个字段。
语法如下:

UPDATE [ ONLY ] table_name [ * ] [ [ AS ] alias ]
    SET { column_name = { expression | DEFAULT } |
          ( column_name [, ...] ) = [ ROW ] ( { expression | DEFAULT } [, ...] ) |
          ( column_name [, ...] ) = ( sub-SELECT )
        } [, ...]
    [ FROM from_list ]
    [ WHERE condition ]

参数说明:

  • table_name: 要更新的表的名称(可以是模式限定的)。如果在表名前指定了 ONLY,只会更新所提及表中的匹配行。如果没有指定 ONLY,会递归地更新所提及表以及子表中所匹配的行。
  • alias: 目标表的一个替代名称。在提供了一个别名时,它会完全隐藏表的真实名称。例如,给定UPDATE foo AS fUPDATE语句的剩余部分必须用 f 而不是 foo 来引用该表。
  • column_name: table_name 所指定的表的一列的名称。如果需要,该列名可以用一个子域名称或者数组下标限定。不要在目标列的说明中包括表的名称,例如 UPDATE table_name SET table_name.col = 1 是非法的。
  • expression: 要被赋值给该列的一个表达式。该表达式可以使用该表中这一列或者其他列的旧值。
  • DEFAULT: 将该列设置为它的默认值(如果没有为它指定默认值表达式,默认值将会为 NULL)。
  • sub-SELECT: 一个SELECT子查询,它产生和在它之前的圆括号中列列表中一样多的输出列。被执行时,该子查询必须得到不超过一行。如果它得到一行,其列值会被赋予给目标列。如果它得不到行,NULL 值将被赋予给目标列。该子查询可以引用被更新表中当前行的旧值。
  • from_list: 表表达式的列表,允许来自其他表的列出现在WHERE 条件和更新表达式中。这类似于可以在 SELECT语句的FROM 子句中指定的表列表。注意目标表不能出现在 from_list中,除非你想做自连接(这种情况下它必须以别名出现在from_list中)。
  • condition: 一个返回boolean类型值的表达式。让这个表达式返回true的行将会被更新。

示例

tbase_insert 表结构如下:

tdsql=#\d tbase_insert;
           Table "public.tbase_insert"
Column   |  Type   | Collation | Nullable |    Default 
-----------+---------+-----------+----------+------------
id        | numeric |           | not null |
name      | text    |           | not null |
value     | numeric |           |          |
create_ts | date    |           | not null | CURRENT_DATE
Indexes:
"tbase_insert_pkey" PRIMARY KEY, btree (id)
"uniq_idx_value" UNIQUE, btree (value)

1、更新 tbase_insert 表中 create_ts 列的所有值。

tdsql=# set nls_date_format to 'YYYY-MM-DD';
SET
tdsql=# select * from tbase_insert;
id |     name      | value | create_ts  
----+---------------+-------+------------
  1 | tbase         |   100 | 2024-03-02
  2 | tbase         |   101 | 2024-03-02
  4 | TDSQL PG      |   103 | 2024-03-02
  5 | TDSQL PG好    |   104 | 2024-03-02
  3 | TDSQL PG Good |   102 | 1999-01-01
  6 | tbase         |   105 | 2024-03-02
(6 rows)

tdsql=# UPDATE tbase_insert SET create_ts = '2022-1-1';
UPDATE 6

tdsql=# select * from tbase_insert;
id |     name      | value | create_ts  
----+---------------+-------+------------
  1 | tbase         |   100 | 2022-01-01
  2 | tbase         |   101 | 2022-01-01
  4 | TDSQL PG      |   103 | 2022-01-01
  5 | TDSQL PG好    |   104 | 2022-01-01
  3 | TDSQL PG Good |   102 | 2022-01-01
  6 | tbase         |   105 | 2022-01-01
(6 rows)

2、 更新部分记录。
在更新表数据时,要注意控制更新量不要太大,否则可能会产生大事务导致执行失败。可以只更新部分记录,通过添加 WHERE 关键字来控制范围。
value 值为 100 的所有列,将其值更新为 value+10

tdsql=# UPDATE tbase_insert SET value = value+10 where value = 100;
UPDATE 1

tdsql=# select * from tbase_insert;
  id |     name      | value | create_ts  
  ----+---------------+-------+------------
  2 | tbase         |   101 | 2022-01-01
  4 | TDSQL PG      |   103 | 2022-01-01
  5 | TDSQL PG好    |   104 | 2022-01-01
  3 | TDSQL PG Good |   102 | 2022-01-01
  6 | tbase         |   105 | 2022-01-01
  1 | tbase         |   110 | 2022-01-01
  (6 rows)

tbase_insert 表中 更新 id = 3 所在行的 name 列的值为 tbase ok

tdsql=# UPDATE tbase_insert SET name = 'tbase ok' WHERE id = 3;
UPDATE 1

tdsql=# select * from tbase_insert;
id |    name    | value | create_ts  
----+------------+-------+------------
2 | tbase      |   101 | 2022-01-01
4 | TDSQL PG   |   103 | 2022-01-01
5 | TDSQL PG好 |   104 | 2022-01-01
6 | tbase      |   105 | 2022-01-01
1 | tbase      |   110 | 2022-01-01
3 | tbase ok   |   102 | 2022-01-01
(6 rows)

3、 唯一性约束冲突。
当表上有唯一性约束时,更新为相同的记录,系统会报错,如,tbase_insert 表中 id 为主键。

tdsql=# select * from tbase_insert;
id |    name    | value | create_ts  
----+------------+-------+------------
  2 | tbase      |   101 | 2022-01-01
  4 | TDSQL PG   |   103 | 2022-01-01
  5 | TDSQL PG好 |   104 | 2022-01-01
  6 | tbase      |   105 | 2022-01-01
  1 | tbase      |   110 | 2022-01-01
  3 | tbase ok   |   102 | 2022-01-01
(6 rows)

tdsql=# UPDATE tbase_insert SET id=3 where value = 105;
ERROR:  (23505) duplicate key value violates unique constraint "tbase_insert_pkey"
DETAIL:  Key (id)=(3) already exists.

说明:

在分布式TDSQL PG中,首列默认为分布键,因此报错信息为:

ERROR: (42P10) Distributed column "ID" can't be updated in current version

value = 105 这一行记录的 id 改为 3,会和当前 id = 3 的记录冲突。
4、 多表关联更新数据。
示例中找到 update_tablei 列和 src_tablei 列相同的记录,将 update_tablej 列值更新为 src_table 对应记录的 j 列值。

tdsql=# create table update_table(i int, j int);
CREATE TABLE
tdsql=# insert into update_table values (1,1);
INSERT 0 1
tdsql=# create table src_table(i int, j int);
CREATE TABLE
tdsql=# insert into src_table values (1,2);
INSERT 0 1
tdsql=# select * from update_table;
 i | j 
---+---
 1 | 1
(1 row)
tdsql=# update update_table set j=src_table.j from src_table where update_table.i=src_table.i;
UPDATE 1
tdsql=# select * from update_table;
i | j 
---+---
 1 | 2
(1 row)

5、 update返回更新的数据
通过returning返回更新结果,可以减少与数据库的交互次数。示例:

tdsql=# update update_table set j=3 returning *;
 i | j 
---+---
 1 | 3
(1 row)

UPDATE 1