Mar*_*ged 6 oracle oracle-11g-r2 plsql
我正在沿着不利的设计路线进行编程。我对架构没有影响,因为它属于现成的标准软件。
为简单起见,假设该软件存储多个用户的地址簿。每个表都分配有相应用户的名称。
这些表是这样创建的:
CREATE TABLE
NAME_OF_USER
(
SURNAME VARCHAR(100),
TOWN VARCHAR(100)
)
Run Code Online (Sandbox Code Playgroud)
所以所有表都有这些列:
存在相当于两个地址簿的两个表:
通讯录已经填写如下:
INSERT
INTO
DONALDDUCK
(
SURNAME,
TOWN
)
VALUES
(
'Dagobert Duck',
'Entenhausen'
)
Run Code Online (Sandbox Code Playgroud)
为了检索我可以运行的完整地址列表
Select * from donaldduck
Select * from daisyduck
Run Code Online (Sandbox Code Playgroud)
但是如果有人为 GOOFY 添加地址簿怎么办?我将不得不更改每个新创建的地址簿的查询,在本例中添加 aSELECT * FROM GOOFY
作为第三行。
为了使这更加复杂,还有其他具有不同设置的表(它们正在存储其他信息,这些信息与我列出给定地址簿中的所有条目的任务完全无关)。所以我不能简单地遍历所有现有的表,因为这会导致处理我在查询中不需要的表。
有没有办法说“从包含名为城镇的列的所有表中选择 *”?这应该通过使用普通 SQL 或 PL/SQL 来解决,因为我想避免使用高级语言编写代码,就像我认为我需要遵循 jsapkota 的建议来做。
Bal*_*app 12
我并不为公开写这样的东西而自豪。
样本+数据:
CREATE TABLE donaldduck ( SURNAME VARCHAR(100), TOWN VARCHAR(100) );
CREATE TABLE daisyduck ( SURNAME VARCHAR(100), TOWN VARCHAR(100) );
CREATE TABLE goofy ( something number(1), SURNAME VARCHAR(100), TOWN VARCHAR(100) );
INSERT INTO DONALDDUCK ( SURNAME, TOWN ) VALUES ( 'Dagobert Duck', 'Entenhausen' );
INSERT INTO daisyduck ( SURNAME, TOWN ) VALUES ( 'Daisy Duck', 'Entenhausen' );
INSERT INTO goofy ( SOMETHING, SURNAME, TOWN ) VALUES ( 1, 'Goofy Dog', 'Entenhausen' );
commit;
Run Code Online (Sandbox Code Playgroud)
使用流水线函数的类型和 PL/SQL:
create type t_NAME_OF_USER as object
(
SURNAME VARCHAR(100),
TOWN VARCHAR(100)
);
/
create type t_name_of_user_tab IS TABLE OF t_NAME_OF_USER;
/
CREATE OR REPLACE FUNCTION get_surname_town RETURN t_name_of_user_tab PIPELINED AS
rc sys_refcursor;
query clob;
l_surname varchar2(100);
l_town varchar2(100);
begin
for t in (
select table_name from user_tables ut
where
'SURNAME' in (select column_name from user_tab_columns utc where utc.table_name = ut.table_name) and
'TOWN' in (select column_name from user_tab_columns utc where utc.table_name = ut.table_name)
)
loop
open rc for 'select surname, town from ' || t.table_name ;
loop
fetch rc into l_surname, l_town;
exit when rc%notfound;
pipe row(t_NAME_OF_USER(l_surname, l_town));
end loop;
end loop;
end;
/
Run Code Online (Sandbox Code Playgroud)
选择:
select * from table(get_surname_town);
SURNAME TOWN
------------------------------ --------------------
Daisy Duck Entenhausen
Dagobert Duck Entenhausen
Goofy Dog Entenhausen
Run Code Online (Sandbox Code Playgroud)
我认为人们很难理解你的问题,因为表格结构太糟糕了,似乎是为了让你头疼。正如Balazs Papp 所指出的,几乎没有什么可以实现扩展或看起来不像被黑客攻击的东西。
然而,有一些解决方案可以在 PL/SQL 中完成。一个流水线表函数最终会看起来像一个视图。它不会扩展到大量用户,但不会看起来像黑客。
另一种解决方案涉及交易执行速度以换取数据的新鲜度。许多数据由 10% 的活动记录和 90% 不太可能更改的存档数据组成。如果您的数据只需每天或每几个小时更新一次,您可以将下面的伪代码实现为打包过程并调用作业来刷新表。
---伪代码,不打算编译--
CREATE TABLE ADDRESS_BOOK(
ID NUMBER(9) NOT NULL,
NAME_OF_USER VARCHAR2(250) NOT NULL,
SURNAME VARCHAR(100) NOT NULL,
TOWN VARCHAR(100) NOT NULL);
Run Code Online (Sandbox Code Playgroud)
--创建你的包
CREATE PACKAGE PKG_ADDRESS_BOOK
AS
PROCEDURE REFRESH;
END PKG_ADDRESS_BOOK;
CREATE OR REPLACE PACKAGE BODY PKG_ADDRESS_BOOK
IS
PROCEDURE REFRESH
CURSOR the_tables IS
select table_name
from user_tab_cols
where column_name ='TOWN';
BEGIN
--clear out old data
DELETE FROM ADDRESS_BOOK;
FOR items in the_tables LOOP
EXECUTE IMMEDIATE('INSERT INTO ADDRESS_BOOK '||
'SELECT null,'
||items.table_name
||','
||'items.table_name.surname,items.table_name.town '
||'FROM '
||items.table_name);
END LOOP;
END REFRESH;
END PKG_ADDRESS_BOOK;
Run Code Online (Sandbox Code Playgroud)
这一切都基于数据正在缓慢变化的想法。优化将包括添加一种仅更改更改数据的方法。
归档时间: |
|
查看次数: |
158 次 |
最近记录: |