带有应用程序上下文的Oracle视图使用" group by"没有奇怪的黑客就没有结果

时间:2018-01-15 03:26:11

标签: sql oracle view

我在Oracle中创建了一个视图,它打算在表中加载部分数据,并受应用程序上下文中设置的参数限制:

CREATE OR REPLACE VIEW VW_SALT_RAW_SUMMARY AS
(
    select
        VENDOR_ID, PRD_CATEGORY, LOGIN_NAME, CURRENCY /*, Some more aggregated fields*/
    from
        VENDOR_RECORD
    where
        (
            order_time between SYS_CONTEXT('CTX_ALERT', 'rptBeginTime') and SYS_CONTEXT('CTX_ALERT', 'rptEndTime')
            AND order_time between SYS_CONTEXT('CTX_ALERT', 'RESTRICT_BEGIN_TIME') AND SYS_CONTEXT('CTX_ALERT', 'RESTRICT_END_TIME')
        )
        and
        (
            (
                SYS_CONTEXT('CTX_ALERT', 'rptVENDOR_ID') = '*'
                or
                (
                    VENDOR_ID in
                    (
                        select
                            regexp_substr(SYS_CONTEXT('CTX_ALERT', 'rptVENDOR_ID'), '[^, ]+',1, rownum) str
                        from
                            dual connect by level <= regexp_count (SYS_CONTEXT('CTX_ALERT', 'rptVENDOR_ID'), '[^, ]+')
                    )
                )
            )
            AND
            (
                SYS_CONTEXT('CTX_ALERT', 'RESTRICT_VENDOR_ID') = '*'
                or
                (
                    VENDOR_ID in
                    (
                        select
                            regexp_substr(SYS_CONTEXT('CTX_ALERT', 'RESTRICT_VENDOR_ID'), '[^, ]+',1, rownum) str
                        from
                            dual connect by level <= regexp_count (SYS_CONTEXT('CTX_ALERT', 'RESTRICT_VENDOR_ID'), '[^, ]+')
                    )
                )
            )
        )
        and
        (
            (
                SYS_CONTEXT('CTX_ALERT', 'rptPRD_CATEGORY') = '*'
                or
                (
                    PRD_CATEGORY in
                    (
                        select
                            regexp_substr(SYS_CONTEXT('CTX_ALERT', 'rptPRD_CATEGORY'), '[^, ]+',1, rownum) str
                        from
                            dual connect by level <= regexp_count (SYS_CONTEXT('CTX_ALERT', 'rptPRD_CATEGORY'), '[^, ]+')
                    )
                )
            )
            AND
            (
                SYS_CONTEXT('CTX_ALERT', 'RESTRICT_PRD_CATEGORY') = '*'
                or
                (
                    PRD_CATEGORY in
                    (
                        select
                            regexp_substr(SYS_CONTEXT('CTX_ALERT', 'RESTRICT_PRD_CATEGORY'), '[^, ]+',1, rownum) str
                        from
                            dual connect by level <= regexp_count (SYS_CONTEXT('CTX_ALERT', 'RESTRICT_PRD_CATEGORY'), '[^, ]+')
                    )
                )
            )
        )
        and
        (
            (
                SYS_CONTEXT('CTX_ALERT', 'rptLOGIN_NAME') = '*'
                or
                (
                    LOGIN_NAME in
                    (
                        select
                            regexp_substr(SYS_CONTEXT('CTX_ALERT', 'rptLOGIN_NAME'), '[^, ]+',1, rownum) str
                        from
                            dual connect by level <= regexp_count (SYS_CONTEXT('CTX_ALERT', 'rptLOGIN_NAME'), '[^, ]+')
                    )
                )
            )
            AND
            (
                SYS_CONTEXT('CTX_ALERT', 'RESTRICT_PRD_CATEGORY') = '*'
                or
                (
                    LOGIN_NAME in
                    (
                        select
                            regexp_substr(SYS_CONTEXT('CTX_ALERT', 'RESTRICT_PRD_CATEGORY'), '[^, ]+',1, rownum) str
                        from
                            dual connect by level <= regexp_count (SYS_CONTEXT('CTX_ALERT', 'RESTRICT_PRD_CATEGORY'), '[^, ]+')
                    )
                )
            )
        )
    group by
        VENDOR_ID, PRD_CATEGORY, LOGIN_NAME, CURRENCY
);

但是,尽管我在应用程序上下文中正确设置了参数,但查询始终不返回任何结果。我尝试了没有group by和聚合字段的相同查询,然后我可以获取数据(当然没有任何分组)。

如果我想通过&#34;来获得&#34;数据属性,我必须添加虚拟语句&#34; rownum&gt; = 0&#34; hack是where子句中的最后一个语句,即:

CREATE OR REPLACE VIEW VW_SALT_RAW_SUMMARY AS
(
    select
        VENDOR_ID, PRD_CATEGORY, LOGIN_NAME, CURRENCY /*, Some more aggregated fields*/
    from
        VENDOR_RECORD
    where
        (
            order_time between SYS_CONTEXT('CTX_ALERT', 'rptBeginTime') and SYS_CONTEXT('CTX_ALERT', 'rptEndTime')
            AND order_time between SYS_CONTEXT('CTX_ALERT', 'RESTRICT_BEGIN_TIME') AND SYS_CONTEXT('CTX_ALERT', 'RESTRICT_END_TIME')
        )
        and
        (
            (
                SYS_CONTEXT('CTX_ALERT', 'rptVENDOR_ID') = '*'
                or
                (
                    VENDOR_ID in
                    (
                        select
                            regexp_substr(SYS_CONTEXT('CTX_ALERT', 'rptVENDOR_ID'), '[^, ]+',1, rownum) str
                        from
                            dual connect by level <= regexp_count (SYS_CONTEXT('CTX_ALERT', 'rptVENDOR_ID'), '[^, ]+')
                    )
                )
            )
            AND
            (
                SYS_CONTEXT('CTX_ALERT', 'RESTRICT_VENDOR_ID') = '*'
                or
                (
                    VENDOR_ID in
                    (
                        select
                            regexp_substr(SYS_CONTEXT('CTX_ALERT', 'RESTRICT_VENDOR_ID'), '[^, ]+',1, rownum) str
                        from
                            dual connect by level <= regexp_count (SYS_CONTEXT('CTX_ALERT', 'RESTRICT_VENDOR_ID'), '[^, ]+')
                    )
                )
            )
        )
        and
        (
            (
                SYS_CONTEXT('CTX_ALERT', 'rptPRD_CATEGORY') = '*'
                or
                (
                    PRD_CATEGORY in
                    (
                        select
                            regexp_substr(SYS_CONTEXT('CTX_ALERT', 'rptPRD_CATEGORY'), '[^, ]+',1, rownum) str
                        from
                            dual connect by level <= regexp_count (SYS_CONTEXT('CTX_ALERT', 'rptPRD_CATEGORY'), '[^, ]+')
                    )
                )
            )
            AND
            (
                SYS_CONTEXT('CTX_ALERT', 'RESTRICT_PRD_CATEGORY') = '*'
                or
                (
                    PRD_CATEGORY in
                    (
                        select
                            regexp_substr(SYS_CONTEXT('CTX_ALERT', 'RESTRICT_PRD_CATEGORY'), '[^, ]+',1, rownum) str
                        from
                            dual connect by level <= regexp_count (SYS_CONTEXT('CTX_ALERT', 'RESTRICT_PRD_CATEGORY'), '[^, ]+')
                    )
                )
            )
        )
        and
        (
            (
                SYS_CONTEXT('CTX_ALERT', 'rptLOGIN_NAME') = '*'
                or
                (
                    LOGIN_NAME in
                    (
                        select
                            regexp_substr(SYS_CONTEXT('CTX_ALERT', 'rptLOGIN_NAME'), '[^, ]+',1, rownum) str
                        from
                            dual connect by level <= regexp_count (SYS_CONTEXT('CTX_ALERT', 'rptLOGIN_NAME'), '[^, ]+')
                    )
                )
            )
            AND
            (
                SYS_CONTEXT('CTX_ALERT', 'RESTRICT_PRD_CATEGORY') = '*'
                or
                (
                    LOGIN_NAME in
                    (
                        select
                            regexp_substr(SYS_CONTEXT('CTX_ALERT', 'RESTRICT_PRD_CATEGORY'), '[^, ]+',1, rownum) str
                        from
                            dual connect by level <= regexp_count (SYS_CONTEXT('CTX_ALERT', 'RESTRICT_PRD_CATEGORY'), '[^, ]+')
                    )
                )
            )
        )
        -- A DIRTY HACK TO MAKE THE QUERY RETURNS DATA
        AND ROWNUM >= 0
    group by
        VENDOR_ID, PRD_CATEGORY, LOGIN_NAME, CURRENCY
)

这个问题让我发疯,我想问一下背后的原因,谢谢。

EDITED: 有关VENDOR_RECORD

的更多信息
  • Oracle版本:11g(11.2.0.4.0)
  • 这是一个非常庞大的存档表(每个日期&gt; 10M记录),并按&#34; order_time&#34;
  • 进行分区
  • 它的目的是成为一个分析DB而不是实时事务DB,因此不需要非常实时的响应。另一方面,准确性很重要。

1 个答案:

答案 0 :(得分:0)

看起来很奇怪,但是您可以通过在视图中作为注释创建一些条件来调试代码,我相信您会找出导致问题的行。添加&#34; AND rownum&gt; 0&#34;如果查询看起来很复杂,那么调试它是不够的,只需先进行调试。