用用户定义的参数构建Oracle Apex Interactive报表的最佳方法是什么?

时间:2018-07-05 06:54:13

标签: plsql oracle-apex oracle-apex-5.1

我正在尝试使用用户参数在Oracle Apex中生成报告。首先,我有一个表格,用户可以选择频率,日期,要报告的人以及其他选项。我会将所有这些详细信息发送到呈现此交互式报告的下一页。到目前为止,我一直在尝试在PL / SQL Function主体中构建查询以返回SQL查询,但是每次我都收到以下错误时。

  

ORA-20999:WWV_FLOW_EXEC.NULL_QUERY_RETURNED_BY_FUNCTION

我的代码示例:

declare
    single_date         char(12)  := ''''||TO_CHAR(TRUNC(to_date(:P21_DATE, 'DD-MM-YYYY')), 'DD.MM.YYYY')||'''';
    start_date_value    char(12)  := ''''||TO_CHAR(TRUNC(to_date(:P21_DATE, 'DD-MM-YYYY'), 'IW'), 'DD.MM.YYYY')||'''';
    end_date_value      char(12)  := ''''||TO_CHAR(TRUNC(to_date(:P21_DATE, 'DD-MM-YYYY'), 'IW') + 6, 'DD.MM.YYYY')||'''';
    first_month_value   char(12)  := ''''||to_char(trunc(to_date(:P21_DATE, 'DD-MM-YYYY'), 'MM'), 'DD.MM.YYYY')||'''';
    last_month_value    char(12)  := ''''||to_char(LAST_DAY(to_date(:P21_DATE,'DD-MM-YYYY')), 'DD.MM.YYYY')||'''';
    first_year_value    char(12)  := ''''||to_char(trunc(to_date(:P21_DATE, 'DD-MM-YYYY'), 'YYYY'), 'DD.MM.YYYY')||'''';
    last_year_value     char(12)  := ''''||to_char(last_day(add_months(to_date(:P21_DATE,'DD-MM-YYYY'),12 - to_number(to_char(to_date(:P21_DATE,'DD-MM-YYYY'),'mm')))), 'DD.MM.YYYY')||'''';
begin
    if :P21_DETAILS = 1 then
        if :P21_FREQUENCY = 1 then
            if :P21_FOR = 1 then
                return q'~
                SELECT <columns> FROM <table> WHERE <date> = '||single_date||' AND <something> = '||lower(:APP_USER)||';
                ~';
            elsif :P21_FOR = 2 then
                return q'~
                SELECT <columns> FROM <table> WHERE <date> = '||single_date||' AND <something> = '||lower(:P21_PERSON)||';
                ~';
            elsif :P21_FOR = 3 then
                return q'~
                SELECT <columns> FROM <table> WHERE <date> = '||single_date||';
                ~';
            end if;
        elsif :P21_FREQUENCY = 2 then
            if :P21_FOR = 1 then
                return q'~
                SELECT <columns> FROM <table> WHERE <date> BETWEEN TO_DATE('||start_date_value||', ''DD.MM.YYYY'') AND TO_DATE('||end_date_value||', ''DD.MM.YYYY'') AND <something> = '||lower(:APP_USER)||';
                ~';
            elsif :P21_FOR = 2 then
                return q'~
                SELECT <columns> FROM <table> WHERE <date> BETWEEN TO_DATE('||start_date_value||', ''DD.MM.YYYY'') AND TO_DATE('||end_date_value||', ''DD.MM.YYYY'') AND <something> = '||lower(:P21_PERSON)||';
                ~';
            elsif :P21_FOR = 3 then
                return q'~
                SELECT <columns> FROM <table> WHERE <date> BETWEEN TO_DATE('||start_date_value||', ''DD.MM.YYYY'') AND TO_DATE('||end_date_value||', ''DD.MM.YYYY'');
                ~';
            end if;
        elsif :P21_FREQUENCY = 3 then
            if :P21_FOR = 1 then
                return q'~
                SELECT <columns> FROM <table> WHERE <date> BETWEEN TO_DATE('||first_month_value||', ''DD.MM.YYYY'') AND TO_DATE('||last_month_value||', ''DD.MM.YYYY'') AND <something> = '||lower(:APP_USER)||';
                ~';
            elsif :P21_FOR = 2 then
                return q'~
                SELECT <columns> FROM <table> WHERE <date> BETWEEN TO_DATE('||first_month_value||', ''DD.MM.YYYY'') AND TO_DATE('||last_month_value||', ''DD.MM.YYYY'') AND <something> = '||lower(:P21_PERSON)||';
                ~';
            elsif :P21_FOR = 3 then
                return q'~
                SELECT <columns> FROM <table> WHERE <date> BETWEEN TO_DATE('||first_month_value||', ''DD.MM.YYYY'') AND TO_DATE('||last_month_value||', ''DD.MM.YYYY'');
                ~';
            end if;
        elsif :P21_FREQUENCY = 4 then
            if :P21_FOR = 1 then
                return q'~
                SELECT <columns> FROM <table> WHERE <date> BETWEEN TO_DATE('||first_year_value||', ''DD.MM.YYYY'') AND TO_DATE('||last_year_value||', ''DD.MM.YYYY'') AND <something> = '||lower(:APP_USER)||';
                ~';
            elsif :P21_FOR = 2 then
                return q'~
                SELECT <columns> FROM <table> WHERE <date> BETWEEN TO_DATE('||first_year_value||', ''DD.MM.YYYY'') AND TO_DATE('||last_year_value||', ''DD.MM.YYYY'') AND <something> = '||lower(:P21_PERSON)||';
                ~';
            elsif :P21_FOR = 3 then
                return q'~
                SELECT <columns> FROM <table> WHERE <date> BETWEEN TO_DATE('||first_year_value||', ''DD.MM.YYYY'') AND TO_DATE('||last_year_value||', ''DD.MM.YYYY'');
                ~';
            end if;
        end if;
    end if;
end;

还尝试了其他方法,在下面进行编码,但也没有成功。

  

ORA-01403:找不到数据

declare
    date_modify         char(12)  := :P24_DATE;
    single_date         char(12)  := ''''||TO_CHAR(TRUNC(to_date(date_modify, 'DD.MM.YYYY')), 'DD.MM.YYYY')||'''';
    start_date_value    char(12)  := ''''||TO_CHAR(TRUNC(to_date(date_modify, 'DD.MM.YYYY'), 'IW'), 'DD.MM.YYYY')||'''';
    end_date_value      char(12)  := ''''||TO_CHAR(TRUNC(to_date(date_modify, 'DD.MM.YYYY'), 'IW') + 6, 'DD.MM.YYYY')||'''';
    first_month_value   char(12)  := ''''||to_char(trunc(to_date(date_modify, 'DD.MM.YYYY'), 'MM'), 'DD.MM.YYYY')||'''';
    last_month_value    char(12)  := ''''||to_char(LAST_DAY(to_date(date_modify,'DD.MM.YYYY')), 'DD.MM.YYYY')||'''';
    first_year_value    char(12)  := ''''||to_char(trunc(to_date(date_modify, 'DD.MM.YYYY'), 'YYYY'), 'DD.MM.YYYY')||'''';
    last_year_value     char(12)  := ''''||to_char(last_day(add_months(to_date(date_modify,'DD.MM.YYYY'),12 - to_number(to_char(to_date(date_modify,'DD.MM.YYYY'),'mm')))), 'DD.MM.YYYY')||'''';
    query               varchar2(500);
begin
    if apex_application.g_f01(1) = 1 then
        if :P24_TYPE = 1 then
            query := 'SELECT <some columns> FROM <table> WHERE <date> = '||single_date||'';
        elsif :P24_TYPE = 2 then
            query := 'SELECT <some columns> FROM <table> WHERE <date> BETWEEN TO_DATE('||start_date_value||', ''DD.MM.YYYY'') AND TO_DATE('||end_date_value||', ''DD.MM.YYYY'')';
        elsif :P24_TYPE = 3 then
            query := 'SELECT <some columns> FROM <table> WHERE <date> BETWEEN TO_DATE('||first_month_value||', ''DD.MM.YYYY'') AND TO_DATE('||last_month_value||', ''DD.MM.YYYY'')';
        elsif :P24_TYPE = 4 then
            query := 'SELECT <some columns> FROM <table> WHERE <date> BETWEEN TO_DATE('||first_year_value||', ''DD.MM.YYYY'') AND TO_DATE('||last_year_value||', ''DD.MM.YYYY'')';
        end if;
    end if;
    if :P24_PERSON <> 'no' then
        query := query||' AND <something_else> = '''||lower(:P24_PERSON)||'''';
    end if;

    return query;
end;

谢谢。

1 个答案:

答案 0 :(得分:1)

考虑到过去和逻辑问题,您的代码当前是一场SQL injection的噩梦,使您的页面容易受到用户查询他们不允许的信息的攻击。它还强制使用文字,这会太快破坏您共享的SQL,forcing hard parsing.

具有本机功能,可让您使用IR链接到页面,并像手动使用过滤器一样预先填充过滤器。

https://docs.oracle.com/database/apex-5.1/HTMDB/linking-to-interactive-reports.htm#HTMDB30108