【问题标题】:Query using a statement within a VARCHAR2 column使用 VARCHAR2 列中的语句进行查询
【发布时间】:2019-12-02 02:54:31
【问题描述】:

有没有办法让选择语句在WHERE 子句中包含表中包含的语句?例如下表:

CREATE TABLE test_tab(
    date_column DATE,
    frequency NUMBER,
    test_statement VARCHAR2(255)
)
/

如果

MOD(SYSDATE - DATE, frequency) = 0

被包含在test_statement 列中,有没有办法选择正确的行? test_statement 会有所不同,并且在整个表格中都不相同。我可以在 PL/SQL 中执行此操作,但希望在不使用 PL/SQL 的情况下执行此操作。

【问题讨论】:

    标签: database oracle oracle12c


    【解决方案1】:

    这种SQL中的动态SQL可以用DBMS_XMLGEN.getXML创建。虽然查询看起来有点奇怪,但您可能需要考虑不同的设计。

    首先,我使用您的 DDL 创建了一个示例表和行。我不确定您要对条件做什么,所以我将它们简化为两行,条件更简单。第一行符合第一个条件,两行都不符合第二个条件。

    --Create sample table and row that matches the condition.
    CREATE TABLE test_tab(
        date_column DATE,
        frequency NUMBER,
        test_statement VARCHAR2(255)
    )
    /
    
    insert into test_tab values(sysdate, 1, 'frequency = 1');
    insert into test_tab values(sysdate, 2, '1=2');
    commit;
    

    这是大查询,它只返回第一行,它只匹配第一个条件。

    --Find rows where ROWID is in a list of ROWIDs that match the condition.
    select *
    from test_tab
    where rowid in
    (
        --Convert XMLType to relational data.
        select the_rowid
        from
        (
            --Convert CLOB to XMLType.
            select xmltype(xml_results) xml_results
            from
            (
                --Create a single XML file with the ROWIDs that match the condition.
                select dbms_xmlgen.getxml('
                    select rowid
                    from test_tab where '||test_statement) xml_results
                from test_tab
            )
            where xml_results is not null
        )
        cross join
        xmltable
        (
            '/ROWSET/ROW'
            passing xml_results
            columns
                the_rowid varchar2(128) path 'ROWID'
        )
    );
    

    【讨论】:

    • 哇,这真的很难看,但它确实有效。非常感谢!
    • 非常好。我不能那样做。
    【解决方案2】:

    这需要动态 SQL,所以 - 是的,处理它的是 PL/SQL。我认为SQL层做不到。

    到目前为止,我不知道您尝试了什么,所以 - 只是一个想法:返回 ref 光标的函数可能会有所帮助,例如

    SQL> create table test (date_column date, frequency number, test_statement varchar2(255));
    
    Table created.
    
    SQL> insert into test values (trunc(sysdate), 2, 'deptno = 30');
    
    1 row created.
    
    SQL> create or replace function f_test return sys_refcursor
      2  is
      3    l_str varchar2(200);
      4    l_rc  sys_refcursor;
      5  begin
      6    select test_statement
      7      into l_str
      8      from test
      9      where date_column = trunc(sysdate);
     10
     11    open l_rc for 'select deptno, ename from emp where ' || l_str;
     12    return l_rc;
     13  end;
     14  /
    
    Function created.
    

    测试:

    SQL> select f_test from dual;
    
    F_TEST
    --------------------
    CURSOR STATEMENT : 1
    
    CURSOR STATEMENT : 1
    
        DEPTNO ENAME
    ---------- ----------
            30 ALLEN
            30 WARD
            30 MARTIN
            30 BLAKE
            30 TURNER
            30 JAMES
    
    6 rows selected.
    
    
    SQL>
    

    这样做的好处是您可以将整个语句保存到该表中并使用相同的函数运行其中的任何一个。

    【讨论】:

    • 使用纯 SQL 执行此操作有一些技巧,请参阅我的回答。但总的来说,我认为像您所做的那样创建单独的对象将是一个更清洁的解决方案。
    • 我将像这样实现它,因为它更干净,但@JonHeller 的解决方案在技术上是我提出的问题的“正确”解决方案。
    【解决方案3】:

    你可以试试这个 select * from test_tab where mod(sysdate - date, frequency) = 0;

    【讨论】:

    • 我认为这个问题是关于创建一个在编译时条件未知的 SQL 语句,因此静态 SQL 语句在这里没有帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-06-26
    • 1970-01-01
    • 1970-01-01
    • 2021-11-03
    • 2011-02-14
    • 2011-05-28
    • 2012-04-09
    相关资源
    最近更新 更多