diff --git a/labs/lab_6.sql b/labs/lab_6.sql new file mode 100644 index 0000000..5208df7 --- /dev/null +++ b/labs/lab_6.sql @@ -0,0 +1,157 @@ +-- 1. +create database "padii_plyugin"; + +-- 2. +create schema schema1; + +-- 3. +create table schema1.test ( + name varchar(20) not null, + price numeric(5,2) null +); + +-- a) +select pg_relation_filepath('schema1.test'::regclass); +-- Функция возвращает относительный путь внутри каталога данных PostgreSQL: +-- сначала каталог базы (его OID), затем имя файла, соответствующее этой таблице. + +-- b) +select oid, relfilenode, reltablespace, reltoastrelid +from pg_class +where relname = 'test' and relnamespace = ( + select oid from pg_namespace where nspname='schema1' +); +-- oid — внутренний идентификатор записи в каталоге +-- relfilenode — номер базового файлового объекта на диске, в котором сейчас хранятся данные таблицы; +-- при создании обычно совпадает с oid, но в принципе может меняться (после CLUSTER/REINDEX). +-- reltablespace — OID табличного пространства для этой таблицы; значение 0 означает, что используется +-- табличное пространство по умолчанию для данной базы данных. +-- reltoastrelid — OID связанной TOAST-таблицы для хранения очень длинных значений; +-- если здесь 0, значит отдельная TOAST-таблица пока не нужна. + +-- c) +insert into schema1.test (name, price) values ('Apple', 1.52); +insert into schema1.test (name, price) values ('Orange', 4.097); +insert into schema1.test (name, price) values ('Peach', 9.5234); +insert into schema1.test (name, price) values ('Banana', 2.2); + +-- d) +select * from schema1.test; +-- Столбец объявлен как NUMERIC(5,2), поэтому значения автоматически округляются до двух знаков +-- после запятой. При обычном выводе клиент может не +-- дописывать незначащие нули (например, показывать 2.2 вместо 2.20). + +select name, to_char(price, 'FM999.00') as price_formatted +from schema1.test; +-- Форматирование выводит ровно два знака после запятой, поэтому здесь все цены будут показаны в виде XX.XX, включая нули. + +-- e) +update schema1.test set price='NaN' where name='Peach'; + +select * from schema1.test; + +-- f) +select name, price +from schema1.test +order by price desc; +-- В PostgreSQL для типа NUMERIC значение NaN в упорядочивании считается больше любого +-- обычного числа. Поэтому при сортировке по убыванию строка с NaN поднимается наверх + +-- 4. +create temp table tmp_test as +select * +from schema1.test; +-- Временная таблица попадает не в schema1, а в специальную временную схему, +-- которая доступна только в текущей сессии. + +-- a) +select c1.oid, c1.reltoastrelid, c2.relname +from pg_class as c1 + left join pg_class as c2 + on c1.reltoastrelid = c2.oid +where c1.relname = 'tmp_test'; +-- На этом этапе reltoastrelid = 0, значит отдельная TOAST-таблица для tmp_test ещё не создана: +-- все значения помещаются прямо в строках основной таблицы. + +-- b) Добавляем вычисляемый столбец со скидкой 20% +alter table tmp_test + add column price_discount numeric(5,2) + generated always as (price * 0.8) stored; +-- Вычисляемый столбец со свойством GENERATED ALWAYS AS ... STORED пересчитывается сервером +-- автоматически при изменении исходной цены и физически хранит уже готовое значение со скидкой. + +-- c) +alter table tmp_test +alter column name type text; + +-- d) +select c1.oid, c1.reltoastrelid, c2.relname +from pg_class as c1 + left join pg_class as c2 + on c1.reltoastrelid = c2.oid +where c1.relname = 'tmp_test'; +-- После изменения типа на text в reltoastrelid появляется ненулевое значение, указывающее +-- на запись с именем вида pg_toast_... — для tmp_test создана отдельная TOAST-таблица, так +-- как поля типа text могут содержать очень длинные значения, которые выносятся за пределы +-- основной строки. + +-- e) +alter table tmp_test +alter column name type varchar(30); + +-- f) +select c1.oid, c1.reltoastrelid, c2.relname +from pg_class as c1 + left join pg_class as c2 + on c1.reltoastrelid = c2.oid +where c1.relname = 'tmp_test'; +-- При переходе к varchar(30) максимальная длина значения становится небольшой, и PostgreSQL +-- может обойтись без отдельной TOAST-таблицы: reltoastrelid снова становится равен 0, все +-- данные (и name, и price_discount) помещаются в строке самой таблицы. + +-- g) +select * from tmp_test; + +-- h) +select relname as temp_table +from pg_class +where relpersistence = 't'; +-- relpersistence = 't' означает временные таблицы текущей сессии. Такие таблицы живут только +-- пока открыто данное соединение. В новом подключении tmp_test уже недоступна, и в этом списке +-- её не будет. + +-- 5. +create unlogged table schema1.teacher ( + teacher_id serial not null, + first_name varchar null, + last_name varchar not null, + birthday date not null, + phone varchar null, + title varchar null +); +-- UNLOGGED-таблица не пишет данные в WAL-журнал, за счет чего операции записи выполняются +-- быстрее, но такая таблица менее надежна: после аварийного завершения сервера данные могут +-- быть потеряны. + +-- a +alter table schema1.teacher + add column middle_name varchar(50); + +-- b) +alter table schema1.teacher +drop column middle_name; + +-- c) +alter table schema1.teacher + rename column birthday to birth_date; + +-- d) +alter table schema1.teacher +alter column phone type bigint[] +using array[phone::bigint]; +-- USING задает способ преобразования старых значений: указанное выражение берёт строковый телефон, +-- приводит его к bigint и оборачивает в массив из одного элемента. + +-- 6. +drop table schema1.teacher; +drop table schema1.test;