2014-08-27 2 views
1

Я хочу создать простой индекс на основе простой таблицы, но я получаю ошибку. Итак, в первую очередь я создал функциюOracle 11gR2 Ошибка индекса на основе функций

CREATE OR REPLACE FUNCTION promo_function(p_promo_category VARCHAR2) 
RETURN VARCHAR2 DETERMINISTIC IS 
BEGIN 
    RETURN UPPER(p_promo_category); 
END promo_function; 

Тогда я бы выполнить это, но терпит неудачу

CREATE INDEX promotions_fbi 
      ON SH.PROMOTIONS (promo_function (promo_category)); 

Почему? Ошибка ORA-00904: "PROMO_FUNCTION": недопустимый идентификатор Но функция хорошо работает в запросе:

SELECT * 
    FROM sh.sales s, 
     sh.promotions p, 
     sh.times t 
WHERE s.promo_id = p.promo_id 
    AND s.time_id = t.time_id 
    AND t.time_id BETWEEN DATE '2000-01-01' AND DATE '2000-03-31' 
    AND promo_function(p.promo_category) = 'AD NEWS'; 

Большое спасибо!

+1

Вы приставкой ссылки таблицы с помощью схемы SH. Кому принадлежит индекс? Кому принадлежит эта функция? – APC

+0

тот же пользователь (назовите его «current_user» или что-то еще) владеет индексом (особенно он будет принадлежать, потому что его еще не существует) и функцией тоже, поэтому я вставил запрос выше, потому что я могу выполнить функцию как «current_user ", но не может создать индекс – Thomas

+0

. Тогда почему вы префикс таблицы refs схемой? Это просто сбивает с толку. Если вы хотите, чтобы люди помогали вам, вам должно быть ясно о вашей ситуации. – APC

ответ

3

Там нет ничего принципиально плохого ваш код. Я могу создать индекс-функции, как это:

SQL> create table promotions (promo_category varchar2(10)) 
    2/

Table created. 

SQL> CREATE OR REPLACE FUNCTION promo_function 
    2  (p_promo_category in VARCHAR2) 
    3  RETURN VARCHAR2 DETERMINISTIC 
    4 IS 
    5 BEGIN 
    6  RETURN UPPER(p_promo_category); 
    7 END promo_function; 
    8/

Function created. 

SQL> CREATE INDEX promotions_fbi 
    2  ON PROMOTIONS (promo_function (promo_category)); 

Index created. 

SQL> 

Единственная разница между моим кодом и ваша в том, что я не предварить таблицу в инструкции CREATE INDEX заявление. Все в одной схеме, поэтому мне это не нужно.

Итак, могу ли я воссоздать ваш сценарий? Вот один из способов. Я падение индекса и функции, а затем дать другой использует все привилегии на Teh таблицы ...

SQL> drop index promotions_fbi; 

Index dropped. 

SQL> drop function PROMO_FUNCTION; 

Function dropped. 

SQL> grant all on promotions to B; 

Grant succeeded. 

SQL> 

Как пользователь я могу создать нормальный индекс ...

SQL> conn b/b 
Connected. 
SQL> select * from apc.promotions; 

no rows selected 

SQL> CREATE INDEX promotions_i 
    2  ON APC.PROMOTIONS (promo_category); 

Index created. 

SQL> 

Однако, если я создаю функция, которую я не могу создать с помощью индекса на основе функций ....

SQL> conn b/b 
Connected. 

SQL> CREATE INDEX promotions_fbi 
    2  ON APC.PROMOTIONS (promo_function (promo_category)); 
     ON APC.PROMOTIONS (promo_function (promo_category)) 
         * 
ERROR at line 2: 
ORA-00904: : invalid identifier 

SQL> 

Недействительный идентификатор передает имя функции. Зачем? Потому что, хотя схема B будет владеть индексной схемой, APC владеет таблицей и должна также иметь возможность выполнять эту функцию. Решения о предоставлении права выполнения на функцию к владельцу таблицы:

SQL> conn b/b 
Connected. 
SQL> grant execute on promo_function to APC; 

Grant succeeded. 

SQL> CREATE INDEX promotions_fbi 
    2 ON APC.PROMOTIONS (B.promo_function (promo_category)); 
Index created. 

SQL> 

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


Не знаю, как @zaratustra получает свои выводы, как я могу определенно создать функцию на основе индексов в с помощью функции слов в имени ...

SQL> r 
    1 select i.table_owner, i.owner as index_owner, i.index_name 
    2   , i.index_type, e.column_expression 
    3 from all_indexes i 
    4  left join all_ind_expressions e 
    5   on i.owner = e.index_owner 
    6    and i.index_name = e.index_name 
    7* where i.table_name = 'PROMOTIONS' 

TABLE_OWNER     INDEX_OWNER 
------------------------------ ------------------------------ 
INDEX_NAME      INDEX_TYPE 
------------------------------ --------------------------- 
COLUMN_EXPRESSION 
-------------------------------------------------------------------------------- 
APC       APC 
PROMOTIONS_FBI     FUNCTION-BASED NORMAL 
"APC"."PROMO_FUNCTION"("PROMO_CATEGORY") 

APC       A 
PROMO_B_I      FUNCTION-BASED NORMAL 
"A"."B_FUNCTION"("PROMO_CATEGORY") 

APC       APC 
PROMOTIONS_I     NORMAL 



SQL> 

Хотя я на другом выпуске точки так, что могло бы объяснить это

SQL> select banner from v$version; 

BANNER 
-------------------------------------------------------------------------------- 
Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - Production 

SQL> 
+0

У меня нет локально установленного сервера Oracle, я использовал apex.oracle.com для выполнения своих действий. Вы можете попробовать apex.oracle.com? – zaratustra

+0

«Решение заключается в предоставлении прав на выполнение функции владельцу таблицы» :) спасибо APC, я тоже думал о priviliges, это очень четкий ответ и решение! – Thomas

0

Во время моих экспериментов я понял, что Oracle не может позволить вам создавать функциональный индекс с функциональным словом во имя процедуры. Похоже, ошибка для меня:

CREATE OR REPLACE FUNCTION func_function(p_promo_category IN VARCHAR2) 
RETURN VARCHAR2 DETERMINISTIC IS 
BEGIN 
    RETURN UPPER(p_promo_category); 
END func_function; 

create table t1 (
    promo_category varchar2(4000) 
); 

Table created 

CREATE INDEX promotions_fbi ON t1 (func_function (promo_category)); 

ORA-00911: invalid character 

Давайте создадим функцию без функции слова в названии:

CREATE OR REPLACE FUNCTION func_functio(p_promo_category IN VARCHAR2) 
RETURN VARCHAR2 DETERMINISTIC IS 
BEGIN 
    RETURN UPPER(p_promo_category); 
END func_functio; 

CREATE INDEX promotions_fbi ON t1 (func_functio (promo_category)); 

Index created 

select index_name, index_type 
    from user_indexes 
where lower(index_name) = 'promotions_fbi' 

INDEX_NAME  INDEX_TYPE 
------------------------------------- 
PROMOTIONS_FBI FUNCTION-BASED NORMAL 

Моя версия Oracle:

select banner from v$version 

BANNER 
---------------------------------------------------------------------------- 
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production 
Смежные вопросы