有时,人们可能希望将某些数据从一列移动到另一列。通过移动(与复制相对应),我的意思是在执行操作之前新列原来是null,并且在执行操作之后应将旧列设置为null
我有一个如此定义的表:
CREATE TABLE photos(id BIGSERIAL PRIMARY KEY, photo1 BYTEA, photo2 BYTEA);
假设表中有一个条目photo1
包含一些数据,photo2
为NULL
。我想UPDATE
photo1
成为NULL
而photo2
包含最初位于photo1
的数据{。{1}}。
为简洁起见,我发出以下SQL命令(WHERE
子句):
UPDATE photos SET photo2 = photo1, photo1 = NULL;
似乎有效。
我也是这样试过的:
UPDATE photos SET photo1 = NULL, photo2 = photo1;
它似乎也有效。
但它能保证有效吗?具体来说,在 photo1
设置为NULL
之前,photo2
可以设置为photo1
,从而导致我以NULL
结束在两个栏目中?
另外,当我的UPDATE
很大时,这个标准BYTEA
语法似乎效率低,因为photo2
必须从photo1
逐字节复制,当一个简单的指针交换可能已经足够。也许有一种我不了解的更有效的方式?
答案 0 :(得分:4)
这绝对是安全的。
UPDATE
中的列引用是指旧列,而不是新值。实际上没有办法从另一列引用计算出的新值。
参见,例如
CREATE TABLE x (a integer, b integer);
INSERT INTO x (a,b) VALUES (1,1), (2,2);
UPDATE x SET a = a + 1, b = a + b;
结果
test=> SELECT * FROM x;
a | b
---+---
2 | 2
3 | 4
...而且作业的顺序并不重要。如果你试图乘以 - 赋值,你就会得到
test=> UPDATE x SET a = a + 1, a = a + 1;
ERROR: multiple assignments to same column "a"
因为两个表达式引用旧的元组值并且顺序不重要,所以多次分配给同一列是没有意义的。
但是,为避免在这种情况下重写完整表格,我只会ALTER TABLE ... ALTER COLUMN ... RENAME ...
然后CREATE
使用旧名称的新列。