Oracle查询主表中的模式(Schema)部分

huangapple go评论112阅读模式
英文:

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),而每个项目都有自己的模式(project1project2等)。

如果任何用户想要访问由另一个用户拥有的数据 - 例如,在你的情况下是root用户将选择由名为project1project2等的用户拥有的数据 - 那么这些用户必须授予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.

huangapple
  • 本文由 发表于 2023年7月7日 02:23:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/76631585.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定