在PostgreSQL

时间:2017-07-09 03:52:01

标签: sql postgresql move

有时,人们可能希望将某些数据从一列移动到另一列。通过移动(与复制相对应),我的意思是在执行操作之前新列原来是null,并且在执行操作之后应将旧列设置为null

我有一个如此定义的表:

CREATE TABLE photos(id BIGSERIAL PRIMARY KEY, photo1 BYTEA, photo2 BYTEA);

假设表中有一个条目photo1包含一些数据,photo2NULL。我想UPDATE photo1成为NULLphoto2包含最初位于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逐字节复制,当一个简单的指针交换可能已经足够。也许有一种我不了解的更有效的方式?

1 个答案:

答案 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使用旧名称的新列。