将日期附加到字符串以在 oracle 中获取表名并对其进行选择查询

Posted

技术标签:

【中文标题】将日期附加到字符串以在 oracle 中获取表名并对其进行选择查询【英文标题】:append date to string to get table name in oracle and do select query on it 【发布时间】:2019-02-04 16:28:25 【问题描述】:

我在 Oracle DB 中有如下表:abc20190101、abc20190102 等。每个都有相同的列数据类型和相同数量的列,只是填充了不同的数据。 我有一个调度程序每天在特定时间对这些表运行查询。 但表名应附加 sysdate。实际上我只需要对 abc20190101,xyz20190101 等 2 个表执行选择和连接操作

我试过这个:

select * from (select concat('abc',(SELECT to_char(sysdate-1,'yyyymmdd') from dual)) as "Table" from dual) ;

但这只是返回表名作为输出,而不是表内的数据值。

我也试过这个 PL/SQL 过程:

declare tabname varchar(32); begin tabname := 'abc'|| TO_CHAR(SYSDATE, 'YYYYMMDD'); execute immediate 'select * from '|| tabname ; end;

但这会产生语法错误。由于我是 PL/SQL 存储过程的新手,所以我找不到错误在哪里。如果有人能告诉如何在附加了动态 sysdate 的表名上运行选择查询,将会很有帮助

【问题讨论】:

这似乎是一个糟糕的数据模型。你为什么这么做?应该有一个包含 DATE 数据类型列的表,以便您可以按日期区分行。然后你只需select * from your_table where date_column = date '2019-01-01'。如果可能的话,放弃你目前正在做的事情,它只是无法扩展,并且无论你看到什么都会带来问题。 @Littlefoot 这就是人们在不支付许可证的情况下进行分区的方式 我确信他们“喜欢”他们的数据分区方式。 @Littlefoot - 考虑到 Oracle 分区许可的成本,一些组织别无选择,只能“享受”它。尽管每个表(即每个分区)有 60m 行的组织确实应该看看他们是否可以一起节省预算。 【参考方案1】:

尝试动态 SQL 是正确的方法,但如果您选择了,则需要指定返回结果的方式。所以你需要这样的东西:

declare
  tabname varchar(32);
  result YOUR_TYPE;
begin
  tabname := 'abc'|| TO_CHAR(SYSDATE, 'YYYYMMDD');
  execute immediate 'select * from ' || tabname into result;
end;

如果您的查询返回单个结果,这将起作用,所以我猜您对此不满意。您可以选择收藏或输入bulk collect

您可能想对您选择的数据做一些事情,这样您就可以以ref cursor 的形式返回结果或在loop 中迭代结果

【讨论】:

如果我的每个表都有大约 6000 万条记录,批量收集是否会有任何性能问题? @katipra - 你真的在运行返回 6000 万行的查询吗?即没有连接或过滤器?嗯,您将需要做一些花哨的事情来满足这一点。您正在探索为什么组织决定支付 Oracle 的分区许可费用。 @APC 大多数日常活动都是由捕获请求和响应并将其放入临时表中的触发器执行的,这些表会在几个小时后被清除。只有几次我们需要查询主表为是必需的。无论如何,我不了解确切的架构。但是在这种特殊情况下有什么“花哨”可以做的吗? @katipra 使用 bult collect 获得的最佳性能,限制和小批量处理。但总的来说,我同意这种架构很奇怪,在不了解架构甚至更改架构的情况下执行查询并非易事。如果这是 60m,那么每个索引都是有意义的,并且没有通用的解决方案【参考方案2】:

下面的代码 sn-p 将解决您的问题。

        set SERVEROUTPUT ON;
    declare
      tabname varchar(32);
      query_sql varchar2(300);
      result1 varchar2(20);
    begin
      tabname := 'tab_'|| TO_CHAR(SYSDATE, 'YYYYMMDD'); -- use your table and date
      query_sql := 'select account_name from '|| tabname; --modify query as per your requirement
      execute immediate query_sql into result1;
      dbms_output.put_line(result1);
    exception 
    when others then
        dbms_output.put_line(sqlerrm);
    end;
    /

【讨论】:

以上是关于将日期附加到字符串以在 oracle 中获取表名并对其进行选择查询的主要内容,如果未能解决你的问题,请参考以下文章

雪花中的 Javascript 函数将表名附加到当前日期

如何从数据库中获取所有表名并对其进行分页

使用变量作为表名并传递给另一个 sql 查询 [重复]

如何在 Oracle SQL 中选择前 1 名并按日期排序? [复制]

oracle使用execute immediate方式完成函数动态传入表名并操作 返回新的主键id值

将字符串转换为带有附加时间的Oracle日期