Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
157 changes: 157 additions & 0 deletions labs/lab_6.sql
Original file line number Diff line number Diff line change
@@ -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;