【问题标题】:Managing common code used in multiple SQL Statements管理多个 SQL 语句中使用的公共代码
【发布时间】:2013-06-05 19:33:21
【问题描述】:

我使用 SQL Developer 创建查询我们公司 Oracle 10g 数据库的 PL/SQL 语句,我发现这些查询有许多通用组件,例如在许多语句中相同的一组连接或条件。我的问题是,当我更新这些部分中的代码时,我必须跟踪并手动更新使用相同公共代码的所有其他语句,以便所有语句彼此一致且相互准确。

我还没有实现源代码控制系统。是否有源代码控制系统(SVN、TFS 或其他)允许我系统地管理各种 SQL 语句的这些“动态”子部分?我的想法是,一旦我更新了一个公共代码块,这些更新将级联并在我使用相同公共代码的任何其他语句中更新。

如果不存在这样的功能,您对按照我描述的方式管理数十个(如果不是数百个)不同的 SQL 语句有什么建议?

【问题讨论】:

  • 如果您发现自己一遍又一遍地查询相同的连接表,您可以使用视图。
  • 确实,当数据/标准一致时,视图很好,但就我而言,代码是不断变化的。随着业务/报告需求的变化,我会修改标准或其他代码以反映最新需求,并在许多不同的陈述中这样做,从而驱动不同但相似的报告。
  • 当然,您可以使用版本控制系统来管理位-n 段查询——列列表、谓词等——但我认为尝试以一致的方式将所有这些位挂在一起可能证明是一种挫折的练习。我对此的第一个看法是 - 您需要提供一个应用程序,允许您的用户指定他们想要运行的查询。分享和享受。
  • 好点@bob-jarvis,您的建议听起来像是动态dashboard 的概念,可以以编程方式生成动态SQL 语句和/或后续结果。我目前没有资源来编写上述应用程序,但我会考虑将其作为未来可能的解决方案。

标签: sql version-control plsql oracle-sqldeveloper


【解决方案1】:
CREATE TABLE example_one
(
    eo_id    NUMBER
,   eo_value NUMBER
);

INSERT INTO example_one(eo_id, eo_value) VALUES(1, 10);    

CREATE TABLE example_two
(
    et_id    NUMBER
,   et_value NUMBER
);

INSERT INTO example_two(et_id, et_value) VALUES(1, 20);    

CREATE TABLE db_sql_statements
(
    s_stmt_id NUMBER
,   s_stmt    VARCHAR2(4000) /* should be CLOB - it can exceed 4000 CHAR */
);

INSERT INTO db_sql_statements(s_stmt_id, s_stmt) VALUES(1,'SELECT ~[columns_list_#00001]~ FROM ~[source_tables_#00001]~ ~[ON join_conditions_#00001]~ ~[WHERE where_conditions_#00001]~');
);

CREATE TABLE db_sql_parameters
(
    p_param_id VARCHAR2(4000)
,   p_param    VARCHAR2(4000)
);

INSERT INTO db_sql_parameters(p_param_id, p_param) VALUES('columns_list_#00001',     'eo.eo_id, eo.eo_value + et.et_value');
INSERT INTO db_sql_parameters(p_param_id, p_param) VALUES('source_tables_#00001',    'example_one eo JOIN example_two et');
INSERT INTO db_sql_parameters(p_param_id, p_param) VALUES('join_conditions_#00001',  'ON eo.eo_id = et.et_id');
INSERT INTO db_sql_parameters(p_param_id, p_param) VALUES('where_conditions_#00001', 'WHERE 1 = 1');

CREATE TABLE db_sql_stmt_param_bridge
(
    pb_stmt_id  NUMBER
,   pb_param_r  NUMBER
,   pb_param_id VARCHAR2(4000)
);

INSERT INTO db_sql_stmt_param_bridge(pb_stmt_id, pb_param_r, pb_param_id) VALUES(1, 1, 'columns_list_#00001');
INSERT INTO db_sql_stmt_param_bridge(pb_stmt_id, pb_param_r, pb_param_id) VALUES(1, 2, 'source_tables_#00001');
INSERT INTO db_sql_stmt_param_bridge(pb_stmt_id, pb_param_r, pb_param_id) VALUES(1, 3, 'join_conditions_#00001');
INSERT INTO db_sql_stmt_param_bridge(pb_stmt_id, pb_param_r, pb_param_id) VALUES(1, 4, 'where_conditions_#00001');

SELECT  s.s_stmt, p.p_param_id, p.p_param
FROM    db_sql_statements s
JOIN    db_sql_stmt_param_bridge pb
ON      s.s_stmt_id = pb.pb_stmt_id
JOIN    db_sql_parameters p
ON      pb.pb_param_id = p.p_param_id
;
/*
SELECT ~[columns_list_#00001]~ FROM ~[source_tables_#00001]~ ~[ON join_conditions_#00001]~ ~[WHERE where_conditions_#00001]~    columns_list_#00001 eo.eo_id, eo.eo_value + et.et_value
SELECT ~[columns_list_#00001]~ FROM ~[source_tables_#00001]~ ~[ON join_conditions_#00001]~ ~[WHERE where_conditions_#00001]~    source_tables_#00001    example_one eo JOIN example_two et
SELECT ~[columns_list_#00001]~ FROM ~[source_tables_#00001]~ ~[ON join_conditions_#00001]~ ~[WHERE where_conditions_#00001]~    join_conditions_#00001  ON eo.eo_id = et.et_id
SELECT ~[columns_list_#00001]~ FROM ~[source_tables_#00001]~ ~[ON join_conditions_#00001]~ ~[WHERE where_conditions_#00001]~    where_conditions_#00001 WHERE 1 = 1
*/

SELECT  REPLACE
        (
            REPLACE
            (
                REPLACE
                (
                    REPLACE
                    (
                        s_stmt
                    ,   '~[columns_list_#00001]~'
                    ,   p_param
                    )
                ,   '~[source_tables_#00001]~'
                ,   lead_p_param
                )
            ,   '~[ON join_conditions_#00001]~'
            ,   lead_p_param2
            )
        ,   '~[WHERE where_conditions_#00001]~'
        ,   lead_p_param3
        )
FROM
(
        SELECT  s.s_stmt
        ,       p.p_param_id
        ,       p.p_param
        ,       LEAD(p.p_param)    OVER (PARTITION BY s.s_stmt ORDER BY pb.pb_param_r) AS lead_p_param
        ,       LEAD(p.p_param, 2) OVER (PARTITION BY s.s_stmt ORDER BY pb.pb_param_r) AS lead_p_param2
        ,       LEAD(p.p_param, 3) OVER (PARTITION BY s.s_stmt ORDER BY pb.pb_param_r) AS lead_p_param3
        ,       ROW_NUMBER()       OVER (PARTITION BY s.s_stmt ORDER BY pb.pb_param_r) AS r_number
        FROM    db_sql_statements s
        JOIN    db_sql_stmt_param_bridge pb
        ON      s.s_stmt_id = pb.pb_stmt_id
        JOIN    db_sql_parameters p
        ON      pb.pb_param_id = p.p_param_id
)
WHERE   r_number = 1
;    
-- SELECT eo.eo_id, eo.eo_value + et.et_value FROM example_one eo JOIN example_two et ON eo.eo_id = et.et_id WHERE 1 = 1

SELECT eo.eo_id, eo.eo_value + et.et_value FROM example_one eo JOIN example_two et ON eo.eo_id = et.et_id WHERE 1 = 1;
-- 1    30

从 PL/SQL 运行它并使用 EXECUTE IMMEDIATE。 我在写db框架的时候做过类似的事情。

【讨论】:

  • 我喜欢这种将片段保存在 DBMS 表中的概念,特别是因为它允许在运行时进行动态生成。可以在所述表中更新代码,这意味着不需要重新编写已经分发的语句。感谢您的中肯建议。
猜你喜欢
  • 2015-11-07
  • 1970-01-01
  • 2011-02-26
  • 1970-01-01
  • 1970-01-01
  • 2011-02-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多