sql - 如何在FROM中调用间接表

标签 sql oracle variables

请告诉我我做错了什么。我尝试过以下方法:

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。

这里有一些表格 - t170428t170429t170430 - 看起来都像这样

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/

相关文章:

oracle - 具有row_number()over()语法的HIVE问题

php - 解析发送到 PayPal 的自定义变量

Shell 脚本参数替换

java - 通过脚本文件或通过 Java 代码初始化 SQL 数据库是否有任何继承优势?

python - 在 django sql 查询中转义 % 会导致列表超出范围

mysql - 数以百万计的 MySQL 插入重复键更新 - 非常慢

oracle - 如何避免 Oracle SQL Developer 中的变量替换

mysql - Oracle DB,mysql不能做什么?

python - 未绑定(bind)本地错误 : local variable 'player' referenced before assignment

mysql - 如果存在两个相同的字段 insert else update