我想使用强制转换来过滤连接的结果。问题是原始字段的一部分无法转换为整数。如果在连接之后应用过滤器,则不会有问题。这就是为什么我想知道是否有一种方法(可能是优化器提示或其他东西)在连接操作之后推送过滤器评估。
这是我为示例构建的查询。我希望它能工作,但因“ORA-01722 无效数字”而失败:
WITH "literal" AS (
SELECT 1 AS "literal_id", 'abc' AS "literal"
FROM "DUAL"
UNION
SELECT 2 AS "literal_id", '7' AS "literal"
FROM "DUAL"
),
"scalar" AS (
SELECT 3 AS "scalar_id", 2 AS "literal_id"
FROM "DUAL"
CONNECT BY ROWNUM <= 10000
)
SELECT *
FROM "scalar"
JOIN "literal" USING ("literal_id")
WHERE TO_NUMBER("literal") > 6;
抛出 ORA-01722 是因为它应用于“文字”CTE,因此崩溃,因为“abc”显然不是数字。 我们可以在执行计划中看到这一点:
为了减少问题原因的可能性,我执行了该查询:
CREATE TABLE "literal" AS (
SELECT 1 AS "literal_id", 'abc' AS "literal"
FROM "DUAL"
UNION
SELECT 2 AS "literal_id", '7' AS "literal"
FROM "DUAL"
);
CREATE TABLE "scalar" AS (
SELECT 3 AS "scalar_id", 2 AS "literal_id"
FROM "DUAL"
CONNECT BY ROWNUM <= 10000
);
CREATE TABLE "joined" AS (
SELECT *
FROM "scalar"
JOIN "literal" USING ("literal_id")
);
SELECT *
FROM "joined"
WHERE TO_NUMBER("literal") > 6;
效果非常好。
那么,有没有办法重写这个查询(尽管我仍然需要将其作为单个查询),这样它就不会尝试转换“abc”?
作为引用,我在 Oracle Database 18c 标准版 2 版本 18.0.0.0.0 以及 Oracle Database 11g 企业版版本 11.2.0.1.0 上尝试过此操作
非常感谢。
最佳答案
老派的技巧是构造查询,使得谓词不能被插入连接中。如果您将联接放入内联 View 并添加 rownum
,这将阻止优化器在联接完成之前评估谓词
WITH "literal" AS (
SELECT 1 AS "literal_id", 'abc' AS "literal"
FROM "DUAL"
UNION
SELECT 2 AS "literal_id", '7' AS "literal"
FROM "DUAL"
),
"scalar" AS (
SELECT 3 AS "scalar_id", 2 AS "literal_id"
FROM "DUAL"
CONNECT BY ROWNUM <= 10000
)
select *
from (
SELECT "scalar_id", "literal_id", "literal", rownum
FROM "scalar"
JOIN "literal" USING ("literal_id")
)
WHERE TO_NUMBER("literal") > 6;
如果您使用的是 12.2 或更高版本,则可以利用 to_number
函数的增强功能,在出现转换错误时返回 NULL。
WITH "literal" AS (
SELECT 1 AS "literal_id", 'abc' AS "literal"
FROM "DUAL"
UNION
SELECT 2 AS "literal_id", '7' AS "literal"
FROM "DUAL"
),
"scalar" AS (
SELECT 3 AS "scalar_id", 2 AS "literal_id"
FROM "DUAL"
CONNECT BY ROWNUM <= 10000
)
SELECT "scalar_id", "literal_id", "literal"
FROM "scalar"
JOIN "literal" USING ("literal_id")
WHERE to_number("literal" default null on conversion error) > 6;
关于sql - 有没有办法强制 Oracle 在加入访问后评估过滤器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56777528/