Сбой подзапроса Oracle View при создании таблицы - PullRequest
1 голос
/ 21 декабря 2011

У меня есть утверждение ниже при создании представления Oracle. Оператор должен возвращать определенное значение в виде столбца MYVALUE.

(SELECT myval 
  FROM (SELECT myval 
          FROM mytable 
         WHERE primary_key = /*CS.primary_key*/ 12345 
         ORDER BY table_primary_key ASC) 
 WHERE ROWNUM < 2) AS MYVALUE,

Внутренний запрос может возвращать более одной строки. Меня интересует только 1-я запись, и она должна быть заказана по table_primary_key, следовательно, использование подзапроса позволяет ROWNUM выбирать.

Когда я создаю запрос в его текущем состоянии выше, представление создается успешно. Когда я раскомментирую CS.primary_key и удаляю жестко закодированный 12345, создание представления завершается неудачно, без описания причины

(SQLDeveloper 2.1): «Ошибка: Предупреждение: выполнение завершено с предупреждением».

Кроме того, просто чтобы попытаться сузить проблему, я удалил ORDER BY и ROWNUM, как показано ниже, и возникает та же ошибка

(SELECT myval 
  FROM (SELECT myval 
          FROM mytable 
         WHERE primary_key = CS.primary_key) 
) AS MYVALUE,

Наконец, я знаю, CS.primary_key является действительной ссылкой, так как я использую ее в других частях моего представления без проблем.

Есть идеи, почему ссылка действительна или как получить более подробное сообщение об ошибке?

редактировать: обновлена ​​начальная открывающая скобка

EDIT2: Спасибо за ответы до сих пор. Вот краткое изложение проблемы, я думаю, что ключ CS.PRIMARY должен находиться в области видимости, так как я использую его в других местах в моем запросе. Приведенный ниже код работает, но если я заменю жестко закодированный 1 на CS.primary_key, произойдет сбой:

drop view myview;
drop table mytable;
drop table mytable_parent;
drop table proof_table;

-- ISSUE TABLES
create table mytable_parent ( primary_key number primary key );
create table mytable ( primary_key number, myval varchar(255), parent_primary_key number);
insert into mytable_parent values (1);
insert into mytable_parent values (2);
insert into mytable values (1, 'myval1-1', 1);
insert into mytable values (2, 'myval1-2', 1);
insert into mytable values (3, 'myval2-1', 2);

-- EXAMPLE TABLE TO PROVE CS.* WORKS
create table proof_table ( primary_key number primary key, parent_primary_key number, any_old_value varchar(255));
insert into proof_table values (1, 1, 'proofval1-1');
insert into proof_table values (2, 2, 'proofval1-2');

-- VIEW
CREATE OR REPLACE FORCE VIEW myview AS 
  SELECT 

  -- PROOF STATEMENT USING CS.primary_key SUCCESSFULLY
  (SELECT any_old_value FROM proof_table WHERE parent_primary_key IN 
    (SELECT primary_key FROM proof_table WHERE parent_primary_key = 

    -- USING CS REFERENCE, NO PROBLEM
    CS.primary_key)

  ) AS PROOF_VALUE,

  -- PROBLEM STATEMENT
  (SELECT myval FROM (SELECT myval FROM mytable 
         WHERE parent_primary_key = /*CS.primary_key*/ 1
         ORDER BY primary_key ASC) 
  WHERE ROWNUM < 2) AS MYVALUE  

  -- DEFINE CS
  FROM mytable_parent CS;

1 Ответ

0 голосов
/ 21 декабря 2011

Из предоставленной вами ограниченной информации я бы предположил, что CS.PRIMARY_KEY выходит за рамки вашего подзапроса. Следовательно, он компилируется нормально, когда вы используете литерал, и не компилируется, когда он должен разрешить ссылку на CS.PRIMARY_KEY.

Включите любую таблицу CS, указанную в подзапросе (с соответствующими критериями), чтобы проверить, что это так. Если это так, то вам нужно переписать запрос, чтобы убедиться, что таблица CS находится в области действия всех ее зависимостей.

Надеюсь, это поможет ...

Подробности см. По этой ссылке: http://etutorials.org/SQL/Mastering+Oracle+SQL/Chapter+5.+Subqueries/5.4+Inline+Views/

Вы увидите, что встроенные представления выполняются до внешнего запроса, а слишком глубокое вложение ссылки на таблицу CS приведет к тому, что она выйдет из области видимости.

Замените вложенный подзапрос, в котором вы делаете заказ:

(SELECT myval 
   FROM (SELECT myval 
           FROM mytable
          WHERE parent_primary_key = CS.primary_key
          ORDER BY primary_key ASC)
   WHERE ROWNUM < 2) AS MYVALUE

с аналитической функцией или другим способом ограничения ваших строк, и он будет работать нормально

Это не проверено, но замена вышеуказанного кода на:

(SELECT DISTINCT 
        FIRST_VALUE(myval) OVER (PARTITION BY parent_primary_key ORDER BY primary_key) 
   FROM mytable
  WHERE parent_primary_key = CS.primary_key) AS MYVALUE 

может быть близко к тому, что вы хотите, и ссылка на CS находится в области видимости.

...