Внутренний язык СУБД. Сравнительные характеристики 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;