Rey*_*rPM 5 sql-server update sql-server-2016
我有下表fields
:
+----------+---------+-----------------+-------------+---------+--------------+---------------+-----------+------------------------------+-------------+------------------+
| field_id | form_id | form_section_id | is_required | grid_id | is_base_grid | field_type_id | field_seq | field_name | field_class | field_class_data |
+----------+---------+-----------------+-------------+---------+--------------+---------------+-----------+------------------------------+-------------+------------------+
| 220481 | 9926 | NULL | 0 | NULL | NULL | 4 | 28 | Test | NULL | NULL |
| 281863 | 9926 | NULL | 0 | NULL | NULL | 10 | 29 | insert after yes no question | NULL | NULL |
| 220496 | 9926 | NULL | 0 | 11 | 1 | 5 | 30 | test | NULL | NULL |
| 249234 | 9926 | NULL | 0 | 12 | 1 | 5 | 32 | | NULL | NULL |
| 279877 | 9926 | NULL | 0 | NULL | NULL | 4 | 33 | Test Text Questions | NULL | NULL |
| 281860 | 9926 | NULL | 0 | NULL | NULL | 10 | 34 | Something | NULL | NULL |
| 281914 | 9926 | NULL | 0 | 23 | 1 | 5 | 35 | sssss | NULL | NULL |
| 281960 | 9926 | NULL | 0 | 38 | 1 | 5 | 36 | yuyuyu | NULL | NULL |
| 281972 | 9926 | NULL | 0 | 40 | 1 | 5 | 40 | ttttt | NULL | NULL |
+----------+---------+-----------------+-------------+---------+--------------+---------------+-----------+------------------------------+-------------+------------------+
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,在这种情况下有两个field_seq
具有相同的值36
。
假设我正在插入一个新行,field_id=281960
而field_seq
这样的新行的36
.
我需要构建一个查询甚至一个存储过程,我可以在其中找出是否存在field_seq
等于或大于的行,36
如果是,则将 的值更新field_seq
为当前值 plus 1
。
前任:
INSERT INTO `fields` VALUES(9999, 9926, NULL, 0, 41, 1, 5, 36, 'lllll', NULL, NULL);
Run Code Online (Sandbox Code Playgroud)
有了这个,请参阅下面的可能案例(每个案例后面都有示例):
情况 1: field_seq=36 的行已经存在于表中
field_seq=36
新行field_seq=current+1
将变为37
37
已经存在则重复上一步直到不再重复field_seq
前:
+----------+---------+-----------------+-------------+---------+--------------+---------------+-----------+-------------+-------------+------------------+
| field_id | form_id | form_section_id | is_required | grid_id | is_base_grid | field_type_id | field_seq | field_nanme | field_class | field_class_data |
+----------+---------+-----------------+-------------+---------+--------------+---------------+-----------+-------------+-------------+------------------+
| 281914 | 9926 | NULL | 0 | 23 | 1 | 5 | 32 | sssss | NULL | NULL |
| 281972 | 9926 | NULL | 0 | 40 | 1 | 5 | 36 | ttttt | NULL | NULL |
| 281960 | 9926 | NULL | 0 | 38 | 1 | 5 | 37 | yuyuyu | NULL | NULL |
| 281978 | 9926 | NULL | 0 | 38 | 1 | 5 | 38 | vvvvv | NULL | NULL |
+----------+---------+-----------------+-------------+---------+--------------+---------------+-----------+-------------+-------------+------------------+
Run Code Online (Sandbox Code Playgroud)
后:
+----------+---------+-----------------+-------------+---------+--------------+---------------+-----------+---------------------+-------------+------------------+
| field_id | form_id | form_section_id | is_required | grid_id | is_base_grid | field_type_id | field_seq | field_nanme | field_class | field_class_data |
+----------+---------+-----------------+-------------+---------+--------------+---------------+-----------+---------------------+-------------+------------------+
| 281914 | 9926 | NULL | 0 | 23 | 1 | 5 | 32 | sssss | NULL | NULL |
| 9999 | 9926 | NULL | 0 | 41 | 1 | 5 | 36 | lllll | NULL | NULL | => new row inserted here
| 281972 | 9926 | NULL | 0 | 40 | 1 | 5 | 37 | ttttt | NULL | NULL | => this was 36 now is updated to 37
| 281960 | 9926 | NULL | 0 | 38 | 1 | 5 | 38 | yuyuyu | NULL | NULL | => this was 37 now is updated to 38
| 281978 | 9926 | NULL | 0 | 38 | 1 | 5 | 39 | vvvvv | NULL | NULL | => this was 38 now is updated to 39
| 220524 | 9926 | NULL | 0 | NULL | NULL | 5 | 40 | Patient Information | NULL | NULL | => we don't care about this cause there is room for one more, if one insert makes the rows above become 40 then this needs to be updated to 41
+----------+---------+-----------------+-------------+---------+--------------+---------------+-----------+---------------------+-------------+------------------+
Run Code Online (Sandbox Code Playgroud)
情况 2: field_seq=36 的行已经存在于表中,但 nextfield_seq
大于37
field_seq=36
新行field_seq=current+1
将变为37
field_seq
前:
+----------+---------+-----------------+-------------+---------+---------------+---------------+-----------+------------+-------------+
| field_id | form_id | form_section_id | is_required | grid_id | is_base_grid | field_type_id | field_seq | field_name | field_class |
+----------+---------+-----------------+-------------+---------+---------------+---------------+-----------+------------+-------------+
| 281914 | 9926 | NULL | 0 | 23 | 1 | 5 | 32 | sssss | NULL |
| 281972 | 9926 | NULL | 0 | 40 | 1 | 5 | 36 | ttttt | NULL |
| 281972 | 9926 | NULL | 0 | 40 | 1 | 5 | 40 | ooooo | NULL |
+----------+---------+-----------------+-------------+---------+---------------+---------------+-----------+------------+-------------+
Run Code Online (Sandbox Code Playgroud)
后:
+----------+---------+-----------------+-------------+---------+---------------+---------------+-----------+------------+-------------+
| field_id | form_id | form_section_id | is_required | grid_id | is_base_grid | field_type_id | field_seq | field_name | field_class |
+----------+---------+-----------------+-------------+---------+---------------+---------------+-----------+------------+-------------+
| 281914 | 9926 | NULL | 0 | 23 | 1 | 5 | 32 | sssss | NULL |
| 281972 | 9926 | NULL | 0 | 41 | 1 | 5 | 36 | lllll | NULL | => new row inserted here
| 281972 | 9926 | NULL | 0 | 40 | 1 | 5 | 37 | ttttt | NULL | => previous row with field_seq=36 was updated to 37
| 281972 | 9926 | NULL | 0 | 40 | 1 | 5 | 40 | ooooo | NULL | => nothing happen to this one since there is room for more
+----------+---------+-----------------+-------------+---------+---------------+---------------+-----------+------------+-------------+
Run Code Online (Sandbox Code Playgroud)
我使用的是 Microsoft SQL Server 2016 (SP1)。我怎么能做到这一点?
你可以尝试一下:
--enter procedure with insert parameters
DECLARE @field_seq INT = 36
DECLARE @field_seq_range INT
IF EXISTS(SELECT * FROM fields WHERE field_seq = @field_seq)
BEGIN
SELECT @field_seq_range = MIN(f.field_seq)
FROM (
SELECT field_seq, LEAD(field_seq, 1, NULL) OVER (ORDER BY field_seq) next_field_seq
FROM fields
) f
WHERE f.field_seq >= @field_seq
AND f.field_seq + 1 < f.next_field_seq
UPDATE f
SET f.field_seq = f.field_seq + 1
FROM fields f
WHERE f.field_seq BETWEEN @field_seq AND @field_seq_range
END
--perform insert
Run Code Online (Sandbox Code Playgroud)
该代码将检查是否存在冲突,field_seq.
如果存在,它将扫描表以查找下一个间隙,更新field_seq
该范围内的所有值,并留下一个间隙来插入新记录。如果没有发现冲突,则跳过更新。不过,我无法对此性能做出任何保证。我确信有更优化的方法可以做到这一点。
这是dbfiddle - 您可以看到更新发生之前和之后,为插入创建了一个间隙。