简体   繁体   English

生成 select 解析所有子表的脚本?

[英]Script to generate a select resolving all child tables?

I'm looking for a way to generate a script that would generate an SQL query that would select all child tables columns from a parent table.我正在寻找一种生成脚本的方法,该脚本将生成一个 SQL 查询,该查询将 select 来自父表的所有子表列。

Let's say you have a table Class (teacher, room, program) and a table Student (firstname, lastname, age, score, email).假设您有一个表 Class(教师、房间、程序)和一个表学生(名字、姓氏、年龄、分数、电子邮件)。

Let's say you want to get a select of all students in Class.假设您想获得 Class 中所有学生的 select。

Sure you could write the query manually.当然,您可以手动编写查询。

But now imagine you have a complex table with dozens of child tables, how do you do this efficiently/programmatically?但是现在假设您有一个包含数十个子表的复杂表,您如何有效/以编程方式执行此操作?

This is something that all programmers would like to have, no?这是所有程序员都想拥有的东西,不是吗? I can't believe no one has ever done that.我不敢相信从来没有人这样做过。

I understand the answer may depend on the DBMS vendor, I'm personally looking for a solution for Oracle.我知道答案可能取决于 DBMS 供应商,我个人正在寻找 Oracle 的解决方案。

Questions that are a bit similar:有点相似的问题:

And here is an idea to solve this partially: use a tool such as PowerBi or Visual Studio to generate Model from database in ASP.NET MVC.这是部分解决此问题的想法:使用 PowerBi 或 Visual Studio 等工具从 ASP.NET MVC 中的数据库生成 Model。 You won't get the SQL query but you will get the data.您不会得到 SQL 查询,但会得到数据。

You can start with this POC:您可以从这个 POC 开始:

select 
    juc.table_name as parent_table, 
    /*
    uc.table_name as child_table, uc.constraint_name, uc.r_constraint_name, 
    juc.constraint_type,
    uccc.column_name as parent_col_name, uccc.position as parent_col_position,
    uccp.column_name as child_col_name, uccp.position as child_col_position,
    */
    'SELECT c.* FROM ' || juc.table_name || ' p JOIN ' || uc.table_name || ' c ON '
    || 
    LISTAGG( 'c.' || uccp.column_name || ' = p.' || uccc.column_name, ' AND ' ) WITHIN GROUP(order by uccc.position)
    as sql
from user_constraints uc
    join user_constraints juc on juc.constraint_name = uc.r_constraint_name 
    join user_cons_columns uccc on uccc.constraint_name = uc.r_constraint_name
    join user_cons_columns uccp on uccp.constraint_name = uc.constraint_name and uccc.position = uccp.position
where uc.constraint_type = 'R'
group by uc.table_name, juc.table_name, uc.constraint_name
;

You can create your own entity relationship model metadata and write PL/SQL that will traverse it and assemble SQL intelligently.您可以创建自己的实体关系 model 元数据并编写将遍历它并智能组装 SQL 的 PL/SQL。 I've done this myself to avoid having to hard-code SQL in my front-end apps.我自己这样做是为了避免在我的前端应用程序中硬编码 SQL。 But it is highly complex and involves a lot of coding, far more than can be shared in a forum like this.但它非常复杂,涉及大量编码,远远超过像这样的论坛可以分享的。 But to give you the general gist, I have the following metadata.tables that describe my model:但为了给您一个大概的要点,我有以下描述我的 model 的 metadata.tables:

sql_statements - associates a logical entity with a primary table, and specifies the PK column. sql_statements - 将逻辑实体与主表相关联,并指定 PK 列。

sql_statement_parents - defines the parent entity and the child attribute used to join to the parent's PK. sql_statement_parents - 定义父实体和用于加入父 PK 的子属性。

sql_attribute_dictionary - lists every available attribute for every statement, the source column, its datatype, plus optional derived column expressions. sql_attribute_dictionary - 列出每个语句的每个可用属性、源列、它的数据类型以及可选的派生列表达式。

attribute_dependencies - used for derived column expressions, specifies which attributes are needed by the derived attribute. attribute_dependencies - 用于派生列表达式,指定派生属性需要哪些属性。

Then you write code that takes a sql_statement name and a list of desired attributes and a set of optional filters, and it builds a list of needed source tables/columns using the data relationships in the metadata, and then using the parent-child relationships recursively builds SQL (using nested query blocks) from the child to whatever parent ancestor(s) it needs to obtain the required columns, intelligently aliasing everything and joining in the write way to be performant.然后编写代码,使用 sql_statement 名称和所需属性列表以及一组可选过滤器,并使用元数据中的数据关系构建所需源表/列的列表,然后递归地使用父子关系构建 SQL(使用嵌套查询块)从子级到它需要获取所需列的任何父级祖先,智能地为所有内容起别名并加入写入方式以提高性能。 It can then pass back the finished SQL as a REF CURSOR which you can then parse, open and fetch from to get results.然后它可以将完成的 SQL 作为 REF CURSOR 传回,然后您可以解析、打开并从中获取结果。 It works great for me, but it did take weeks of work to perfect, and that's with decades of experience in SQL and PL/SQL.它对我来说非常有用,但它确实需要数周的工作才能完善,而这是在 SQL 和 PL/SQL 方面数十年的经验。 This is no simple task, but it is doable.这不是一项简单的任务,但它是可行的。 And of course there are always complex needs that defy the capabilities of our metadata model, and so for those we end up either creating views or pipeline functions, and registering those in our metadata so that generated SQL can invoke them when needed.当然,总是有一些复杂的需求违背了我们的元数据 model 的功能,因此对于那些我们最终创建视图或管道函数,并将它们注册到我们的元数据中,以便生成的 SQL 可以在需要时调用它们。

But in the end, however you do it, you will not get away from having to describe your data model in detail so that code can walk it.但最后,无论你怎么做,你都无法避免必须详细描述你的数据 model 以便代码可以遍历它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM