为何Oracle内置程序LNNVL无法在DBA_PROCEDURES中查询到?
为什么LNNVL可正常执行但在DBA_PROCEDURES中查不到记录
核心原因很简单:LNNVL根本不是常规意义上的内置函数/存储程序,而是SQL引擎在语法层面直接识别处理的条件判断算子,从设计上就不会被收录到DBA_PROCEDURES视图里,它和你能查到的REGEXP_LIKE不属于同一类对象:
- REGEXP_LIKE是标准的内置函数,属于数据库里登记在册的可调用程序对象,不管是写在SELECT列表里返回值,还是放在WHERE子句中做条件判断都能正常使用,元数据会被完整记录在DBA_PROCEDURES中,所以用名称匹配可以查到对应记录。
- LNNVL从语法设计上就不是给用户当普通函数调用的:它仅能出现在WHERE、HAVING这类需要写判断条件的子句位置,作用是对传入条件的结果做反向补全——当传入条件返回FALSE或者NULL时返回TRUE,传入条件返回TRUE时返回FALSE。如果强行把它当普通函数写在SELECT列表里当返回值用,比如执行
select LNNVL(1=1) from dual,会直接抛出语法错误,连SQL解析阶段都过不了。这类语法级的特殊结构本质是解析器的识别规则,不是独立存在的程序单元,DBA_PROCEDURES作为存储程序元数据视图,本来就不会收录这类对象。
你可以通过两个简单测试验证这个差异:
- 把REGEXP_LIKE作为普通函数调用可顺利执行:
-- 执行后正常返回1,符合普通函数的行为特征 select 1 from dual where REGEXP_LIKE('abc','^a');
- 脱离条件位置在SELECT子句直接调用LNNVL会直接触发语法异常:
-- 无法通过SQL解析,证明其不是可独立返回值的函数对象 select LNNVL(1=1) from dual;
你之前执行的select 1 from dual where not(LNNVL(1=1));能正常运行,本质是SQL解析器在WHERE条件位置识别到了LNNVL特殊语法做了定向处理,不是像调用普通函数那样先去DBA_PROCEDURES里匹配对象元数据再执行。Oracle里这类可以在SQL中正常使用、但DBA_PROCEDURES查不到记录的语法级算子还有不少,比如层级查询用到的PRIOR、CONNECT_BY_ROOT都属于这类情况。
内容的提问来源于stack exchange,提问作者Pierre-olivier Gendraud
相关产品推荐
相关产品推荐

