元编程oracle sql select语句

元编程oracle sql select语句,sql,oracle,Sql,Oracle,假设我有一个如下的查询: SELECT CASE WHEN ONE = 1 THEN 1 ELSE 0 END, CASE WHEN JUST_ONE = 1 THEN 1 ELSE 0 END, CASE WHEN ANOTHER_ONE = 1 THEN 1 ELSE 0 END, CASE WHEN TWO = 1 THEN 1 ELSE 0 END, CASE WHEN JUST_TWO = 1 THEN 1 ELSE 0 END, CASE WHEN ANOT

假设我有一个如下的查询:

SELECT
  CASE WHEN ONE = 1 THEN 1 ELSE 0 END,
  CASE WHEN JUST_ONE = 1 THEN 1 ELSE 0 END,
  CASE WHEN ANOTHER_ONE = 1 THEN 1 ELSE 0 END,

  CASE WHEN TWO = 1 THEN 1 ELSE 0 END,
  CASE WHEN JUST_TWO = 1 THEN 1 ELSE 0 END,
  CASE WHEN ANOTHER_TWO = 1 THEN 1 ELSE 0 END

  -- 20 more things like that where changes only columns name
FROM
  SOME_TABLE;

如您所见,这两个组之间的唯一区别在于,在第一个组中,我使用的列有'1',在第二个组中,我使用的列有'2',在我的实际查询中,我有大约30个这样的组,所以我想知道是否有办法以某种方式缩短它?

因为它们是不同的列,您必须在“选择”列表中分别明确提及它们。您无法在纯SQL中动态执行此操作

我建议,使用一个好的文本编辑器,编写整个SQL几乎不需要一两分钟

您可以使用解码,这将有一些较少的语法,而不是冗长的大小写表达式

比如说,

  DECODE(ONE, 1, 1, 0) AS col1, 
  DECODE(JUST_ONE, 1, 1, 0) AS col2,
  DECODE(ANOTHER_ONE, 1, 1, 0) AS col3,
  DECODE(TWO, 1, 1, 0) AS col4,
  DECODE(JUST_TWO, 1, 1, 0) AS col5,
  DECODE(ANOTHER_TWO, 1, 1, 0) as col6
我建议坚持使用SQL,而不要使用PL/SQL。它们不一样,它们是不同的引擎<代码>PL-->过程语言

但是如果您坚持,那么您可以使用循环的光标来循环[DBA | all | USER]_TAB _COLS中的所有列。您可以使用SYS\u REFCURSOR查看数据。首先,您必须构建动态SQL

,生成方法(在SQL受限的manuall后期处理中)可以是

给予

CASE WHEN ONE = 1 THEN 1 ELSE 0 END,
CASE WHEN JUST_ONE = 1 THEN 1 ELSE 0 END,
CASE WHEN ANOTHER_ONE = 1 THEN 1 ELSE 0 END,

CASE WHEN TWO = 1 THEN 1 ELSE 0 END,
CASE WHEN JUST_TWO = 1 THEN 1 ELSE 0 END,
CASE WHEN ANOTHER_TWO = 1 THEN 1 ELSE 0 END,
请注意,您提供了列名列表并获得扩展语法。
通常需要删除最后一个分隔符并添加换行选择框。

下面是动态创建查询的示例。如果希望创建更多查询,可以将其放入游标变量中

select 'SELECT ' || listagg('CASE WHEN '||column_name||' = 1 THEN 1 ELSE 0 END ' || column_name,',') within group(order by column_name) || ' FROM YOUR_TABLE_NAME'
from cols 
where data_type in ('NUMBER')
and table_name = 'YOUR_TABLE_NAME';

您可以使用
COLS
视图获取所有表的所有列名及其数据类型。

通过将Oracle数据盒带和任何类型相结合,可以进行Oracle SQL元编程

即使使用现有包进行元编程,在查询中构建查询也很复杂,应尽可能避免。其他答案通常更好,尽管它们可能需要额外的步骤,并且不是“纯”SQL

如果您真的需要在一条SQL语句中完成所有操作,请尝试我的。安装后,创建一个示例架构:

create table some_table(
    one number, just_one number, another_one number,
    two number, just_two number, another_two number);

insert into some_table values(1,1,1,2,2,2);
运行此查询,根据数据字典生成真正的SELECT语句:

select * from table(method4.dynamic_query(
    q'[
        --Find columns that match pattern and aggregate into SELECT list.
        select
            'SELECT'||chr(10)||
            rtrim(listagg('  CASE WHEN '||column_name||' = 1 THEN 1 ELSE 0 END '||column_name||',', chr(10))
                within group (order by order_by1, order_by2), ',')||chr(10)||
            'FROM some_table' sql_statement
        from user_tab_columns
        join
        (
            --Column names that might match the pattern [null|JUST_|ANOTHER]SPELLED_NUMBER.
            select prefix||spelled_number possible_column_names
                ,order_by1, order_by2
            from
            (
                --Numbers 1-10.
                select upper(to_char(to_date(level, 'j'), 'jsp')) spelled_number
                    ,level order_by1
                from dual
                --Increase this number up to the maximum possible number.
                connect by level <= 10
            )
            cross join
            (
                --Possible prefixes.
                select null prefix, 1 order_by2 from dual union all
                select 'JUST_' prefix, 2 order_by2 from dual union all
                select 'ANOTHER_' prefix, 3 order_by2 from dual
            )
        ) column_names
            on user_tab_columns.column_name = column_names.possible_column_names
        where table_name = 'SOME_TABLE'
    ]'
));
这是一些非常复杂的编码,以避免键入几行。当经理第一次听说硬编码总是不好的时候,他就会想出这种解决方案


这从字面上回答了关于对Oracle SQL SELECT语句进行元编程的问题。在少数情况下,这种方法可以挽救生命。但是99.9%的情况下,即使自动化程度稍低,也最好用简单的方法来处理问题。

不是用普通的SQL,但您可以尝试动态生成此查询。我可以用PL/SQL来做吗?我没有访问任何编程语言的权限。PL/SQL=过程语言/结构化查询语言当然,您可以在PL/SQL过程中通过动态构建
SELECT
子句并使用
executeimmediate
语句来运行它。这可能是最好的方法。但是有一些技巧可用于在单个SQL语句中运行此查询。我的答案有一个例子,虽然这个场景有点过于复杂。+1虽然复杂,但回答了元编程的问题。我认为可以使用XML解决方案将其最小化。谢谢分享
select * from table(method4.dynamic_query(
    q'[
        --Find columns that match pattern and aggregate into SELECT list.
        select
            'SELECT'||chr(10)||
            rtrim(listagg('  CASE WHEN '||column_name||' = 1 THEN 1 ELSE 0 END '||column_name||',', chr(10))
                within group (order by order_by1, order_by2), ',')||chr(10)||
            'FROM some_table' sql_statement
        from user_tab_columns
        join
        (
            --Column names that might match the pattern [null|JUST_|ANOTHER]SPELLED_NUMBER.
            select prefix||spelled_number possible_column_names
                ,order_by1, order_by2
            from
            (
                --Numbers 1-10.
                select upper(to_char(to_date(level, 'j'), 'jsp')) spelled_number
                    ,level order_by1
                from dual
                --Increase this number up to the maximum possible number.
                connect by level <= 10
            )
            cross join
            (
                --Possible prefixes.
                select null prefix, 1 order_by2 from dual union all
                select 'JUST_' prefix, 2 order_by2 from dual union all
                select 'ANOTHER_' prefix, 3 order_by2 from dual
            )
        ) column_names
            on user_tab_columns.column_name = column_names.possible_column_names
        where table_name = 'SOME_TABLE'
    ]'
));
       ONE   JUST_ONE ANOTHER_ONE        TWO   JUST_TWO ANOTHER_TWO
---------- ---------- ----------- ---------- ---------- -----------
         1          1           1          0          0           0