使用单个SQL查询测试列的顺序性

时间:2010-05-13 11:34:45

标签: sql mysql

我有一个包含多组连续数据集的表,如下所示:

ID set_ID some_column n
1 'set-1' 'aaaaaaaaaa' 1
2 'set-1' 'bbbbbbbbbb' 2
3 'set-1' 'cccccccccc' 3
4 'set-2' 'dddddddddd' 1
5 'set-2' 'eeeeeeeeee' 2
6 'set-3' 'ffffffffff' 2
7 'set-3' 'gggggggggg' 1

在对这些行进行多种类型修改的事务结束时,我想确保在单个集合中,“n”的所有值仍然是顺序的(否则回滚)。它们不需要按照PK的顺序排列,只需按顺序排列,如1-2-3或3-1-2,但不要像1-3-4或1-2-3-3-4。

由于单个集合中可能有数千行,我宁愿在数据库中执行此操作,以避免在进行一些小的更改后仅仅为了验证而获取数据的开销。

还存在并发问题。锁定InnoDB(可重复读取)的方式(据我所知)是如果我在“n”上有一个索引,那么InnoDB也会锁定值之间的“间隙”。如果我将set_ID和n组合到一个索引中,是否会消除出现幻像行的问题?

在我看来,这是一个常见的问题。有什么好主意吗?

谢谢!

注意:使用MySQL + InnoDB

2 个答案:

答案 0 :(得分:1)

查找max - min + 1 > count

的序列
IF EXISTS (SELECT set_ID
             FROM mytable
            GROUP BY set_ID
           HAVING MAX(n) - MIN(n) + 1 > COUNT(n)
          )
    ROLLBACK

如果序列必须从1开始,请改为:

IF EXISTS (SELECT set_ID
             FROM mytable
            GROUP BY set_ID
           HAVING MIN(n) = 1 AND MAX(n) > COUNT(n)
          )
    ROLLBACK

您还需要避免重复的序列号。但这可以通过在set_IDn上创建唯一键来完成。

答案 1 :(得分:0)

试试这个:

IF EXISTS (SELECT set_ID
               FROM mytable
               GROUP BY set_ID
               HAVING MIN(n) = 1 AND MAX(n) <> COUNT(DISTINCT n)
          )
    ROLLBACK

适用于SQL Server(我没有MySql来试用):

DECLARE @YourTable table (ID int, set_ID char(5), some_column char(10),n int)
INSERT @YourTable VALUES (1, 'set-1' ,'aaaaaaaaaa' ,1)
INSERT @YourTable VALUES (2, 'set-1' ,'bbbbbbbbbb' ,2)
INSERT @YourTable VALUES (3, 'set-1' ,'cccccccccc' ,3)
INSERT @YourTable VALUES (4, 'set-2' ,'dddddddddd' ,1)
INSERT @YourTable VALUES (5, 'set-2' ,'eeeeeeeeee' ,2)
INSERT @YourTable VALUES (6, 'set-3' ,'ffffffffff' ,2)
INSERT @YourTable VALUES (7, 'set-3' ,'gggggggggg' ,1)
INSERT @YourTable VALUES (8, 'set-3' ,'ffffffffff' ,4)
INSERT @YourTable VALUES (9, 'set-3' ,'ffffffffff' ,4)

--this will list all "bad" sets
SELECT set_ID
    FROM @YourTable
    GROUP BY set_ID
    HAVING MIN(n) = 1 AND MAX(n) <> COUNT(DISTINCT n)

输出:

set_ID
------
set-3