2016-04-12 2 views
0

Я использую виртуальный столбец (оракул 11g) с детерминированной пользовательской функцией, которая берет первичный ключ строки как параметр и возвращает простое скалярное значение. виртуальные столбцы обновляются без каких-либо проблем, но когда я обновляю таблицу, она выдает ошибку: - ora-00054 ресурс занят и приобретается с указанным значением nowait или таймаутом, истекшим в оракуле. моя таблица структуры и функции, являются следующими: -Виртуальная колонка с использованием детерминированной пользовательской функции

----------------------------------------------------------------------- 
    id employee_name employee_dept employee_leaves (vir column) 
----------------------------------------------------------------------- 
    2  patrick   mgmt   getEmpLeaves(id) 
    3  jack    sales   " 
----------------------------------------------------------------------- 

    create or replace function getEmpLeaves(empId number) 
     return number 
      DETERMINISTIC 
     is 
      emp_leaves number; 
     begin 
      select leaves into emp_leaves from tbl_emp_leaves 
      where tbl_emp_leaves.id = empId; 
      return emp_leaves; 
     end ; 
    ------------------------------------------------------------- 

Как преодолеть эту ошибку?

+0

Можете ли вы показать инструкции создания таблицы для обеих таблиц и выставляемые вами инструкции для получения этого исключения? Может быть, полезно сказать, какую версию (выпуск 1 или релиз 2) и уровень патча вы находитесь. Я не могу сразу воспроизвести в 11.2.0.4.7, но я делаю некоторые предположения. Также есть индекс? –

ответ

2

Я не собираюсь искать причину этой ошибки.
Короткий ответ: удалить этот виртуальный Колум из таблицы, и создать представление вместо:

create view vw_employees AS 
SELECT t.id, t.employee_name, t.employee_dept, x.leaves As employee_leaves 
FROM tbl_employees t 
JOIN tbl_emp_leaves x 
ON t.id = x.id; 

Длинный ответ: Пожалуйста, обратите внимание на ниже простого теста:

create table tbl_emp_leaves as 
select object_id as id, trunc(dbms_random.value(0,100)) as leaves 
from all_objects; 
alter table tbl_emp_leaves add primary key(id); 

create or replace function getEmpLeaves(empId number) 
     return number 
      DETERMINISTIC 
     is 
      emp_leaves number; 
     begin 
      select leaves into emp_leaves from tbl_emp_leaves 
      where tbl_emp_leaves.id = empId; 
      return emp_leaves; 
     end ; 
    /

create table tbl_employees as 
select object_id as id, object_name as employee_name, object_type as employee_dept 
from all_objects; 

alter table tbl_employees 
add employee_leaves as (getEmpLeaves(id)); 

create view vw_employees AS 
SELECT t.id, t.employee_name, t.employee_dept, x.leaves As employee_leaves 
FROM tbl_employees t 
JOIN tbl_emp_leaves x 
ON t.id = x.id; 

А теперь сравните производительность двух простых запросов:

SQL> set timing on; 
SQL> select sum(employee_leaves) from vw_employees; 

SUM(EMPLOYEE_LEAVES) 
-------------------- 
      3675425 

Elapsed: 00:00:00.07 
SQL> select sum(employee_leaves) from tbl_employees; 

SUM(EMPLOYEE_LEAVES) 
-------------------- 
      3675425 

Elapsed: 00:00:03.09 

3.09 секунды против 0,07 секунды - вы видите, что виртуальный столбец на основе функции 44 раза (то есть: 4400%) медленнее простого соединения.

+0

поэтому ответ на мой вопрос заключается в том, что виртуальный столбец не может использоваться так, как я его использовал. Фактически данные поступают из 4 таблиц и накапливаются в одном столбце в 5-й таблице. (хотя это было бы медленным) и материализованное представление (это не было бы в режиме реального времени, потребуются обновления), и триггеры должны быть применены к 4 таблицам (добавьте, обновите и удалите, чтобы нарисовать точное изображение). виртуальный столбец был самым простым и чистым способом сделать это, но у меня есть технические ограничения, пока Oracle не решает эту проблему в какой-то версии. – jaykio77

1

У меня была аналогичная проблема, когда я создал функцию, которая выбирает другую таблицу.

Ключевое слово DETERMINISTIC означает, что функция всегда возвращает то же значение для заданного входного параметра. Ответственность за это несет разработчик.

Oracle позволяет функции как это:

create or replace function getNumber(x number) 
    return number DETERMINISTIC is 
begin 
    return DBMS_RANDOM.RANDOM; 
end; 

Хотя это действительно противоположность детерминированной функции.

Возвращаемое значение вашей функции изменяется после заявления UPDATE tbl_emp_leaves SET leaves = ....

Итак, я должен согласиться с ответом kordirko: удалите этот виртуальный столбец и создайте представление или используйте триггер, чтобы установить значение столбца employee_leaves.

Смежные вопросы