我正在编写一个Java程序,它从Oracle数据库中获取(SQL查询)字符串,对同一个数据库执行该字符串,然后执行另一个查询以获取所需的列映射以验证该数据反对外部结果。
我想在一次SQL调用中完成所有操作,以便我可以使用PreparedStatement.executeQuery干净地返回Java ResultSet对象
到目前为止,我解决这个问题的方法是首先引用列映射查询,然后编写一个从存储的查询中获取必要列的包装器。例如,结果SQL查询可能如下所示:
SELECT col1, col2 FROM(
select col1, col2, col3 from table a
)
在上面的例子中,col3被丢弃,我不必编辑存储的SQL查询。
这一直有效,直到我达到以下边缘情况 - 我的代码产生的SQL是:
SELECT NVL(RESTRICTTABLE.FIRSTRESTRICT,0), NVL(RESTRICTTABLE.LASTRESTRICT,0) FROM(
select a, NVL(RESTRICTTABLE.FIRSTRESTRICT,0), NVL(RESTRICTTABLE.LASTRESTRICT,0)
from (sometable and wheres)
)
尽我所知,似乎没有办法在没有原始查询中的别名的情况下引用该函数调用,对吧?我无法在不写入临时表的情况下参考列号(并且我没有使用此应用程序的写入权限),我无法通过其功能签名直接引用它。 / p>
有一些简单的方法吗?
答案 0 :(得分:2)
使用WITH
子句(11.2 +):
WITH X (C1, C2, C3) AS (
select a, NVL(RESTRICTTABLE.FIRSTRESTRICT,0), NVL(RESTRICTTABLE.LASTRESTRICT,0)
from (sometable and wheres)
)
SELECT C2, C3
FROM X
<强>更新强>
如果SELECT
语句已经以WITH
子句开头,则不能这样做,但您可以重新排列语句“相当”简单,即找到实际的SELECT
声明并将其移动到新的WITH
元素中。
示例:
-- Before
WITH A AS (
SELECT ... FROM tableA ...
), B AS (
SELECT ... FROM tableB ...
)
SELECT ... FROM A, B, tableC ...
-- After
WITH A AS (
SELECT ... FROM tableA ...
), B AS (
SELECT ... FROM tableB ...
), X (C1, C2, C3) AS (
SELECT ... FROM A, B, tableC ...
)
SELECT C2, C3
FROM X
答案 1 :(得分:1)
您应该能够在外部查询中用双引号括起列表达式,首先转换为大写。这有效:
select "LOWER(DUMMY)"
from
(
select lower(dummy) from dual
)
LOWER(DUMMY)
------------
x
所以理论上你可以强制你的陈述:
SELECT "NVL(RESTRICTTABLE.FIRSTRESTRICT,0)", "NVL(RESTRICTTABLE.LASTRESTRICT,0)" FROM(
select a, NVL(RESTRICTTABLE.FIRSTRESTRICT,0), NVL(RESTRICTTABLE.LASTRESTRICT,0)
from (sometable and wheres)
)
但是,您受限于标识符的最大长度,该标识符仅为30个字节,最高为12cR1,并从12cR2增加到128个字节。截断标识符可能有效,但是你可以接受冲突。
您可能最好为原始内部查询获取result set metadata并确定要使用哪些列。它取决于列映射的工作方式以及查询实际返回的内容。
(或者,当然,您可以坚持存储的查询为其所有列表达式设置别名,以便您可以参考这些 - 但听起来这不是一个选项。)