英文:
Oracle Query with Schema in main table
问题
我找到了许多类似的文章,但没有一个完全涵盖我所需的内容。我没有设计这个表,也无法修改它。我只能担任只读角色。
我在根模式中有一个信息表。我们称之为SchemaRoot。在信息表中,每个记录都包含一个附加模式的字段。
Info.RootSchema
ID | SchemaName | ProjectOwner |
---|---|---|
1 | Project1 | Bob |
2 | Project2 | Larry |
然后,所有项目信息都位于其自己的模式中。
ProjectInfo.Project1或ProjectInfo.Project2
ProjectDetail1 | ProjectDetail2 | ProjectDetail3 |
---|---|---|
Blah | Blah | Blah |
Blah | Blah | Blah |
我需要能够在一个查询中查询RootSchema和SubSchema。
因此,我需要一些东西,它会给我:
| ProjectOwner | ProjectDetail1 | ProjectDetail2 | ProjectDetail3 |
对于Info.RootSchema中的每个项目。
英文:
I'm finding a lot of similar articles, but none quite covering what I need. I didn't design the table nor can I modify it. I am limited to a Read Only role.
I have an Info table in a root schema. Let's call it SchemaRoot. In the info table it contains a field with addition schema's for each record.
Info.RootSchema
ID | SchemaName | ProjectOwner |
---|---|---|
1 | Project1 | Bob |
2 | Project2 | Larry |
Then all the project info is in it's own Schema.
ProjectInfo.Project1 or ProjectInfo.Project2
ProjectDetail1 | ProjectDetail2 | ProjectDetail3 |
---|---|---|
Blah | Blah | Blah |
Blah | Blah | Blah |
I need to be able to query the the RootSchema and SubSchema's in one query.
So I need something that'll give me.
| ProjectOwner | ProjectDetail1 | ProjectDetail2 | ProjectDetail3 |
for every project in Info.RootSchema.
答案1
得分: 1
抱歉,但我不确定我们是否在这里讨论Oracle。你究竟是指什么是“模式”?在Oracle数据库中,我们创建一个用户,然后用户创建其表、视图、存储过程等,因此用户+其所有对象代表一个模式。我认为这是你试图表达的意思。
有一个“主”模式(root
),而每个项目都有自己的模式(project1
,project2
等)。
如果任何用户想要访问由另一个用户拥有的数据 - 例如,在你的情况下是root
用户将选择由名为project1
,project2
等的用户拥有的数据 - 那么这些用户必须授予root
特定的权限。
因此,你需要:
connect project1/its_password
grant select on projectinfo to root;
connect project2/its_password
grant select on projectinfo to root;
然后,以root
用户身份连接并访问其他用户拥有的数据,要么通过在表名之前加上其所有者(例如,project1.projectinfo
- 不是反之亦然,这是你发布的内容 - 如果我理解正确的话),要么通过创建同义词:
create synonym project1_projectinfo for project1.projectinfo;
create synonym project2_projectinfo for project2.projectinfo;
对于示例数据:
SQL> select * from info;
SCHEMANA PROJE
-------- -----
Project1 Bob
Project2 Larry
SQL> select * From project1_projectinfo;
PROJECTD PROJECTD
-------- --------
1 info 1 1 info 2
1 info 3 1 info 4
SQL> select * from project2_projectinfo;
PROJECTD PROJECTD
-------- --------
2 info 6 2 info 7
你可以获得:
SQL> select r.projectowner, a.projectdetail1, a.projectdetail2
2 from info r cross join project1_projectinfo a
3 where r.schemaname = 'Project1'
4 union all
5 select r.projectowner, b.projectdetail1, b.projectdetail2
6 from info r cross join project2_projectinfo b
7 where r.schemaname = 'Project2';
PROJE PROJECTD PROJECTD
----- -------- --------
Bob 1 info 1 1 info 2
Bob 1 info 3 1 info 4
Larry 2 info 6 2 info 7
SQL>
这基本上是硬编码的解决方案。是否可以以“动态”的方式完成?是的;一个选项是创建一个函数,该函数组合select
语句,作为引用游标的源。例如:
SQL> create or replace function f_test
2 return sys_refcursor
3 is
4 l_str varchar2(10000);
5 rc sys_refcursor;
6 begin
7 for cur_r in (select schemaname, projectowner from info) loop
8 l_str := l_str ||
9 'select ' || chr(39) || cur_r.projectowner || chr(39) || ' as projectowner, ' ||
10 'projectdetail1, projectdetail2 from ' || cur_r.schemaname ||'_projectinfo' ||
11 ' union all ';
12 end loop;
13 l_str := regexp_replace(l_str, ' union all $');
14 open rc for l_str;
15 return rc;
16 end;
17 /
测试:
SQL> select f_test from dual;
F_TEST
--------------------
CURSOR STATEMENT : 1
CURSOR STATEMENT : 1
PROJE PROJECTD PROJECTD
----- -------- --------
Bob 1 info 1 1 info 2
Bob 1 info 3 1 info 4
Larry 2 info 6 2 info 7
SQL>
如果这不是你要的,请原谅我没有理解你在谈论Oracle。
英文:
Excuse me, but I'm not sure we speak Oracle here. What exactly do you call a "schema"? In an Oracle database, we create a user who then creates its tables, views, procedures etc., so user + all its objects represent a schema. I think that this is what you're trying to say.
There is one "master" schema (root
), while every project has its own schema (project1
, project2
, etc.).
If any user wants to access data owned by another user - for example, in your case it is the root
user who will select data owned by users named project1
, project2
, etc. - then these users have to grant certain privileges to root
.
Therefore, you'd
connect project1/its_password
grant select on projectinfo to root;
connect project2/its_password
grant select on projectinfo to root;
Then, connect as root
and access data owned by other users either by preceding table name with its owner (e.g. project1.projectinfo
- not vice versa, which is what you posted - if I got you right), or by creating synonyms as
create synonym project1_projectinfo for project1.projectinfo;
create synonym project2_projectinfo for project2.projectinfo;
For sample data:
SQL> select * from info;
SCHEMANA PROJE
-------- -----
Project1 Bob
Project2 Larry
SQL> select * From project1_projectinfo;
PROJECTD PROJECTD
-------- --------
1 info 1 1 info 2
1 info 3 1 info 4
SQL> select * from project2_projectinfo;
PROJECTD PROJECTD
-------- --------
2 info 6 2 info 7
you'd get
SQL> select r.projectowner, a.projectdetail1, a.projectdetail2
2 from info r cross join project1_projectinfo a
3 where r.schemaname = 'Project1'
4 union all
5 select r.projectowner, b.projectdetail1, b.projectdetail2
6 from info r cross join project2_projectinfo b
7 where r.schemaname = 'Project2';
PROJE PROJECTD PROJECTD
----- -------- --------
Bob 1 info 1 1 info 2
Bob 1 info 3 1 info 4
Larry 2 info 6 2 info 7
SQL>
That's pretty much hardcoded solution. Can it be done "dynamically"? Yes; one option is to create a function which composes select
statement to be used as a source for ref cursor. For example:
SQL> create or replace function f_test
2 return sys_refcursor
3 is
4 l_str varchar2(10000);
5 rc sys_refcursor;
6 begin
7 for cur_r in (select schemaname, projectowner from info) loop
8 l_str := l_str ||
9 'select ' || chr(39) || cur_r.projectowner || chr(39) || ' as projectowner, ' ||
10 'projectdetail1, projectdetail2 from ' || cur_r.schemaname ||'_projectinfo' ||
11 ' union all ';
12 end loop;
13 l_str := regexp_replace(l_str, ' union all $');
14 open rc for l_str;
15 return rc;
16 end;
17 /
Function created.
Testing:
SQL> select f_test from dual;
F_TEST
--------------------
CURSOR STATEMENT : 1
CURSOR STATEMENT : 1
PROJE PROJECTD PROJECTD
----- -------- --------
Bob 1 info 1 1 info 2
Bob 1 info 3 1 info 4
Larry 2 info 6 2 info 7
SQL>
If that's not it, then I obviously didn't understand you speaking Oracle.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论