请告诉我我做错了什么。我尝试过以下方法:
SELECT *
FROM 'A'||(TO_CHAR(SYSDATE, 'YYMMDD'))||'B'
SELECT *
FROM CAST('A'||(TO_CHAR(SYSDATE, 'YYMMDD'))||'B' AS varchar2(8))
SELECT *
FROM table( CAST('A'||(TO_CHAR(SYSDATE, 'YYMMDD'))||'B' AS varchar2(8)))
DEFINE tName = CAST('A'||(TO_CHAR(SYSDATE, 'YYMMDD'))||'B' AS varchar2(8))
SELECT *
FROM &tName
SET tName AS CAST('A'||(TO_CHAR(SYSDATE, 'YYMMDD'))||'B' AS varchar2(8))
SELECT *
FROM &tName
SET @tName AS CAST('A'||(TO_CHAR(SYSDATE, 'YYMMDD'))||'B' AS varchar2(8))
SELECT *
FROM @tName
SELECT *
FROM
(
SELECT CAST('A'||(TO_CHAR(SYSDATE, 'YYMMDD'))||'B' AS varchar2(8))
FROM DUAL
)
(注意:我还尝试在上面所有示例中的表之前添加所有者,如下面的第二个示例所示)
我已验证
SELECT CAST('A'||(TO_CHAR(SYSDATE, 'YYMMDD'))||'B' AS varchar2(8))
FROM DUAL
显示A170429B
SELECT CAST('owner.A'||(TO_CHAR(SYSDATE, 'YYMMDD'))||'B' AS varchar2(8))
FROM DUAL
显示所有者。A170429B
但我无法使用 FROM 语句将其视为表格
数据库每天都会创建一张新表;这就是我尝试这样做的原因。
最佳答案
正如其他人所观察到的,分区是安排这种情况的优雅方式。但分区仍然是企业版上的许可附加功能,而且价格昂贵。所以这里有一些更便宜的选择。
第一个选项是执行您现在尝试执行的操作,并按名称查询每个表。要使这种方法发挥作用,您需要使用动态 SQL。
这里有一些表格 - t170428
、t170429
、t170430
- 看起来都像这样
create table t170428 (
id number not null primary key
, type varchar2(10)
, col1 varchar2(10)
, col2 number
, col3 date not null
)
/
要查询它们,我们需要一个带有与表投影匹配的签名的 SQL 类型:
create or replace type tyymmdd_t as object (
id number
, type varchar2(10)
, col1 varchar2(10)
, col2 number
, col3 date
);
/
create or replace type tyymmdd_nt as table of tyymmdd_t
/
这是一个函数,它根据传递的日期动态构建表名称并返回该表中的行的嵌套表:
create or replace function get_date_table
( p_target_date in date)
return tyymmdd_nt
is
return_value tyymmdd_nt;
begin
execute immediate
' select tyymmdd_t(id, type, col1, col2, col3) from t'
||to_char(p_target_date, 'yymmdd')
bulk collect into return_value;
return return_value;
end;
/
要查询表,我们使用 table()
函数,如下所示:
SQL> select * from table(get_date_table(sysdate));
ID TYPE COL1 COL2 COL3
---------- ---------- ---------- ---------- ---------
9 D2 SUN 1 30-APR-17
10 D2 SUN 2 30-APR-17
SQL> select * from table(get_date_table(date'2017-04-28'));
ID TYPE COL1 COL2 COL3
---------- ---------- ---------- ---------- ---------
1 D1 FRI 1 28-APR-17
2 D1 FRI 2 28-APR-17
3 D1 FRI 3 28-APR-17
4 D1 FRI 4 28-APR-17
5 D1 FRI 5 28-APR-17
SQL> select * from table(get_date_table(sysdate+1));
select * from table(get_date_table(sysdate+1))
*
ERROR at line 1:
ORA-00942: table or view does not exist
ORA-06512: at "FOX.GET_DATE_TABLE", line 7
SQL>
第二个选项是分区 View 。这是一项古老的技术(来自上个千年!),它允许我们使用 UNION ALL 运算符在多个表上构建 View ,并获得分区的许多好处,例如分区修剪 - 前提是您使用的是真正旧版本的 Oracle。分区 View 在 8.0 中已被弃用,Oracle 在 9iR2 中停止支持它们。该文档可以追溯到 Oracle7 Find out more 。
无论如何,分区 View 的原理是这样的:
- 对“分区键”实现检查约束
- 在分区键列上构建索引
- 收集统计数据
- 构建 View
与表投影一样,所有表的约束和索引必须相同。
alter table t170428 add constraint t170428_ptn_key_ck check (col3 = date '2017-04-28');
alter table t170429 add constraint t170429_ptn_key_ck check (col3 = date '2017-04-29');
alter table t170430 add constraint t170430_ptn_key_ck check (col3 = date '2017-04-30');
create unique index t170428_ptn_idx on t170428(col3, id) compress 1;
create unique index t170429_ptn_idx on t170429(col3, id) compress 1;
create unique index t170430_ptn_idx on t170430(col3, id) compress 1;
exec dbms_stats.gather_table_stats('FOX', 'T170428', cascade=>true)
exec dbms_stats.gather_table_stats('FOX', 'T170429', cascade=>true)
exec dbms_stats.gather_table_stats('FOX', 'T170430', cascade=>true)
create or replace view v_all_the_dates as
select * from t170428
union all
select * from t170429
union all
select * from t170430
/
因为 Oracle 在更高版本的数据库中不支持分区 View ,所以这种方法不会为您提供分区修剪。但只要您严格遵守索引和检查约束,它仍然可能非常有效。
可能适合的第三个选项是外部表。创建日期表表明每日负载。如果这些只是作为以文件形式到达的数据的临时表,您可以使用外部表来访问数据。 table 将是一个稳定的结构;您需要更改的只是每日提要文件的位置。 Find out more .
关于sql - 如何在FROM中调用间接表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43693147/