当我想写类似的东西时,我经常卡住
IF v_shortname IN (SELECT sname FROM table)
或者
IF EXISTS (SELECT sname FROM mmstrephdr
WHERE sname= v_short)
我知道 EXISTS 和 IN 不能那样工作。而且我总是可以调整我的代码以获得这样的结果,但我总是想知道 SQL 中是否有一个编程结构可以为我完成这项工作!
如果您摆脱IF
前缀,IN()
并以这种EXISTS()
方式工作。
首先,使用的版本IN()
通常是 Bad Idea™ - 在性能方面,您最好使用 JOIN 或派生表而不是 WHERE 子句中的子查询。
-- instead of:
SELECT * FROM tbl1 WHERE tbl1.v_short IN (SELECT tbl2.sname FROM tbl2)
-- you would want something like:
SELECT tbl1.* FROM tbl1 JOIN tbl2 ON (tbl2.sname = tbl1.v_short)
EXISTS()
另一方面是非常有用的。它被优化为与 INNER JOIN 相同,同时NOT EXISTS()
与带有 IS NULL 检查的 LEFT JOIN 相同。该[NOT] EXISTS()
版本更容易阅读,就好像它是英文一样。请注意,将列列表传递给 EXISTS 中的 SELECT 是没有意义的——它没有被使用,它每次都被优化为 SELECT *。
-- easy to read:
SELECT * FROM tbl1 WHERE EXISTS (SELECT * FROM tbl2 WHERE tbl2.sname = tbl1.v_short)
-- same thing, just more SQL-like than English-like:
SELECT tbl1.* FROM tbl1 JOIN tbl2 ON (tbl2.sname = tbl1.v_short)
你为什么会卡住?PL/SQL 提供了允许我们实现该逻辑的结构。
declare
.....
function name_exists (p_sname table_a.sname%type)
return boolean
is
l_shortname table_a.sname%type;
begin
SELECT sname
FROM table_a
where sname = p_sname;
return true;
exception
when no_data_found then
return false;
end name_exists;
....
begin
....
if name_exists ('KNOX') then
还有其他方法可以做到这一点,但我喜欢嵌套函数的封装。