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

Одним из основных преимуществ реляционных
Функция оптимизатора - выбрать наиболее
В
CBO управляется optimizer_mode, который может указываться на уровне сессии или на уровне экземпляра. Он может иметь следующие значения.
optimizer_mode = (был заморожен в версии 7), RBO, например, не умеет пользоваться индексами.
optimizer_mode = all_rows - CBO, выбирает план выполнения с оптимальной стоимостью, режим работы оптимизатора по умолчанию.
optimizer_mode = first_rows - CBO, вычисляется
optimizer_mode = - all_rows, а если ни по одной из таблиц нет, то - . Если RBO не поддерживает -индексы), то используется CBO. CBO может оптимизировать запросы по таблицам, по которым не собрана
optimizer_mode = first_rows_1, first_rows_10, first_rows_1000 - при использовании first_rows first_rows_n вычисляет n строк, а
Пример:
alter session set optimizer_mode= first_rows;
Отсутствие ) таблицы, число возможных значений столбца и распределение данных. ) и распределения данных для каждой таблицы, индекса и материализованного представления. DBMS_STATS. Статистические данные можно собирать либо путем чтения всех строк, либо путем проведения оценки на основе чтения только небольшой выборки строк или блоков. В пакете DBMS_STATS предлагаются процедуры для сбора
analyze table t compute statistics for table for all indexes for all columns; analyze table t compute statistics for table for all indexes for all indexed columns; analyze table t compute statistics for table for columns i, s; analyze index t_i compute statistics for table for all indexes for all columns; analyze table t estimate statistics for table for all indexes for all columns sample 10 rows; analyze table t estimate statistics for table for all indexes for all columns sample 10 percent; analyze table t compute statistics for table for all indexes for all columns size 100; analyze table t compute statistics for table for columns i size 100, s size 200;
execute dbms_stats.gather_index_stats(ownname=>'stud',
indname=>'i', partname=>null, estimate_percent=>50, stattab=>null, statid=>null, statown=>null);
execute dbms_stats.gather_table_stats(ownname=>'stud',
tabname=>'t', partname=>null, estimate_percent=>50, block_sample=>false,
method_opt=>'FOR ALL COLUMNS', degree=>null,
cascade=>true, stattab=>null, statid=>null, statown=>null);
execute dbms_stats.gather_table_stats(ownname=>'stud',
tabname=>'t', partname=>null, estimate_percent=>50, block_sample=>false,
method_opt=>'FOR COLUMNS object_name, object_id',
degree=>null, cascade=>true, stattab=>null,
statid=>null, statown=>null);
execute dbms_stats.gather_schema_stats(ownname=>'stud',
estimate_percent=>50, block_sample=>false, method_opt=>'FOR ALL COLUMNS',
degree=>null, cascade=>true, stattab=>null, statid=>null, statown=>null);
execute dbms_stats.delete_index_stats(ownname=>'stud',
indname=>'i', partname=>null, stattab=>null, statid=>null, statown=>null);
execute dbms_stats.delete_table_stats(ownname=>'stud',
tabname=>'t', partname=>null, stattab=>null, statid=>null,
statown=>null, cascade_parts=>true, cascade_columns=>true);
execute dbms_stats.delete_schema_stats(ownname=>'stud', stattab=>null,
statid=>null, statown=>null);
Данные по статистике таблиц можно посмотреть в словаре USER_TABLES. Основная
Пример:
select * from user_tables where table_name = 'T';
analyze table t delete statistics;
select num_rows, blocks, empty_blocks, avg_space,
chain_cnt, avg_row_len, avg_space_freelist_blocks,
num_freelist_blocks, sample_size, last_analyzed from user_tables
where table_name = 'T';
analyze table t compute statistics for table;
select num_rows, blocks, empty_blocks, avg_space,
chain_cnt, avg_row_len, avg_space_freelist_blocks,
num_freelist_blocks, sample_size, last_analyzed from user_tables
where table_name = 'T';
USER_INDEXES. Основная
Пример:
analyze table t delete statistics;
select blevel, leaf_blocks, distinct_keys,
avg_leaf_blocks_per_key, avg_data_blocks_per_key,
clustering_factor, num_rows, sample_size,
last_analyzed from user_indexes
where table_name = 'T' and index_name = 'T_I';
analyze table t compute statistics for all indexes;
select blevel, leaf_blocks, distinct_keys,
avg_leaf_blocks_per_key, avg_data_blocks_per_key,
clustering_factor, num_rows, sample_size,
last_analyzed from user_indexes
where table_name = 'T' and index_name = 'T_I';
USER_TAB_COLUMNS, USER_TAB_COL_STATISTICS.
null Пример:
select * from user_tab_columns where table_name = 'T' and column_name = 'I'; select * from user_tab_col_statistics where table_name = 'T' and column_name = 'I'; analyze table t delete statistics; select * from user_tab_col_statistics where table_name = 'T' and column_name = 'I'; analyze table t compute statistics for all columns; select * from user_tab_col_statistics where table_name = 'T' and column_name = 'I';
Данная
Сбалансированные по
Пример:
analyze table t compute statistics for columns s size 254;
select endpoint_number, endpoint_value,
substr(endpoint_actual_value, 1, 30)
from user_tab_histograms where table_name =
'T' and column_name = 'S';
analyze table t compute statistics for columns s size 8;
select endpoint_number, endpoint_value,
substr(endpoint_actual_value, 1, 30)
from user_tab_histograms where table_name =
'T' and column_name = 'S';
analyze table t compute statistics for columns s size 254;
select endpoint_number, endpoint_value,
substr(endpoint_actual_value, 1, 30)
from user_tab_histograms where table_name =
'T' and column_name = 'S';
select s, count(*) from t group by s;
-- создание объектов drop table h; -- create table h(p number constraint pk primary key, s varchar2(100) null, n number null, nu number null constraint un unique); create table h(p number, s varchar2(100) null, n number null, nu number null);
Для >25-30% записей в таблице. Возникает проблема
-- полное сканирование таблицы. high water mark insert into h select -rownum, object_name, object_id, object_id from all_objects where rownum < 100; insert into h select rownum, object_name, object_id, object_id from all_objects; select * from h where p < 0; analyze table h compute statistics for table for all columns for all indexes; select num_rows, blocks, empty_blocks from user_tables where table_name = 'H'; delete from h where p > 0;
Индексы на основе В*-

Блоки самого нижнего уровня в индексе, которые называют листовыми вершинами, содержат все проиндексированные rid на схеме), ссылающиеся на соответствующие строки. Промежуточные блоки над листовыми вершинами называют блоками
where x between 20 and 30
-- индексы
-- структура индекса, rowid
truncate table h;
insert into h select rownum, object_name,
object_id, object_id from all_objects where rownum < 10;
commit;
select rowid, p from h;
select * from h where rowid =
'AAAN95AAEAAAAfHAAA';
declare
r_t number;
o_n number;
f_n number;
b_n number;
r_n number;
r rowid;
begin
select rowid into r from h where rownum < 2;
dbms_rowid.rowid_info(r, r_t, o_n, f_n, b_n, r_n);
dbms_output.put_line('rowid type = ' || r_t);
dbms_output.put_line('object number = ' || o_n);
dbms_output.put_line('file number = ' || f_n);
dbms_output.put_line('block number = ' || b_n);
dbms_output.put_line('row number = ' || r_n);
end;
select * from user_objects where object_name = 'H';
select * from user_tables where table_name = 'H';
select * from dba_data_files;
-- создание индексов
truncate table h;
insert into h select rownum, object_name, object_id, object_id from all_objects;
commit;
create index ind_s on h(s);
select * from user_indexes where table_name = 'H';
drop index ind_s;
select * from user_indexes where table_name = 'H';
create index ind_s_1 on h(s desc);
create unique index ind_n on h(n);
select index_name, index_type, table_name, status, funcidx_status from user_indexes where table_name = 'H';
-- информация по таблицам и индексам
select * from user_tables;
select * from user_tab_columns;
select * from user_constraints;
select * from user_cons_columns;
select * from user_indexes;
select * from user_ind_columns;
analyze table h compute statistics for table for all indexes for all indexed columns; set autotrace on set timing on -- операции по индексу drop index ind_s on h(s); select * from h where s = 'aaaa'; create index ind_s on h(s); select * from h where s = 'aaaa'; select * from h where s||'a' = 'aaaa'; select * from h where upper(s) = 'aaaa'; select * from h where s like 'aaaa%'; select * from h where s like '%aaaa'; drop index ind_nu; select * from h where nu = 1222; create index ind_nu on h(nu); select * from h where nu = 1222; select * from h where nu+1 = 1222; select * from h where nu = 1222+1; select * from h where abs(nu) = 1222; select * from h where s = '123'; select * from h where s = 123; -- выбор между доступом по индексам и full scan delete from h; insert into h(p, s, n, nu) select object_id, object_name, object_id, object_id from all_objects where rownum < 5; analyze table h compute statistics for table for all indexes for all indexed columns; select * from h where s = 'DUAL'; delete from h; insert into h(p, s, n, nu) select object_id, object_name, object_id, object_id from all_objects; -- со старой статистикой !!! select * from h where s = 'DUAL'; analyze table h compute statistics for table for all indexes for all indexed columns; -- с новой статистикой !!! select * from h where s = 'DUAL'; -- обработка null значений -- поля null не проверяются на уникальность insert into h(p, s, n, nu) values(-1, 'asd', null, null); insert into h(p, s, n, nu) values(-2, 'asd', null, null); insert into h(p, s, n, nu) values(-3, 'asd', null, -1); select * from h where s is null;
Индексы по функции. Эти индексы на основе В*-
SELECT * FROM T WHERE ФУНКЦИЯ(СТОЛБЕЦ) = НЕКОТОРОЕ_ЗНАЧЕНИЕ,
поскольку значение ФУНКЦИЯ(СТОЛБЕЦ) уже вычислено и хранится в индексе.
-- функциональные индексы select * from h where n*n = 100; -- надо иметь такие права для создания функциональных индексов alter system set query_rewrite_enabled=true; grant query rewrite to stud; create index ind_f_n on h(n*n); select * from h where n*n = 100; create index ind_n on h(n); select index_name, index_type, table_name, status, funcidx_status from user_indexes where table_name = 'H'; select * from h where n = 100; select * from h where n > 0;
Обычно в В*-Y, N и , — в таблице с миллионом строк очень хорошо подходит для в таблице ЕМР:
create BITMAP index job_idx on emp(job);
Сервер

Это показывает, что в строках 8, 10 и 13 находится значение , тогда как в строках 4, 6 и 7 — значение . Также понятно, что пустых строк нет (индексы на основе битовых карт содержат записи для пустых значений — отсутствие такой записи в индексе означает, что пустых строк нет). Если необходимо посчитать, в скольких строках хранится значение , индекс на основе битовых карт позволит сделать это очень быстро. Если необходимо найти все строки, в которых в столбце хранится значение CLERK или , достаточно просто скомбинировать соответствующие битовые карты из индекса.
-- bitmap индексы drop table bt; create table bt(n number, s varchar2(100), b number, i number); select min(object_id), max(object_id), 0.5*(max(object_id)+min(object_id)) from all_objects; delete from bt; insert into bt(n, s, b, i) select object_id, object_name, case when object_id > 36116 then 1 else 2 end, case when object_id > 36116 then 1 else 2 end from all_objects; create index ibt_i on bt(i); create bitmap index ibt_b on bt(b); select index_name, index_type, table_name, status, funcidx_status from user_indexes where table_name = 'BT'; analyze table bt compute statistics for table for all indexes for all indexed columns; select i from bt where i = 1; select b from bt where b = 1; drop index ibt_i; create bitmap index ibt_i on bt(i); select * from bt where i = 0 or b = 0; select * from bt where i = 1 or b = 0; drop index ibt_i; create index ibt_i on bt(i); select /*+ index(bt ibt_b) */ * from bt where b = 1; select /*+ index(bt ibt_i) */ * from bt where i = 1; select count(*) from bt where b = 1; select count(*) from bt where i = 1; update bt set b = null where rownum < 100; update bt set i = null where rownum < 100; select * from bt where i is null; select * from bt where b is null;
Индекс-организованные таблицы - кластерные индексы, в индексе хранятся значения столбцов, выбранных для индекса, соединенные в одно значение. Индекс-организованные таблицы имеют фиктивный rowid - значение индекса. При запросе осуществляется быстрое сканирование индексов. Использование кластерных индексов способно заметно увеличить
-- индекс-организованные таблицы
drop table ih;
create table ih(p number constraint ipk primary key, s varchar2(100) null, n number null, nu number null constraint iun unique)
organization index;
select constraint_name, constraint_type, table_name, index_name from user_constraints where table_name = 'IH';
select index_name, index_type, table_name, status, funcidx_status from user_indexes where table_name = 'IH';
insert into ih(p, s, n, nu) select object_id, object_name, object_id, object_id from all_objects;
analyze table ih compute statistics for table for all indexes for all indexed columns;
commit;
select * from ih where s = 'h';
select s from ih where p = 123;
create index iind_s on ih(s);
analyze table ih compute statistics for table for all indexes for all indexed columns;
select * from ih where s = 'h';
-- фактически это не сегмент таблицы а сегмент индекса
select * from user_segments where segment_name in ('H', 'IH', 'PK', 'IPK');
-- отсутствие full table scan - вместо этого fast full scan
select * from ih;
-- отсутствие rowid в индексных таблицах
select rowid from ih where rownum < 10;
Полного сканирования таблицы при запросе, в том числе и в
Как известно, представление (
drop table h1; drop table h2; create table h1(n number primary key, s varchar2(100) null, n1 number null, s1 varchar2(100)); create table h2(n number primary key, s varchar2(100) null, n1 number null, s1 varchar2(100)); insert into h1(n, s, n1, s1) select object_id, object_name, object_id, owner from all_objects; insert into h2(n, s, n1, s1) select object_id, object_name, object_id, owner from all_objects; analyze table h1 compute statistics for table for all columns for all indexes; analyze table h2 compute statistics for table for all columns for all indexes; create view v1 as select h1.n, h1.s, h2.s1, h2.n1 from h1 inner join h2 on h1.n = h2.n and h1.s = h2.s; select * from v1 where n = 10 and s = '23423'; grant create materialized view to bor; grant query rewrite to bor; create materialized view v2 as select h1.n, h1.s, h2.s1, h2.n1 from h1 inner join h2 on h1.n = h2.n and h1.s = h2.s; select * from v2 where n = 10 and s = '23423'; create index iv on v2(n); select * from v2 where n = 10 and s = '23423';
select * from user_mviews;
select * from user_views;
select * from user_segments where segment_name in
('V1', 'V2');
create materialized view v3 as select h1.s1 s1,
count(h1.n1) n1 from h1 group by s1 having count(*) > 1;
select h1.s1 s1, count(h1.n1) n1
from h1 group by s1 having count(*) > 1;
select s1, n1 from v3;
variable v_rows number variable v_bytes number exec DBMS_MVIEW.ESTIMATE_MVIEW_SIZE (1, 'select h1.s1 s1, count(h1.n1) n1 from h1 group by s1 having count(*) > 1', :v_rows, :v_bytes); print :v_rows :v_bytes
Существует два способа формирования представления - непосредственно при его создании или отложенное, по явной команде.
drop materialized view v3;
create materialized view v3 build immediate as select h1.s1 s1,
count(h1.n1) n1 from h1 group by s1 having count(*) > 1;
create materialized view v3 build deferred as select h1.s1 s1,
count(h1.n1) n1 from h1 group by s1 having count(*) > 1;
select * from v3;
exec dbms_mview.refresh('V3');
select * from v3;
Материализованное представление может синхронизироваться с исходными данными или автоматически на момент завершения
drop materialized view v3;
create materialized view v3 build immediate refresh complete on commit as select h1.s1 s1, count(h1.n1) n1 from h1 group by s1;
insert into h1(n, s, n1, s1) values(-1, 'aaa', -1, 'aaa');
insert into h1(n, s, n1, s1) values(-2, 'aaa', -2, 'aaa');
select * from v3;
commit;
select * from v3;
drop materialized view v3;
create materialized view v3 build immediate refresh complete on commit as select h1.s1 s1, count(h1.n1) n1 from h1 group by s1 having count(*) > 1;
create materialized view v3 build immediate refresh complete on demand as select h1.s1 s1, count(h1.n1) n1 from h1 group by s1 having count(*) > 1;
insert into h1(n, s, n1, s1) values(-3, 'bbb', -3, 'bbb');
insert into h1(n, s, n1, s1) values(-4, 'bbb', -4, 'bbb');
commit;
exec dbms_mview.refresh('V3', 'F' /* ? C */);
drop materialized view v3;
create materialized view v3 build immediate refresh complete start with '17-MAY-2004' next sysdate+1 as select h1.s1 s1, count(h1.n1) n1 from h1 group by s1 having count(*) > 1;
@?/rdbms/admin/utlxmv.sql
set linesize 200
column statement_id format a15
column mvowner format a5
column mvname format a10
column statement_id format a3
column related_text format a10
column msgtxt format a60
exec dbms_mview.explain_mview('v3', '111');
select * from mv_capabilities_table;
exec dbms_mview.explain_mview('select h1.s1 s1, count(h1.n1) n1 from h1 group by s1', '222');
select * from mv_capabilities_table where statement_id = 222;
Существует два основных способа обновления материализованных представлений
drop materialized view v3;
create materialized view v3 build immediate refresh complete as select h1.s1 s1, count(h1.n1) n1 from h1 group by s1 having count(*) > 1;
insert into h1(n, s, n1, s1) values(-1, 'aaa', -1, 'aaa');
insert into h1(n, s, n1, s1) values(-2, 'aaa', -2, 'aaa');
commit;
exec dbms_mview.refresh('v3');
select * from v3;
drop materialized view v3;
create materialized view v3 refresh fast as select h1.s1 s1, count(h1.n1) n1 from h1 group by s1 having count(*) > 1;
create materialized view v3 refresh fast as select h1.s1 s1, count(h1.n1) n1 from h1 group by s1;
create materialized view v3 refresh fast as select h1.s1 s1, avg(n1) n, count(h1.n1) n1 from h1 group by s1;
create materialized view v3 refresh fast as select h1.s1 s1, avg(n1) n from h1 group by s1;
create materialized view log on h1 nologging with sequence, rowid (n1, s1) including new values;
create materialized view log on h2 nologging with sequence, rowid (n1, s1) including new values;
drop materialized view v3;
create materialized view v3 refresh fast on commit as select h1.s1 s1, count(h1.n1) n1 from h1 group by s1;
insert into h1(n, s, n1, s1) values(-11, 'aaa1', -11, 'aaa1');
insert into h1(n, s, n1, s1) values(-21, 'aaa1', -21, 'aaa1');
commit;
exec dbms_mview.explain_mview('v3', '2');
select * from mv_capabilities_table where statement_id = 2;
drop materialized view v3;
exec dbms_mview.explain_mview('select h1.s1 s1, count(h1.n1) n1 from h1 group by s1', '4');
select * from mv_capabilities_table where statement_id = 4;
select * from user_segments where segment_name like 'MLOG%';
select * from user_mview_logs;
drop materialized view log on h1;
drop materialized view log on h2;
create materialized view log on h1 nologging with sequence, rowid (n, n1, s1) including new values;
create materialized view log on h2 nologging with sequence, rowid (n, n1, s1) including new values;
truncate table mv_capabilities_table;
exec dbms_mview.explain_mview('select h1.s1 s1, h2.s1 s2, h1.n n from h1, h2 where h1.n = h2.n', '5');
select * from mv_capabilities_table where statement_id = 5;
truncate table mv_capabilities_table;
exec dbms_mview.explain_mview('select h1.rowid h1_rowid, h2.rowid h2_rowid, h1.s1 s1, h2.s1 s2, h1.n n from h1, h2 where h1.n = h2.n', '5');
select * from mv_capabilities_table where statement_id = 5;
drop materialized view v3;
create materialized view v3 refresh fast as select h1.s1 s1, h2.s1 s2, h1.n n from h1, h2 where h1.n = h2.n;
create materialized view v3 refresh fast as select h1.rowid h1_rowid, h2.rowid h2_rowid, h1.s1 s1, h2.s1 s2, h1.n n from h1, h2 where h1.n = h2.n;
create materialized view v3 refresh fast on commit as select h1.s1 s1, h2.s1 s2, h1.n n from h1, h2 where h1.n = h2.n;
create materialized view v3 refresh fast on commit as select h1.rowid h1_rowid, h2.rowid h2_rowid, h1.s1 s1, h2.s1 s2, h1.n n from h1, h2 where h1.n = h2.n;
Презентация по ER-моделированию
Видео-презентация (Для проигрывания требуется Windows Media Player)
Видео-презентация (Для проигрывания требуется Windows Media Player)
Примеры к презентации
SQL-скрипты, проект и исходные коды
package org.mai806.jdbcsample;
import java.sql.*;
public class QuerySample {
public static void main(String[] args) throws Exception {
/* ======== Подключение к MS SQL Server ===== */
// Загрузка драйвера
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
// Соединение с базой данных
Connection connection = DriverManager.getConnection(
"jdbc:sqlserver://localhost:1433;databaseName=o01;",
// localhost - сервер СУБД, o01 - имя базы данных
"sa", "123"); // пользователь, пароль
/* ======== Подключение к Oracle ============
// Загрузка драйвера
Class.forName("oracle.jdbc.OracleDriver");
// Соединение с базой данных
Connection connection = DriverManager.getConnection(
"jdbc:oracle:thin:@localhost:1521:orcl",
// localhost - сервер СУБД, orcl - SID базы оракла
"o01", "o01"); // пользователь, пароль
// Создание Statement
PreparedStatement stmt = connection.prepareStatement
("select ID, NAME from PERSON where NAME like ?");
stmt.setString(1, "%S%");
// Выполнение запроса
ResultSet rs = stmt.executeQuery();
// Перебор результата выполнения запроса
while(rs.next()) {
// Пример выбора параметра по номеру или по имени
System.out.println("ID: " +
rs.getLong(1) + "; NAME="+
rs.getString("NAME"));
}
// закрытие использованных ресурсов БД
rs.close();
stmt.close();
connection.close();
}
}
package org.mai806.jdbcsample;
import java.sql.*;
import java.util.ResourceBundle;
public class StoredProcedureSample {
private static Connection connection = null;
public static void main(String[] args) throws Exception {
// Получение соединения из значений параметров в файле properties
ResourceBundle properties = ResourceBundle.getBundle("database");
Class.forName(properties.getString("driver"));
connection = DriverManager.getConnection(
properties.getString("url"),
properties.getString("user"),
properties.getString("password"));
transferAmount(1,2,100.0);
connection.close();
}
/**
* Переводит указанную сумму с одного счета на другой
* @param from счет плательщика
* @param to счет получателя
* @param amount сумма
*/
public static void transferAmount(long from, long to, double amount)
throws Exception {
// Создание Statement
CallableStatement stmt
= connection.prepareCall("{call TransferAmount(?,?,?)}");
// Установка параметров
stmt.setLong(1, from);
stmt.setLong(2, to);
stmt.setDouble(3, amount);
// Выполнение процедуры
stmt.execute();
}
}
package org.mai806.jdbcsample;
import java.sql.*;
import java.util.ResourceBundle;
public class TransactionalSample {
private static Connection connection = null;
public static void main(String[] args) throws Exception {
// Получение соединения из значений параметров в файле properties
ResourceBundle properties = ResourceBundle.getBundle("database");
Class.forName(properties.getString("driver"));
connection = DriverManager.getConnection(
properties.getString("url"),
properties.getString("user"),
properties.getString("password"));
// Ручное управление транзакциями
connection.setAutoCommit(false);
try {
transferAmount(2, 1, 10.0);
} finally {
connection.close();
}
}
/**
* Переводит указанную сумму с одного счета на другой
* @param from счет плательщика
* @param to счет получателя
* @param amount сумма
*/
public static void transferAmount(long from, long to,
double amount) throws Exception {
PreparedStatement stmt = null;
Statement query = null;
try {
stmt = connection.prepareStatement
("update ACCOUNT set AMOUNT=AMOUNT+? where ID=?");
// Забираем сумму со счета плательщика
stmt.setDouble(1, -amount);
stmt.setLong(2, from);
stmt.execute();
// Добавляем сумму на счет получателя
stmt.setDouble(1, amount);
stmt.setLong(2, to);
stmt.execute();
// Пост-проверка: отрицательность счета плательщика
query = connection.createStatement();
ResultSet rs = query.executeQuery(
"select AMOUNT from ACCOUNT where ID="+from+" and AMOUNT<0");
if (rs.next()) {
throw new Exception("На счете №"+from+"
недосточно средств ["+(amount+rs.getDouble(1))+"]
для снятия суммы ["+amount+"]");
}
connection.commit();
System.out.println("Перечисление средств успешно выполнено");
} catch(Exception e) {
e.printStackTrace();
connection.rollback();
} finally {
if (stmt!=null)
stmt.close();
if (query!=null)
query.close();
}
}
}
Все
На первой фазе запрос, заданный на
На второй фазе запрос во внутреннем представлении подвергается логической
Третий этап обработки запроса состоит в выборе на основе информации, которой располагает оптимизатор, набора альтернативных процедурных
На четвертом этапе по внутреннему представлению наиболее
Наконец, на пятом этапе обработки запроса происходит его реальное выполнение.

Одним из основных преимуществ реляционных
Функция оптимизатора - выбрать наиболее
В
CBO управляется optimizer_mode, который может указываться на уровне сессии или на уровне экземпляра. Он может иметь следующие значения.
optimizer_mode = (был заморожен в версии 7), RBO, например, не умеет пользоваться индексами.
optimizer_mode = all_rows - CBO, выбирает план выполнения с оптимальной стоимостью, режим работы оптимизатора по умолчанию.
optimizer_mode = first_rows - CBO, вычисляется
optimizer_mode = - all_rows, а если ни по одной из таблиц нет, то - . Если RBO не поддерживает -индексы), то используется CBO. CBO может оптимизировать запросы по таблицам, по которым не собрана
optimizer_mode = first_rows_1, first_rows_10, first_rows_1000 - при использовании first_rows first_rows_n вычисляет n строк, а
Пример:
alter session set optimizer_mode= first_rows;
Отсутствие ) таблицы, число возможных значений столбца и распределение данных. ) и распределения данных для каждой таблицы, индекса и материализованного представления. DBMS_STATS. Статистические данные можно собирать либо путем чтения всех строк, либо путем проведения оценки на основе чтения только небольшой выборки строк или блоков. В пакете DBMS_STATS предлагаются процедуры для сбора
analyze table t compute statistics for table for all indexes for all columns; analyze table t compute statistics for table for all indexes for all indexed columns; analyze table t compute statistics for table for columns i, s; analyze index t_i compute statistics for table for all indexes for all columns; analyze table t estimate statistics for table for all indexes for all columns sample 10 rows; analyze table t estimate statistics for table for all indexes for all columns sample 10 percent; analyze table t compute statistics for table for all indexes for all columns size 100; analyze table t compute statistics for table for columns i size 100, s size 200;
execute dbms_stats.gather_index_stats(ownname=>'stud',
indname=>'i', partname=>null, estimate_percent=>50, stattab=>null, statid=>null, statown=>null);
execute dbms_stats.gather_table_stats(ownname=>'stud',
tabname=>'t', partname=>null, estimate_percent=>50, block_sample=>false,
method_opt=>'FOR ALL COLUMNS', degree=>null,
cascade=>true, stattab=>null, statid=>null, statown=>null);
execute dbms_stats.gather_table_stats(ownname=>'stud',
tabname=>'t', partname=>null, estimate_percent=>50, block_sample=>false,
method_opt=>'FOR COLUMNS object_name, object_id',
degree=>null, cascade=>true, stattab=>null,
statid=>null, statown=>null);
execute dbms_stats.gather_schema_stats(ownname=>'stud',
estimate_percent=>50, block_sample=>false, method_opt=>'FOR ALL COLUMNS',
degree=>null, cascade=>true, stattab=>null, statid=>null, statown=>null);
execute dbms_stats.delete_index_stats(ownname=>'stud',
indname=>'i', partname=>null, stattab=>null, statid=>null, statown=>null);
execute dbms_stats.delete_table_stats(ownname=>'stud',
tabname=>'t', partname=>null, stattab=>null, statid=>null,
statown=>null, cascade_parts=>true, cascade_columns=>true);
execute dbms_stats.delete_schema_stats(ownname=>'stud', stattab=>null,
statid=>null, statown=>null);
Данные по статистике таблиц можно посмотреть в словаре USER_TABLES. Основная
Пример:
select * from user_tables where table_name = 'T';
analyze table t delete statistics;
select num_rows, blocks, empty_blocks, avg_space,
chain_cnt, avg_row_len, avg_space_freelist_blocks,
num_freelist_blocks, sample_size, last_analyzed from user_tables
where table_name = 'T';
analyze table t compute statistics for table;
select num_rows, blocks, empty_blocks, avg_space,
chain_cnt, avg_row_len, avg_space_freelist_blocks,
num_freelist_blocks, sample_size, last_analyzed from user_tables
where table_name = 'T';
USER_INDEXES. Основная
Пример:
analyze table t delete statistics;
select blevel, leaf_blocks, distinct_keys,
avg_leaf_blocks_per_key, avg_data_blocks_per_key,
clustering_factor, num_rows, sample_size,
last_analyzed from user_indexes
where table_name = 'T' and index_name = 'T_I';
analyze table t compute statistics for all indexes;
select blevel, leaf_blocks, distinct_keys,
avg_leaf_blocks_per_key, avg_data_blocks_per_key,
clustering_factor, num_rows, sample_size,
last_analyzed from user_indexes
where table_name = 'T' and index_name = 'T_I';
USER_TAB_COLUMNS, USER_TAB_COL_STATISTICS.
null Пример:
select * from user_tab_columns where table_name = 'T' and column_name = 'I'; select * from user_tab_col_statistics where table_name = 'T' and column_name = 'I'; analyze table t delete statistics; select * from user_tab_col_statistics where table_name = 'T' and column_name = 'I'; analyze table t compute statistics for all columns; select * from user_tab_col_statistics where table_name = 'T' and column_name = 'I';
Данная
Сбалансированные по
Пример:
analyze table t compute statistics for columns s size 254;
select endpoint_number, endpoint_value,
substr(endpoint_actual_value, 1, 30)
from user_tab_histograms where table_name =
'T' and column_name = 'S';
analyze table t compute statistics for columns s size 8;
select endpoint_number, endpoint_value,
substr(endpoint_actual_value, 1, 30)
from user_tab_histograms where table_name =
'T' and column_name = 'S';
analyze table t compute statistics for columns s size 254;
select endpoint_number, endpoint_value,
substr(endpoint_actual_value, 1, 30)
from user_tab_histograms where table_name =
'T' and column_name = 'S';
select s, count(*) from t group by s;
-- создание объектов drop table h; -- create table h(p number constraint pk primary key, s varchar2(100) null, n number null, nu number null constraint un unique); create table h(p number, s varchar2(100) null, n number null, nu number null);
Для >25-30% записей в таблице. Возникает проблема
-- полное сканирование таблицы. high water mark insert into h select -rownum, object_name, object_id, object_id from all_objects where rownum < 100; insert into h select rownum, object_name, object_id, object_id from all_objects; select * from h where p < 0; analyze table h compute statistics for table for all columns for all indexes; select num_rows, blocks, empty_blocks from user_tables where table_name = 'H'; delete from h where p > 0;
Индексы на основе В*-

Блоки самого нижнего уровня в индексе, которые называют листовыми вершинами, содержат все проиндексированные rid на схеме), ссылающиеся на соответствующие строки. Промежуточные блоки над листовыми вершинами называют блоками
where x between 20 and 30
-- индексы
-- структура индекса, rowid
truncate table h;
insert into h select rownum, object_name,
object_id, object_id from all_objects where rownum < 10;
commit;
select rowid, p from h;
select * from h where rowid =
'AAAN95AAEAAAAfHAAA';
declare
r_t number;
o_n number;
f_n number;
b_n number;
r_n number;
r rowid;
begin
select rowid into r from h where rownum < 2;
dbms_rowid.rowid_info(r, r_t, o_n, f_n, b_n, r_n);
dbms_output.put_line('rowid type = ' || r_t);
dbms_output.put_line('object number = ' || o_n);
dbms_output.put_line('file number = ' || f_n);
dbms_output.put_line('block number = ' || b_n);
dbms_output.put_line('row number = ' || r_n);
end;
select * from user_objects where object_name = 'H';
select * from user_tables where table_name = 'H';
select * from dba_data_files;
-- создание индексов
truncate table h;
insert into h select rownum, object_name, object_id, object_id from all_objects;
commit;
create index ind_s on h(s);
select * from user_indexes where table_name = 'H';
drop index ind_s;
select * from user_indexes where table_name = 'H';
create index ind_s_1 on h(s desc);
create unique index ind_n on h(n);
select index_name, index_type, table_name, status, funcidx_status from user_indexes where table_name = 'H';
-- информация по таблицам и индексам
select * from user_tables;
select * from user_tab_columns;
select * from user_constraints;
select * from user_cons_columns;
select * from user_indexes;
select * from user_ind_columns;
analyze table h compute statistics for table for all indexes for all indexed columns; set autotrace on set timing on -- операции по индексу drop index ind_s on h(s); select * from h where s = 'aaaa'; create index ind_s on h(s); select * from h where s = 'aaaa'; select * from h where s||'a' = 'aaaa'; select * from h where upper(s) = 'aaaa'; select * from h where s like 'aaaa%'; select * from h where s like '%aaaa'; drop index ind_nu; select * from h where nu = 1222; create index ind_nu on h(nu); select * from h where nu = 1222; select * from h where nu+1 = 1222; select * from h where nu = 1222+1; select * from h where abs(nu) = 1222; select * from h where s = '123'; select * from h where s = 123; -- выбор между доступом по индексам и full scan delete from h; insert into h(p, s, n, nu) select object_id, object_name, object_id, object_id from all_objects where rownum < 5; analyze table h compute statistics for table for all indexes for all indexed columns; select * from h where s = 'DUAL'; delete from h; insert into h(p, s, n, nu) select object_id, object_name, object_id, object_id from all_objects; -- со старой статистикой !!! select * from h where s = 'DUAL'; analyze table h compute statistics for table for all indexes for all indexed columns; -- с новой статистикой !!! select * from h where s = 'DUAL'; -- обработка null значений -- поля null не проверяются на уникальность insert into h(p, s, n, nu) values(-1, 'asd', null, null); insert into h(p, s, n, nu) values(-2, 'asd', null, null); insert into h(p, s, n, nu) values(-3, 'asd', null, -1); select * from h where s is null;
Индексы по функции. Эти индексы на основе В*-
SELECT * FROM T WHERE ФУНКЦИЯ(СТОЛБЕЦ) = НЕКОТОРОЕ_ЗНАЧЕНИЕ,
поскольку значение ФУНКЦИЯ(СТОЛБЕЦ) уже вычислено и хранится в индексе.
-- функциональные индексы select * from h where n*n = 100; -- надо иметь такие права для создания функциональных индексов alter system set query_rewrite_enabled=true; grant query rewrite to stud; create index ind_f_n on h(n*n); select * from h where n*n = 100; create index ind_n on h(n); select index_name, index_type, table_name, status, funcidx_status from user_indexes where table_name = 'H'; select * from h where n = 100; select * from h where n > 0;
Обычно в В*-Y, N и , — в таблице с миллионом строк очень хорошо подходит для в таблице ЕМР:
create BITMAP index job_idx on emp(job);
Сервер

Это показывает, что в строках 8, 10 и 13 находится значение , тогда как в строках 4, 6 и 7 — значение . Также понятно, что пустых строк нет (индексы на основе битовых карт содержат записи для пустых значений — отсутствие такой записи в индексе означает, что пустых строк нет). Если необходимо посчитать, в скольких строках хранится значение , индекс на основе битовых карт позволит сделать это очень быстро. Если необходимо найти все строки, в которых в столбце хранится значение CLERK или , достаточно просто скомбинировать соответствующие битовые карты из индекса.
-- bitmap индексы drop table bt; create table bt(n number, s varchar2(100), b number, i number); select min(object_id), max(object_id), 0.5*(max(object_id)+min(object_id)) from all_objects; delete from bt; insert into bt(n, s, b, i) select object_id, object_name, case when object_id > 36116 then 1 else 2 end, case when object_id > 36116 then 1 else 2 end from all_objects; create index ibt_i on bt(i); create bitmap index ibt_b on bt(b); select index_name, index_type, table_name, status, funcidx_status from user_indexes where table_name = 'BT'; analyze table bt compute statistics for table for all indexes for all indexed columns; select i from bt where i = 1; select b from bt where b = 1; drop index ibt_i; create bitmap index ibt_i on bt(i); select * from bt where i = 0 or b = 0; select * from bt where i = 1 or b = 0; drop index ibt_i; create index ibt_i on bt(i); select /*+ index(bt ibt_b) */ * from bt where b = 1; select /*+ index(bt ibt_i) */ * from bt where i = 1; select count(*) from bt where b = 1; select count(*) from bt where i = 1; update bt set b = null where rownum < 100; update bt set i = null where rownum < 100; select * from bt where i is null; select * from bt where b is null;
Индекс-организованные таблицы - кластерные индексы, в индексе хранятся значения столбцов, выбранных для индекса, соединенные в одно значение. Индекс-организованные таблицы имеют фиктивный rowid - значение индекса. При запросе осуществляется быстрое сканирование индексов. Использование кластерных индексов способно заметно увеличить
-- индекс-организованные таблицы
drop table ih;
create table ih(p number constraint ipk primary key, s varchar2(100) null, n number null, nu number null constraint iun unique)
organization index;
select constraint_name, constraint_type, table_name, index_name from user_constraints where table_name = 'IH';
select index_name, index_type, table_name, status, funcidx_status from user_indexes where table_name = 'IH';
insert into ih(p, s, n, nu) select object_id, object_name, object_id, object_id from all_objects;
analyze table ih compute statistics for table for all indexes for all indexed columns;
commit;
select * from ih where s = 'h';
select s from ih where p = 123;
create index iind_s on ih(s);
analyze table ih compute statistics for table for all indexes for all indexed columns;
select * from ih where s = 'h';
-- фактически это не сегмент таблицы а сегмент индекса
select * from user_segments where segment_name in ('H', 'IH', 'PK', 'IPK');
-- отсутствие full table scan - вместо этого fast full scan
select * from ih;
-- отсутствие rowid в индексных таблицах
select rowid from ih where rownum < 10;
Полного сканирования таблицы при запросе, в том числе и в
Как известно, представление (
drop table h1; drop table h2; create table h1(n number primary key, s varchar2(100) null, n1 number null, s1 varchar2(100)); create table h2(n number primary key, s varchar2(100) null, n1 number null, s1 varchar2(100)); insert into h1(n, s, n1, s1) select object_id, object_name, object_id, owner from all_objects; insert into h2(n, s, n1, s1) select object_id, object_name, object_id, owner from all_objects; analyze table h1 compute statistics for table for all columns for all indexes; analyze table h2 compute statistics for table for all columns for all indexes; create view v1 as select h1.n, h1.s, h2.s1, h2.n1 from h1 inner join h2 on h1.n = h2.n and h1.s = h2.s; select * from v1 where n = 10 and s = '23423'; grant create materialized view to bor; grant query rewrite to bor; create materialized view v2 as select h1.n, h1.s, h2.s1, h2.n1 from h1 inner join h2 on h1.n = h2.n and h1.s = h2.s; select * from v2 where n = 10 and s = '23423'; create index iv on v2(n); select * from v2 where n = 10 and s = '23423';
select * from user_mviews;
select * from user_views;
select * from user_segments where segment_name in
('V1', 'V2');
create materialized view v3 as select h1.s1 s1,
count(h1.n1) n1 from h1 group by s1 having count(*) > 1;
select h1.s1 s1, count(h1.n1) n1
from h1 group by s1 having count(*) > 1;
select s1, n1 from v3;
variable v_rows number variable v_bytes number exec DBMS_MVIEW.ESTIMATE_MVIEW_SIZE (1, 'select h1.s1 s1, count(h1.n1) n1 from h1 group by s1 having count(*) > 1', :v_rows, :v_bytes); print :v_rows :v_bytes
Существует два способа формирования представления - непосредственно при его создании или отложенное, по явной команде.
drop materialized view v3;
create materialized view v3 build immediate as select h1.s1 s1,
count(h1.n1) n1 from h1 group by s1 having count(*) > 1;
create materialized view v3 build deferred as select h1.s1 s1,
count(h1.n1) n1 from h1 group by s1 having count(*) > 1;
select * from v3;
exec dbms_mview.refresh('V3');
select * from v3;
Материализованное представление может синхронизироваться с исходными данными или автоматически на момент завершения
drop materialized view v3;
create materialized view v3 build immediate refresh complete on commit as select h1.s1 s1, count(h1.n1) n1 from h1 group by s1;
insert into h1(n, s, n1, s1) values(-1, 'aaa', -1, 'aaa');
insert into h1(n, s, n1, s1) values(-2, 'aaa', -2, 'aaa');
select * from v3;
commit;
select * from v3;
drop materialized view v3;
create materialized view v3 build immediate refresh complete on commit as select h1.s1 s1, count(h1.n1) n1 from h1 group by s1 having count(*) > 1;
create materialized view v3 build immediate refresh complete on demand as select h1.s1 s1, count(h1.n1) n1 from h1 group by s1 having count(*) > 1;
insert into h1(n, s, n1, s1) values(-3, 'bbb', -3, 'bbb');
insert into h1(n, s, n1, s1) values(-4, 'bbb', -4, 'bbb');
commit;
exec dbms_mview.refresh('V3', 'F' /* ? C */);
drop materialized view v3;
create materialized view v3 build immediate refresh complete start with '17-MAY-2004' next sysdate+1 as select h1.s1 s1, count(h1.n1) n1 from h1 group by s1 having count(*) > 1;
@?/rdbms/admin/utlxmv.sql
set linesize 200
column statement_id format a15
column mvowner format a5
column mvname format a10
column statement_id format a3
column related_text format a10
column msgtxt format a60
exec dbms_mview.explain_mview('v3', '111');
select * from mv_capabilities_table;
exec dbms_mview.explain_mview('select h1.s1 s1, count(h1.n1) n1 from h1 group by s1', '222');
select * from mv_capabilities_table where statement_id = 222;
Существует два основных способа обновления материализованных представлений
drop materialized view v3;
create materialized view v3 build immediate refresh complete as select h1.s1 s1, count(h1.n1) n1 from h1 group by s1 having count(*) > 1;
insert into h1(n, s, n1, s1) values(-1, 'aaa', -1, 'aaa');
insert into h1(n, s, n1, s1) values(-2, 'aaa', -2, 'aaa');
commit;
exec dbms_mview.refresh('v3');
select * from v3;
drop materialized view v3;
create materialized view v3 refresh fast as select h1.s1 s1, count(h1.n1) n1 from h1 group by s1 having count(*) > 1;
create materialized view v3 refresh fast as select h1.s1 s1, count(h1.n1) n1 from h1 group by s1;
create materialized view v3 refresh fast as select h1.s1 s1, avg(n1) n, count(h1.n1) n1 from h1 group by s1;
create materialized view v3 refresh fast as select h1.s1 s1, avg(n1) n from h1 group by s1;
create materialized view log on h1 nologging with sequence, rowid (n1, s1) including new values;
create materialized view log on h2 nologging with sequence, rowid (n1, s1) including new values;
drop materialized view v3;
create materialized view v3 refresh fast on commit as select h1.s1 s1, count(h1.n1) n1 from h1 group by s1;
insert into h1(n, s, n1, s1) values(-11, 'aaa1', -11, 'aaa1');
insert into h1(n, s, n1, s1) values(-21, 'aaa1', -21, 'aaa1');
commit;
exec dbms_mview.explain_mview('v3', '2');
select * from mv_capabilities_table where statement_id = 2;
drop materialized view v3;
exec dbms_mview.explain_mview('select h1.s1 s1, count(h1.n1) n1 from h1 group by s1', '4');
select * from mv_capabilities_table where statement_id = 4;
select * from user_segments where segment_name like 'MLOG%';
select * from user_mview_logs;
drop materialized view log on h1;
drop materialized view log on h2;
create materialized view log on h1 nologging with sequence, rowid (n, n1, s1) including new values;
create materialized view log on h2 nologging with sequence, rowid (n, n1, s1) including new values;
truncate table mv_capabilities_table;
exec dbms_mview.explain_mview('select h1.s1 s1, h2.s1 s2, h1.n n from h1, h2 where h1.n = h2.n', '5');
select * from mv_capabilities_table where statement_id = 5;
truncate table mv_capabilities_table;
exec dbms_mview.explain_mview('select h1.rowid h1_rowid, h2.rowid h2_rowid, h1.s1 s1, h2.s1 s2, h1.n n from h1, h2 where h1.n = h2.n', '5');
select * from mv_capabilities_table where statement_id = 5;
drop materialized view v3;
create materialized view v3 refresh fast as select h1.s1 s1, h2.s1 s2, h1.n n from h1, h2 where h1.n = h2.n;
create materialized view v3 refresh fast as select h1.rowid h1_rowid, h2.rowid h2_rowid, h1.s1 s1, h2.s1 s2, h1.n n from h1, h2 where h1.n = h2.n;
create materialized view v3 refresh fast on commit as select h1.s1 s1, h2.s1 s2, h1.n n from h1, h2 where h1.n = h2.n;
create materialized view v3 refresh fast on commit as select h1.rowid h1_rowid, h2.rowid h2_rowid, h1.s1 s1, h2.s1 s2, h1.n n from h1, h2 where h1.n = h2.n;
Презентация по ER-моделированию
Видео-презентация (Для проигрывания требуется Windows Media Player)
Видео-презентация (Для проигрывания требуется Windows Media Player)
Примеры к презентации
SQL-скрипты, проект и исходные коды
package org.mai806.jdbcsample;
import java.sql.*;
public class QuerySample {
public static void main(String[] args) throws Exception {
/* ======== Подключение к MS SQL Server ===== */
// Загрузка драйвера
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
// Соединение с базой данных
Connection connection = DriverManager.getConnection(
"jdbc:sqlserver://localhost:1433;databaseName=o01;",
// localhost - сервер СУБД, o01 - имя базы данных
"sa", "123"); // пользователь, пароль
/* ======== Подключение к Oracle ============
// Загрузка драйвера
Class.forName("oracle.jdbc.OracleDriver");
// Соединение с базой данных
Connection connection = DriverManager.getConnection(
"jdbc:oracle:thin:@localhost:1521:orcl",
// localhost - сервер СУБД, orcl - SID базы оракла
"o01", "o01"); // пользователь, пароль
// Создание Statement
PreparedStatement stmt = connection.prepareStatement
("select ID, NAME from PERSON where NAME like ?");
stmt.setString(1, "%S%");
// Выполнение запроса
ResultSet rs = stmt.executeQuery();
// Перебор результата выполнения запроса
while(rs.next()) {
// Пример выбора параметра по номеру или по имени
System.out.println("ID: " +
rs.getLong(1) + "; NAME="+
rs.getString("NAME"));
}
// закрытие использованных ресурсов БД
rs.close();
stmt.close();
connection.close();
}
}
package org.mai806.jdbcsample;
import java.sql.*;
import java.util.ResourceBundle;
public class StoredProcedureSample {
private static Connection connection = null;
public static void main(String[] args) throws Exception {
// Получение соединения из значений параметров в файле properties
ResourceBundle properties = ResourceBundle.getBundle("database");
Class.forName(properties.getString("driver"));
connection = DriverManager.getConnection(
properties.getString("url"),
properties.getString("user"),
properties.getString("password"));
transferAmount(1,2,100.0);
connection.close();
}
/**
* Переводит указанную сумму с одного счета на другой
* @param from счет плательщика
* @param to счет получателя
* @param amount сумма
*/
public static void transferAmount(long from, long to, double amount)
throws Exception {
// Создание Statement
CallableStatement stmt
= connection.prepareCall("{call TransferAmount(?,?,?)}");
// Установка параметров
stmt.setLong(1, from);
stmt.setLong(2, to);
stmt.setDouble(3, amount);
// Выполнение процедуры
stmt.execute();
}
}
package org.mai806.jdbcsample;
import java.sql.*;
import java.util.ResourceBundle;
public class TransactionalSample {
private static Connection connection = null;
public static void main(String[] args) throws Exception {
// Получение соединения из значений параметров в файле properties
ResourceBundle properties = ResourceBundle.getBundle("database");
Class.forName(properties.getString("driver"));
connection = DriverManager.getConnection(
properties.getString("url"),
properties.getString("user"),
properties.getString("password"));
// Ручное управление транзакциями
connection.setAutoCommit(false);
try {
transferAmount(2, 1, 10.0);
} finally {
connection.close();
}
}
/**
* Переводит указанную сумму с одного счета на другой
* @param from счет плательщика
* @param to счет получателя
* @param amount сумма
*/
public static void transferAmount(long from, long to,
double amount) throws Exception {
PreparedStatement stmt = null;
Statement query = null;
try {
stmt = connection.prepareStatement
("update ACCOUNT set AMOUNT=AMOUNT+? where ID=?");
// Забираем сумму со счета плательщика
stmt.setDouble(1, -amount);
stmt.setLong(2, from);
stmt.execute();
// Добавляем сумму на счет получателя
stmt.setDouble(1, amount);
stmt.setLong(2, to);
stmt.execute();
// Пост-проверка: отрицательность счета плательщика
query = connection.createStatement();
ResultSet rs = query.executeQuery(
"select AMOUNT from ACCOUNT where ID="+from+" and AMOUNT<0");
if (rs.next()) {
throw new Exception("На счете №"+from+"
недосточно средств ["+(amount+rs.getDouble(1))+"]
для снятия суммы ["+amount+"]");
}
connection.commit();
System.out.println("Перечисление средств успешно выполнено");
} catch(Exception e) {
e.printStackTrace();
connection.rollback();
} finally {
if (stmt!=null)
stmt.close();
if (query!=null)
query.close();
}
}
}
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.