获取日期范围内的所有表
get all the tables within a date range
我有许多具有相同结构和列但名称不同的每周备份表,其中包含一些特定于用户的信息,例如这样。
user_details
user_details_20211126
user_details_20211119
user_details_20211112
and so on....
现在我想在一个日期范围内查找表格,例如:如果我选择 2021-11-20
到 2021-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
数据类型列并使所有内容 很多 更简单。
我有许多具有相同结构和列但名称不同的每周备份表,其中包含一些特定于用户的信息,例如这样。
user_details
user_details_20211126
user_details_20211119
user_details_20211112
and so on....
现在我想在一个日期范围内查找表格,例如:如果我选择 2021-11-20
到 2021-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
数据类型列并使所有内容 很多 更简单。