在我的数据库中,我有一个带有列的表,指示每条记录的代码(除了ID列)。此字段是唯一的,每次用户尝试将记录插入表中时,应将第一个未使用的代码分配给记录。现在,表格中包含以下顺序的代码列:
+------+
code
+------+
1
+------+
2
+------+
3
+------+
5
+------+
我希望查询返回4作为结果。 请注意,此查询在我的系统中非常频繁,并且将以最短的执行时间进行最佳查询。
答案 0 :(得分:2)
使用自联接是否可以接受?如果是这样的话:
-- your test data:
WITH data AS (SELECT 1 AS code FROM DUAL
UNION SELECT 2 FROM DUAL
UNION SELECT 3 FROM DUAL
UNION SELECT 5 FROM DUAL)
-- request:
SELECT COALESCE(MIN(d1.code+1),1)
FROM data d1 LEFT JOIN data d2 ON d1.code+1 = d2.code
WHERE d2.code IS NULL;
这将构建没有后继的data.code
列表。使用MIN(...+1)
,您将获得第一个空插槽。我使用COALESCE(...)
来处理数据表中没有任何条目的特定情况。
使用序列生成器的替代形式可能可以带来更好的性能,因为不需要遍历整个表来执行聚合函数MIN()
:
-- your test data:
WITH data AS (SELECT 1 AS code FROM DUAL
UNION SELECT 5 FROM DUAL
UNION SELECT 2 FROM DUAL
UNION SELECT 3 FROM DUAL)
-- request:
SELECT T.code FROM (SELECT d1.code
FROM (SELECT LEVEL code FROM DUAL CONNECT BY LEVEL < 9999) d1 LEFT JOIN data d2
ON d1.code = d2.code
WHERE d2.code IS NULL
ORDER BY d1.code ASC
) T WHERE ROWNUM < 2
缺点是你现在有一个硬编码的上限。它可能是从数据表中动态推断出来的。所以是不是真的阻止。我让你自己比较时间。
此字段是唯一的,每次用户尝试将记录插入表中时,应将第一个未使用的代码分配给记录
请注意,如果两个并发会话尝试同时插入一行,则会导致竞争条件。根据您的示例,他们都会尝试使用code = 4
插入一行 - 显然两者都不会成功,因为您的列是唯一的...
答案 1 :(得分:1)
我最近使用以下代码:
SELECT t1.id+1
FROM table t1
LEFT OUTER JOIN table t2 ON (t1.id + 1 = t2.id)
WHERE t2.id IS NULL
and rownum = 1
ORDER BY t1.id;
每次我需要插入新行并使用最小未使用的 id 时,我都会运行它。
我希望它适用于您的目的。
答案 2 :(得分:0)
select level unusedval from dual connect by level < 10
minus
select tno from t2);
您可以根据最大值更改级别条件。