在 PostgreSQL 中将数据从一列移动到另一列

Ber*_*ard 5 sql postgresql move

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

我有一个这样定义的表:

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

假设表中有一个条目,其中photo1包含一些数据,并且photo2NULL。我想做一个UPDATE查询,它photo1变成NULLphoto2包含最初在photo1.

我发出以下 SQL 命令(WHERE为简洁起见省略了子句):

UPDATE photos SET photo2 = photo1, photo1 = NULL;

它似乎工作。

我也这样试过:

UPDATE photos SET photo1 = NULL, photo2 = photo1;

它似乎也有效。

但它保证工作吗?具体来说,可以photo1设置为NULL before photo2设置为photo1,从而导致我NULL在两列中结束?

顺便说一句,UPDATE当我的BYTEAs 很大时,这种标准语法似乎效率低下,因为photo2必须从 逐字节复制photo1,当简单的指针交换可能就足够了。也许有一种我不知道的更有效的方法?

Cra*_*ger 5

这绝对是安全的。

在列引用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;
Run Code Online (Sandbox Code Playgroud)

结果是

test=> SELECT * FROM x;
 a | b 
---+---
 2 | 2
 3 | 4
Run Code Online (Sandbox Code Playgroud)

...并且分配的顺序并不重要。如果你尝试乘法赋值,你会得到

test=> UPDATE x SET a = a + 1, a = a + 1;
ERROR:  multiple assignments to same column "a"
Run Code Online (Sandbox Code Playgroud)

因为多次分配给同一列是没有意义的,因为两个表达式都引用了旧的元组值,并且顺序并不重要。

但是,为了避免在这种情况下,一个完整的表重写,我只想ALTER TABLE ... ALTER COLUMN ... RENAME ...CREATE与旧名称的新列。