【问题标题】:Changing a column value to several records in a consecutive fashion using clever statements in SQL使用 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 语句吗?

拉斐尔

【问题讨论】:

    标签: sql node.js postgresql express


    【解决方案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
      

      【讨论】:

        猜你喜欢
        • 2018-10-23
        • 2018-04-29
        • 2011-11-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-03-30
        相关资源
        最近更新 更多