我正在寻找一种解决方案,告诉Oracle" 此查询意味着像视图一样重复使用" (如果我问的话,如果可能的话,我不想/不能创建完整的全局视图。)
使用以下最小模型(我遗漏了其他列):
因此,以下创建语句(我没有针对Oracle验证它们,它更多地用于理解问题 而不是测试)。
create table owners( owner_id number not null, constraint pk_owners primary key (owner_id));
create table books( book_id number not null, constraint pk_books primary key (book_id));
create table authors( author_id number not null, constraint pk_authors primary key (author_id));
create table chapters( chapter_id number not null, constraint pk_chapters primary key (chapter_id));
create table owned_books(
owner_id number not null,
book_id number not null,
constraint pk_owned_books primary key (owner_id, book_id),
constraint fk_owned_books_1 foreign key (owner_id) references owners (owner_id),
constraint fk_owned_books_2 foreign key (book_id) references books (book_id)
);
create table book_authors(
book_id number not null,
author_id number not null,
constraint pk_book_authors primary key (book_id, author_id),
constraint fk_book_authors_1 foreign key (author_id) references authors (author_id),
constraint fk_book_authors_2 foreign key (book_id) references books (book_id)
);
create table chapter_authors(
chapter_id number not null,
author_id number not null,
constraint pk_chapter_authors primary key (chapter_id, author_id),
constraint fk_chapter_authors_1 foreign key (author_id) references authors (author_id),
constraint fk_chapter_authors_2 foreign key (chapter_id) references chapters (chapter_id)
);
create table book_chapters(
chapter_id number not null,
book_id number not null,
constraint pk_book_chapters primary key (chapter_id, book_id),
constraint fk_book_chapters_1 foreign key (chapter_id) references chapters (chapter_id)
constraint fk_book_chapters_2 foreign key (book_id) references books (book_id)
);
create table authors_related_data1(
author_id number not null,
constraint pk_authors_related_data1 primary key (author_id),
constraint fk_authors_related_data1_1 foreign key (author_id) references authors (author_id)
);
create table authors_related_data2(
data_id number not null,
author_id number not null,
constraint pk_authors_related_data2 primary key (data_id),
constraint authors_related_data2 foreign key (author_id) references authors (author_id)
);
我想要做的查询(和重复的部分):
with v_books as (
select books.book_id
from owned_books
inner join books on books.book_id = owned_books.book_id
where owned_books.owner_id = P_OWNER_ID
), v_authors as (
select authors.author_id
from v_books
inner join book_authors on book_authors.book_id = v_books.book_id
inner join authors on authors.author_id = book_authors.author_id
union
select authors.author_id
from v_books
inner join book_chapters on book_chapters.book_id = v_books.book_id
inner join chapter_authors on chapter_authors.chapter_id = book_chapters.chapter_id
inner join authors on authors.author_id = book_chapters.author_id
)
select authors_related_data1.*
from v_authors
inner join authors_related_data1 on authors_related_data1.author_id = v_authors.author_id
;
with v_books as (
select books.book_id
from owned_books
inner join books on books.book_id = owned_books.book_id
where owned_books.owner_id = P_OWNER_ID
), v_authors as (
select authors.author_id
from v_books
inner join book_authors on book_authors.book_id = v_books.book_id
inner join authors on authors.author_id = book_authors.author_id
union
select authors.author_id
from v_books
inner join book_chapters on book_chapters.book_id = v_books.book_id
inner join chapter_authors on chapter_authors.chapter_id = book_chapters.chapter_id
inner join authors on authors.author_id = book_chapters.author_id
)
select authors_related_data2.*
from v_authors
inner join authors_related_data2 on authors_related_data2.author_id = v_authors.author_id
;
第一部分(带...)对于两个查询都是相同的。
这样的观点会很棒:
create view v_owned_authors as (
with v_books as (
select books.book_id
from owned_books
inner join books on books.book_id = owned_books.book_id
)
(
select authors.author_id
from v_books
inner join book_authors on book_authors.book_id = v_books.book_id
inner join authors on authors.author_id = book_authors.author_id
union
select authors.author_id
from v_books
inner join book_chapters on book_chapters.book_id = v_books.book_id
inner join chapter_authors on chapter_authors.chapter_id = book_chapters.chapter_id
inner join authors on authors.author_id = book_chapters.author_id
)
;
以前的查询很简单:
select authors_related_data2.*
from v_owned_authors
inner join authors_related_data2 on authors_related_data2.author_id = v_authors.author_id
where v_owned_authors.owner_id = P_OWNER_ID
可是:
答案 0 :(得分:1)
您可以使用表函数或流水线函数
以下是表函数的示例: http://oracle-base.com/articles/misc/pipelined-table-functions.php
CREATE TYPE t_tf_row AS OBJECT (
id NUMBER,
description VARCHAR2(50)
);
/
CREATE TYPE t_tf_tab IS TABLE OF t_tf_row;
/
-- Build the table function itself.
CREATE OR REPLACE FUNCTION get_tab_tf (p_rows IN NUMBER) RETURN t_tf_tab AS
l_tab t_tf_tab := t_tf_tab();
BEGIN
FOR i IN 1 .. p_rows LOOP
l_tab.extend;
l_tab(l_tab.last) := t_tf_row(i, 'Description for ' || i);
END LOOP;
RETURN l_tab;
END;
/
-- Test it.
SELECT *
FROM TABLE(get_tab_tf(10))
ORDER BY id DESC;
以下是流水线功能的示例:
CREATE OR REPLACE FUNCTION get_tab_ptf (p_rows IN NUMBER) RETURN t_tf_tab PIPELINED AS
r t_tf_row%rowtype;
BEGIN
for z in (select id, desc from sometalbe) loop
r.id := z.id;
r.description := z.desc;
PIPE ROW(r);
END LOOP;
RETURN;
END;
答案 1 :(得分:0)
这样的程序会满足您的需求吗?
create or replace procedure p_statement (cur in out sys_refcursor)
is
begin
open cur for
select 1 num from dual union select 2 num from dual;
end;
(我把那里的select选为double,而你可以用你的复杂查询替换它并定义变量来相应地获取)
实际的通话可能是这样的:
declare
mycur sys_refcursor;
num number;
begin
p_statement(mycur);
LOOP
FETCH mycur INTO num;
EXIT WHEN mycur%NOTFOUND;
DBMS_OUTPUT.put_line(num);
END LOOP;
end;