【发布时间】:2019-05-16 07:15:55
【问题描述】:
我有一个具有一元关系的位置表,并且正在尝试设置一个视图以用作引用该位置表的其他表中的连接,以获取到根位置值的完整路径。但是,在使用分层查询设置视图后,每当我尝试加入主键或在 WHERE 子句中使用该列时,都会收到“使用 SYS_CONNECT_BY_PATH 函数时,不能将分隔符作为列的一部分”错误消息.
过度简化的表格示例;
LOCATION_TBL
LOCATION_ID NAME TYPE PARENT_ID [etc. . .]
----------- --------------- --------- ---------
1 'United States' 'Country' NULL
2 'France' 'Country' NULL
3 'Washington' 'Region' 1
4 'Normandie' 'Region' 2
5 'Seattle' 'City' 3
6 'Rouen' 'City' 4
创建视图语句;
CREATE VIEW v_locationPath AS (
SELECT location_id
SYS_CONNECT_BY_PATH(name,'/') AS path
FROM location_tbl
START WITH parent_id IS NULL
CONNECT BY PRIOR location_id=parent_id
);
直接从没有WHERE子句的视图中选择返回预期的结果;
SELECT location_id,path FROM v_locationPath;
LOCATION_ID PATH
----------- -----------------------------------
1 '/United States'
2 '/France'
3 '/United States/Washington'
4 '/France/Normandie'
5 '/United States/Washington/Seattle'
6 '/France/Normandie/Rouen'
但是,如果我尝试从视图中选择一条记录,受位置 ID 值的限制
SELECT location_id,path FROM v_locationPath WHERE location_id=3;
我收到错误消息。我已经仔细检查过,没有一个名称值包含正在使用的分隔符(在本例中为“/”)。 以下查询也返回了相同的错误;
SELECT a.location_id,b.path
FROM location_tbl a
JOIN v_locationPath b ON a.location_id=b.location_id
WHERE a.location_id=3;
------------------------------------------------
WITH limitedLocations AS (
SELECT location_id
FROM location_tbl
WHERE location_id=3
)
SELECT a.location_id,b.path
FROM limitedLocations a
JOIN v_locationPath b ON a.location_id=b.location_id;
我也尝试过将视图的分层查询封装为视图本身的子查询;
CREATE VIEW v_locationPath AS (
SELECT location_id,path
FROM (
SELECT location_id
SYS_CONNECT_BY_PATH(name,'/') AS path
FROM location_tbl
START WITH parent_id IS NULL
CONNECT BY PRIOR location_id=parent_id
)
);
尝试相同的选择语句都会返回相同的错误消息。摆弄了一下,我能够得到一个返回的结果,它的值是我期望的,但是,位置表中的每一行都返回了一条记录;
WITH limitedLocations AS (
SELECT 3 AS location_id
FROM location_tbl
)
SELECT a.location_id,b.path
FROM limitedLocations a
JOIN v_locationPath b ON a.location_id=b.location_id;
-Returned-
LOCATION_ID PATH
----------- ---------------------------
3 '/United States/Washington'
3 '/United States/Washington'
3 '/United States/Washington'
3 '/United States/Washington'
3 '/United States/Washington'
3 '/United States/Washington'
我有点受阻,错误消息本身似乎没有任何意义,因为 location_id 不在 SYS_CONNECT_BY_PATH 列中,任何名称值也不包含分隔符值。
--编辑--
发现问题:查询根本不是问题(至少不是结构)。原来有一条记录包含名称列中的分隔符值。
数据看起来更准确:
LOCATION_TBL
LOCATION_ID NAME TYPE PARENT_ID [etc. . .]
----------- --------------- --------- ---------
1 'United States' 'Country' NULL
2 'France' 'Country' NULL
3 'Washington' 'Region' 1
4 'Normandie' 'Region' 2
5 'Seattle' 'City' 3
6 'Rouen' 'City' 4
... ... ... ...
4500 'Blighter/' 'City' 3
当我在 Oracle SQL Developer 中测试视图的 Select 语句时,程序正在执行查询,同时只返回前 50 行左右。由于它没有抛出任何错误,我错误地认为所有记录都很好。
一旦我实际运行查询以检查名称列中是否存在分隔符:
SELECT * FROM location_tbl WHERE name LIKE '%/%';
我找到了错误的记录。在将分隔符参数替换为位置表中未找到的参数后,查询工作正常。
至于 SQL Developer 没有抛出错误,当我返回并再次运行原始 select 语句时,我最终通过向下滚动结果表得到了错误,直到它试图返回包含分隔符值的记录。 WHERE location_id=n,一定是强制它在返回任何记录之前查看整个结果集。
【问题讨论】:
-
对我来说就像一个冠军。您使用的是什么版本的 Oracle? dbfiddle here
-
@BobJarvis:我得仔细检查一下 Oracle 版本(我想是 10 种),今天很晚才开始工作,然后回家后凭记忆写了这篇文章,所以完全是这可能只是我的 ID10-t 错误。
-
Eeeeeeeew! 10只是简单的抽搐。我不能比这更具体,但 10 是/是我使用过的最糟糕的 Oracle 版本。
标签: oracle oracle-sqldeveloper hierarchical-data