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;
【讨论】:
statementFETCH 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 从所选结果中选择的主要内容,如果未能解决你的问题,请参考以下文章