为什么我在函数和匿名块中执行同一个查询时会得到两个不同的结果
Why am i getting two different results from same query when executing it in a function vs anonymous block
我有相同的逻辑来检查给定的 table 是否存在于我的数据库中。一方面,我将我的逻辑放在一个函数中,另一方面,我将我的逻辑放在一个匿名块中。当我调用该函数时,我得到一个答案,而当我 运行 匿名博克时,我得到另一个答案。
这是我的功能:
CREATE OR REPLACE FUNCTION table_exists(in_table_name IN varchar2) RETURN int
is
var_regex varchar2(30) := '(\w*)([^\.])';
var_exists number(1);
BEGIN
SELECT CASE WHEN EXISTS( SELECT 1 FROM all_tab_cols WHERE TABLE_NAME = UPPER( REGEXP_SUBSTR ( in_table_name, var_regex , 1, 2)))
THEN 1 ELSE 0 END INTO var_exists FROM dual;
DBMS_OUTPUT.PUT_LINE('var_exists is: ' || var_exists);
IF (var_exists = 1)
THEN
RETURN var_exists;
ELSE
RETURN var_exists;
END IF;
END;
这是我调用此函数的方式:
select table_exists('test_schama.test_table') as table_exits from DUAL;
函数return为零,表示table不存在。这不是真的,因为 'test_schama.test_table' 确实存在。
我的匿名块如下:
DECLARE
in_table_name varchar2(100) := 'test_schama.test_table';
var_regex varchar2(30) := '(\w*)([^\.])';
var_exists int;
BEGIN
SELECT CASE WHEN EXISTS( SELECT 1 FROM all_tab_cols WHERE TABLE_NAME = UPPER( REGEXP_SUBSTR ( in_table_name, var_regex , 1, 2)))
THEN 1 ELSE 0 END INTO var_exists FROM dual;
DBMS_OUTPUT.PUT_LINE('var_exists is: ' || var_exists);
END;
Var_exists这里的值为1,表示table存在。这是真的。
我不明白的是为什么我从同一个确切的查询中得到两个不同的答案?
您正在查询 all_tab_cols
。这会向您显示您有权访问的所有 table。那不一定是数据库中的所有table。在定义者权限存储的函数(例如您的 table_exists
)中,将您限制为函数所有者已被授予直接访问权限而不是通过角色访问的 tables。在匿名块中,all_tab_cols
将显示您可以通过当前会话中启用的角色访问的任何 table 的数据。由于匿名块有效而存储的函数无效,我假设该函数的所有者没有直接在 table 上授予访问权限,但您当前的会话确实具有具有该访问权限的已启用角色。
很可能,您需要
- 使用调用者权限存储函数(在这种情况下,
all_tab_cols
中的行将基于当前会话的权限),
- 改用
dba_tab_cols
数据字典table,或者
- 直接授予存储函数的所有者
select
对 table 的访问权限,而不是通过角色。
我有相同的逻辑来检查给定的 table 是否存在于我的数据库中。一方面,我将我的逻辑放在一个函数中,另一方面,我将我的逻辑放在一个匿名块中。当我调用该函数时,我得到一个答案,而当我 运行 匿名博克时,我得到另一个答案。 这是我的功能:
CREATE OR REPLACE FUNCTION table_exists(in_table_name IN varchar2) RETURN int
is
var_regex varchar2(30) := '(\w*)([^\.])';
var_exists number(1);
BEGIN
SELECT CASE WHEN EXISTS( SELECT 1 FROM all_tab_cols WHERE TABLE_NAME = UPPER( REGEXP_SUBSTR ( in_table_name, var_regex , 1, 2)))
THEN 1 ELSE 0 END INTO var_exists FROM dual;
DBMS_OUTPUT.PUT_LINE('var_exists is: ' || var_exists);
IF (var_exists = 1)
THEN
RETURN var_exists;
ELSE
RETURN var_exists;
END IF;
END;
这是我调用此函数的方式:
select table_exists('test_schama.test_table') as table_exits from DUAL;
函数return为零,表示table不存在。这不是真的,因为 'test_schama.test_table' 确实存在。
我的匿名块如下:
DECLARE
in_table_name varchar2(100) := 'test_schama.test_table';
var_regex varchar2(30) := '(\w*)([^\.])';
var_exists int;
BEGIN
SELECT CASE WHEN EXISTS( SELECT 1 FROM all_tab_cols WHERE TABLE_NAME = UPPER( REGEXP_SUBSTR ( in_table_name, var_regex , 1, 2)))
THEN 1 ELSE 0 END INTO var_exists FROM dual;
DBMS_OUTPUT.PUT_LINE('var_exists is: ' || var_exists);
END;
Var_exists这里的值为1,表示table存在。这是真的。 我不明白的是为什么我从同一个确切的查询中得到两个不同的答案?
您正在查询 all_tab_cols
。这会向您显示您有权访问的所有 table。那不一定是数据库中的所有table。在定义者权限存储的函数(例如您的 table_exists
)中,将您限制为函数所有者已被授予直接访问权限而不是通过角色访问的 tables。在匿名块中,all_tab_cols
将显示您可以通过当前会话中启用的角色访问的任何 table 的数据。由于匿名块有效而存储的函数无效,我假设该函数的所有者没有直接在 table 上授予访问权限,但您当前的会话确实具有具有该访问权限的已启用角色。
很可能,您需要
- 使用调用者权限存储函数(在这种情况下,
all_tab_cols
中的行将基于当前会话的权限), - 改用
dba_tab_cols
数据字典table,或者 - 直接授予存储函数的所有者
select
对 table 的访问权限,而不是通过角色。