sqlplus 从所选结果中选择

Posted

技术标签:

【中文标题】sqlplus 从所选结果中选择【英文标题】:sqlplus SELECT from the selected result 【发布时间】:2018-09-07 09:51:25 【问题描述】:

我正在使用 Oracle sqlplus 并尝试使用从以下代码中选择的结果并再次从 Table_1 中选择列

SELECT * 
FROM
(
SELECT Column_Name 
FROM All_Tab_columns 
WHERE Table_Name=UPPER('Table_1')
)
INTERSECT
(
SELECT Column_Name 
FROM All_Tab_columns 
WHERE Table_Name=UPPER('Table_2')
);

我怎样才能执行这样的操作:

SELECT <Columns_That_Intersected>
FROM Table_1;

是否可以将 Columns_That_Intersected 存储在变量/函数/过程中并再次将其用于其他 select 语句?

【问题讨论】:

【参考方案1】:

是的,这是可能的。只需将查询的聚合结果保存在substitution variable 中。像这样的:

create table items1 as 
select rownum id, 'me '||rownum name, 1 dummy
from xmlTable ('1 to 3');
create table items2 as select id, name from items1;

set verify off
col Columns_That_Intersected new_value Columns_That_Intersected noprint 

select listagg (column_name, ',') within group (order by null) Columns_That_Intersected
from (
    select column_name
    from All_Tab_Columns 
    where Table_Name=UPPER('items1')
    intersect
    select column_name
    from All_Tab_columns 
    where Table_Name=UPPER('items2')
);

prompt Columns_That_Intersected=&Columns_That_Intersected
select &Columns_That_Intersected 
from items1; 

输出:

Columns_That_Intersected=ID,NAME

        ID NAME
---------- -------------------------------------------
         1 me 1
         2 me 2
         3 me 3

About col[umn] command

【讨论】:

谢谢,0xdb。我花了很长时间才明白这一点。只是想和你确认几件事。我可以说 SELECT 背后的语法必须是“列变量”吗?换句话说,如果我将 Columns_That_Intersected 声明为 CHAR,它不会起作用? “SELECT 后面的语法必须是“列变量”是什么意思? SELECT 子句没有特殊语法。这里,“Columns_That_Intersected”是 CHAR 数据类型的列别名。 对不起,我的意思是“语法 after SELECT ”。澄清一下,所以 COLUMN 命令是 SELECT FROM WHERE 查询语法的一部分。 NEW_VALUE 将 Columns_That_Intersected 存储到一个替换变量中,以便在脚本的后面部分使用。对吗? COLUMN 命令是 SQL*Plus 的一部分。它不是 SELECT 查询语法的一部分。 NEW_VALUE 指定一个变量来保存查询执行后的列值。【参考方案2】:

只需获取表 table1 和 table2 中都存在的列名,您可以使用以下查询:

SELECT Column_Name
  FROM all_tab_columns t1
 WHERE table_name = 'Table1'
   AND EXISTS (SELECT 1
                 FROM all_tab_columns t2
                WHERE table_name = 'Table2'
                  AND t2.Column_Name = t1.Column_Name);

然后要从 Table1 中获取这些列值,您可以使用以下 PL/SQL 构造:

DECLARE
v_sql_statement VARCHAR2(2000);
v_cols          VARCHAR2(2000);
BEGIN
 FOR cn IN (SELECT Column_Name
              FROM all_tab_columns t1
             WHERE table_name = 'Table1'
               AND EXISTS (SELECT 1
                             FROM all_tab_columns t2
                            WHERE table_name = 'Table2'
                              AND t2.Column_Name = t1.Column_Name))
 LOOP
    v_cols := v_cols || ', ' || cn.column_name;

 END LOOP;

 v_cols := ltrim(v_cols, ',');
 v_sql_statement := 'SELECT ' || v_cols || ' FROM Table1';
 EXECUTE IMMEDIATE v_sql_statement;

END; 

【讨论】:

【参考方案3】:

例如,您可以使用动态 sql。

您的选择结果可以使用 listagg 函数聚合到一个列表中

SELECT listagg( Column_Name,',') WITHIN GROUP (ORDER BY 1) cols
FROM
(
  SELECT Column_Name 
  FROM All_Tab_columns 
  WHERE Table_Name=UPPER('tab1')      
  INTERSECT      
  SELECT Column_Name 
  FROM All_Tab_columns 
  WHERE Table_Name=UPPER('tab2')

);

结果你会得到例如。 col1, col2, col3 借助此列表,您可以在 plsql 块中创建一个游标,然后循环遍历它以打印出您想要的 wat。

declare
  v_cols    VARCHAR2(2000);
  v_select_string varchar(2000);
  csr                SYS_REFCURSOR;
  v1            VARCHAR2(2000);
BEGIN
  SELECT listagg( Column_Name,',') WITHIN GROUP (ORDER BY 1) cols
  into v_cols
  FROM
  (
    SELECT Column_Name 
    FROM All_Tab_columns 
    WHERE Table_Name=UPPER('tab1')    
    INTERSECT    
    SELECT Column_Name 
    FROM All_Tab_columns 
    WHERE Table_Name=UPPER('tab2')  
  );

  v_select_string   := 'SELECT ' || v_cols  ||
                       ' FROM tab1';

  OPEN csr FOR v_select_string;

  LOOP
    FETCH csr INTO v1;

    EXIT WHEN csr%NOTFOUND;         

    DBMS_OUTPUT.PUT_LINE( v1);
  END LOOP;

  CLOSE csr;
END P1;

【讨论】:

statement FETCH csr INTO v1; 如果v_cols 中有多个列,则会出错。为避免这种情况,请使用FOR i IN csr 而不是LOOP 您好修补程序,只是想澄清一些事情。对于命令 DBMS_OUTPUT.PUT_LINE( v1) ,是否类似于:将 VARCHAR(2) 值作为语法放入脚本中? @FlyFlyWing DBMS_OUTPUT.PUT_LINE 在屏幕上打印字符串。这样你就可以看到变量的值了。 @hotfix 我明白了...所以将字符串作为语法执行的部分是 OPEN csr FOR v_select_string; 我对吗?

以上是关于sqlplus 从所选结果中选择的主要内容,如果未能解决你的问题,请参考以下文章

如何将select的结果分配到sqlplus变量中

如何将 SQLPlus 的结果存储到 shell 变量中

离子3从所选日期开始设定日期

结果不打印 Python - SQlplus

Oracle--sqlplus如何设置SQLPlus结果显示的宽度,ORACLE sqlplus提示符设置

调整从所选单元格到特定范围的Excel选择