【问题标题】:Oracle: Selecting Records from Hierarchical Data where Child ID=nOracle:从子 ID=n 的分层数据中选择记录
【发布时间】: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


【解决方案1】:

正如我在编辑中解释的那样,问题是包含分隔符值“/”的名称值,我没有发现它,因为 Oracle SQL Developer 只返回查询结果的子集,除非您滚动浏览它们。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-06
    相关资源
    最近更新 更多