Том Кайт: об убыстрении, особенностях работы с NLS-параметрами и написании чисел по буквамИсточник: oracle Том Кайт
Наш эксперт определяет операционную систему, "убыстряет" работу приложений, объясняет особенности работы с NLS-параметрами и написание чисел по буквам. Вопрос. Я как-то видел на вашем сайте, как кто-то показывал, как определить операционную систему, в которой работает утилита SQL*Plus; однако теперь я не могу найти эту информацию. У меня есть SQL-скрипт, который я использую для создания других SQL-скриптов. Я хочу расширить этот скрипт так, чтобы при его вызове на UNIX-платформе, на которой работает утилита SQL*Plus, он создавал бы как SQL-скрипт, так и скрипт командной оболочки (shell script). Ответ. Я думаю, вы на сайте Ask Tom видели, как определить операционную систему, в которой работает сервер базы данных. Это можно сделать с помощью функции DBMS_UTILITY.PORT_STRING: SQL> begin 2 dbms_output.put_line( 3 dbms_utility.port_string ); 4 end; 5 / Linuxi386/Linux-2.0.34-8.1.0 Это говорит вам не о том, в какой операционной системе работает ваш клиент SQL*Plus, а о том, в какой операционной системе работает сам сервер базы данных (они могут отличаться). Однако вам могут помочь два столбца представления V$SESSION - PROGRAM и PROCESS. Столбец PROGRAM в общем показывает имя программы клиента, которая соединена с сервером базы данных (но это имя может легко вводить в заблуждение, если файлы копируются с другими именами), а столбец PROCESS показывает идентификатор процесса клиента, соединенного с сервером базы данных - идентификатор процесса из самой клиентской машины. Оба этих столбца помогут вам выяснить имя клиентской операционной системы, в которой работает утилита SQL*Plus. Выполним следующий запрос: SQL> select program, process. 2 from v$session 3 where sid = 4 (select sid 5 from v$mystat 6 where rownum = 1 7 ) 8 / PROGRAM PROCESS ------------ -------------- sqlplus.exe 704:416 В данном случае это - клиент Windows SQL*Plus, это подтверждается наличием ".exe" в имени программы, а также двоеточием (:) в идентификаторе процесса. Если же для подключения к этому же серверу базы данных я использую UNIX-клиента, я увижу что-то похожее на это: SQL> select program, process . . . 8 / PROGRAM PROCESS ------------------------- -------------- sqlplus@host(TNS V1-V3) 10227 В имени программы отсутствует расширение ".exe", поскольку оно не используется в среде UNIX, а в идентификаторе процесса клиента отсутствует двоеточие, как это было у Windows-клиента. Исходное интерактивное обсуждение и развитие это темы см. на сайте asktom.oracle.com/~tkyte/DetermineOS.html. Благодарю всех интерактивных участников за хорошие идеи. "Убыстряем" работу приложений Вопрос. У нас есть приложение, которое создает пользователей и определяет для них приватные синонимы. Иногда администратор системы безопасности выполняет множественные удаления пользователей, которым больше не нужен доступ к базе данных. Для удаления пользователя, у которого имеется около тысячи приватных синонимов может потребоваться около двух минут. Я неудовлетворен таким слишком медленным удалением вышедших из употребления учетных записей. Есть ли у вас какие-то предложения по повышению производительности выполнения оператора DROP USER, не считая перевода системы на использование публичных синонимов? Ответ. Все дело в восприятии. Всякий раз когда я имею долго работающий процесс, я думаю, как его выполнять в фоновом режиме, чтобы "несчастливый" конечный пользователь никогда не ждал его завершения. Если конечный пользователь не должен ждать завершения процесса, он будет казаться ему сработавшим мгновенно. Итак, будем выполнять долго работающий процесс в фоновом режиме, и конечный пользователь подумает: "Класс, в самом деле он работает быстро"! Я рекомендую выполнять оператор DROP USER имя_пользователя CASCADE следующим образом: 1. ALTER USER имя_пользователя LOCK; (Учетная запись блокируется, так что достигается "цель обеспечения безопасности".) 2. dbms_job.submit( l_job, 'execute immediate ''drop user a cascade'';' ); 3. commit; Пользователь сразу же получает сообщение, что все в порядке. Блокирование учетной записи запрещает ей доступ к базе данных, а фактическое удаление схемы пользователя (на него может потребоваться какое-то время) начнется в фоновом режиме вскоре после выполнения оператора COMMIT (конечный пользователь не должен ожидать завершения удаления). Я прибегаю к этому способу всегда, когда появляются предположительно долго выполняющиеся задачи - скрытие реальной работы, благодаря фоновому режиму, и немедленное продолжение работы конечных пользователей, так что они думают, приложение работает намного быстрее, чем это есть на самом деле. Не работает параметр NLS_DATE_FORMAT Вопрос. Почему параметр NLS_DATE_FORMAT (формат даты) в моем файле init.ora иногда не работает? Я устанавливаю его, но в моих приложениях формат даты по умолчанию не устанавливается правильно. Ответ. Если в среде клиента установлены какие-либо NLS-параметры, они всегда перекрывают NLS-параметры на стороне сервера. Например, если клиент установит параметр NLS_LANG, все NLS-параметры на стороне сервера будут игнорироваться. Сервер будет использовать значения, указанные клиентом, и значения по умолчанию для всех других NLS-параметров, игнорируя установки в файле init.ora. Обычно это происходит в Windows-клиентах. При инсталляции таких клиентов в реестре по умолчанию устанавливается параметр NLS_LANG. Решить вашу проблему можно одним из следующих способов:
Лично я предпочитаю второй способ. Если ваше приложение зависит от конкретного формата даты, устанавливаемого по умолчанию, то его следует запрашивать явно. Причина: если вы в одной системе базы данных инсталлируете два приложения с конфликтующим форматами даты, вы не сможете их использовать без явной установки форматов дат. Лучше всего, чтобы приложения не зависели от конкретных установок форматов по умолчанию в файле init.ora. create or replace trigger data_logon_trigger after logon ON DATABASE begin execute immediate 'alter session set nls_date_format = ''your format here'' '; end; / Написание чисел по буквам Вопрос. Я пытаюсь писать числа по буквам. То есть, я хочу чтобы число 123 печаталось как one hundred twenty-three. Есть ли для этого соответствующие функции? Ответ. Верите или нет, почти все это есть. Есть формат дат 'Jsp', который позволяет писать по буквам юлианское представление даты: SQL> select to_char(sysdate,'J'), 2 to_char(sysdate,'Jsp') 3 from dual; TO_CHAR ---------------- TO_CHAR(SYSDATE,'JSP') ------------------------------------------ 2453812 Two Million Four Hundred Fifty-Three Thousand Eight Hundred Twelve Это работает и для чисел в пределах диапазона юлианских дат, иначе вы получите сообщение об ошибке: ERROR at line 1: ORA-01854: julian date must be between 1 and 5373484 Немного творчества и я могу расширить этот диапазон (если число 5 373 484 недостаточно большое). Функция PL/SQL на листинге 1 показывает, как вы может сделать это же. Я предлагаю ознакомиться с интерактивным обсуждением этой темы на сайте asktom.oracle.com/~tkyte/SpellNumber.html, там же вы можете увидеть ее развитие, включая вклад участников в написание чисел по буквам на других языках.
Составление отчетов о свободном пространстве в базе данных Вопрос. Мне нужно в утилите SQL*Plus выводить отчеты, которые для каждого табличного пространства показывают свободное пространство. Есть ли у вас работающий запрос, который умеет это делать? Ответ. Мне приходилось делать это. В основном, мне нужно написать запрос, который показывает свободное пространство для каждого табличного пространства (группируя представление DBA_FREE_SPACE на уровне табличных пространств) и соединить его с запросом, который показывает выделенное пространство в каждом табличном пространстве (включая временные табличные пространства). Проблема в том, что в представлении DBA_FREE_SPACE свободное пространство показывается на уровне экстентов, а в представлениях DBA_DATA_FILES и DBA_TEMP_FILES показывается выделенное пространство в файлах данных табличных пространств. Перед объединением этих представлений мне нужно сгруппировать их данные на уровне табличных пространств. Для этого хорошо подходят вложенные представления, поэтому я буду использовать их в запросе, показанном на листинге 2. Кроме того, для приспособления запроса к табличным пространствам, которые полностью заполнены (в представлении DBA_FREE_SPACE отсутствуют записи о них), поэтому для получения полного ответа я буду использовать внешнее соединение.
Этот запрос позволяет получить:
Преобразование представлений чисел в другие системы счисления 1Вопрос. Как преобразовывать числа в какие-то другие системы счисления (скажем, с основанием 2 или 16) и наоборот? Ответ. В ответе две части. Начиная с СУБД Oracle8i, функции TO_CHAR и TO_NUMBER могут преобразовывать числа с основанием 10 (десятичная система счисления) в числа с основанием 16 (шестнадцатеричная система счисления) и наоборот: SQL> select to_char(123,'XX') to_hex, 2 to_number('7B','XX') from_hex 3 from dual 4 / TO_ FROM_HEX ------ ----------------- 7B 123 Если вам нужны другие системы счисления, такие как восьмеричная (с основанием 8) или двоичная (с основанием 2), вы можете сделать это очень легко, используя язык PL/SQL; на самом деле, я также буду преобразовывать и числа с основанием 16. Сначала я напишу функцию, которая преобразовывает положительные десятичные числа в числа с любым другим основанием - до основания 36 (расширение алгоритма, используемого для представления чисел в разных системах счисления, вплоть до шестнадцатеричной системы счисления). См. листинг 3.
Теперь мне нужна соответствующая функция для обратного преобразования чисел с любым заданным основанием в десятичные числа. Она показана на листинге 4.
Для удобства я для наиболее распространенных преобразований использую небольшую функцию, показанную на листинге 5.
Привилегия SYSDBA Вопрос. Мне нужно в среде Microsoft Windows Server 2003 запретить пользователям, которые имеют роль oradba подключение без пароля к серверу моей базы данных. Когда я подключаюсь как администратор (член группы oradba) я могу, указывая AS SYSDBA, подключиться к серверу с любым паролем, даже с пустым. Ответ. На самом деле, с технической точки зрения, вы использовали пароль. Вы вошли в операционную систему, введя пароль. Привилегия SYSDBA - чрезвычайно мощная привилегия. Когда вы подключаетесь, указывая AS SYSDBA, то используется аутентификация на уровне операционной системы; аутентификация на уровне базы данных не требуется. По сути, она нужна для подключения, когда еще не запущен экземпляр сервера базы данных. Вам нужно ограничивать возможности учетных записей, которые находятся в этой группе. Удалите из нее пользователей, которые не должны иметь такие чрезмерно большие возможности. |