我试图了解如何使用function-based index正常工作,如果函数依赖于来自另一个(不是创建索引的那个)表的数据。
假设,我有以下测试数据:
SQL> drop table table_with_data;
2 drop table table_test_a;
3 drop table table_test_b;
4
5 create table table_with_data (data_id integer, val1 number);
6 create table table_test_a (val1 number, val2 varchar2(100));
7 create table table_test_b (val1 number, val2 varchar2(100));
8
9 insert into table_with_data values (1,1);
10 insert into table_with_data values (10,2);
11 insert into table_with_data values (30,3);
12
13 insert into table_test_b values (1, 'one');
14 insert into table_test_b values (20, 'two');
15 insert into table_test_b values (30, 'three');
16
17 insert into table_test_a values (1, 'first');
18 insert into table_test_a values (2, 'second');
19 insert into table_test_a values (3, 'third');
另外,我定义了一个函数:
SQL> create or replace function test_func(val_in number)
2 return number deterministic as
3 output number;
4 begin
5 select val1
6 into output
7 from table_with_data
8 where data_id = val_in;
9
10 return output;
11 end;
加快这样的查询
SQL> select a.*, (select b.val2
2 from table_test_b b
3 where test_func(b.val1) = a.val1)
4 from table_test_a a;
我决定使用function-based index
SQL> create index test_func_indx on table_test_b(test_func(val1));
它工作正常。
但是如果有人会更新table_with_data中的值
SQL> update table_with_data set data_id = 20 where val1 = 2;
上述查询的输出不会改变。
如果函数依赖于来自另一个表的数据,是否有任何正确的方法来更新基于函数的索引?
或者在这种情况下还有其他方法可以构建基于函数的索引?
只有始终为相同参数 - 确定性函数返回相同结果的函数才能被索引。这就是为什么在函数依赖于来自另一个表的数据时更新基于函数的索引是无效的并且为null。除了确定性之外,PostgreSQL和Oracle数据库要求在索引中使用时声明函数是确定性的,因此您必须使用关键字DETERMINISTIC(Oracle)或IMMUTABLE(PostgreSQL)。
但是如果你更新table_with_data它不再是确定性的
update table_with_data set data_id = 1 where val1 = 2;
和oracle不允许在用户定义的函数上使用基于非确定性函数的索引。