Сделать часть каталога динамической при вызове функции BFILENAME в Oracle 10g - PullRequest
1 голос
/ 16 ноября 2011

Я пытаюсь открыть существующий физический файл из файловой системы в процедуре в Oracle 10g.Функция bfilename требует каталог и путь.Я хочу передать каталог, такой как «c: \ abc», непосредственно процедуре, т.е. я не хочу передавать объект каталога.Причина в том, что каталог может измениться, и я не знаю, как создать или заменить каталог внутри процедуры (команда всегда возвращает ошибку, говоря, что переменная не разрешена).Я также не уверен в том, как это работает в многопользовательской среде, потому что новый каталог не является локальным для процедуры.

Когда я запускаю команду:

bfilename ('c: \ abc', 'myfile.txt');

возвращает ошибку, что каталог не существует.Я проверил, заканчивая каталог с "\", т.е. сделать его "c: \ work \".Я также проверил, используя заглавные буквы внутри процедуры.Если я сделаю объект каталога с именем DOCUMENTS и передам его bfilename, то он будет работать.

bfilename ('DOCUMENTS', 'myfile.txt');

Есть ли какой-нибудь способ сделать часть каталога динамической?

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

ВЫПОЛНИТЬ НЕМЕДЛЕННЫЙ 'СОЗДАТЬ ИЛИ ЗАМЕНИТЬ КАТАЛОГ WORKDIR AS' 'c: \ work' '';

Процедура скомпилирована успешно, но при запуске выдает следующую ошибку:

Недостаточно прав.

У меня есть только один пользователь в моей тестовой базе данных, у этого пользователя есть роль sysdba.У меня есть физический доступ к файлу через файловую систему.Пользователь базы данных может создать каталог через sqlplus.

Ответы [ 2 ]

3 голосов
/ 16 ноября 2011

Ответ Марка решает вашу конкретную проблему (вы не можете использовать привилегии, полученные с помощью роли SYSDBA в процедурах), но я хочу обсудить основные проблемы.

Соответствующей привилегией является CREATE ANY DIRECTORY. Все объекты каталога принадлежат SYS, поэтому эту привилегию следует предоставлять с осторожностью.

Имейте в виду, что при втором запуске хранимой процедуры произойдет сбой. Это потому, что каталог уже существует. Синтаксис ALTER DIRECTORY отсутствует. Это означает, что вам нужно удалить и заново создать каталог каждый раз, когда вы хотите изменить его путь. Следовательно, вам также необходимо предоставить DROP ANY DIRECTORY пользователю. Кроме того, в производственной среде вам необходимо будет повторно предоставить привилегии, предоставленные этому каталогу, всем другим пользователям, которые в этом нуждаются.


Почему Oracle затрудняет динамическую работу с объектами каталогов? Потому что нам не нужно это делать .

Структура каталогов ОС полна потенциальных опасностей для базы данных. Доступ к файлам ОС из базы данных должен строго контролироваться. Это означает, что мы должны указать конкретные каталоги для известных целей (DataPump, запись дампов и файлов журналов, импорт файлов CSV и т. Д.) И придерживаться их. Разрешение процедурам изменять пути каталогов на лету - это красный флаг для плохого бизнес-процесса.

Но иногда объекты каталогов - это настоящая боль. Например, однажды я работал над системой, которая генерировала миллионы файлов. Чтобы распространить их по операционной системе, не превышая ограничение unix inode, у нас была древовидная структура, основанная на двух последних цифрах идентификатора заголовка и предпоследних двух цифрах идентификатора заголовка. Некоторым нравится это:

$OUT_FILES/whatever/00/00
$OUT_FILES/whatever/00/01
...
$OUT_FILES/whatever/99/98
$OUT_FILES/whatever/99/99

Это было бы десять тысяч объектов каталога на канал. Который много. Поэтому мы использовали (не рекомендуется) параметр UTL_FILE_DIR. Этот параметр не рекомендуется по крайней мере по трем причинам:

  1. Он устанавливается в файле INIT.ORA и для его изменения требуется перезапуск базы данных.
  2. Нет детализации. Каждый пользователь базы данных имеет права на любой каталог ОС в списке
  3. Безопасность слабее, потому что она позволяет использовать подстановочные знаки.

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

Однако, если вы работаете с игрушечной базой данных, этот параметр может решить вашу головную боль. Узнать больше .

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

2 голосов
/ 16 ноября 2011

Попробуйте предоставить привилегию 'CREATE DIRECTORY' непосредственно пользователю (т. Е. Не через роль).

Что-то вроде:

grant create directory to the_user;

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

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

...