2017-07-09 99 views
2

有时候,有人可能想要的某些数据从一列移动到另一列。通过移动(相当于拷贝),我的意思是在执行操作之前新列最初为空,并且在执行操作之后应将旧列设置为空。在PostgreSQL中将数据从一列移动到另一列

我有定义为这样的表:

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之前photo2设置为photo1,从而导致我在两列中结束NULL

顺便说一句,这个标准UPDATE语法似乎是低效的,当我BYTEA s为大,为photo2必须从photo1,当指针的简单交换可能已经足以复制逐字节。也许有一种我不知道的更有效的方式?

+0

是的,这是保证工作(和SQL标准要求) –

回答

3

这绝对安全。

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

+0

谢谢,这应该减少我对非确定性行为的恐惧。关于列重命名,我不能这样做,因为它不是一个完整的表重写。当我说“为了简洁而忽略WHERE子句”时,我的意思是在'UPDATE'语句中有'WHERE'子句,我省略了(因此并不是所有的行都会受到影响)。也许我不清楚这一点。 – Bernard

+0

我同意@ Jacobm001现在删除的帖子的评论,说你在从列到列移动数据方面做的事情有点奇怪。我会标准化为边桌,并将引用的FK更新为新照片。 –

+0

我在帖子被删除之前没有看到评论,并且我没有足够的声望查看删除的评论。您能否详细说明为什么使用边桌会更好,以及我是否应该仅仅为大数据(比如'BYTEA')或小文本字段来做这件事? – Bernard

相关问题