获取日期范围内的所有表

get all the tables within a date range

我有许多具有相同结构和列但名称不同的每周备份表,其中包含一些特定于用户的信息,例如这样。

user_details
user_details_20211126
user_details_20211119
user_details_20211112
and so on....

现在我想在一个日期范围内查找表格,例如:如果我选择 2021-11-202021-11-13 的日期范围,那么获取的表格将是 user_details, user_details_20211126, user_details_20211119 以供使用它们在包含对所有已提取表的 union 操作的查询中。 知道怎么做吗?

如前所述,多么可怕的想法……你不应该那样做。一个带有 DATE 数据类型列的 table 应该顺便做一下。我建议你切换到它 - 越早越好。


与此同时 - 尽管您没有指定您使用的数据库并且我使用的是 Oracle - 无论数据库如何,您可能都必须执行以下操作:某种 动态 SQL,因为您必须“动态地”编写 SELECT 语句,仅使用满足条件的 table。因为你必须从数据字典中获取他们的名字,所以你没有太多选择,但是 - 正如我所说 - 动态 SQL.

好的,给你。

设置日期格式(您不必这样做):

SQL> alter session set nls_date_format = 'dd.mm.yyyy';

Session altered.

名称为 user_details_something 的表:

SQL> select table_name
  2  from user_tables
  3  where table_name like 'USER_DETAILS%'
  4  order by table_name;

TABLE_NAME
------------------------------
USER_DETAILS
USER_DETAILS_20211126
USER_DETAILS_20211127
USER_DETAILS_20211128

如何 select 仅 table 其名称包含介于所需值之间的日期?

  • 查询数据字典(在Oracle中,即user_tables
  • 提取他们名字的 DATE 部分(我选择了 regexp_substr 函数;您可以使用任何您认为合适的函数)
  • 将提取的子字符串转换为有效的日期值(使用 TO_DATE 函数)

因此:

SQL> select table_name
  2  from user_tables
  3  where table_name like 'USER_DETAILS%'
  4    and to_date(regexp_substr(table_name, '\d+$'), 'yyyymmdd')
  5        between date '2021-11-26' and date '2021-11-27';

TABLE_NAME
------------------------------
USER_DETAILS_20211126
USER_DETAILS_20211127

好的;在 2021 年 11 月 26 日和 2021 年 11 月 27 日之间有两个 table(我不想创建更多)。


工作的第二部分实际上是 从那些 table 中获取 数据。这是一个接受日期周期作为参数和 returns ref cursor 的函数(当然,您可以选择其他内容)。阅读代码中的注释:

SQL> create or replace function f_test(par_date_from in date,
  2                                    par_date_to   in date)
  3    return sys_refcursor
  4  is
  5    l_str varchar2(1000);  -- contains the whole SELECT statement
  6    rc    sys_refcursor;
  7  begin
  8    -- loop through all tables whose names satisfy the condition
  9    for cur_r in
 10    (select table_name
 11     from user_tables
 12     where table_name like 'USER_DETAILS%'
 13       and to_date(regexp_substr(table_name, '\d+$'), 'yyyymmdd')
 14           between par_date_from and par_date_to
 15    ) loop
 16      -- compose a SELECT statement
 17      l_str := l_str ||
 18        'select ename, job, datum from ' || cur_r.table_name || ' union all ';
 19    end loop;
 20
 21    -- remove trailing UNION ALL
 22    l_str := rtrim(l_str, ' union all');
 23
 24    -- open and return ref cursor
 25    open rc for l_str;
 26    return rc;
 27  end;
 28  /

Function created.

好的,我们试试看:

SQL> select f_test(date '2021-11-26', date '2021-11-27') from dual;

F_TEST(DATE'2021-11-
--------------------
CURSOR STATEMENT : 1

CURSOR STATEMENT : 1

ENAME      JOB       DATUM
---------- --------- ----------
SMITH      CLERK     26.11.2021
JONES      MANAGER   26.11.2021
SCOTT      ANALYST   26.11.2021
ADAMS      CLERK     26.11.2021
FORD       ANALYST   26.11.2021
ALLEN      SALESMAN  27.11.2021
WARD       SALESMAN  27.11.2021
MARTIN     SALESMAN  27.11.2021
BLAKE      MANAGER   27.11.2021
TURNER     SALESMAN  27.11.2021
JAMES      CLERK     27.11.2021

11 rows selected.


SQL>

对我有用;我希望你根本不需要让它“工作”,但是 - 在你应用我们已经建议的内容之后 - 运行 一个简单的

SQL> select * from user_details
  2  where datum between date '2021-11-26' and date '2021-11-27';

    DEPTNO      EMPNO ENAME      JOB       DATUM
---------- ---------- ---------- --------- ----------
        20       7369 SMITH      CLERK     26.11.2021
        20       7566 JONES      MANAGER   26.11.2021
        20       7788 SCOTT      ANALYST   26.11.2021
        20       7876 ADAMS      CLERK     26.11.2021
        20       7902 FORD       ANALYST   26.11.2021
        30       7499 ALLEN      SALESMAN  27.11.2021
        30       7521 WARD       SALESMAN  27.11.2021
        30       7654 MARTIN     SALESMAN  27.11.2021
        30       7698 BLAKE      MANAGER   27.11.2021
        30       7844 TURNER     SALESMAN  27.11.2021
        30       7900 JAMES      CLERK     27.11.2021

11 rows selected.

SQL>

显然,我的 user_details table 包含 DATE 数据类型列并使所有内容 很多 更简单。