如何从Oracle中的列中获取最小的未使用数量?

时间:2014-09-20 09:51:43

标签: oracle oracle11g

在我的数据库中,我有一个带有列的表,指示每条记录的代码(除了ID列)。此字段是唯一的,每次用户尝试将记录插入表中时,应将第一个未使用的代码分配给记录。现在,表格中包含以下顺序的代码列:

+------+
code
+------+
1
+------+
2
+------+
3
+------+
5
+------+

我希望查询返回4作为结果。 请注意,此查询在我的系统中非常频繁,并且将以最短的执行时间进行最佳查询。

3 个答案:

答案 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);

您可以根据最大值更改级别条件。