在PostgreSQL的UPDATE命令RETURNING子句中返回旧值OLD
在PostgreSQL的UPDATE命令中,可以使用子句RETURNING返回值。默认情况下,RETURNING只返回新值,即NEW值。但是有些情况下,我们需要知道更新之前的旧值,即OLD值,以便决定是否需要进行其它操作。本文将介绍使用UPDATE命令中RETURNING子句,返回OLD值的方法。
1、需求原因
在实际应用中,我们更新数据记录之后,需要根据旧值来判断是否需要执行其它操作。这时至少有两种解决方案:
- 在更新之前先查询一次,把旧值取出来。在更新前后,判断是否需要执行其它操作。
- 在更新数据时,同时将旧值取出来,以便判断是否需要执行其它操作。
在上述第1种方案中,不管是否需要在更新前后执行其它操作,都需要执行一次查询;也就是说,至少需要执行两次查询,甚至更多。而第2种方法,在更新数据后,如果不需要执行其它操作,则只需要执行一次查询即可。虽然第1种方案也可以实现预期,但是显然,从查询次数来说,第2种方案更优。
2、解决方案
2.1 为需要返回旧值的字段创建备用字段
在表中创建字段时,将需要返回旧值的字段分别额外建立一个备用字段。在更新时,同时将旧值更新到备用字段,并在返回时一并返回。例如在table_name表中,new_field和old_field是它的字段。其中new_field是需要返回旧值的字段,old_field是它的备用字段。则在更新new_field时,可以用如下代码返回new_field的旧值:
UPDATE table_name SET new_field = 'new', old_field = new_field WHERE condition RETURNING old_field;
在上述例句中,可以通过修改RETURNING子句来控制返回的旧值数据范围。这种方案有个弊端,就是old_field从某种意义上说,属于冗余字段,会造成数据冗余。
2.2 使用UPDATE的FROM子句
先在UPDATE的FROM子句中,将旧值取出来,并保存到一个别名中;再在RETURNING子句中,将所需的旧值返回给查询端。详细示例代码如下:
UPDATE table_name n
SET user_id = 1, user_name = 'jack'
FROM (SELECT user_id, user_name FROM table_name WHERE user_id = 1 FOR UPDATE) o
WHERE n.user_id = o.user_id
RETURNING o.user_id AS old_id, o.user_name AS old_name, n.user_id, n.user_name;
使用此方法,可以在RETURNING子句中任意地设置返回的旧值和新值。相比于上一种方法,该种方法更为灵活,修改起来更为简便。
3、其它说明
本文仅就查询次数和使用简便灵活进行了分析,并未考虑不同查询类型的性能差异。有兴趣的小伙伴可以自行测试。