PL/SQL 根据动态 table 名称创建视图

PL/SQL create view base on dynamic table name

我正在尝试创建一个视图来访问所有以相同名称开头的表,它们具有完全相同的结构,并且及时会有更多。

Table 姓名:

TEMP_ENTITIES_1000
TEMP_ENTITIES_1001
TEMP_ENTITIES_1002

以后还会有

TEMP_ENTITIES_1003
TEMP_ENTITIES_1004

等等...

我需要的是使用以下脚本中的表列表,然后使用对象名称结果列表的结果在视图中访问。

select object_name
from user_objects 
where object_type  = 'TABLE'
and object_name like upper('temp_entities_%');

create view entities_join as
select * from (object_name)

是否可以实现?

可能吗?是的,使用动态 SQL.

但是,根据您的描述,您使用的数据模型似乎错误。您应该只有一个具有 标识符 的 table 来产生差异(那些 1000、1001、... 值)。

那么你根本不需要一个视图,并且用那个单一的 table 做所有事情。我建议你考虑这样做。


以下是您可能会做的事情的示例(按照您的要求):

几个样本tables:

SQL> select * from temp_entities_1000;

        ID NAME
---------- ------
      1000 Little

SQL> select * from temp_entities_1001;

        ID NAME
---------- ----
      1001 Foot

SQL> select * from temp_entities_1002;

        ID NAME
---------- -----
      1002 Scott

程序:

SQL> DECLARE
  2     l_str  VARCHAR2 (2000);
  3  BEGIN
  4     FOR cur_r IN (SELECT object_name
  5                     FROM user_objects
  6                    WHERE     object_type = 'TABLE'
  7                          AND object_name LIKE 'TEMP_ENTITIES%')
  8     LOOP
  9        l_str :=
 10           l_str || ' select * from ' || cur_r.object_name || ' union all ';
 11     END LOOP;
 12
 13     l_str :=
 14           'create or replace view entities_join as '
 15        || RTRIM (l_str, ' union all');
 16
 17     EXECUTE IMMEDIATE l_str;
 18  END;
 19  /

PL/SQL procedure successfully completed.

结果:

SQL> select * from entities_join;

        ID NAME
---------- ------
      1000 Little
      1001 Foot
      1002 Scott

SQL>

每次创建新 table 时,您都必须 运行 该过程,以便将其包含在视图中。

在现代版本的 Oracle 中,您可以使用 SQL table macros 而无需任何计划。它将即时构建动态查询,并可用作普通视图。

示例如下:

SQL> insert all 
  2    when mod(rownum, 5) = 0 then into TEMP_ENTITIES_1000 values (l, dt, val) 
  3    when mod(rownum, 5) = 1 then into TEMP_ENTITIES_1001 values (l, dt, val) 
  4    when mod(rownum, 5) = 2 then into TEMP_ENTITIES_1002 values (l, dt, val) 
  5    when mod(rownum, 5) = 3 then into TEMP_ENTITIES_1003 values (l, dt, val) 
  6    when mod(rownum, 5) = 4 then into TEMP_ENTITIES_1004 values (l, dt, val) 
  7  
  8  select 
  9    level as l, 
 10    sysdate + level as dt, 
 11    level as val 
 12  from dual 
 13  connect by level < 10;

9 rows inserted.

SQL> 
SQL> create or replace function f_temp_entities_union 
  2  /*Create a macro*/
  3  return varchar2 SQL_MACRO
  4  is 
  5    v_union varchar2(4000); 
  6  begin 
  7    select listagg('select ''' || table_name || ''' as src, a.* from ' || table_name || ' a ', chr(10) || 'union all' || chr(10)) 
  8      into v_union 
  9    from all_tables 
 10    where table_name like 'TEMP_ENTITIES%' 
 11      and owner = sys_context('USERENV', 'CURRENT_SCHEMA') 
 12    ; 
 13  
 14    return v_union; 
 15  end;
 16  /

Function F_TEMP_ENTITIES_UNION compiled

SQL> 
SQL> select * 
  2  from f_temp_entities_union();
TEMP_ENTITIES_1000          5 20.09.21          5
TEMP_ENTITIES_1001          1 16.09.21          1
TEMP_ENTITIES_1001          6 21.09.21          6
TEMP_ENTITIES_1002          2 17.09.21          2
TEMP_ENTITIES_1002          7 22.09.21          7
TEMP_ENTITIES_1003          3 18.09.21          3
TEMP_ENTITIES_1003          8 23.09.21          8
TEMP_ENTITIES_1004          4 19.09.21          4
TEMP_ENTITIES_1004          9 24.09.21          9

9 rows selected. 

SQL> 
SQL> /*Add new table*/
SQL> create table TEMP_ENTITIES_1005 as select * from TEMP_ENTITIES_1001 where 1 = 0;

Table TEMP_ENTITIES_1005 created.

SQL> insert into TEMP_ENTITIES_1005
  2  select 1000 + rownum, sysdate + rownum, rownum - 100 from TEMP_ENTITIES_1000;

1 row inserted.

SQL> 
SQL> /*Check that new data is here*/
SQL> select *
  2  from v_demo;
TEMP_ENTITIES_1000          5 20.09.21          5
TEMP_ENTITIES_1001          1 16.09.21          1
TEMP_ENTITIES_1001          6 21.09.21          6
TEMP_ENTITIES_1002          2 17.09.21          2
TEMP_ENTITIES_1002          7 22.09.21          7
TEMP_ENTITIES_1003          3 18.09.21          3
TEMP_ENTITIES_1003          8 23.09.21          8
TEMP_ENTITIES_1004          4 19.09.21          4
TEMP_ENTITIES_1004          9 24.09.21          9
TEMP_ENTITIES_1005       1001 16.09.21        -99

10 rows selected.