【发布时间】:2016-10-12 15:44:44
【问题描述】:
我正在为此而发疯。我对动态 SQL 还很陌生,所以我可能只是没有向 Google 提出正确的问题,但这就是我正在尝试做的事情......我有一个动态 SQL 查询。当我运行该查询时,它会产生几行。所有这些行(大约 30 行)构成一个联合查询。我可以复制所有这些行并粘贴到一个新查询中并运行 - 工作正常,但我需要做的是在一个查询中运行这一切。我已经查找了使用立即执行和获取的示例,但我似乎无法让他们真正吐出数据......他们最终只是说“成功执行”之类的话,但实际上并没有产生任何结果行.下面 SQL 的结果列名是“qry_txt”——我不想按面值生成它,而是想将它作为查询执行。同样,我可能没有很好地表达这一点,但我基本上是在尝试将 2 个查询(涉及手动复制/粘贴步骤)变成一个查询。希望这是有道理的......
这是我的 SQL:
Select CASE when
lead(ROWNUM) over(order by ROWNUM) is null then
'SELECT '||''''||T.TABLE_NAME||''''||' as TABLE_NAME,'||''''||T.COLUMN_NAME||''''||' as COLUMN_NAME, cast('|| T.COLUMN_NAME ||' as
varchar2(100)) as SAMPLE_DATA ||
from rpt.'||T.TABLE_NAME ||' where '||T.COLUMN_NAME||' is not null and ROWNUM=1;'
else
'SELECT '||''''||T.TABLE_NAME||''''||' as TABLE_NAME,'||''''||T.COLUMN_NAME||''''||' as COLUMN_NAME, cast('|| T.COLUMN_NAME ||' as
varchar2(100)) as SAMPLE_DATA from rpt.'||T.TABLE_NAME ||' where '||T.COLUMN_NAME||' is not null and ROWNUM=1 union ' end as qry_txt
from all_tab_columns t where T.OWNER='rpt' and T.DATA_TYPE != 'BLOB' and T.DATA_TYPE != 'LONG' and T.TABLE_NAME = 'NME_DMN'
ORDER BY ROWNUM asc;
【问题讨论】:
-
您的目标是打开一个游标,该游标返回给调用者,然后获取行(这更容易,可以通过
execute immediate完成)。或者您是否需要一个 PL/SQL 块来获取所有行(这更难,而且几乎肯定会涉及使用dbms_sql包的更复杂的路由)? -
从我一直在阅读的内容来看,打开光标听起来像是正确的轨道。是的,我需要获取所有行,就好像我正在运行直接选择查询一样。只要我以行结束,我对任何一种方法都持开放态度,但就我能够重复该技术而言,最简单的方法是最好的...... ;)
-
如果你想打开一个返回给调用者的游标,调用者不能是一个获取数据的 PL/SQL 块(好吧,如果你使用的是 12.1 并且你'愿意变得更复杂)。您可以将游标返回到
SQL*Plus或随后可以获取数据的 C# 应用程序。如果您想要一个 PL/SQL 块来获取所有行,您将需要更复杂的dbms_sql路径。我不确定其中哪一个真的适合你。 -
我想说,如果它不是 oracle 中原生 sql 的一个特性(开箱即用),那么它可能对我不起作用。我遇到的所有 dbms_sql 示例对我来说都失败了。那么,也许打开光标不是答案?您是否看到我可以用来实现我想要的任何其他开箱即用的方法?这是我第一次尝试这样的事情,所以也许这甚至是不可能的。从我在 Google 上看到的结果来看,我是这个星球上第一个尝试这样做的人,所以也许这不可行......
-
这是非常可行的。使用
execute immediate,您可以愉快地将游标返回给应用程序,该应用程序知道如何询问游标以确定列的数量和类型等信息,以便获取数据。SQL*Plus知道如何做到这一点,实际上,任何客户端 API(JDBC/ODBC/OLE DB/ 等)也是如此。如果你想编写一个获取数据的 PL/SQL 块,那么你需要编写更复杂的dbms_sql代码。execute immediate和dbms_sql都存在“开箱即用”。一个比另一个简单得多。