【问题标题】:Function-based index behavior when function depends on data from another (not the one on which the index was created) table当函数依赖于另一个(不是创建索引的那个)表中的数据时,基于函数的索引行为
【发布时间】:2019-09-08 03:20:36
【问题描述】:

如果函数依赖于另一个(不是创建索引的那个)表中的数据,我正在尝试了解如何正确使用 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;

上述查询的输出没有改变。

如果函数依赖于另一个表中的数据,是否有任何适当的方法来更新基于函数的索引?

或者在这种情况下,也许还有其他方法可以构建基于函数的索引?

【问题讨论】:

  • @nikhilsugandh 你能更清楚地告诉我应该在哪里声明 val1 吗?我会修好它。在函数 test_func val1 是 select ... into 子句的一部分,据我所知,它不应该被声明。
  • 我的错!!!!!!!!!

标签: sql oracle indexing plsql


【解决方案1】:

只有对于相同参数总是返回相同结果的函数(确定性函数)才能被索引。这就是为什么如果函数依赖于另一个表中的数据,则更新基于函数的索引无效且为空的原因。 除了确定性之外,PostgreSQL 和 Oracle 数据库还要求在索引中使用函数时声明为确定性,因此您必须使用关键字 DETERMINISTIC (Oracle) 或 IMMUTABLE (PostgreSQL)。

但如果你更新 table_with_data 它不再是确定性的

update table_with_data set data_id = 1 where val1 = 2; 

oracle 不允许基于用户定义函数的非确定性函数索引。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-08-13
    • 2015-07-02
    • 2016-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-22
    相关资源
    最近更新 更多