Какой тип привязки PL/SQL использует?

Я наткнулся на следующий вопрос.

PL/SQL использует один из следующих

  • (A) Нет привязки
  • (B) Ранняя привязка
  • (C) Поздняя привязка
  • (D) Отложенная привязка

Но не удалось найти удовлетворительных ответов.

Кто-нибудь может объяснить это?

Ответы

Ответ 1

(E) Все выше

Это смешной вопрос с множественным выбором. Сроки раннего, позднего и отсроченного связывания неоднозначны. И PL/SQL можно запускать разными способами, в том числе в SQL.

Вот мои (возможно неправильные) определения вариантов:

  • Нет привязки - переменные не имеют типов.
  • Раннее связывание - переменные типы фиксируются во время компиляции.
  • Late Binding. Переменные типы являются гибкими и могут быть установлены во время выполнения.
  • Отложенное связывание. Во время компиляции определяются несколько типов переменных, но во время выполнения выбирается только один из них.

Теперь мы должны сопоставлять эти варианты с различными контекстами PL/SQL: статические SQL и PL/SQL, пустые анонимные блоки, удаленные процедуры, динамический SQL и PL/SQL, совместное использование адаптивных курсоров, операции FILTER, объектно-ориентированные PL/SQL, ЛЮБЫЕ * типы, и я, вероятно, пропустил еще немного.

(A) Нет привязки

У пустого анонимного блока нет переменных, поэтому ничего не связано. Я не уверен, что это действительно соответствует определению без привязки, похоже, похоже на краевой случай. На некоторых языках всегда есть объект, и что-то всегда должно быть связано, но не в PL/SQL.

(B) Ранняя привязка

Обычный SQL и PL/SQL используют раннее связывание - переменным присваивается тип, и они должны придерживаться его. Несоответствия типов либо выдают ошибку компилятора, либо требуют неявного преобразования.

Удаленные вызовы процедур с REMOTE_DEPENDENCIES_MODE, установленными на "TIMESTAMP", возможно, раннее связывание. Временная метка устанавливается во время компиляции, когда все проверяется. Он по-прежнему проверяется во время выполнения, но это простая и быстрая проверка.

(C) Поздняя привязка

Динамический SQL и PL/SQL используют позднюю привязку, потому что код даже не скомпилирован до времени выполнения. Это относится как к DBMS_SQL, так и к execute immediate.

Объектно-ориентированный PL/SQL использует позднюю привязку. Тип устанавливается во время компиляции, но во время выполнения может использоваться другой подтип.

ANYTYPE, ANYDATA и ANYDATASET также используют последнее связывание, так как они могут быть созданы во время выполнения или получены и выполнены во время выполнения.

Удаленные вызовы процедур с REMOTE_DEPENDENCIES_MODE, установленными на "ПОДПИСЬ", возможно, связаны с поздним связыванием. Подпись проверяется как во время компиляции, так и во время выполнения, и допускает крошечную гибкость в типах.

(D) Отложенная привязка

Некоторые функции Oracle SQL создают несколько путей кода, но выполняют только один из них. Адаптивные функции обмена курсором и FILTER будут создавать несколько способов запуска одного и того же оператора SQL, а соответствующая версия будет выбрана во время выполнения.


Права и права защитника

Права и права детектора также усложняют этот вопрос. Но я думаю, что в конечном счете они не имеют никакого значения, и что оба они все еще ранние. Компилятор все еще решает тип во время компиляции. Хотя вы можете использовать права invoker для скрытного изменения типа во время выполнения, он будет генерировать ошибку только потому, что он не соответствует ожидаемому типу.

Например, скажем, есть две схемы, которые имеют одинаковые имена таблиц и столбцов, но разные типы:

create table user1.test_table(a number);
insert into suer1.test_table values(1);

create table user2.test_table(a date);
insert into user2.test_table values(sysdate);

Если вы создаете эту функцию в USER1, это выглядит так: тип V_VALUE является динамическим и может меняться с пользователем.

create or replace function user1.test_function return varchar2 authid current_user is
    v_value test_table.a%type;
begin
    select a into v_value from test_table;
    return to_char(v_value);
end;
/

Код компилируется с использованием типов из USER1 и отлично работает при запуске USER1. Однако, когда USER2 запускает его, генерируется эта ошибка: ORA-00932: inconsistent datatypes: expected NUMBER got DATE.

Это заставляет меня думать, что права на вызовы и определители не влияют на привязку. Они оба используют раннее связывание в статических SQL и PL/SQL.

Ответ 2

Вы можете найти ответ в очень старой документации, связанной с Oracle 8:
https://docs.oracle.com/cd/A58617_01/server.804/a58236/05_ora.htm

Эффективность и гибкость

Прежде чем программа PL/SQL может быть выполнена, она должна быть скомпилирована. Компилятор PL/SQL решает ссылки на объекты схемы Oracle на поиск их определений в словаре данных. Затем компилятор присваивает адреса памяти программным переменным, которые будут удерживаться Oracle, чтобы Oracle мог искать адреса во время выполнения. Эта процесс называется связыванием.

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

Предназначен в первую очередь для высокоскоростной обработки транзакций, PL/SQL повышает эффективность за счет объединения SQL-инструкций и избежания времени выполнения сборник. В отличие от SQL, который скомпилирован и выполнен оператор-by-statement во время выполнения (поздняя привязка), обрабатывается PL/SQL в машиносчитываемый p-код во время компиляции (раннее связывание). При запуске время, механизм PL/SQL просто выполняет p-код.

Но Oracle в последующих версиях удалил из документации всю главу Взаимодействие с Oracle.

Итак, в соответствии с вышеизложенным, ответ: (B) Ранняя привязка - наверняка для Oracle версии 8 и, возможно, в более поздних версиях.

Ответ 3

edit. Я просто перефразировал ответ, чтобы немного ускорить процесс.

короткий ответ

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

Отложенное связывание лежит в основе механизма SQL и делает его чрезвычайно удобным для изменения распределения данных; это основная функция, о которой все должны знать, поэтому я думаю, что вопрос был задан, если только "PL/SQL" не означает "PL" (как часто это делают документы Oracle).

В следующем примере, надеюсь, сразу становится ясно. У нас есть два пользователя ( "demo" и "scott" ), которым принадлежит таблица и каждая процедура с одинаковыми именами.

demo
  invoked_proc
  x_table

scott
  invoked_proc
  x_table

Если мы создадим процедуру, приведенную ниже в схеме "demo", так Oracle может разрешить символы во время компиляции и во время выполнения

compilation
  "invoked_proc": demo.invoked_proc
  "x_table": demo.x_table

execution when logged as "demo": the same

execution when logged as "scott"
  "invoked_proc": demo.invoked_proc <- resolves as per compilation
  "x_table": scott.x_table <- resolved differently

Вот процедура, и тот факт, что мы используем права invoker, не является основополагающим, это просто делает этот вопрос более очевидным:

CREATE or replace PROCEDURE demo.invoker_proc
AUTHID CURRENT_USER 
IS
n number := 1;
BEGIN

   invoked_proc();

   select id into n
   from X_TABLE where id = n;

END;
/

Длинный ответ

Применяются все типы привязки (b, c, d). Среди них отсроченная привязка, вероятно, самая замечательная, поэтому, если они попросили выбрать только один ответ, я бы окончательно пошел на "d" (отложенное обязательство), когда говорил о SQL, и "b" (раннее связывание) при работе с PL.

Мы, вероятно, должны начать с того, чтобы сказать, что терминология важна, и что, возможно, ответ krokodilko является наиболее авторитетным с учетом документов, на которые он указывает ( даже если эта ссылка потенциально устарела).

Однако я твердо верю, что дело в том, что в Oracle, движок PL и движок SQL почти полностью расставлены и разрешают имена совершенно по-разному. В то время как первое обычно связано с некоторой формой раннего или позднего связывания (в основном, раннего связывания), последнее всегда подразумевает отсроченное связывание: операторы SQL "компилируются" в исполняемые планы при выполнении, а не во время компиляции. Семантическое разрешение символов откладывается до тех пор, пока запрос не будет выполнен, поэтому имена будут разрешены в соответствии с текущим контекстом (в первую очередь, с текущим пользователем). Это также тип привязки, используемый при выпуске оператора execute immediate, dbms_sql или dbms_job.submit, вызванного с помощью NO_PARSE = true.

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

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

Единственным предварительно испеченным продуктом компиляции модуля PL является разрешение его прямых зависимостей, которое происходит во время компиляции (информация, которая хранится в коде DIANA) и позволяет движку чтобы обнаружить, когда пришло время повторно скомпилировать блок PL из-за внешних изменений (например, изменения в структуре таблицы, упомянутой в SQL-заявлении). Обратите внимание, что этот превентивный механизм не подходит при правильном использовании invoker, потому что Oracle не может знать, что имя будет ссылаться позже, во время выполнения.

Все это очень заметно, когда мы используем права invoker для запуска процедуры. Рассмотрим вышеупомянутый случай, в котором у двух пользователей есть процедура и таблица по их соответствующим схемам, именованные равными (таблицы являются идентичными, за исключением того, что таблица scott имеет индекс на нем)

CONNECT demo/demo

CREATE PROCEDURE invoked_proc IS
BEGIN
   DBMS_OUTPUT.put_line ('invoked_proc owned by demo');
END;
/
GRANT execute on invoked_proc to public;

create table X_TABLE (id number);
insert into x_table values(1);
commit;


CONNECT scott/tiger

CREATE PROCEDURE invoked_proc IS
BEGIN
   DBMS_OUTPUT.put_line ('invoked_proc owned by scott');
END;
/


create table X_TABLE (id number);
create index X_INDEX ON X_TABLE(id);
insert into x_table values(1);
commit;

и подумайте о том, что происходит, когда вы компилируете третью процедуру (по одной схеме), которая ссылается на эти имена и которая выполняется с правами invoker:

CREATE or replace PROCEDURE invoker_proc
AUTHID CURRENT_USER 
IS
n number := 1;
BEGIN

   invoked_proc();

   select id into n
   from X_TABLE where id = n;

END;
/

Что мы можем сказать о символах, которые были разрешены компилятором? Мы можем быстро вывести их, посмотрев зависимости INVOKER_PROC:

select owner, name,
referenced_owner, referenced_name
from dba_dependencies
where name = 'INVOKER_PROC';


OWNER   NAME          REFERENCED_OWNER   REFERENCED_NAME
------- ------------- ------------------ -----------------
DEMO    INVOKER_PROC  DEMO               X_TABLE
DEMO    INVOKER_PROC  DEMO               INVOKED_PROC

Таким образом, как процедура, так и таблица, идентифицированные компилятором, принадлежат DEMO, пользователю, которому принадлежат процедуры.
Что касается плана, лежащего в основе запроса sql, пока ничего не определено:

Select substr(sql_text,1,40),
sql_id,
plan_hash_value,
parsing_schema_name,
child_number
from v$sql
where sql_text like '%X_TABLE%'
;

no relevant records found...

Тем не менее, все начинает меняться при запуске SQL-движка, чего не происходит до выполнения.

connect demo/demo

EXEC demo.invoker_proc

> invoked_proc owned by demo

и глядя на планы, мы видим, что новый план вокруг

Select substr(sql_text,1,40),
sql_id,
plan_hash_value,
parsing_schema_name,
child_number
from v$sql
where sql_text like '%X_TABLE%'
;


SUBSTR(SQL_TEXT,1,40)                  SQL_ID        PLAN_HASH_VALUE PARSING_SCHEMA_NAME CHILD_NUMBER 
-------------------------------------- ------------- --------------- ------------------- ------------ 
SELECT ID FROM X_TABLE WHERE ID = :B1  01a77qj300y18      1220025608 DEMO                           0 

Если мы запустим ту же процедуру из перспективы scott и посмотрим на планы, мы увидим, что был вызван тот же invoked_proc, который принадлежит DEMO (он выводит "invoked_proc owned by demo" ).
Таким образом, разрешение имени части PL, переносимое во время компиляции, по-прежнему остается верным (раннее связывание). То же самое не совсем верно для части SQL:

connect scott/tiger

EXEC demo.invoker_proc;

> invoked_proc owned by demo


SUBSTR(SQL_TEXT,1,40)                  SQL_ID        PLAN_HASH_VALUE PARSING_SCHEMA_NAME CHILD_NUMBER 
-------------------------------------- ------------- --------------- ------------------- ------------ 
SELECT ID FROM X_TABLE WHERE ID = :B1  01a77qj300y18      1220025608 DEMO                           0 
SELECT ID FROM X_TABLE WHERE ID = :B1  01a77qj300y18      3707869577 SCOTT                          1 

Мы видим, что он создал другой план для нового запроса с другим child_number. Второй план ссылается на другую таблицу, отличную от той, которая была определена во время компиляции (отложенная привязка). Это подтверждается, если мы посмотрим на содержание планов; первый план включает в себя простой стол, на котором может выполняться только полное сканирование:

select plan_table_output
from table(dbms_xplan.display_cursor(
    SQL_ID => '01a77qj300y18'
    ,CURSOR_CHILD_NO =>  0
    ));


SQL_ID  01a77qj300y18, child number 0
-------------------------------------
SELECT ID FROM X_TABLE WHERE ID = :B1

Plan hash value: 1220025608

-----------------------------------------------------------------------------
| Id  | Operation         | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |         |       |       |     4 (100)|          |
|*  1 |  TABLE ACCESS FULL| X_TABLE |     1 |    13 |     4   (0)| 00:00:01 |
-----------------------------------------------------------------------------

а вторая таблица, которая предлагает индекс, позволяет Oracle получить лучший путь кода (в этом случае сканирование диапазона индекса)

select plan_table_output
from table(dbms_xplan.display_cursor(
    SQL_ID => '01a77qj300y18'
    ,CURSOR_CHILD_NO =>  1
    ));

SQL_ID  01a77qj300y18, child number 1
-------------------------------------
SELECT ID FROM X_TABLE WHERE ID = :B1

Plan hash value: 3707869577

----------------------------------------------------------------------------
| Id  | Operation        | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT |         |       |       |     1 (100)|          |
|*  1 |  INDEX RANGE SCAN| X_INDEX |     1 |    13 |     1   (0)| 00:00:01 |
----------------------------------------------------------------------------

Вывод заключается в том, что PL обычно включает раннее или позднее связывание, тогда как SQL всегда откладывается.

Есть дополнительные соображения, которые могут вступить в игру, например, использование BASELINES (предварительно скомпилированные планы, которые постоянно сохраняются и могут быть выбраны или нет в зависимости от того, что оптимизатор считает более дешевым) или ADAPTIVE CURSORS (альтернативные планы, хранящиеся в пул библиотек, выбранный во время выполнения); и они включают несколько иные понятия. Однако, учитывая отсутствие консенсуса в отношении термина "отсроченное обязательство", возможно, все они могут считаться частью "отложенной обязательной вещи" (мне любопытно узнать мнение о том, кто написал оригинальную викторину).

Например, это не противоречит тому, что я вижу в .NET: отложенное связывание, по-видимому, является темой, слабо связанной с кодом, который рефлексивно сгенерирован и скомпилирован во время выполнения. Хотя GWT утверждает, что использует "отложенное обязательство"; что: альтернативные сегменты кода скомпилированы и только один выбран во время выполнения (для их цитирования "По сути, отложенное связывание является ответом GWT на отражение Java", см. здесь)

Ответ 4

Из опубликованного запроса я понимаю, что использование какого типа PL/SQL привязки вообще разрабатывается. В этом случае опция (B) Ранняя привязка является ответом в качестве оракула. ​​

Далее

  • PL - Сохраненные процедуры - раннее связывание.
  • PL - Удаленные процедуры - Поздняя привязка.
  • Динамический SQL - поздняя привязка.

Ответ 5

Прежде чем программа PL/SQL может быть выполнена, она должна быть скомпилирована. Компилятор PL/SQL решает ссылки на объекты Oracle, просматривая их определения в словаре данных. Затем компилятор назначает адреса хранилища программным переменным, которые будут хранить данные Oracle, чтобы Oracle мог искать адреса во время выполнения. Этот процесс называется привязкой.

Как язык базы данных реализует привязку, влияет на эффективность выполнения и гибкость?

Связывание во время компиляции, называемое статическим или ранним связыванием, повышает эффективность, потому что определения объектов базы данных просматриваются тогда, а не во время выполнения.

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

Ответ 6

Его (B) Ранняя привязка, которая используется в время компиляции и (C) Late Binding, которая используется при запуске время.