【问题标题】:Update sub-index when inserting in SQL在 SQL 中插入时更新子索引
【发布时间】:2015-12-25 19:14:11
【问题描述】:

我有一张简化后的表格,如下所示:

group   index    value
1       1        text 1
1       2        text 2
1       3        text 3
2       1        text 4
2       2        text 5
2       3        text 6

Group 是一个外键,也用于对表中的项目进行分组。

Index 是用于对组内的项目进行排序的内部索引。

文本只是一个值。

然后,如果我执行插入或运行存储过程来执行插入

INSERT INTO Table VALUES (1, 2, 'new text')

我想更新第 1 组项目的索引,使表格如下所示:

group   index    value
1       1        text 1
1       2        new text (inserted)
1       3        text 2   (index updated)
1       4        text 3   (index updated)
2       1        text 4
2       2        text 5
2       3        text 6

(在 MS SQL-Server 2008 上运行)

【问题讨论】:

  • 当用户删除记录/更新一条时怎么办?

标签: sql sql-server sql-insert


【解决方案1】:

这是您可以使用的存储过程。接受 3 个参数,grp、idx 和 value:

CREATE PROCEDURE ReIndex
@grp int,
@idx int,
@value nvarchar(30)
AS
IF NOT EXISTS(SELECT 1 FROM [tbl] WHERE grp = @grp and idx =@idx)
INSERT INTO tbl VALUES (@grp, @idx, @value)
else
update tbl
set idx = idx+1
where
grp =@grp and
idx >= @idx

INSERT INTO tbl VALUES (@grp, @idx, @value)

用法:

exec reindex 1, 2, 'new text'

sqlfiddle:http://sqlfiddle.com/#!3/3323d/11

【讨论】:

  • 绝妙的答案!我要收藏它以备将来使用!
【解决方案2】:

在这个答案中,我假设第一列名称是 grpidx,分别为 groupindex 是 SQL 中的保留字。

您可以使用MAX(idx)+1 公式来使用下一个可用的idx 值,如下所示:

INSERT INTO t1(grp, idx, value)
SELECT 1, IFNULL(MAX(idx),0)+1, 'new text'
FROM   t1
WHERE  grp = 1;

但是这种方式大约在同一时间插入的两条记录可能会得到相同的 idx 值。为避免这种情况,您可以在插入记录时锁定表。您可以通过使用表锁定/解锁语句包装上述语句来做到这一点:

LOCK TABLES t1;
...
UNLOCK TABLES;

但是,此方法不能在过程中使用。该解决方案涉及创建事务和SELECT ... FOR UPDATE。请注意,您需要InnoDB Storage

CREATE PROCEDURE ins_val(IN pgrp int, IN pvalue varchar(200)) 
BEGIN
    DECLARE newidx INT;
    START TRANSACTION;

        SELECT IFNULL(MAX(idx),0)+1
        INTO   newidx
        FROM   t1
        WHERE  grp = pgrp;
        FOR UPDATE;

        INSERT INTO t1(grp, idx, value)
        VALUES (pgrp, newidx, pvalue);

    COMMIT;
END;

请注意,如果您稍后删除记录,这些将在 idx 编号中留下空白,上述方法不会再次填充。另一方面,如果删除了具有最高 idx 值的记录,则下一个插入的记录将重新使用该 idx 值。

【讨论】:

    猜你喜欢
    • 2012-03-31
    • 1970-01-01
    • 2021-12-14
    • 1970-01-01
    • 1970-01-01
    • 2020-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多