Автор статей нашего портала

Стас Белков

Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript.

Автор статьи. Известный специалист в мире IT. Консультант по продуктам и решениям Oracle. Практикующий программист и администратор баз данных. Подробнее.

Вести бизнес было бы удобнее, если бы все на Земле говорили на безупречном английском. Вопреки распространенному мнению, только каждый пятый человек в мире может говорить по-английски, а каждый четвертый говорит на нем как на родном. Более того, это не считая того факта, что это самый изучаемый язык в мире, а французский занимает второе место.

Ниже приведены различные формы команд, допустимые в оболочке Bash операционной системы Linux.

 

cmd & Выполнить указанную команду cmd в фоновом режиме
{ cmd1 ; cmd2 ; } Выполнить указанные команды группой в текущей
оболочке
( cmd1 ; cmd2 ; ) Выполнить указанные команды группой в подоболочке
cmd1 | cmd2 Передать выход из команды cmd1 по каналу на вход
команды cmd2
cmd1 `cmd2` Произвести подстановку команд. В частности, использовать результат, выводимый из команды cmd2,
в качестве аргумента команды cmd1
cmd1 $ ( cmd2) Произвести подстановку команд по стандарту POSIX.
Допускается вложение
cmd $ ( (выражение) ) Произвести арифметическую подстановку по стандарту POSIX. В частности, использовать числовой
результат вычисления заданного выражения в качестве аргумента указанной команды cmd
cmd1 && cmd2 Выполнить логическую операцию И. В частности,
выполнить сначала указанную команду cmd1, а затем
команду cmd2 при удачном исходе выполнения
команды cmd1. Это "укороченная" форма логической
операции, при которой команда cmd2 вообще не
выполняется при неудачном исходе выполнения
команды cmd1
cmd1 || cmd2 Выполнить логическую операцию ИЛИ . В частности ,
выполнить указанную команду cmd1, а при неудачном исходе ее выполнения - команду cmd2.
Это "укороченная · форма логической операции , при
которой команда cmd2 вообще не выполняется при
удачном исходе выполнения команды cmd1
 ! cmd  Выполнить логическую операцию НЕ. В частности,
выполнить указанную команду cmd и выдать нулевой
код завершения, если выполнение команды cmd
завершится ненулевым кодом. В противном случае
выдать ненулевой код завершения , если выполнение
команды сmd завершится нулевым кодом

 

Примеры применения спецсимволов в командах Bash

# Выполнить указанные команды в фоновом режиме
$ nroff file > file . txt &

# Выполнить указанные команды последовательно
$ cd ; ls

# Переадресовать все выводимые результаты
$ (date ; who ; pwd) > logfile

# Отсортировать файл , подготовить, а затем произвести
# постраничный вывод полученных результатов
$ sort file | pr -З | lpr

# Отредактиро вать файлы , обнаруженные командой grep
$ gvim `grep -1 ifdef *.срр`

# Указать список искомых файлов
$ egrep '(yeslno)' `cat list`

# Версия предыдущей формы команды по стандарту POSIX
$ egrep '(yeslno)' $(cat list)


 

Последний представитель S-серии Vivo, как ожидается, будет выпущен 3 августа с запуском модели S7. До сих пор мы видели только несколько рендеров и спецификаций устройства, но теперь мы получаем больше деталей благодаря просочившейся брошюре.

Прежде чем переходить к описанию механизма выполнения программ PL/SQL, необходимо определить пару важных понятий:

  •  Исполняющее ядро PL/SQL (виртуальная машина PL/SQL). Так называется компонент Oracle, выполняющий байт-код программ PL/SQL, который при необходимости вызывает сервер базы данных и возвращает результаты вызывающей среде. Исполняющее ядро написано на языке C. Традиционно оно включалось в некоторые клиентские инструменты, например Oracle Forms, где оно открывает сеанс подключения к удаленной базе данных и взаимодействует с ядром SQL через сетевой протокол.
  • Сеанс (Oracle). Для большей части (серверного) кода PL/SQL сеансом называется процесс и пространство памяти, связанные с аутентифицированным пользователем. Каждый сеанс имеет собственную область памяти, в которой хранятся данные выполняемой программы. Сеансы начинаются с момента входа пользователя в систему и завершаются при выходе из нее. Для получения информации о текущих сеансах используется представление V$SESSI0N. Oracle поддерживает для сеанса различные виды памяти, включая PGA (Process Global Area), UGA (User Global Area) и CGA (Call Global Area); они будут рассматриваться далее в этом разделе.

Рассмотрим несколько способов выполнения простейшей программы из очень популярной клиентской среды SQL *Plus. Это прекрасный пример приложения, ориентированного на выполнение в рамках сеанса и предоставляющего доступ к окружению PL/SQL, которое входит в состав сервера базы данных. (Об SQL*Plus и его использовании для выполнения кода PL/SQL рассказывается в этом блоге.) Конечно, при желании к серверу можно обращаться с вызовами из других приложений (например, из клиентских программ Oracle и даже из таких языков, как Perl, C или Java). Происходящее на сервере практически не зависит от клиентского окружения.

При выполнении кода PL/SQL из SQI?Plus задействован анонимный блок верхнего уровня. Вы, вероятно, знаете, что команда EXECUTE в SQL *Plus преобразует вызов программы в анонимный блок, но известно ли вам, что команда SQL CALL тоже генерирует упрощенную разновидность анонимного блока? По сути, прежде чем в Oracle9i появилась возможность непосредственного вызова PL/SQL из SQL, все такого рода вызовы производились с использованием анонимных блоков.

 

Пример

Начнем с простейшего анонимного блока:

BEGIN
   NULL;
END;

Что происходит при его отправке серверу Oracle? Чтобы ответить на этот вопрос, об­ратимся к Рис. 1.

Проанализируем процесс, представленный на этом рисунке.

  1.  Пользователь вводит исходный код блока, а затем отдает SQLfPlus команду на выполнение (косая черта). Как следует из рисунка, SQLfPlus отправляет весь блок, за исключением косой черты, серверу. Передача осуществляется через соединение, установленное для текущего сеанса (например, через Oracle Net или механизм межпроцессных коммуникаций).

Выполнение тривиального анонимного блока

Рис. 1. Выполнение тривиального анонимного блока

 

  1. Компилятор PL/SQL пытается откомпилировать полученный анонимный блок в байт-код. На первом этапе компилятор проверяет синтаксис и убеждается в том, что программа соответствует грамматике языка. В нашем тривиальном примере код не содержит ни одного идентификатора, а только ключевые слова языка. Если компиляция проходит успешно, Oracle помещает байт-код блока в общую область памяти, а если нет — возвращает сообщения об ошибках сеансу SQLfPlus.
  2. Исполняющее ядро PL/SQL интерпретирует байт-код и возвращает сеансу SQLfPlus признак успешного или неудачного завершения сеанса.

Добавим в анонимный блок SQL-запрос и посмотрим, как изменится процесс его выполнения. На Рис. 2 показаны некоторые компоненты сервера Oracle, участвующие в выполнении команд SQL.

В этом примере значение столбца извлекается из встроенной таблицы DUAL.

Убедившись в том, что код PL/SQL не содержит синтаксических ошибок, компилятор PL/SQL передает код SQL компилятору SQL. Аналогичным образом при вызове программ PL/SQL из команд SQL компилятор SQL передает вызовы PL/SQL компилятору PL/SQL. Компилятор SQL приводит выражения к непосредственно исполняемому виду, анализирует возможности применения кэшированных результатов функций (начиная с Oraclellg), проверяет семантику и синтаксис, проводит разрешение имен и определяет оптимальный план выполнения. Все эти действия являются частью фазы разбора SQL-выражения и предшествуют подстановкам связанных переменных, выполнению и выборке команд SQL.

Хотя PL/SQL использует компилятор SQL совместно с базой данных, это не означает, что в PL/SQL доступны все функции SQL. Например, SQL поддерживает функцию NVL2:

SELECT NVL2(NULL, 1, 2) FROM DUAL;

Однако попытка вызова NVL2 непосредственно из PL/SQL приводит к ошибке (PLS- 00201):

SQL> EXEC DBMS_OUTPUT.PUT_LINE(NVL2(NULL, 1, 2));
   2 BEGIN DBMS_OUTPUT.PUT_LINE (NVL2(NULL, 1, 2)); END;

*
ERROR at line 1:
ORA-06550: line 1, column 28:
PLS-00201: identifier 'NVL2' must be declared
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored

 

Выполнение анонимного блока, содержащего команду SQL

Рис. 2. Выполнение анонимного блока, содержащего команду SQL

При компиляции программы PL/SQL встроенные команды SQL подвергаются незначительным преобразованиям: из них удаляются секции INTO, на место локальных переменных программы подставляются связанные значения, удаляются комментарии, а многие идентификаторы (ключевые слова, имена столбцов, имена таблиц и т. д., но не рекомендации и литералы) преобразуются в верхний регистр. Например, если myvar является локальной переменной, PL/SQL преобразует команду select dummy into str from dual where dummy = myvar к следующему виду:

select dummy into str from dual where dummy = myvar

к следующему виду:

SELECT DUMMY FROM DUAL WHERE DUMMY = :B1

Из кода PL/SQL могут совершаться внешние вызовы двух типов:

  • Хранимые процедуры Java. Стандартная установка сервера баз данных включает не только виртуальную машину PL/SQL, но и виртуальную машину Java. Вы можете написать спецификацию вызова PL/SQL, логика которого реализуется в виде статического класса Java.
  •  Внешние процедуры. Исполняемую часть подпрограммы PL/SQL также можно реализовать в коде C. Во время работы база данных будет выполнять код в особом процессе и пространстве памяти, отделенных от главного сервера базы данных. Вы отвечаете за поддержку двоичных файлов и наличие копии у каждого узла RAS.

 

Ограничения компилятора

При компиляции очень большой программы PL/SQL от сервера можно получить сообщение об ошибке PLS-00123. Это означает, что компилятор вышел за пределы максимально допустимого количества узлов в дереве разбора. В таком случае программу проще всего разбить на несколько меньших подпрограмм или изменить ее архитектуру (например, использовать временную таблицу вместо 10 000 параметров). Трудно предсказать, сколько узлов понадобится для реализации программы, потому что не каждый узел соответствует какой-либо легко идентифицируемой единице исходного кода (лексеме, строке кода и т. д.).

По данным Oracle, «типичная» хранимая программа создает в среднем четыре узла на каждую строку кода, что дает следующие приблизительные ограничения:

Тип программы PL/SQL Приблизительный максимальный размер исходного кода в байтах
Тело пакета или типа; автономные функции и процедуры 256 Мбайт
Сигнатура (заголовок) отдельной функции или процедуры 128 Kбайт
Спецификация пакета или типа данных, анонимный блок 128 Kбайт

Приведенные значения весьма приблизительны; в реальных программах возможны значительные отклонения в обоих направлениях.

Некоторые из других документированных ограничений компилятора PL/SQL перечислены в следующей таблице.

Тип программы PL/SQL Максимальное значение
(приблизительное)
Уровни вложения блоков 255
Параметры, передаваемые процедуре или функции 65 536
Уровни вложения записей 64
Ссылки на объекты в программах 65 536
Количество обработчиков исключений в одной программе 65 536
Точность NUMBER (в знаках) 38
Размер VARCHAR2 (в байтах) 32 767

 

Телефоны Redmi - это то, с чего началась история успеха для Xiaomi, и эта серия до сих пор остается самой важной для компании. За прошедшие годы он значительно вырос (и буквально, и фигурально), и топовые модели Редми даже смогли тягаться на равных с некоторыми из самых мощных флагманов на рынке. Тем не менее, истинные телефоны Redmi всегда придерживались одной и той же формулы - обеспечивают надежную работу смартфона при минимально возможном бюджете, максимально увеличивая соотношение цены и качества.

Детализированный аудит FGA в PL/SQL для безопасностиДетализированный аудит (FGA, Fine-Grained Auditing) предоставляет механизм для регистрации факта выдачи пользователями определенных команд и выполнения некоторых условий. При этом регистрируется команда, введенная пользователем, а также другая информация: время, терминал и т. д.

Под традиционным аудитом в Oracle понимается механизм регистрации того, какая схема выполнила то или иное действие: пользователь Joe выполняет процедуру X, пользователь John выполнил выборку данных из таблицы Y и т. д. Протокол всех этих действий, называемый журналом аудита, хранится в таблице AUD$ в схеме SYS, доступной для всех пользователей через несколько представлений словаря данных — например, DBA_AUDIT_TRAIL. Журналы аудита также могут записываться в файлы операционной системы вместо таблиц базы данных. Независимо от того, где хранится эта информация, главный недостаток традиционного аудита остается неизменным: он следит за тем, кто выполнил ту или иную команду, а не за тем, что при этом было сделано. Например, из журнала аудита можно узнать, что пользователь Joe получил данные из таблицы ACCOUNTS, но какие именно записи — остается неизвестным. Если вы хотите знать измененные значения, приходится устанавливать для таблиц триггеры DML и сохранять значения в таблице, определенной вами. Но поскольку определить триггер для команды SELECT не удастся, для ситуации с Joe этот вариант не подойдет.