Внутренний язык СУБД. Сравнительные характеристики T-SQL и PL/SQL
Введение
Практически каждая СУБД имеет в своем составе процедурное расширение языка SQL. Эти языки используются для реализации бизнес-логики и дополнительных проверок целостности на уровне сервера. Программные модули, написанные на этих языках, хранятся в СУБД и выполняются специальным компонентом непосредственно в ядре СУБД. Синтаксис таких языков разработан для максимально простой и удобной интеграции с SQL. Модули процедурного расширения SQL могут быть одного из следующих типов
Oracle. Процедурное расширение - PL/SQL. Синтаксис похож на ADA. Помимо СУБД, входит в другие продукты Oracle, например Oracle Developer. Является наиболее мощным из процедурных языков основных СУБД.
SQL Server. Процедурное расширение - Transact-SQL (T-SQL). Обладает основными возможностями. До версии 2005 отсутствовала обработка исключений.
Основные характеристики PL/SQL и T-SQL
- Полный диапазон типов данных
- Явно определяемая структура кода - блоки данных, процедуры и т.д.
- Операторы управления потоком команд - условные, циклы и т.д.
- Обработчики исключений
- Повторно используемые именованные блоки кода, такие как функции, процедуры, пакеты (только в PL/SQL)
- Тесная интеграция с SQL - непосредственный вызов команд SQL из процедурного кода
Блок PL/SQL. Структура
Вызов из sqlplus:
call dbms_output.put_line('aaa')
exec dbms_output.put_line('aaa')Структура блока plsql
declare
i number;
d date;
begin
i := 0;
select count(*) into i from all_users;
if i > 10 then
dbms_output.put_line('> 10');
else
dbms_output.put_line('<= 10');
end if;
begin
select sysdate into d from dual;
exception
when no_data_found then
d := null;
raise;
end;
end;Основные элементы plsql
Комментарии
/* многострочные комментарии */
Идентификаторы
declare
LongName number;
begin
longname := 10;
dbms_output.put_line(LONGNAME);
end;
declare
"LongName" number;
begin
longname := 10;
dbms_output.put_line(LONGNAME);
end;
declare
n_$# number;
begin
n_$# := 10;
end;Логический тип
declare
b boolean;
begin
b := true;
-- error
-- dbms_output.put_line(b);
dbms_output.put_line(case b when true then 1 else 0 end);
if b then
dbms_output.put_line(1);
else
dbms_output.put_line(0);
end if;
end;Декларации
declare
n1 number;
n2 number := 10;
n3 number default 10;
n4 number not null := 30;
begin
dbms_output.put_line(nvl(n1, -100));
dbms_output.put_line(n2);
dbms_output.put_line(n3);
dbms_output.put_line(n4);
end;
declare
n test.i%type;
r test%rowtype;
begin
n := 10;
dbms_output.put_line(n);
select * into r from test where i = 1;
dbms_output.put_line(r.i);
dbms_output.put_line(r.s);
end;
-- видимость переменных
declare
a number := 10;
b number := 20;
begin
dbms_output.put_line(a);
dbms_output.put_line(b);
declare
a number;
c number;
begin
a := 30;
c := 40;
dbms_output.put_line('---->'||a);
dbms_output.put_line('---->'||b);
dbms_output.put_line('---->'||c);
end;
dbms_output.put_line(a);
dbms_output.put_line(b);
end;Именованные блоки
<<my_block>>
declare
a number := 10;
b number := 20;
begin
dbms_output.put_line(a);
dbms_output.put_line(b);
declare
a number;
c number;
begin
a := 30;
c := 40;
dbms_output.put_line('---->'||my_block.a);
dbms_output.put_line('---->'||a);
dbms_output.put_line('---->'||b);
dbms_output.put_line('---->'||c);
end;
dbms_output.put_line(a);
dbms_output.put_line(b);
end;
<<my_block1>>
declare
a number := 10;
begin
dbms_output.put_line('my_block1 '||a);
<<my_block2>>
declare
a number := 20;
begin
dbms_output.put_line('my_block2 '||my_block1.a);
dbms_output.put_line('my_block2 '||a);
<<my_block3>>
declare
a number := 30;
begin
dbms_output.put_line('my_block3 '||my_block1.a);
dbms_output.put_line('my_block3 '||my_block2.a);
dbms_output.put_line('my_block3 '||a);
end;
end;
dbms_output.put_line('my_block1 '||a);
end;Управляющие конструкции
declare
n number;
begin
n := 10;
if n > 10 then
n := 20;
dbms_output.put_line(n);
else
n := 30;
dbms_output.put_line(n);
end if;
if n > 10 then
n := 20;
dbms_output.put_line(n);
end if;
if n > 10 then
n := 20;
dbms_output.put_line(n);
elsif n > 5 then
n := 30;
dbms_output.put_line(n);
else
n := 40;
dbms_output.put_line(n);
end if;
case n
when 10 then
n := 100;
dbms_output.put_line(n);
when 12 then
n := 200;
dbms_output.put_line(n);
else
n := 300;
dbms_output.put_line(n);
end case;
case
when n = 10 then
n := 100;
dbms_output.put_line(n);
when n = 12 then
n := 200;
dbms_output.put_line(n);
else
n := 300;
dbms_output.put_line(n);
end case;
end;
declare
n number := 10;
begin
case n
when 1 then
dbms_output.put_line('1');
when 2 then
dbms_output.put_line('1');
end case;
exception
when case_not_found then
dbms_output.put_line('case not found');
end;
declare
n number;
begin
n := 1;
loop
dbms_output.put_line(n);
n := n+1;
exit when n > 10;
end loop;
end;
declare
n number;
begin
n := 1;
loop
dbms_output.put_line(n);
n := n+1;
if n > 10 then
exit;
end if;
end loop;
end;
declare
n number;
begin
n := 1;
while n <= 10 loop
dbms_output.put_line(n);
n := n+1;
end loop;
end;
declare
n number;
begin
for n in 1..10 loop
dbms_output.put_line(n);
end loop;
end;
declare
n number;
begin
for n in reverse 1..10 loop
dbms_output.put_line(n);
end loop;
end;
