使用 SQL 中的巧妙语句以连续方式将列值更改为多条记录

Posted

技术标签:

【中文标题】使用 SQL 中的巧妙语句以连续方式将列值更改为多条记录【英文标题】:Changing a column value to several records in a consecutive fashion using clever statements in SQL 【发布时间】:2022-01-04 17:11:55 【问题描述】:

我有一个 Postgres 表,其中有一个订单视图字段,我正在使用带有 express 的 Nodejs

这个订单视图是 INTEGER 类型,并且有 NOT NULL 和 UNIQUE 的约束

插入新记录可能会带来问题,因为如果现有记录的视图顺序为 [1, 2, 3, 4, 5],而新记录的顺序视图为 4,那么当前的4要改成5,当前的5要改成6

(我强制这个订单视图是连续的数字,从前端)

我希望在服务器端执行此插入过程(更新现有记录的订单视图)

我想到的是在终点执行一个循环,通过读取订单视图大于或等于新订单视图的记录,并将其更新为 (current + 1)

另一个问题是另一个表中的相关记录,但我认为可以通过级联更新来进行

有人可以找出一个不需要编写循环的 SQL 语句吗?

拉斐尔

【问题讨论】:

【参考方案1】:

您可以在单个语句中完成插入和更新。但首先您需要(很可能)更改唯一约束以使其成为deferrable。

alter table <table name>  
  drop constraint if exists <order view constraint name>;
alter <table name> 
  add constraint <order view constraint name> 
        unique(order_view) 
        deferrable initially deferred;

Postgres 允许在 cte 中使用 DML,因此现在您可以编写 SQL 语句来完成这两个操作:

with updt as
     ( update <table name>  
          set order_view = order_view+1 
        where order_view >= :new_order_view
     ) 
insert into test (order_view, <other columns list>) 
   values (:new_order_view, <other columns list values>);

其中 <...> 是适当的名称/值。见demo。以上也可以用作 SQL 过程 - 也在演示处理中插入作为最后一项自动设置适当的值。虽然是一个过程,但它仍然只是单个 SQL 语句,因此可以将其拉出并独立运行。 缺点:

Order_view 指定为 0。结果将重新排序导致跳过 Order_view = 1。 Order_view 指定 > 当前 Max+1。结果按指定存储,因此产生了间隙。 受多用户竞争条件的影响。 所有基于 Max+1 的作业也是如此。

【讨论】:

【参考方案2】:

几乎从不需要在 SQL 中执行任何类型的“循环”——您只需要考虑您正在使用的行的集合,以及它们的共同点。

在这种情况下:

order_view 小于 4 的行不需要更改 order_view 为 4 或更高的行需要增加 1,以“腾出空间”

所以SQL真的很简单:

UPDATE some_table
SET order_view = order_view + 1
WHERE order_view >= 4

【讨论】:

以上是关于使用 SQL 中的巧妙语句以连续方式将列值更改为多条记录的主要内容,如果未能解决你的问题,请参考以下文章

KeyError:在熊猫中尝试使用.loc方法将布尔列值更改为字符串时

SQL:将列值链接到列名以满足某些条件

SQL 将列值拆分为 Netezza 中的行

根据循环内另一列的值将列的值更改为nan

如果下拉列值更改为某个值,则动态禁用TextBoxFor

如何从 PySpark Dataframe 中删除重复项并将剩余列值更改为 null