繁体   English   中英

SQL:使用移位插入到唯一列

[英]SQL: insert to unique column with shift

我需要使用 varchar 名称和 Integer intValue 存储数据。 所有整数值都是唯一的,我需要遵守该合同

我需要使用以下规则编写查询以添加元素:如果插入后存在 intValue 重复 - 我们需要增加现有元素的 intValue 以解决冲突。 重复该操作,直到没有冲突为止。

例子:

B | 2  |                      | B | 2  |
C | 3  |                      | E | 3  |
D | 4  | => insert (E 3) =>   | C | 4  | 
A | 1  |                      | D | 5  |
Z | 7  |                      | A | 1  |
                              | Z | 7  |                                            

唯一的想法是在循环中运行更新查询,但这看起来效率太低了。

我需要在 Spring JPA 中编写这个查询,所以唯一的要求是查询不应该是特定于数据库的

商业案例:

假设队列中有一个人。 而 intValue 是队列中的位置。 因此,“添加”意味着有人来付钱并说:我不想成为队列中的最后一个。 例如,我想成为第三个。 所以你拿了钱,把那个人放在一个队列中,这样其他人在他之后 - 增加他们的位置。

与队列的唯一区别 - 在我的情况下允许有间隙

啊哈,我们可以说是由于人们离开队列而造成的。

让我们试试这个。 循环是不可避免的——要么是服务器做的,要么我们可以像 SQL 一样做。

-- prepare test data
declare @PeopleQueue table (pqname varchar(100), intValue  int);

insert into @PeopleQueue

        SELECT 'B' AS pqname, 2 as intValue  UNION ALL
        SELECT 'C' AS pqname, 3 as intValue  UNION ALL
        SELECT 'D' AS pqname, 4 as intValue  UNION ALL
        SELECT 'A' AS pqname, 1 as intValue  UNION ALL
        SELECT 'Z' AS pqname, 7 as intValue  
;
        --SELECT '' AS pqname, 0 as intValue  UNION ALL

Select * from @PeopleQueue;  - verify good test data

-- Solve the problem
Declare @pqnameNEW varchar(100) = 'E';
Declare @intNEW  int = 3;   -- 3 for conflict,  or for no conflict, use 13
Declare @intHIGH int;

IF  EXISTS ( SELECT 1 FROM @PeopleQueue WHERE intValue = @intNEW )
BEGIN
        -- find the end of the sequence, before the gap
        SET @intHIGH = (
        SELECT  TOP 1
                intValue   
        FROM    @PeopleQueue pq
        WHERE   NOT EXISTS
                (
                SELECT  NULL
                FROM    @PeopleQueue pn 
                WHERE   pn.intValue = pq.intValue + 1
                )
        AND     pq.intValue >= @intNEW
        )
        ;
        -- now Update all from intNEW thru intHIGH
        UPDATE @PeopleQueue
          SET intValue = intValue + 1
          WHERE intValue >= @intNEW
          AND   intValue <= @intHIGH

End;

-- finally insert the new item
INSERT into @PeopleQueue Values (@pqnameNEW, @intNEW);


Select * from @PeopleQueue;  -- verify correct solution

编辑--11/28 17:00 或者,估计 Bump-the-Line-Inserts 的数量(vs 附加到末尾插入),并将 intValues 设计为最初是十 (10) 的倍数,以便长序列更新被最小化。

update queue 
SET intValue = intValue + 1
WHERE intValue >= 3 
AND intValue <= (
    SELECT q1.intValue 
    FROM queue as q1 LEFT JOIN queue AS q2 ON q1.intValue + 1 = q2.intValue 
    WHERE q2.name is NULL AND q1.intValue > 3
    ORDER BY q1.intValue 
    LIMIT 1
)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM