2017-01-20 8 views
0

я объявил следующую процедуру:ORA-01403: Нет данных ПОЧЕМУ?

CREATE OR REPLACE PROCEDURE MODIFY_NOT_NULL(
     v_tbName  IN VARCHAR2, 
     v_cName  IN VARCHAR2, 
     v_defaultValue IN VARCHAR2) 
    IS 
     v_is_null VARCHAR2(1); 
    BEGIN 

     SELECT nullable INTO v_is_null 
     FROM USER_TAB_COLUMNS 
     WHERE TABLE_NAME = v_tbName 
     AND COLUMN_NAME = v_cName; 

     IF v_is_null = 'Y' THEN 
      EXECUTE IMMEDIATE ('ALTER TABLE ' || v_tbName 
       || ' MODIFY (' || v_cName 
       || ' DEFAULT ' || v_defaultValue 
       || ' NOT NULL)'); 
     END IF; 
    END; 

Однако когда я исполню мой код:

BEGIN 
    modify_not_null('TABLE_NAME', 'COLUMN_NAME ' ,'0'); 
END; 
/

Я получаю

"ORA-01403: No Data Found"

Это исключение будет обычно самостоятельно, если «SELECT INTO» оператор не возвращает никакого значения, однако я всегда получаю значение, когда я выполнить это:

Select nullable 
from USER_TAB_COLUMNS 
WHERE table_name = 'TABLE_NAME' 
AND column_name = 'COLUMN_NAME'; 

Когда я выполняю код выше, я получаю «N» или «Y», как результат. Поэтому я всегда получаю результат. Я не знаю, почему это исключение брошено.

+0

Почему выбирают данные в ' v_is_null', но условие 'IF' находится на' l_nullable'? Может быть, что 'l_nullable' является объявленной локальной переменной, но инициализируется. –

+0

Мне очень жаль, это была опечатка снова в моем посте ... Это, к сожалению, не ошибка, но очень важно для подсказки – NoName123

+0

Выполняете ли вы запрос и блок PL SQL от разных пользователей? В случае, если идентификатор пользователя отличается, данные в USER_TAB_COLUMNS изменяются. Лучший способ отладки - поместить dbms_output после каждой строки в вашем коде, чтобы понять происхождение исключения. –

ответ

4

Ваш звонок содержит замыкающий пробел:

modify_not_null('TABLE_NAME', 'COLUMN_NAME ' ,'0'); 
             ^

Так прок не проливает найденных данных, потому что 'COLUMN_NAME ' != 'COLUMN_NAME'

Используйте upper(trim(v_cName)), чтобы предотвратить опечатки, вызывающие ошибки. Применитесь ко всем параметрам.

+0

thx, сейчас он работает – NoName123

1

Вы передаете параметр v_defaultValue для имени столбца.

Изменить процедура

SELECT nullable INTO v_is_null 
FROM USER_TAB_COLUMNS 
WHERE TABLE_NAME = v_tbName AND COLUMN_NAME = v_cName ; 
+0

Sry, это была опечатка, я отредактировал свой вопрос ..... Это была не ошибка .. – NoName123

0

Перед вашим SELECT .... INTO вы должны убедиться, что есть что выбрать. Поскольку в зависимости от того, какой пользователь вы и какие параметры вы даете, в вашей таблице могут не быть данных.

Простой способ будет иметь COUNT в начале до SELECT:

CREATE OR REPLACE PROCEDURE MODIFY_NOT_NULL(
     v_tbName  IN VARCHAR2, 
     v_cName  IN VARCHAR2, 
     v_defaultValue IN VARCHAR2) 
    IS 
     v_is_null VARCHAR2(1); 
     v_count number; 
    BEGIN 
     -- added select count 
     SELECT count(1) INTO v_count FROM USER_TAB_COLUMNS WHERE TABLE_NAME = trim(v_tbName) AND COLUMN_NAME = trim(v_cName); 
     -- added if v_count=1 
     if v_count = 1 then 
     SELECT nullable INTO v_is_null FROM USER_TAB_COLUMNS WHERE TABLE_NAME = trim(v_tbName) AND COLUMN_NAME = trim(v_cName); 

     IF v_is_null = 'Y' THEN 
     EXECUTE IMMEDIATE ('ALTER TABLE ' || v_tbName || ' MODIFY (' || v_cName || ' DEFAULT ' || v_defaultValue || ' NOT NULL)'); 
     END IF; 
     -- added 
     end if; 
    END; 
/

Share и наслаждаться

+0

@APC , да, моя ошибка. Я тестировал, но ошибался »:/... Я вернул свой первый ответ. –

-1

оставаться классным :)

create or replace procedure modify_not_null(v_tbName  in varchar2, 
              v_cName  in varchar2, 
              v_defaultValue in varchar2) is 
    cursor c_tbl(cp_tbname in varchar2, 
       cp_cname in varchar2) is 
    select nullable 
     from user_tab_columns 
    where table_name = upper(cp_tbname) 
     and column_name = upper(cp_cname); 

    l_tbl c_tbl%rowtype; 
begin 

    open c_tbl(cp_tbname => v_tbName, 
      cp_cname => v_cName); 
    fetch c_tbl into l_tbl; 
    close c_tbl; 

    if l_tbl.nullable = 'Y' then 
    execute immediate 'alter table ' || v_tbName || ' modify (' || v_cName || 
         ' default ' || v_defaultValue || ' not null)'; 
    end if; 
exception 
    when others then 
    raise_application_error(-20000, dbms_utility.format_error_stack); 
end modify_not_null; 
+0

Похоже, что ошибка OP связана с конечным пространством в аргументе, и весь ваш дополнительный код на самом деле не исправляет это. – APC

+0

Как это устранить проблему OP? Если исходный код вызывает ORA-01403, этот код будет страдать от одной и той же проблемы (кроме скрытия реального места, где произошло исключение). –

+0

Что такое проблема ОП? он не вызывает никаких ошибок, если таблица не найдена. – TheName