В этом уроке мы поработаем с таблицами: будем создавать их, добавлять, модифицировать и удалять данные. Также разберем типы данных таблицы.
Создание базы данных
Прежде чем создать таблицу, создадим базу данных hexlet с помощью SQL (если вы еще этого не сделали). Для этого подключитесь к СУБД через psql. При этом не указывайте базу данных, чтобы подключиться к базе по умолчанию. Далее выполните следующие запросы:
В примере выше два SQL запроса:
Базовые правила построения запросов:
-
Каждый запрос должен заканчиваться точкой с запятой. Иначе psql будет думать, что вы продолжаете вводить команды
-
Регистр не важен. Можно было написать drop database hexlet;. По традиции принято использовать верхний регистр для ключевых слов самого SQL. Это позволяет визуально разделять структуру запроса от данных внутри него. Последнее в примере — это имя базы данных, которое может быть произвольным
Если подключиться к той же базе данных, которую вы хотите удалить или пересоздать, то во время попытки удаления СУБД будет ругаться, что к базе есть активное соединение — ваше соединение. Поэтому важно подключиться к любой другой базе данных.
Команды createdb и createuser, которые мы разобрали в прошлых уроках, выполняют SQL-запросы внутри СУБД. Их сделали ради удобства первоначальной настройки, и чтобы использовать в скриптах автоматизации.
SQL поддерживает комментарии — строчка, которая начинается с двух дефисов. Комментарии игнорируются СУБД при построении запросов:
Нам удалось создать базу данных hexlet, поэтому можно переходить к созданию таблицы. Подключитесь к созданной базе данных
Создание таблиц
Таблица создается с помощью запроса CREATE TABLE:
Чтобы создать таблицу, необходимо указать ее имя, набор полей и их типы. В примере выше названия полей — это name, slug, lessons_count и body, а varchar(255), integer и text — их типы.
Типы данных
У каждого поля в PostgreSQL определенный тип, который задается на этапе создания таблицы. Это значит, что значением этого поля могут быть только определенные данные. Если поле имеет числовой тип, то в него невозможно вставить строку, и наоборот. База данных выдаст ошибку при попытке выполнить подобный запрос.
В PostgreSQL встроено много различных типов данных, но на практике используются не все. Ниже мы разбираем только самые популярные типы.
Строки
Для строк в базах данных в основном используются два типа:
-
varchar — для строк с ограничением максимальной длины
-
text — для строк без ограничения. Как правило, это полноценные тексты
В базах данных нельзя оставить первый тип без указания длины. Это связано с производительностью и эффективностью. Данные в базах данных физически хранятся на дисках в файлах. Быстрый доступ к этим данным возможен только тогда, когда у данных фиксированный размер. Это позволяет быстро перемещаться по ним и считать смещения.
Если размер данных не известен, то придется просматривать весь файл в поисках нужного значения. Чтобы избежать подобной ситуации, тип text хранится отдельно. Это тоже негативно влияет на скорость, но уже не так сильно. Если размер строки известен или он меньше какого-то значения, то предпочтительнее использовать varchar.
-
varchar. Полное название типа character varying (varchar может использоваться как псевдоним). Размер строки с таким типом указывается в скобках после названия типа, например, varchar(10). Это значит, что в поле с таким типом можно записать строку длиной до 10 символов.
-
text. Не требует указания размера и может содержать текст произвольной длины
Пример создания таблицы с такими типами:
Числа
Для чисел в основном используются два типа данных: integer и bigint. Какой конкретно указывать тип, зависит от потенциального потолка значения. Ниже указаны диапазоны, допустимые в рамках этих типов:
Пример создания таблицы с такими типами:
Даты
Типы для хранения дат отличаются друг от друга очень сильно, в первую очередь по решаемой задаче. Нам надо хранить день без конкретного времени? Это тип date. Нужно конкретный момент времени, тогда timestamp. Просто время без даты? Тогда time.
Пример создания таблицы с такими типами:
Хорошей практикой считается добавление и заполнение полей created_at и updated_at в каждую таблицу базы данных. С их помощью всегда можно узнать, когда запись создалась и обновилась.
Значения даты и времени принимаются практически в любом известном формате. Вот несколько примеров того, как можно задавать дату:
Логический тип
Содержит всего два значения: true и false. Этот тип используется для флагов:
Пример создания таблицы с такими типами:
Состояние «true» может задаваться следующими значениями:
TRUE
't'
'true'
'y'
'yes'
'on'
'1'
Для состояния «false» можно использовать следующие варианты:
FALSE
'f'
'false'
'n'
'no'
'off'
'0'
NULL
Помимо типов данных для реальных значений, в базе существует специальное значение NULL, чтобы обозначать пустоту. Оно используется, когда у конкретного поля нет значения. Тип поля при этом не важен. Подробнее с NULL мы разберемся в следующих уроках.
Анализ структуры базы данных
Чтобы исследовать структуру таблиц в визуальном режиме, используется PgAdmin:
SQL для анализа структуры базы данных не существует. Если вы хотите посмотреть список таблиц и их структуру в базе данных, то придется использовать команды самого psql:
Просмотр списка таблиц базы данных hexlet
Здесь мы видим список таблиц в базе данных hexlet. Все что здесь отображается, было создано в этом уроке выше.
В первом столбце видим новое для нас понятие — schema. Это пространство имен, которое позволяет группировать таблицы в различных ситуациях. На практике эта возможность используется редко, поэтому мы не обращаем на нее внимание. По умолчанию все таблицы публикуются в общей схеме public, которую можно не указывать.
Просмотр структуры таблицы courses
В этом выводе показана структура таблицы courses. Здесь мы видим все имена полей и их типы.
Кроме перечисленных полезными могут оказаться следующие команды:
- \l — список всех баз данных
- \dt — список всех таблиц
- \? — вывод справки
Удаление таблиц
Чтобы удалить таблицу, выполняется запрос DROP:
Будьте внимательны, так как удаление таблицы приводит к безвозвратной потере данных.
Выводы
В этом уроке мы разобрали работу с таблицами: создавали базу данных и таблицу, устанавливали типы данных и анализировали структуру базы. Еще мы показали, как удалять таблицу. Попрактикуйтесь создавать таблицы — проходите каждый шаг, описанный в уроке, и со временем для вас это станет легкой задачей.
<!DOCTYPE html>
<html class="h-100" data-bs-theme="light" data-mantine-color-scheme="light" lang="ru" prefix="og: https://ogp.me/ns#">
<head>
<meta content="width=device-width, initial-scale=1.0" name="viewport">
<meta content="IE=Edge" http-equiv="X-UA-Compatible">
<link crossorigin="true" href="https://cdn.hexlet.io" rel="preconnect">
<link href="https://mc.yandex.ru" rel="preconnect">
<meta content="aa2vrdtq64dub8knuf83lwywit311w" name="facebook-domain-verification">
<link href="/favicon.ico" rel="icon" sizes="any">
<link href="/favicon.svg" rel="icon" type="image/svg+xml">
<link href="/apple-touch-icon.png" rel="apple-touch-icon">
<link href="/manifest.webmanifest" rel="manifest">
<script>
//<![CDATA[
window.gon={};gon.ym_counter="25559621";gon.is_bot=true;gon.applications={};gon.current_user={"id":null,"last_viewed_notification_id":null,"email":null,"state":null,"first_name":"","last_name":"","created_at":"2026-02-26 20:39:36 UTC","current_program":null,"current_team":null,"full_name":"","guest":true,"can_use_paid_features":false,"is_hexlet_employee":false,"sanitized_phone_number":"","can_subscribe":true,"can_renew_education":false};gon.token="UDw23mCZLK58tnc_qI2vuwuO1EAE50O-Y3KKoPFAFLy_7f3pkueBzsr1U6ekgl_My4f56gzQvRzekhD0o0fz0g";gon.locale="ru";gon.language="ru";gon.theme="light";gon.rails_env="production";gon.mobile=false;gon.google={"analytics_key":"UA-1360700-51","optimize_key":"GTM-5QDVFPF"};gon.captcha={"google_v3_site_key":"6LenGbgZAAAAAM7HbrDbn5JlizCSzPcS767c9vaY","yandex_site_key":"ysc1_Vyob5ZPPUdPBsu0ykt8bVFdzsfpoVjQChLGl2b4g19647a89","verification_failed":null};gon.social_signin=false;gon.typoreporter_google_form_id="1FAIpQLSeibfGq-KvWQ2Fyru-zkFFRVTLBuzXAHAoEyN1p49FtDmNoNA";
//]]>
</script>
<meta charset="utf-8">
<title>Создание таблиц | Основы реляционных баз данных</title>
<meta name="description" content="Создание таблиц / Основы реляционных баз данных: Учимся создавать таблицы и познакомимся с базовыми типами данных в PostgreSQL">
<link rel="canonical" href="https://ru.hexlet.io/courses/rdb-basics/lessons/sql-ddl/theory_unit">
<meta name="robots" content="noarchive">
<meta property="og:title" content="Создание таблиц">
<meta property="og:title" content="Основы реляционных баз данных">
<meta property="og:description" content="Создание таблиц / Основы реляционных баз данных: Учимся создавать таблицы и познакомимся с базовыми типами данных в PostgreSQL">
<meta property="og:url" content="https://ru.hexlet.io/courses/rdb-basics/lessons/sql-ddl/theory_unit">
<meta name="csrf-param" content="authenticity_token" />
<meta name="csrf-token" content="SPkJRRWLhohI7dppnEFbQZZveLmYWsJgSM0hvVvSs6enKMJy5_Ur6P6u_vGQTqs2VmZVE5BtPML1LbvpCdVUyQ" />
<script src="/vite/assets/inertia-DfXos102.js" crossorigin="anonymous" type="module"></script><link rel="modulepreload" href="/vite/assets/chunk-DsPFFUou.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/preload-helper-BJ4cLWpC.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/init-BrRXra1y.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/ahoy-DrlRQ-1D.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/analytics-cb8xch9l.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/ErrorFallbackBlock-naDSYSy9.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Surface-DL2bpZA-.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/gon-D3e4yh1x.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/mantine-CGMYrt2Y.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/utils-DRqSHbQE.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/routes-CCH8ilKF.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/extends-C-EagtpE.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/inheritsLoose-BBd-DCVI.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/objectWithoutPropertiesLoose-DRHXDhjp.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/index.esm-DAqKOkZ0.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Button-CGPUux8l.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/CloseButton-D1euiPao.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Group-BX48WcuU.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Loader-BQEY8g6v.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Modal-Cy3HByv7.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/OptionalPortal-1Hza5P2w.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Stack-CtjJzfw4.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Textarea-Ck64llAy.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Box-B5-OOzBf.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/DirectionProvider-Dc9zdUke.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/events-DJQOhap0.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/use-reduced-motion-D2owz4wa.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/use-disclosure-zKtK5W1r.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/use-hotkeys-Cnc_Rwkb.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/random-id-DOQyszCZ.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/notifications.store-C-3AFSMn.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/exports-C_MrNx_T.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/axios-BEvgo0ym.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/dayjs.min-BkKovM-s.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/i18next-BlSq9s7B.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/client-U9M77rxp.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/react-dom-DaLxUz_h.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/useTranslation-Bx1Cdrkz.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/compiler-runtime-6XxiPFnt.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/jsx-runtime-CwjcCKJi.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/react-CkL4ZRHB.js" as="script" crossorigin="anonymous">
<link rel="stylesheet" href="/vite/assets/application-BqhCP46M.js" />
<script src="/vite/assets/application-Df9RExpe.js" crossorigin="anonymous" type="module"></script><link rel="modulepreload" href="/vite/assets/chunk-DsPFFUou.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/autocomplete-VMNbxKGl.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/routes-CCH8ilKF.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/createPopper-C3aM9r1M.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/js.cookie-D1-O8zkX.js" as="script" crossorigin="anonymous"><link rel="stylesheet" href="/vite/assets/application-C8HjmMaq.css" media="screen" />
<script>
window.ym = function(){(ym.a=ym.a||[]).push(arguments)};
window.addEventListener('load', function() {
setTimeout(function() {
ym.l = 1*new Date();
ym(window.gon.ym_counter, "init", {
clickmap: true,
trackLinks: true,
accurateTrackBounce: true,
webvisor: true
});
// Загружаем скрипт
var k = document.createElement('script');
k.async = 1;
k.src = 'https://mc.yandex.ru/metrika/tag.js';
document.head.appendChild(k);
ym(window.gon.ym_counter, 'getClientID', function(clientID) {
window.ymClientId = clientID;
});
}, 1500);
});
</script>
<!-- Google Tag Manager - deferred -->
<script>
// dataLayer stub сразу — пуши работают до загрузки скрипта
window.dataLayer = window.dataLayer || [];
// Сам скрипт — отложенно после load
window.addEventListener('load', function() {
setTimeout(function() {
dataLayer.push({'gtm.start': new Date().getTime(), event: 'gtm.js'});
var j = document.createElement('script');
j.async = true;
j.src = 'https://www.googletagmanager.com/gtm.js?id=GTM-WK88TH';
document.head.appendChild(j);
}, 1500);
});
</script>
<!-- End Google Tag Manager -->
</head>
<body>
<noscript>
<div>
<img alt="" src="https://mc.yandex.ru/watch/25559621" style="position:absolute; left:-9999px;">
</div>
</noscript>
<header class="sticky-top bg-body">
<nav class="navbar navbar-expand-lg">
<div class="container-xxl">
<a class="navbar-brand" href="/"><img alt="Логотип Хекслета" height="24" src="https://ru.hexlet.io/vite/assets/logo_ru_light-BpiEA1LT.svg" width="96">
</a><button aria-controls="collapsable" aria-expanded="false" aria-label="Меню" class="navbar-toggler border-0 mb-0 mt-1" data-bs-target="#collapsable" data-bs-toggle="collapse">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="collapsable">
<ul class="navbar-nav mb-lg-0 mt-lg-1">
<li class="nav-item dropdown">
<button aria-haspopup class="btn nav-link" data-bs-toggle="dropdown" type="button">
Все курсы
<span class="bi bi-chevron-down align-middle ms-1"></span>
</button>
<ul class="dropdown-menu">
<li>
<a class="dropdown-item d-flex py-2" href="/courses"><div class="fw-bold me-auto">Все что есть</div>
<div class="text-muted">117</div>
</a></li>
<li>
<hr class="dropdown-divider">
</li>
<li class="dropdown-item">
<b>Популярные категории</b>
</li>
<li>
<a class="dropdown-item py-2" href="/courses_devops">Курсы по DevOps
</a></li>
<li>
<a class="dropdown-item py-2" href="/courses_data_analytics">Курсы по аналитике данных
</a></li>
<li>
<a class="dropdown-item py-2" href="/courses_programming">Курсы по программированию
</a></li>
<li>
<a class="dropdown-item py-2" href="/courses_testing">Курсы по тестированию
</a></li>
<li>
<hr class="dropdown-divider">
</li>
<li class="dropdown-item">
<b>Популярные курсы</b>
</li>
<li>
<a class="dropdown-item py-2" href="/programs/devops-engineer-from-scratch">DevOps-инженер с нуля
</a></li>
<li>
<a class="dropdown-item py-2" href="/programs/go">Go-разработчик
</a></li>
<li>
<a class="dropdown-item py-2" href="/programs/java">Java-разработчик
</a></li>
<li>
<a class="dropdown-item py-2" href="/programs/python">Python-разработчик
</a></li>
<li>
<a class="dropdown-item py-2" href="/programs/qa-auto-engineer-java">Автоматизатор тестирования на Java
</a></li>
<li>
<a class="dropdown-item py-2" href="/programs/data-analytics">Аналитик данных
</a></li>
<li>
<a class="dropdown-item py-2" href="/programs/frontend">Фронтенд-разработчик
</a></li>
</ul>
</li>
<li class="nav-item dropdown">
<button aria-haspopup class="btn nav-link" data-bs-toggle="dropdown" type="button">
О Хекслете
<span class="bi bi-chevron-down align-middle"></span>
</button>
<ul class="dropdown-menu bg-body">
<li>
<a class="dropdown-item py-2" href="/pages/about">О нас
</a></li>
<li>
<a class="dropdown-item py-2" href="/blog">Блог
</a></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://special.hexlet.io/hse-research" role="button">Результаты (Исследование)
</span></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://career.hexlet.io" role="button">Хекслет Карьера
</span></li>
<li>
<a class="dropdown-item py-2" href="/testimonials">Отзывы студентов
</a></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://t.me/hexlet_help_bot" role="button">Поддержка (В ТГ)
</span></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://special.hexlet.io/referal-program/?promo_creative=priglasite-druzei&promo_name=referal-program&promo_position=promo_position&promo_start=010724&promo_type=link" role="button">Реферальная программа
</span></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://special.hexlet.io/certificate" role="button">Подарочные сертификаты
</span></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://hh.ru/employer/4307094" role="button">Вакансии
</span></li>
<li>
<span class="dropdown-item d-flex external-link" rel="noopener noreferrer nofollow" data-href="https://b2b.hexlet.io" data-target="_blank" role="button">Компаниям
</span></li>
<li>
<span class="dropdown-item d-flex external-link" rel="noopener noreferrer nofollow" data-href="https://hexly.ru/" data-target="_blank" role="button">Колледж
</span></li>
<li>
<span class="dropdown-item d-flex external-link" rel="noopener noreferrer nofollow" data-href="https://hexlyschool.ru/" data-target="_blank" role="button">Частная школа
</span></li>
</ul>
</li>
<li><a class="nav-link" href="/subscription/new">Подписка</a></li>
</ul>
<ul class="navbar-nav flex-lg-row align-items-lg-center gap-2 ms-auto">
<li>
<a class="nav-link" aria-label="Переключить тему" href="/theme/switch?new_theme=dark"><span aria-hidden="true" class="bi bi-moon"></span>
</a></li>
<li>
<span data-target="_self" class="nav-link external-link" data-href="/u/new" role="button"><span>Регистрация</span>
</span></li>
<li>
<span data-target="_self" class="nav-link external-link" data-href="https://ru.hexlet.io/session/new" role="button"><span>Вход</span>
</span></li>
</ul>
</div>
</div>
</nav>
</header>
<div class="x-container-xxxl">
</div>
<main class="mb-6 min-vh-100 h-100">
<div id="app" data-page="{"component":"web/courses/lessons/theory_unit","props":{"errors":{},"locale":"ru","language":"ru","httpsHost":"https://ru.hexlet.io","host":"ru.hexlet.io","colorScheme":"light","auth":{"user":{"id":null,"last_viewed_notification_id":null,"email":null,"state":null,"first_name":"","last_name":"","created_at":"2026-02-26T20:39:36.110Z","current_program":null,"current_team":null,"full_name":"","guest":true,"can_use_paid_features":false,"is_hexlet_employee":false,"sanitized_phone_number":"","can_subscribe":true,"can_renew_education":false}},"cloudflareTurnstileSiteKey":"0x4AAAAAAA15KmeFXzd2H0Xo","vkIdClientId":"51586979","yandexIdClientId":"88d071f1d3384eb4bd1deb37910235c7","formAuthToken":"uZ0KuclwW53_ISmN2lCznFeMhCLfybJL3YdW06ApNt5WTMGOOw72_UliDRXWX0Prl4WpiNf-TOlgZ8yH8i7RsA","topics":[{"id":28753,"title":"дли**нн**ой! ","plain_title":"длинной! ","creator":{"public_name":"Владимир Толстов","id":229160,"is_tutor":false},"comments":[{"creator":{"public_name":"Сергей К.","id":5174,"is_tutor":false},"id":62024,"body":"Поправил! Спасибо :)","topic_id":28753}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Создание таблиц","entity_url":null,"active":true}},{"id":42068,"title":"> Если подключиться к той же базе данных, которую вы хотите удалить или пересоздать, то во время попытки удаления СУБД будет ругаться на то, что к базе есть активное соединение (ваше)\n\nЯ б еще добавил, что pgadmin тоже имеет активное подклбчение и с запущенной программой удаление не даст произвести)\nПо крайней мере у меня очень долго ругался, пока я не попробовал его отключить)","plain_title":"Если подключиться к той же базе данных, которую вы хотите удалить или пересоздать, то во время попытки удаления СУБД будет ругаться на то, что к базе есть активное соединение (ваше) Я б еще добавил, что pgadmin тоже имеет активное подклбчение и с запущенной программой удаление не даст произвести) По крайней мере у меня очень долго ругался, пока я не попробовал его отключить) ","creator":{"public_name":"Евгений Вафиев","id":255088,"is_tutor":false},"comments":[{"creator":{"public_name":"Stanislav Dzisiak","id":212236,"is_tutor":true},"id":91779,"body":"Приветствую, Евгений!\n\nАга, удалить БД не получится если есть активные подключения к ней. Скоро дополним теорию. Спасибо.\n","topic_id":42068}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Создание таблиц","entity_url":null,"active":true}},{"id":30209,"title":"Вводил-вводил правильный код, но все тщетно. Решение оказалось точно таким же кодом, который вводил\nОшибка та же\nmake: Entering directory '/usr/src/app'\nDEBUG=knex:query npm test -s\n(node:316) ExperimentalWarning: The fs.promises API is experimental\n2019-07-26T22:16:31.044Z knex:query BEGIN; trx1\n2019-07-26T22:16:31.049Z knex:query drop table if exists \"courses\" trx1\n2019-07-26T22:16:31.052Z knex:query drop table if exists \"users\" trx1\n2019-07-26T22:16:31.053Z knex:query drop table if exists \"course_members\" trx1\n2019-07-26T22:16:31.056Z knex:query trx1\n2019-07-26T22:16:31.059Z knex:query insert into \"courses\" (\"body\", \"created_at\", \"name\") values (?, ?, ?) trx1\n2019-07-26T22:16:31.070Z knex:query ROLLBACK trx1\n FAIL __tests__/test.js\n ✕ solution (65ms)\n\n ● solution\n\n error: relation \"courses\" does not exist\n\n at Connection.Object.<anonymous>.Connection.parseE (../../lib/node_modules/pg/lib/connection.js:602:11)\n at Connection.Object.<anonymous>.Connection.parseMessage (../../lib/node_modules/pg/lib/connection.js:399:19)\n at Socket.<anonymous> (../../lib/node_modules/pg/lib/connection.js:121:22)\n From previous event:\n at Client_PG._query (../../lib/node_modules/knex/lib/dialects/postgres/index.js:234:12)\n at Client_PG.query (../../lib/node_modules/knex/lib/client.js:158:17)\n at ../../lib/node_modules/knex/lib/transaction.js:305:24\n From previous event:\n at Client_PG.trxClient.query (../../lib/node_modules/knex/lib/transaction.js:300:12)\n at Runner.query (../../lib/node_modules/knex/lib/runner.js:135:36)\n at ../../lib/node_modules/knex/lib/runner.js:39:23\n From previous event:\n at Runner.run (../../lib/node_modules/knex/lib/runner.js:25:16)\n at Builder.Target.then (../../lib/node_modules/knex/lib/interface.js:14:43)\n\nTest Suites: 1 failed, 1 total\nTests: 1 failed, 1 total\nSnapshots: 0 total\nTime: 0.668s, estimated 1s\nRan all test suites.\nMakefile:2: recipe for target 'test' failed\nmake: Leaving directory '/usr/src/app'\nmake: *** [test] Error 1","plain_title":"Вводил-вводил правильный код, но все тщетно. Решение оказалось точно таким же кодом, который вводил Ошибка та же make: Entering directory '/usr/src/app' DEBUG=knex:query npm test -s (node:316) ExperimentalWarning: The fs.promises API is experimental 2019-07-26T22:16:31.044Z knex:query BEGIN; trx1 2019-07-26T22:16:31.049Z knex:query drop table if exists \"courses\" trx1 2019-07-26T22:16:31.052Z knex:query drop table if exists \"users\" trx1 2019-07-26T22:16:31.053Z knex:query drop table if exists \"coursemembers\" trx1 2019-07-26T22:16:31.056Z knex:query trx1 2019-07-26T22:16:31.059Z knex:query insert into \"courses\" (\"body\", \"createdat\", \"name\") values (?, ?, ?) trx1 2019-07-26T22:16:31.070Z knex:query ROLLBACK trx1 FAIL tests/test.js ✕ solution (65ms) ● solution error: relation \"courses\" does not exist at Connection.Object.<anonymous>.Connection.parseE (../../lib/node_modules/pg/lib/connection.js:602:11) at Connection.Object.<anonymous>.Connection.parseMessage (../../lib/node_modules/pg/lib/connection.js:399:19) at Socket.<anonymous> (../../lib/node_modules/pg/lib/connection.js:121:22) From previous event: at Client_PG._query (../../lib/node_modules/knex/lib/dialects/postgres/index.js:234:12) at Client_PG.query (../../lib/node_modules/knex/lib/client.js:158:17) at ../../lib/node_modules/knex/lib/transaction.js:305:24 From previous event: at Client_PG.trxClient.query (../../lib/node_modules/knex/lib/transaction.js:300:12) at Runner.query (../../lib/node_modules/knex/lib/runner.js:135:36) at ../../lib/node_modules/knex/lib/runner.js:39:23 From previous event: at Runner.run (../../lib/node_modules/knex/lib/runner.js:25:16) at Builder.Target.then (../../lib/node_modules/knex/lib/interface.js:14:43) Test Suites: 1 failed, 1 total Tests: 1 failed, 1 total Snapshots: 0 total Time: 0.668s, estimated 1s Ran all test suites. Makefile:2: recipe for target 'test' failed make: Leaving directory '/usr/src/app' make: *** [test] Error 1 ","creator":{"public_name":"Игорь Парфененков","id":196161,"is_tutor":false},"comments":[{"creator":{"public_name":"Игорь Парфененков","id":196161,"is_tutor":false},"id":65450,"body":">make: Entering directory '/usr/src/app'\nDEBUG=knex:query npm test -s\n(node:130) ExperimentalWarning: The fs.promises API is experimental\n2019-07-26T22:24:06.201Z knex:query BEGIN; trx1\n2019-07-26T22:24:06.207Z knex:query drop table if exists \"courses\" trx1\n2019-07-26T22:24:06.210Z knex:query drop table if exists \"users\" trx1\n2019-07-26T22:24:06.213Z knex:query drop table if exists \"course_members\" trx1\n2019-07-26T22:24:06.216Z knex:query trx1\n2019-07-26T22:24:06.219Z knex:query insert into \"courses\" (\"body\", \"created_at\", \"name\") values (?, ?, ?) trx1\n2019-07-26T22:24:06.230Z knex:query ROLLBACK trx1\n FAIL __tests__/test.js\n ✕ solution (76ms)\n\n ● solution\n\n error: relation \"courses\" does not exist\n\n at Connection.Object.<anonymous>.Connection.parseE (../../lib/node_modules/pg/lib/connection.js:602:11)\n at Connection.Object.<anonymous>.Connection.parseMessage (../../lib/node_modules/pg/lib/connection.js:399:19)\n at Socket.<anonymous> (../../lib/node_modules/pg/lib/connection.js:121:22)\n From previous event:\n at Client_PG._query (../../lib/node_modules/knex/lib/dialects/postgres/index.js:234:12)\n at Client_PG.query (../../lib/node_modules/knex/lib/client.js:158:17)\n at ../../lib/node_modules/knex/lib/transaction.js:305:24\n From previous event:\n at Client_PG.trxClient.query (../../lib/node_modules/knex/lib/transaction.js:300:12)\n at Runner.query (../../lib/node_modules/knex/lib/runner.js:135:36)\n at ../../lib/node_modules/knex/lib/runner.js:39:23\n From previous event:\n at Runner.run (../../lib/node_modules/knex/lib/runner.js:25:16)\n at Builder.Target.then (../../lib/node_modules/knex/lib/interface.js:14:43)\n\nTest Suites: 1 failed, 1 total\nTests: 1 failed, 1 total\nSnapshots: 0 total\nTime: 0.702s, estimated 1s\nRan all test suites.\nMakefile:2: recipe for target 'test' failed\nmake: Leaving directory '/usr/src/app'\nmake: *** [test] Error 1","topic_id":30209},{"creator":{"public_name":"Игорь Парфененков","id":196161,"is_tutor":false},"id":65453,"body":"\\dt\n List of relations\n Schema | Name | Type | Owner \n--------+----------------+-------+--------\n public | course_members | table | nobody\n public | courses | table | nobody\n public | users | table | nobody\n(3 rows)\n\nnobody=# \\d users \n Table \"public.users\"\n Column | Type | Collation | Nullable | Default \n------------+------------------------+-----------+----------+---------\n first_name | character varying(255) | | | \n email | character varying(255) | | | \n manager | boolean | | | \n\nnobody=# \\d courses\n Table \"public.courses\"\n Column | Type | Collation | Nullable | Default \n------------+-----------------------------+-----------+----------+---------\n name | character varying(255) | | | \n body | text | | | \n created_at | timestamp without time zone | | | \n\nnobody=# \\d course_members \n Table \"public.course_members\"\n Column | Type | Collation | Nullable | Default \n------------+-----------------------------+-----------+----------+---------\n user_id | integer | | | \n course_id | integer | | | \n created_at | timestamp without time zone | | | \n","topic_id":30209},{"creator":{"public_name":"Игорь Парфененков","id":196161,"is_tutor":false},"id":65451,"body":"И не стоит снимать за это баллы","topic_id":30209},{"creator":{"public_name":"Игорь Парфененков","id":196161,"is_tutor":false},"id":65452,"body":"'''nobody=# \\dt\n List of relations\n Schema | Name | Type | Owner \n--------+----------------+-------+--------\n public | course_members | table | nobody\n public | courses | table | nobody\n public | users | table | nobody\n(3 rows)\n\nnobody=# \\d users \n Table \"public.users\"\n Column | Type | Collation | Nullable | Default \n------------+------------------------+-----------+----------+---------\n first_name | character varying(255) | | | \n email | character varying(255) | | | \n manager | boolean | | | \n\nnobody=# \\d courses\n Table \"public.courses\"\n Column | Type | Collation | Nullable | Default \n------------+-----------------------------+-----------+----------+---------\n name | character varying(255) | | | \n body | text | | | \n created_at | timestamp without time zone | | | \n\nnobody=# \\d c'''","topic_id":30209}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Создание таблиц","entity_url":null,"active":true}},{"id":51706,"title":"Появилась проблема! Когда создаю БД пишет:\n\ncreatedb hexlet\n\nWARNING: could not flush dirty data: Function not implemented\n\n\nБаза создалась, но отображения в pgAdmin нету. Интернет перерыл. Решить проблему весь день не могу!","plain_title":"Появилась проблема! Когда создаю БД пишет: createdb hexlet WARNING: could not flush dirty data: Function not implemented База создалась, но отображения в pgAdmin нету. Интернет перерыл. Решить проблему весь день не могу! ","creator":{"public_name":"Олександр","id":341504,"is_tutor":false},"comments":[{"creator":{"public_name":"Maksim Litvinov","id":198906,"is_tutor":true},"id":110517,"body":"Добрый день. Скажите, пожалуйста, на какой операционной системе вы работаете?","topic_id":51706},{"creator":{"public_name":"Maksim Litvinov","id":198906,"is_tutor":true},"id":110618,"body":"Спасибо!\n\nПоиск в гугле показывает, что это известная проблема, которая показывает тот факт, что WSL не совсем нативная среда для запуска linux-программ. [Вот](https://www.postgresql-archive.org/WARNING-could-not-flush-dirty-data-Function-not-implemented-td6036573.html) ссылка на тред с подобным обсуждением. Обратите внимание, что это не ошибка, а предупреждение.\n\nПредлагаю вам задуматься о переходе на linux. Это поможет избежать подобных проблем и поможет быстрее находить в гугле ответы на вопросы. Современные дистрибутивы, например Ubuntu, просты в установке и настройке. Для начала можно установить их в качестве второй ОС. \n\nДля более оперативной помощи в настройке окружения и при каких-либо проблемах с операционной системой можно сразу писать в наш слак. Там много опытных разработчиков и кто-то обязательно сталкивался с такой же проблемой. О том как подключиться к слаку можно почитать здесь — https://help.hexlet.io/article/66-slack","topic_id":51706},{"creator":{"public_name":"Олександр","id":341504,"is_tutor":false},"id":110534,"body":"**Максим Литвинов**, windows и интегрировал под linux, но не помогло. Ещё пробовал скачать 9-тую версию psql, но не прошла установка. Нужно поставить старый visual studio c++.","topic_id":51706}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Создание таблиц","entity_url":null,"active":true}},{"id":40723,"title":"Зачем в уроке \"Подготовка к работе\" мы грузили и импортировали данные из _pg-dump-example_, если тут все равно дропаем и создаем таблицу \"hexlet\"? :)","plain_title":"Зачем в уроке \"Подготовка к работе\" мы грузили и импортировали данные из pg-dump-example, если тут все равно дропаем и создаем таблицу \"hexlet\"? :) ","creator":{"public_name":"Андрей Бирюков","id":204221,"is_tutor":false},"comments":[{"creator":{"public_name":"Stanislav Dzisiak","id":212236,"is_tutor":true},"id":88996,"body":"Приветствую, Андрей!\n\nЭто требуется для закрепления знаний полученных в теории к данному уроку.","topic_id":40723}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Создание таблиц","entity_url":null,"active":true}},{"id":44406,"title":"В задании написано что запросы скопирвоать в файл\n\nЯ сделал запросы по заданию. у меня все рабоатет\n\n```\nCREATE TABLE courses (name varchar(255), body text, created_at timestamp);\nCREATE TABLE users(first_name varchar(255), email varchar(255), manager boolean);\nCREATE TABLE course_member (user_id integer, course_id integer, created_at timestamp);\n```\nа тут валятся шибки.\n\n```\nmake: Entering directory '/usr/src/app'\nDEBUG=knex:query npm test -s\n\n2020-06-22T00:40:16.518Z knex:query BEGIN; trx1\n\n2020-06-22T00:40:16.523Z knex:query drop table if exists \"courses\" trx1\n\n2020-06-22T00:40:16.526Z knex:query drop table if exists \"users\" trx1\n\n2020-06-22T00:40:16.527Z knex:query drop table if exists \"course_members\" trx1\n\n2020-06-22T00:40:16.530Z knex:query CREATE TABLE courses (name varchar(255), body text, created_at timestamp);\nCREATE TABLE users(first_name varchar(255), email varchar(255), manager boolean);\nCREATE TABLE course_member (user_id integer, course_id integer, created_at timestamp);\n trx1\n\n2020-06-22T00:40:16.564Z knex:query insert into \"courses\" (\"body\", \"created_at\", \"name\") values (?, ?, ?) trx1\n\n2020-06-22T00:40:16.570Z knex:query insert into \"users\" (\"email\", \"first_name\", \"manager\") values (?, ?, ?) trx1\n\n2020-06-22T00:40:16.571Z knex:query insert into \"course_members\" (\"course_id\", \"created_at\", \"user_id\") values (?, ?, ?) trx1\n\n2020-06-22T00:40:16.574Z knex:query ROLLBACK trx1\n\n FAIL __tests__/test.js\n\n ✕ solution (113ms)\n\n ● solution\n\n error: insert into \"course_members\" (\"course_id\", \"created_at\", \"user_id\") values ($1, $2, $3) - relation \"course_members\" does not exist\n\n at Connection.parseE (../../lib/node_modules/pg/lib/connection.js:581:48)\n at Connection.parseMessage (../../lib/node_modules/pg/lib/connection.js:380:19)\n at Socket.<anonymous> (../../lib/node_modules/pg/lib/connection.js:116:22)\n\n\nTest Suites: 1 failed, 1 total\nTests: 1 failed, 1 total\nSnapshots: 0 total\nTime: 2.576s, estimated 5s\nRan all test suites.\n\nmake: *** [Makefile:2: test] Error 1\n\nmake: Leaving directory '/usr/src/app'\n```\nпочему ?","plain_title":"В задании написано что запросы скопирвоать в файл Я сделал запросы по заданию. у меня все рабоатет CREATE TABLE courses (name varchar(255), body text, created_at timestamp); CREATE TABLE users(first_name varchar(255), email varchar(255), manager boolean); CREATE TABLE course_member (user_id integer, course_id integer, created_at timestamp); а тут валятся шибки. make: Entering directory '/usr/src/app' DEBUG=knex:query npm test -s 2020-06-22T00:40:16.518Z knex:query BEGIN; trx1 2020-06-22T00:40:16.523Z knex:query drop table if exists \"courses\" trx1 2020-06-22T00:40:16.526Z knex:query drop table if exists \"users\" trx1 2020-06-22T00:40:16.527Z knex:query drop table if exists \"course_members\" trx1 2020-06-22T00:40:16.530Z knex:query CREATE TABLE courses (name varchar(255), body text, created_at timestamp); CREATE TABLE users(first_name varchar(255), email varchar(255), manager boolean); CREATE TABLE course_member (user_id integer, course_id integer, created_at timestamp); trx1 2020-06-22T00:40:16.564Z knex:query insert into \"courses\" (\"body\", \"created_at\", \"name\") values (?, ?, ?) trx1 2020-06-22T00:40:16.570Z knex:query insert into \"users\" (\"email\", \"first_name\", \"manager\") values (?, ?, ?) trx1 2020-06-22T00:40:16.571Z knex:query insert into \"course_members\" (\"course_id\", \"created_at\", \"user_id\") values (?, ?, ?) trx1 2020-06-22T00:40:16.574Z knex:query ROLLBACK trx1 FAIL __tests__/test.js ✕ solution (113ms) ● solution error: insert into \"course_members\" (\"course_id\", \"created_at\", \"user_id\") values ($1, $2, $3) - relation \"course_members\" does not exist at Connection.parseE (../../lib/node_modules/pg/lib/connection.js:581:48) at Connection.parseMessage (../../lib/node_modules/pg/lib/connection.js:380:19) at Socket.<anonymous> (../../lib/node_modules/pg/lib/connection.js:116:22) Test Suites: 1 failed, 1 total Tests: 1 failed, 1 total Snapshots: 0 total Time: 2.576s, estimated 5s Ran all test suites. make: *** [Makefile:2: test] Error 1 make: Leaving directory '/usr/src/app' почему ? ","creator":{"public_name":"Igor Linder","id":261935,"is_tutor":false},"comments":[{"creator":{"public_name":"Igor Linder","id":261935,"is_tutor":false},"id":96063,"body":"точнО! букву s в конце пропустил)","topic_id":44406},{"creator":{"public_name":"Nikolai Gagarinov","id":104929,"is_tutor":true},"id":96023,"body":"Добрый день.\nПроверьте, корректно ли у вас названы имена таблиц.","topic_id":44406}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Создание таблиц","entity_url":null,"active":true}},{"id":44318,"title":"Ниже уже было подобное сообщение, но ответа нет. В данном уроке есть предложение:\n> Подключитесь к СУБД через psql (не указывая базу данных, тогда произойдет подключение к базе данных по умолчанию)\n>\nНо в предыдущих уроках говорили, что если не указываем аргументов, то подключение идет от текущего пользователя, вызывающего команду к базе данных с тем же именем, таким образом, подключение к базе данных по умолчанию не происходит, так как мы создали роль с нашим именем, но базу данных с тем же именем не создавали.\n","plain_title":"Ниже уже было подобное сообщение, но ответа нет. В данном уроке есть предложение: Подключитесь к СУБД через psql (не указывая базу данных, тогда произойдет подключение к базе данных по умолчанию) Но в предыдущих уроках говорили, что если не указываем аргументов, то подключение идет от текущего пользователя, вызывающего команду к базе данных с тем же именем, таким образом, подключение к базе данных по умолчанию не происходит, так как мы создали роль с нашим именем, но базу данных с тем же именем не создавали. ","creator":{"public_name":"Вильдан Фазлыев","id":252958,"is_tutor":false},"comments":[{"creator":{"public_name":"Sergei Melodyn","id":162475,"is_tutor":true},"id":96036,"body":"**Вильдан Фазлыев**, значит можно переключиться на пользователя postgres и из под него подключиться к БД. При установке точно происходит ассоциация одного с другим, но это конкретно особенности постгреса, курс же рассказывает о реляционных БД, просто на его примере. Если интересно разобраться конкретно с постгресом, то можно развернуть локально или поднять в контейнере. ","topic_id":44318},{"creator":{"public_name":"Sergei Melodyn","id":162475,"is_tutor":true},"id":96020,"body":"**Вильдан Фазлыев**, приветствую.\n\nЕсли я правильно помню, при установке постгрес сам читает имя текущего пользователя и создаёт под него БД, в самом простом случае это root/root. Если выполнить `whoami` в терминале упражнения и посмотреть имя пользователя, а потом подключиться к постгресу, то имя БД и пользователя будут соответствовать тем, что указаны в терминале","topic_id":44318},{"creator":{"public_name":"Вильдан Фазлыев","id":252958,"is_tutor":false},"id":96034,"body":"**Сергей Мелодин**, по умолчанию создается только база данных с именем postgres.","topic_id":44318}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Создание таблиц","entity_url":null,"active":true}},{"id":21556,"title":"Упражнение прошел, в решении учителя создается таблица курсов, ее забыли в задание написать?)","plain_title":"Упражнение прошел, в решении учителя создается таблица курсов, ее забыли в задание написать?) ","creator":{"public_name":"Sergey Tabb","id":148171,"is_tutor":false},"comments":[{"creator":{"public_name":"Kirill Mokevnin","id":1,"is_tutor":false},"id":45806,"body":"fixed!)","topic_id":21556}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Создание таблиц","entity_url":null,"active":true}},{"id":31206,"title":"Как \n>Подключитесь к СУБД через psql (не указывая базу данных) и выполните следующие запросы:\n\nсочетается с\n>Надо сказать что невозможно соединиться с СУБД просто так: соединение всегда происходит с конкретной базой данных\n\n?\n\nЭто из одного из прошлых уроков.\n\nЯ подключался к postgres, ","plain_title":"Как Подключитесь к СУБД через psql (не указывая базу данных) и выполните следующие запросы: сочетается с Надо сказать что невозможно соединиться с СУБД просто так: соединение всегда происходит с конкретной базой данных Это из одного из прошлых уроков. Я подключался к postgres, ","creator":{"public_name":"Сергей Егупов","id":184023,"is_tutor":false},"comments":[{"creator":{"public_name":"Kirill Mokevnin","id":1,"is_tutor":false},"id":67770,"body":"Потому что если база данных не указана в cli, то подключение идет к дефолтной базе данных.\n\n> Я подключался к postgres\n\nТакой базы данных нет, это имя пользователя.","topic_id":31206},{"creator":{"public_name":"Евгений Квач","id":196310,"is_tutor":false},"id":70309,"body":"ситуация как у Сергея. тоже подключился \npsql postgres. \nсудя по \npostgres=> \nэто бд. или что-то не то?","topic_id":31206}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Создание таблиц","entity_url":null,"active":true}},{"id":56844,"title":"Доброго дня, вижу похожий пост с проблемой (неправильно названы наименования), перепроверил все 20 тыщ мильонов раз, все равно ошибка, не понимаю, почему( \nhttps://ru.hexlet.io/code_reviews/435236","plain_title":"Доброго дня, вижу похожий пост с проблемой (неправильно названы наименования), перепроверил все 20 тыщ мильонов раз, все равно ошибка, не понимаю, почему( https://ru.hexlet.io/code_reviews/435236 ","creator":{"public_name":"Дмитрий Князев","id":342841,"is_tutor":false},"comments":[{"creator":{"public_name":"Roman Ashikov","id":226258,"is_tutor":true},"id":120490,"body":"Приветствую, Дмитрий!\n\nОтвечу без намёков. :) Дело в опечатке в наименовании поля в таблице course_members. Нужно исправить имя поля cours**t**_id. Бывает опечатаешься и, как вы и сказали, перепроверяешь всё много-много раз, а дело было лишь в одном символе.","topic_id":56844}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Создание таблиц","entity_url":null,"active":true}}],"lesson":{"exercise":null,"units":[{"id":2635,"name":"theory","url":"/courses/rdb-basics/lessons/sql-ddl/theory_unit"},{"id":2797,"name":"quiz","url":"/courses/rdb-basics/lessons/sql-ddl/quiz_unit"}],"links":[{"id":422869,"name":"Онлайн-песочница для выполнения SQL-запросов","url":"https://www.db-fiddle.com/"},{"id":422870,"name":"Типы данных","url":"https://postgrespro.ru/docs/postgresql/15/datatype"},{"id":422871,"name":"CREATE TABLE","url":"https://www.postgresql.org/docs/current/static/sql-createtable.html"}],"ordered_units":[{"id":2635,"name":"theory","url":"/courses/rdb-basics/lessons/sql-ddl/theory_unit"},{"id":2797,"name":"quiz","url":"/courses/rdb-basics/lessons/sql-ddl/quiz_unit"}],"id":1265,"slug":"sql-ddl","state":"approved","name":"Создание таблиц","course_order":370,"goal":"Учимся создавать таблицы и познакомимся с базовыми типами данных в PostgreSQL","self_study":null,"theory_video_provider":null,"theory_video_uid":null,"theory":"В этом уроке мы поработаем с таблицами: будем создавать их, добавлять, модифицировать и удалять данные. Также разберем типы данных таблицы.\n\n## Создание базы данных\n\nПрежде чем создать таблицу, создадим базу данных `hexlet` с помощью SQL (если вы еще этого не сделали). Для этого подключитесь к СУБД через `psql`. При этом не указывайте базу данных, чтобы подключиться к базе по умолчанию. Далее выполните следующие запросы:\n\n```sql\nDROP DATABASE hexlet;\nCREATE DATABASE hexlet;\n```\n\nВ примере выше два SQL запроса:\n\n* `DROP DATABASE hexlet` — удаляет базу данных с именем `hexlet`\n\n* `CREATE DATABASE hexlet` — создает базу данных с таким же именем\n\nБазовые правила построения запросов:\n\n* Каждый запрос должен заканчиваться точкой с запятой. Иначе `psql` будет думать, что вы продолжаете вводить команды\n\n* Регистр не важен. Можно было написать `drop database hexlet;`. По традиции принято использовать верхний регистр для ключевых слов самого SQL. Это позволяет визуально разделять структуру запроса от данных внутри него. Последнее в примере — это имя базы данных, которое может быть произвольным\n\nЕсли подключиться к той же базе данных, которую вы хотите удалить или пересоздать, то во время попытки удаления СУБД будет ругаться, что к базе есть активное соединение — ваше соединение. Поэтому важно подключиться к любой другой базе данных.\n\nКоманды `createdb` и `createuser`, которые мы разобрали в прошлых уроках, выполняют SQL-запросы внутри СУБД. Их сделали ради удобства первоначальной настройки, и чтобы использовать в скриптах автоматизации.\n\nSQL поддерживает **комментарии** — строчка, которая начинается с двух дефисов. Комментарии игнорируются СУБД при построении запросов:\n\n```sql\nhexlet=> -- i am comment\nhexlet=>\n```\n\nНам удалось создать базу данных `hexlet`, поэтому можно переходить к созданию таблицы. Подключитесь к созданной базе данных\n\n## Создание таблиц\n\nТаблица создается с помощью запроса `CREATE TABLE`:\n\n```sql\n-- Это один запрос, хоть и многострочный.\n-- Описание запроса заканчивается символом ;\nCREATE TABLE courses (\n name varchar(255),\n slug varchar(255),\n lessons_count integer,\n body text\n);\n```\n\nЧтобы создать таблицу, необходимо указать ее имя, набор полей и их типы. В примере выше названия полей — это `name`, `slug`, `lessons_count` и `body`, а `varchar(255)`, `integer` и `text` — их типы.\n\n### Типы данных\n\nУ каждого поля в PostgreSQL определенный тип, который задается на этапе создания таблицы. Это значит, что значением этого поля могут быть только определенные данные. Если поле имеет числовой тип, то в него невозможно вставить строку, и наоборот. База данных выдаст ошибку при попытке выполнить подобный запрос.\n\n```sql\n-- Выполняем запрос на вставку передавая в lessons_count строку вместо числа\nERROR: invalid input syntax for type integer: \"wrong value\"\n```\n\nВ PostgreSQL встроено много различных типов данных, но на практике используются не все. Ниже мы разбираем только самые популярные типы.\n\n#### Строки\n\nДля строк в базах данных в основном используются два типа:\n\n* *varchar* — для строк с ограничением максимальной длины\n* *text* — для строк без ограничения. Как правило, это полноценные тексты\n\nВ базах данных нельзя оставить первый тип без указания длины. Это связано с производительностью и эффективностью. Данные в базах данных физически хранятся на дисках в файлах. Быстрый доступ к этим данным возможен только тогда, когда у данных фиксированный размер. Это позволяет быстро перемещаться по ним и считать смещения.\n\nЕсли размер данных не известен, то придется просматривать весь файл в поисках нужного значения. Чтобы избежать подобной ситуации, тип *text* хранится отдельно. Это тоже негативно влияет на скорость, но уже не так сильно. Если размер строки известен или он меньше какого-то значения, то предпочтительнее использовать *varchar*.\n\n| Имя | Описание |\n|-----------------------------------|----------------------------------------|\n| character varying(n), varchar(n) | строка ограниченной переменной длины |\n| text | строка неограниченной переменной длины |\n\n* *varchar*. Полное название типа *character varying* (*varchar* может использоваться как псевдоним). Размер строки с таким типом указывается в скобках после названия типа, например, *varchar(10)*. Это значит, что в поле с таким типом можно записать строку длиной до 10 символов.\n\n* *text*. Не требует указания размера и может содержать текст произвольной длины\n\nПример создания таблицы с такими типами:\n\n```sql\nCREATE TABLE blog_posts (\n name varchar(80),\n body text\n);\n```\n\n#### Числа\n\nДля чисел в основном используются два типа данных: *integer* и *bigint*. Какой конкретно указывать тип, зависит от потенциального потолка значения. Ниже указаны диапазоны, допустимые в рамках этих типов:\n\n| Имя | Описание | Диапазон |\n|---------|--------------------------------|---------------------------------------------|\n| integer | типичный выбор для целых чисел | -2147483648 .. +2147483647 |\n| bigint | целое в большом диапазоне | -9223372036854775808 .. 9223372036854775807 |\n\nПример создания таблицы с такими типами:\n\n```sql\nCREATE TABLE users (\n id bigint,\n age integer\n);\n```\n\n#### Даты\n\nТипы для хранения дат отличаются друг от друга очень сильно, в первую очередь по решаемой задаче. Нам надо хранить день без конкретного времени? Это тип *date*. Нужно конкретный момент времени, тогда *timestamp*. Просто время без даты? Тогда *time*.\n\n| Имя | Описание | Наименьшее значение | Наибольшее значение | Точность |\n|-------------|------------------------------------|---------------------|---------------------|----------------|\n| timestamp | дата и время (без часового пояса) | 4713 до н. э. | 294276 н. э. | 1 микросекунда |\n| date | дата (без времени суток) | 4713 до н. э. | 5874897 н. э. | 1 день |\n| time | время суток (без даты) | 00:00:00 | 24:00:00 | 1 микросекунда |\n\nПример создания таблицы с такими типами:\n\n```sql\nCREATE TABLE events (\n start_date date,\n -- имя поля может называться как тип данных\n time time,\n updated_at timestamp,\n created_at timestamp\n);\n```\n\nХорошей практикой считается добавление и заполнение полей *created_at* и *updated_at* в каждую таблицу базы данных. С их помощью всегда можно узнать, когда запись создалась и обновилась.\n\nЗначения даты и времени принимаются практически в любом известном формате. Вот несколько примеров того, как можно задавать дату:\n\n| Пример | Описание |\n|-----------------|---------------------------------|\n| 1999-01-08 | ISO 8601 (рекомендуемый формат) |\n| January 8, 1999 | |\n\n#### Логический тип\n\nСодержит всего два значения: `true` и `false`. Этот тип используется для флагов:\n\n| Имя | Описание |\n|----------|----------------------------------|\n| boolean | true или false (истина или ложь) |\n\nПример создания таблицы с такими типами:\n\n```sql\nCREATE TABLE blog_posts (\n -- флаг: опубликован?\n published boolean\n);\n```\n\nСостояние «true» может задаваться следующими значениями:\n\n```\nTRUE\n't'\n'true'\n'y'\n'yes'\n'on'\n'1'\n```\n\nДля состояния «false» можно использовать следующие варианты:\n\n```\nFALSE\n'f'\n'false'\n'n'\n'no'\n'off'\n'0'\n```\n\n#### NULL\n\nПомимо типов данных для реальных значений, в базе существует специальное значение `NULL`, чтобы обозначать пустоту. Оно используется, когда у конкретного поля нет значения. Тип поля при этом не важен. Подробнее с `NULL` мы разберемся в следующих уроках.\n\n## Анализ структуры базы данных\n\nЧтобы исследовать структуру таблиц в визуальном режиме, используется _PgAdmin_:\n\n\n\nSQL для анализа структуры базы данных не существует. Если вы хотите посмотреть список таблиц и их структуру в базе данных, то придется использовать команды самого `psql`:\n\n**Просмотр списка таблиц базы данных hexlet**\n\n```bash\nhexlet=> \\d\n List of relations\n Schema | Name | Type | Owner\n--------+------------+-------+---------\n public | courses | table | vagrant\n public | events | table | vagrant\n public | blog_posts | table | vagrant\n```\n\nЗдесь мы видим список таблиц в базе данных *hexlet*. Все что здесь отображается, было создано в этом уроке выше.\n\nВ первом столбце видим новое для нас понятие — *schema*. Это пространство имен, которое позволяет группировать таблицы в различных ситуациях. На практике эта возможность используется редко, поэтому мы не обращаем на нее внимание. По умолчанию все таблицы публикуются в общей схеме *public*, которую можно не указывать.\n\n**Просмотр структуры таблицы courses**\n\n```bash\nhexlet=> \\d courses\n# public - обозначает схему по умолчанию\n Table \"public.courses\"\n Column | Type | Modifiers\n---------------+------------------------+-----------\n name | character varying(255) |\n slug | character varying(255) |\n lessons_count | integer |\n body | text |\n```\n\nВ этом выводе показана структура таблицы *courses*. Здесь мы видим все имена полей и их типы.\n\nКроме перечисленных полезными могут оказаться следующие команды:\n\n* `\\l` — список всех баз данных\n* `\\dt` — список всех таблиц\n* `\\?` — вывод справки\n\n## Удаление таблиц\n\nЧтобы удалить таблицу, выполняется запрос `DROP`:\n\n```sql\nDROP TABLE courses;\n```\n\nБудьте внимательны, так как удаление таблицы приводит к безвозвратной потере данных.\n\n## Выводы\n\nВ этом уроке мы разобрали работу с таблицами: создавали базу данных и таблицу, устанавливали типы данных и анализировали структуру базы. Еще мы показали, как удалять таблицу. Попрактикуйтесь создавать таблицы — проходите каждый шаг, описанный в уроке, и со временем для вас это станет легкой задачей.\n"},"lessonMember":null,"courseMember":null,"course":{"start_lesson":{"exercise":null,"units":[{"id":2631,"name":"theory","url":"/courses/rdb-basics/lessons/intro/theory_unit"}],"links":[],"ordered_units":[{"id":2631,"name":"theory","url":"/courses/rdb-basics/lessons/intro/theory_unit"}],"id":1261,"slug":"intro","state":"approved","name":"Введение","course_order":100,"goal":"Знакомимся с курсом","self_study":null,"theory_video_provider":null,"theory_video_uid":null,"theory":"\n\nЛюбая нетривиальная программная система состоит минимум из двух компонентов:\n\n* Программного кода, отвечающего за логику работы\n* Хранилища, в котором содержатся данные, необходимые для работы\n\nВозьмем для примера Хекслет. Это большой контентный проект, внутри которого есть данные: например, курсы и их содержимое.\n\nБолее того, довольно много контента создается самими пользователями: они вводят данные при регистрации, создают и заполняют профили, описывают свои решения и переписываются с поддержкой через топики. Все эти данные непрерывно добавляются на сайт и только увеличиваются в объемах.\n\nПри этом данные нужно не только хранить, но и непрерывно считывать и показывать пользователям. Причем иногда в довольно хитрых формах, например: «Показать на странице испытания три последних код-ревью по этому испытанию, исключая код-ревью пользователя, который прямо сейчас смотрит на эту страницу».\n\nПодобные сложные запросы к системе хранения делаются ежесекундно, и многие из них значительно сложнее приведенного примера.\n\nКроме того, пользователи на сайтах работают независимо друг от друга, что создает конкуренцию при обращении к одним и тем же данным. А что, если один пользователь читает данные, которые в это время модифицируются другим пользователем?\n\nЗа реализацию всех этих возможностей отвечают **системы управления базами данных (СУБД)**. Как правило, они отвязаны от того языка программирования, на котором идет разработка. СУБД — это отдельная программа, которая умеет эффективно сохранять и читать то, что ее попросят.\n\nТаких систем существует довольно много, но это не значит, что все они абсолютно разные. Схожие системы делят на классы — множества систем со схожими характеристиками.\n\nЧаще всего используются **реляционные СУБД (РСУБД)** — системы, работа которых основана на **реляционной модели данных**. С технической точки зрения такие базы данных основаны на табличном представлении данных.\n\nДля работы с ними нужно понимать две основные вещи:\n\n* Реляционная модель данных — звучит страшно, но в итоге все сводится к таблицам\n* SQL — специализированный язык для управления базой данных и данными внутри нее\n\nОба пункта практически не зависят от реализации конкретной РСУБД. Изучив одну СУБД, вы крайне легко сможете переключиться на другую. В этом курсе мы рассмотрим популярную СУБД PostgreSQL. Она поставляется со специальной программой *psql*, которая представляет собой интерактивную оболочку — REPL. Через нее можно управлять PostgreSQL и взаимодействовать с базами данных, набирая команды в реальном времени.\n\n## Основные темы курса\n\nВ этом курсе мы затронем такие основные темы:\n\n* Установка и настройка\n* Создание и модификация базы данных (DDL)\n* Наполнение базы данных (DML)\n* Выборка данных (`SELECT`, `WHERE`, `ORDER`, `LIMIT`, `DISTINCT`, `GROUP`, `HAVING`)\n* Агрегирующие функции (`COUNT`)\n* Соединения (`JOIN`, `LEFT JOIN`)\n* Транзакции (уровни изоляции)\n* Реляционная алгебра (основы теории множеств)\n* Ключи (первичные, внешние)\n* Нормализация данных\n* Связи (один-к-одному, один-ко-многим, многие-ко-многим)\n* Производительность (индексы)\n\nВся практика в этом курсе выполняется в нашей среде, но если вы разработчик или вам это необходимо, то настройте базу данных локально для экспериментов. Эффективное обучение невозможно без повторения примеров из уроков в своей среде. Поэтому в начале курса необходимо установить PostgreSQL локально. Сделайте это по [инструкции](https://github.com/Hexlet/ru-instructions/blob/main/postgresql.md).\n"},"id":172,"slug":"rdb-basics","challenges_count":0,"name":"Основы реляционных баз данных","allow_indexing":true,"state":"approved","course_state":"finished","pricing_type":"free","description":"На этом курсе вы изучите основы реляционных баз данных. Вы узнаете больше об архитектуре СУБД и языке SQL. В итоге вы научитесь создавать таблицы, добавлять, модифицировать и удалять данные. Курс пригодится, если вы решите использовать базу данных в вашем приложении или вам нужно использовать данные из базы в любых других местах. Знания из этого курса помогают выполнять запросы для выборки данных, объединять таблицы и использовать транзакции.","kind":"sandbox","updated_at":"2026-01-20T11:39:09.852Z","language":"sql","duration_cache":25500,"skills":["Создавать полноценные базы данных для приложений на любых языках","Правильно организовывать (нормализовать) архитектуру хранения данных с помощью нормальных форм","Отображать предметную область на таблицы с учетом связей между сущностями (o2o, o2m, m2m)","Выполнять запросы на выборку данных по сложным условиям"],"keywords":["postgresql","транзакции","нормальные формы","СУБД"],"lessons_count":24,"cover":"https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6NjA4MSwicHVyIjoiYmxvYl9pZCJ9fQ==--18d92b90e9f04ddc693b77ace032c133fb2dfdd5/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJqcGciLCJyZXNpemVfdG9fZmlsbCI6WzYwMCw0MDBdfSwicHVyIjoidmFyaWF0aW9uIn19--39ba06fa99226096df9fc6bb31f84e1d29ea98e9/image.png"},"recommendedLandings":[],"lessonMemberUnit":null,"accessToLearnUnitExists":true,"accessToCourseExists":true},"url":"/courses/rdb-basics/lessons/sql-ddl/theory_unit","version":"8f286f6358a90a7bef2263b3a6edf5a90a94fa42","encryptHistory":false,"clearHistory":false}"><style data-mantine-styles="true">:root, :host{--mantine-font-family: Arial, sans-serif;--mantine-font-family-headings: Arial, sans-serif;--mantine-heading-font-weight: normal;--mantine-radius-default: 0rem;--mantine-primary-color-filled: var(--mantine-color-indigo-filled);--mantine-primary-color-filled-hover: var(--mantine-color-indigo-filled-hover);--mantine-primary-color-light: var(--mantine-color-indigo-light);--mantine-primary-color-light-hover: var(--mantine-color-indigo-light-hover);--mantine-primary-color-light-color: var(--mantine-color-indigo-light-color);--mantine-spacing-xxl: calc(4rem * var(--mantine-scale));--mantine-font-size-xs: 12px;--mantine-font-size-sm: 14px;--mantine-font-size-md: 16px;--mantine-font-size-lg: clamp(16.0000px, calc(15.2727px + 0.2273vw), 18.0000px);--mantine-font-size-xl: clamp(16.0000px, calc(14.5455px + 0.4545vw), 20.0000px);--mantine-font-size-display-3: clamp(32.0000px, calc(26.1818px + 1.8182vw), 48.0000px);--mantine-font-size-display-2: clamp(36.0000px, calc(25.8182px + 3.1818vw), 64.0000px);--mantine-font-size-display-1: clamp(40.0000px, calc(25.4545px + 4.5455vw), 80.0000px);--mantine-font-size-h1: clamp(28.0000px, calc(23.6364px + 1.3636vw), 40.0000px);--mantine-font-size-h2: clamp(24.0000px, calc(21.0909px + 0.9091vw), 32.0000px);--mantine-font-size-h3: clamp(20.0000px, calc(17.0909px + 0.9091vw), 28.0000px);--mantine-font-size-h4: clamp(16.0000px, calc(13.0909px + 0.9091vw), 24.0000px);--mantine-font-size-h5: clamp(16.0000px, calc(14.5455px + 0.4545vw), 20.0000px);--mantine-font-size-h6: 1rem;--mantine-primary-color-0: var(--mantine-color-indigo-0);--mantine-primary-color-1: var(--mantine-color-indigo-1);--mantine-primary-color-2: var(--mantine-color-indigo-2);--mantine-primary-color-3: var(--mantine-color-indigo-3);--mantine-primary-color-4: var(--mantine-color-indigo-4);--mantine-primary-color-5: var(--mantine-color-indigo-5);--mantine-primary-color-6: var(--mantine-color-indigo-6);--mantine-primary-color-7: var(--mantine-color-indigo-7);--mantine-primary-color-8: var(--mantine-color-indigo-8);--mantine-primary-color-9: var(--mantine-color-indigo-9);--mantine-color-red-0: #ffeaea;--mantine-color-red-1: #fed4d4;--mantine-color-red-2: #f4a7a8;--mantine-color-red-3: #ec7878;--mantine-color-red-4: #e55050;--mantine-color-red-5: #e03131;--mantine-color-red-6: #e02829;--mantine-color-red-7: #c71a1c;--mantine-color-red-8: #b21218;--mantine-color-red-9: #9c0411;--mantine-color-violet-0: #fce9ff;--mantine-color-violet-1: #f1cfff;--mantine-color-violet-2: #e09bff;--mantine-color-violet-3: #d16fff;--mantine-color-violet-4: #be37fe;--mantine-color-violet-5: #b51afe;--mantine-color-violet-6: #b009ff;--mantine-color-violet-7: #9b00e4;--mantine-color-violet-8: #8a00cc;--mantine-color-violet-9: #7800b3;--mantine-color-indigo-0: #edecff;--mantine-color-indigo-1: #d6d5fe;--mantine-color-indigo-2: #aaa9f4;--mantine-color-indigo-3: #7b79eb;--mantine-color-indigo-4: #5451e4;--mantine-color-indigo-5: #3b37e0;--mantine-color-indigo-6: #2d2adf;--mantine-color-indigo-7: #1f1ec7;--mantine-color-indigo-8: #1819b2;--mantine-color-indigo-9: #0c149e;--mantine-color-cyan-0: #dffdff;--mantine-color-cyan-1: #caf5ff;--mantine-color-cyan-2: #99e8ff;--mantine-color-cyan-3: #64daff;--mantine-color-cyan-4: #3ccffe;--mantine-color-cyan-5: #24c8fe;--mantine-color-cyan-6: #00c2ff;--mantine-color-cyan-7: #00ade4;--mantine-color-cyan-8: #009acd;--mantine-color-cyan-9: #0085b5;--mantine-color-green-0: #e9fdec;--mantine-color-green-1: #d7f6dc;--mantine-color-green-2: #b0eab9;--mantine-color-green-3: #86df94;--mantine-color-green-4: #62d574;--mantine-color-green-5: #4ccf5f;--mantine-color-green-6: #3fcc54;--mantine-color-green-7: #2fb344;--mantine-color-green-8: #25a03b;--mantine-color-green-9: #138a2e;--mantine-color-yellow-0: #fff7e2;--mantine-color-yellow-1: #ffeecd;--mantine-color-yellow-2: #ffdc9c;--mantine-color-yellow-3: #ffc966;--mantine-color-yellow-4: #feb93a;--mantine-color-yellow-5: #feae1e;--mantine-color-yellow-6: #ffa90f;--mantine-color-yellow-8: #ca8200;--mantine-color-yellow-9: #af7000;--mantine-h1-font-size: clamp(28.0000px, calc(23.6364px + 1.3636vw), 40.0000px);--mantine-h1-font-weight: normal;--mantine-h2-font-size: clamp(24.0000px, calc(21.0909px + 0.9091vw), 32.0000px);--mantine-h2-font-weight: normal;--mantine-h3-font-size: clamp(20.0000px, calc(17.0909px + 0.9091vw), 28.0000px);--mantine-h3-font-weight: normal;--mantine-h4-font-size: clamp(16.0000px, calc(13.0909px + 0.9091vw), 24.0000px);--mantine-h4-font-weight: normal;--mantine-h5-font-size: clamp(16.0000px, calc(14.5455px + 0.4545vw), 20.0000px);--mantine-h5-font-weight: normal;--mantine-h6-font-size: 1rem;--mantine-h6-font-weight: normal;}
:root[data-mantine-color-scheme="dark"], :host([data-mantine-color-scheme="dark"]){--mantine-color-anchor: var(--mantine-color-text);--mantine-color-dimmed: #495057;--mantine-color-dark-filled: var(--mantine-color-dark-5);--mantine-color-dark-filled-hover: var(--mantine-color-dark-6);--mantine-color-dark-light: rgba(105, 105, 105, 0.15);--mantine-color-dark-light-hover: rgba(105, 105, 105, 0.2);--mantine-color-dark-light-color: var(--mantine-color-dark-0);--mantine-color-dark-outline: var(--mantine-color-dark-1);--mantine-color-dark-outline-hover: rgba(184, 184, 184, 0.05);--mantine-color-gray-filled: var(--mantine-color-gray-5);--mantine-color-gray-filled-hover: var(--mantine-color-gray-6);--mantine-color-gray-light: rgba(222, 226, 230, 0.15);--mantine-color-gray-light-hover: rgba(222, 226, 230, 0.2);--mantine-color-gray-light-color: var(--mantine-color-gray-0);--mantine-color-gray-outline: var(--mantine-color-gray-1);--mantine-color-gray-outline-hover: rgba(241, 243, 245, 0.05);--mantine-color-red-filled: var(--mantine-color-red-5);--mantine-color-red-filled-hover: var(--mantine-color-red-6);--mantine-color-red-light: rgba(236, 120, 120, 0.15);--mantine-color-red-light-hover: rgba(236, 120, 120, 0.2);--mantine-color-red-light-color: var(--mantine-color-red-0);--mantine-color-red-outline: var(--mantine-color-red-1);--mantine-color-red-outline-hover: rgba(254, 212, 212, 0.05);--mantine-color-pink-filled: var(--mantine-color-pink-5);--mantine-color-pink-filled-hover: var(--mantine-color-pink-6);--mantine-color-pink-light: rgba(250, 162, 193, 0.15);--mantine-color-pink-light-hover: rgba(250, 162, 193, 0.2);--mantine-color-pink-light-color: var(--mantine-color-pink-0);--mantine-color-pink-outline: var(--mantine-color-pink-1);--mantine-color-pink-outline-hover: rgba(255, 222, 235, 0.05);--mantine-color-grape-filled: var(--mantine-color-grape-5);--mantine-color-grape-filled-hover: var(--mantine-color-grape-6);--mantine-color-grape-light: rgba(229, 153, 247, 0.15);--mantine-color-grape-light-hover: rgba(229, 153, 247, 0.2);--mantine-color-grape-light-color: var(--mantine-color-grape-0);--mantine-color-grape-outline: var(--mantine-color-grape-1);--mantine-color-grape-outline-hover: rgba(243, 217, 250, 0.05);--mantine-color-violet-filled: var(--mantine-color-violet-5);--mantine-color-violet-filled-hover: var(--mantine-color-violet-6);--mantine-color-violet-light: rgba(209, 111, 255, 0.15);--mantine-color-violet-light-hover: rgba(209, 111, 255, 0.2);--mantine-color-violet-light-color: var(--mantine-color-violet-0);--mantine-color-violet-outline: var(--mantine-color-violet-1);--mantine-color-violet-outline-hover: rgba(241, 207, 255, 0.05);--mantine-color-indigo-filled: var(--mantine-color-indigo-5);--mantine-color-indigo-filled-hover: var(--mantine-color-indigo-6);--mantine-color-indigo-light: rgba(123, 121, 235, 0.15);--mantine-color-indigo-light-hover: rgba(123, 121, 235, 0.2);--mantine-color-indigo-light-color: var(--mantine-color-indigo-0);--mantine-color-indigo-outline: var(--mantine-color-indigo-1);--mantine-color-indigo-outline-hover: rgba(214, 213, 254, 0.05);--mantine-color-blue-filled: var(--mantine-color-blue-5);--mantine-color-blue-filled-hover: var(--mantine-color-blue-6);--mantine-color-blue-light: rgba(116, 192, 252, 0.15);--mantine-color-blue-light-hover: rgba(116, 192, 252, 0.2);--mantine-color-blue-light-color: var(--mantine-color-blue-0);--mantine-color-blue-outline: var(--mantine-color-blue-1);--mantine-color-blue-outline-hover: rgba(208, 235, 255, 0.05);--mantine-color-cyan-filled: var(--mantine-color-cyan-5);--mantine-color-cyan-filled-hover: var(--mantine-color-cyan-6);--mantine-color-cyan-light: rgba(100, 218, 255, 0.15);--mantine-color-cyan-light-hover: rgba(100, 218, 255, 0.2);--mantine-color-cyan-light-color: var(--mantine-color-cyan-0);--mantine-color-cyan-outline: var(--mantine-color-cyan-1);--mantine-color-cyan-outline-hover: rgba(202, 245, 255, 0.05);--mantine-color-teal-filled: var(--mantine-color-teal-5);--mantine-color-teal-filled-hover: var(--mantine-color-teal-6);--mantine-color-teal-light: rgba(99, 230, 190, 0.15);--mantine-color-teal-light-hover: rgba(99, 230, 190, 0.2);--mantine-color-teal-light-color: var(--mantine-color-teal-0);--mantine-color-teal-outline: var(--mantine-color-teal-1);--mantine-color-teal-outline-hover: rgba(195, 250, 232, 0.05);--mantine-color-green-filled: var(--mantine-color-green-5);--mantine-color-green-filled-hover: var(--mantine-color-green-6);--mantine-color-green-light: rgba(134, 223, 148, 0.15);--mantine-color-green-light-hover: rgba(134, 223, 148, 0.2);--mantine-color-green-light-color: var(--mantine-color-green-0);--mantine-color-green-outline: var(--mantine-color-green-1);--mantine-color-green-outline-hover: rgba(215, 246, 220, 0.05);--mantine-color-lime-filled: var(--mantine-color-lime-5);--mantine-color-lime-filled-hover: var(--mantine-color-lime-6);--mantine-color-lime-light: rgba(192, 235, 117, 0.15);--mantine-color-lime-light-hover: rgba(192, 235, 117, 0.2);--mantine-color-lime-light-color: var(--mantine-color-lime-0);--mantine-color-lime-outline: var(--mantine-color-lime-1);--mantine-color-lime-outline-hover: rgba(233, 250, 200, 0.05);--mantine-color-yellow-filled: var(--mantine-color-yellow-5);--mantine-color-yellow-filled-hover: var(--mantine-color-yellow-6);--mantine-color-yellow-light: rgba(255, 201, 102, 0.15);--mantine-color-yellow-light-hover: rgba(255, 201, 102, 0.2);--mantine-color-yellow-light-color: var(--mantine-color-yellow-0);--mantine-color-yellow-outline: var(--mantine-color-yellow-1);--mantine-color-yellow-outline-hover: rgba(255, 238, 205, 0.05);--mantine-color-orange-filled: var(--mantine-color-orange-5);--mantine-color-orange-filled-hover: var(--mantine-color-orange-6);--mantine-color-orange-light: rgba(255, 192, 120, 0.15);--mantine-color-orange-light-hover: rgba(255, 192, 120, 0.2);--mantine-color-orange-light-color: var(--mantine-color-orange-0);--mantine-color-orange-outline: var(--mantine-color-orange-1);--mantine-color-orange-outline-hover: rgba(255, 232, 204, 0.05);--app-cta-gradient: linear-gradient(90deg, var(--mantine-color-blue-9) 0%, var(--mantine-color-cyan-7) 100%);--app-color-surface: #2e2e2e;}
:root[data-mantine-color-scheme="light"], :host([data-mantine-color-scheme="light"]){--mantine-color-anchor: var(--mantine-color-text);--mantine-color-dimmed: #495057;--mantine-color-red-light: rgba(224, 40, 41, 0.1);--mantine-color-red-light-hover: rgba(224, 40, 41, 0.12);--mantine-color-red-outline-hover: rgba(224, 40, 41, 0.05);--mantine-color-violet-light: rgba(176, 9, 255, 0.1);--mantine-color-violet-light-hover: rgba(176, 9, 255, 0.12);--mantine-color-violet-outline-hover: rgba(176, 9, 255, 0.05);--mantine-color-indigo-light: rgba(45, 42, 223, 0.1);--mantine-color-indigo-light-hover: rgba(45, 42, 223, 0.12);--mantine-color-indigo-outline-hover: rgba(45, 42, 223, 0.05);--mantine-color-cyan-light: rgba(0, 194, 255, 0.1);--mantine-color-cyan-light-hover: rgba(0, 194, 255, 0.12);--mantine-color-cyan-outline-hover: rgba(0, 194, 255, 0.05);--mantine-color-green-light: rgba(63, 204, 84, 0.1);--mantine-color-green-light-hover: rgba(63, 204, 84, 0.12);--mantine-color-green-outline-hover: rgba(63, 204, 84, 0.05);--mantine-color-yellow-light: rgba(255, 169, 15, 0.1);--mantine-color-yellow-light-hover: rgba(255, 169, 15, 0.12);--mantine-color-yellow-outline-hover: rgba(255, 169, 15, 0.05);--app-color-surface: #f1f3f5;--app-cta-gradient: linear-gradient(90deg, var(--mantine-color-blue-filled) 0%, var(--mantine-color-cyan-5) 100%);}</style><style data-mantine-styles="classes">@media (max-width: 35.99375em) {.mantine-visible-from-xs {display: none !important;}}@media (min-width: 36em) {.mantine-hidden-from-xs {display: none !important;}}@media (max-width: 47.99375em) {.mantine-visible-from-sm {display: none !important;}}@media (min-width: 48em) {.mantine-hidden-from-sm {display: none !important;}}@media (max-width: 61.99375em) {.mantine-visible-from-md {display: none !important;}}@media (min-width: 62em) {.mantine-hidden-from-md {display: none !important;}}@media (max-width: 74.99375em) {.mantine-visible-from-lg {display: none !important;}}@media (min-width: 75em) {.mantine-hidden-from-lg {display: none !important;}}@media (max-width: 87.99375em) {.mantine-visible-from-xl {display: none !important;}}@media (min-width: 88em) {.mantine-hidden-from-xl {display: none !important;}}</style><div style="position:absolute;top:0rem" class=""></div><div style="max-width:var(--container-size-xl);height:100%;min-height:0rem" class=""><style data-mantine-styles="inline">.__m__-_R_5ub_{--grid-gutter:0rem;}</style><div style="height:100%;min-height:0rem" class="m_410352e9 mantine-Grid-root __m__-_R_5ub_"><div class="m_dee7bd2f mantine-Grid-inner" style="height:100%"><style data-mantine-styles="inline">.__m__-_R_rdub_{--col-flex-grow:auto;--col-flex-basis:91.66666666666667%;--col-max-width:91.66666666666667%;}@media(min-width: 48em){.__m__-_R_rdub_{--col-flex-grow:auto;--col-flex-basis:83.33333333333334%;--col-max-width:83.33333333333334%;}}</style><div style="min-width:0rem;height:100%;min-height:0rem;display:flex" class="m_96bdd299 mantine-Grid-col __m__-_R_rdub_"><style data-mantine-styles="inline">.__m__-_R_6qrdub_{margin-top:0rem;padding-inline:var(--mantine-spacing-xs);width:100%;}@media(min-width: 48em){.__m__-_R_6qrdub_{margin-top:var(--mantine-spacing-xl);width:80%;}}@media(min-width: 62em){.__m__-_R_6qrdub_{padding-inline:var(--mantine-spacing-xl);}}</style><div style="margin-inline:auto;max-width:var(--mantine-breakpoint-xl)" class="__m__-_R_6qrdub_"><div style="color:var(--mantine-color-dimmed)" class="m_4451eb3a mantine-Center-root" data-inline="true"><div style="--ti-size:var(--ti-size-xs);--ti-bg:transparent;--ti-color:var(--mantine-color-indigo-light-color);--ti-bd:calc(0.0625rem * var(--mantine-scale)) solid transparent;margin-inline-end:calc(0.125rem * var(--mantine-scale));color:inherit" class="m_7341320d mantine-ThemeIcon-root" data-variant="transparent" data-size="xs"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-lock "><path d="M5 13a2 2 0 0 1 2 -2h10a2 2 0 0 1 2 2v6a2 2 0 0 1 -2 2h-10a2 2 0 0 1 -2 -2v-6"></path><path d="M11 16a1 1 0 1 0 2 0a1 1 0 0 0 -2 0"></path><path d="M8 11v-4a4 4 0 1 1 8 0v4"></path></svg></div><p style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Основы реляционных баз данных</p></div><h1 style="--title-fw:var(--mantine-h1-font-weight);--title-lh:var(--mantine-h1-line-height);--title-fz:var(--mantine-h1-font-size);margin-bottom:var(--mantine-spacing-xl)" class="m_8a5d1357 mantine-Title-root" data-order="1">Теория: Создание таблиц</h1><script type="application/ld+json">{"@context":"https://schema.org","@type":"LearningResource","name":"Создание таблиц","inLanguage":"ru","isPartOf":{"@type":"LearningResource","name":"Основы реляционных баз данных"},"isAccessibleForFree":"False","hasPart":{"@type":"WebPageElement","isAccessibleForFree":"False","cssSelector":".paywalled"}}</script><div class=""><div style="--alert-color:var(--mantine-color-indigo-light-color);margin-bottom:var(--mantine-spacing-lg);font-size:var(--mantine-font-size-lg)" class="m_66836ed3 mantine-Alert-root" id="mantine-_R_remqrdub_" role="alert" aria-describedby="mantine-_R_remqrdub_-body" aria-labelledby="mantine-_R_remqrdub_-title"><div class="m_a5d60502 mantine-Alert-wrapper"><div class="m_667f2a6a mantine-Alert-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-rocket "><path d="M4 13a8 8 0 0 1 7 7a6 6 0 0 0 3 -5a9 9 0 0 0 6 -8a3 3 0 0 0 -3 -3a9 9 0 0 0 -8 6a6 6 0 0 0 -5 3"></path><path d="M7 14a6 6 0 0 0 -3 6a6 6 0 0 0 6 -3"></path><path d="M14 9a1 1 0 1 0 2 0a1 1 0 1 0 -2 0"></path></svg></div><div class="m_667c2793 mantine-Alert-body"><div class="m_6a03f287 mantine-Alert-title"><span id="mantine-_R_remqrdub_-title" class="m_698f4f23 mantine-Alert-label">Полный доступ к материалам</span></div><div id="mantine-_R_remqrdub_-body" class="m_7fa78076 mantine-Alert-message"><div style="--group-gap:var(--mantine-spacing-md);--group-align:center;--group-justify:space-between;--group-wrap:wrap" class="m_4081bf90 mantine-Group-root"><p class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Зарегистрируйтесь и получите доступ к этому и десяткам других курсов</p><a style="--button-height:var(--button-height-xs);--button-padding-x:var(--button-padding-x-xs);--button-fz:var(--mantine-font-size-xs);--button-bg:linear-gradient(45deg, var(--mantine-color-blue-filled) 0%, var(--mantine-color-cyan-filled) 100%);--button-hover:linear-gradient(45deg, var(--mantine-color-blue-filled) 0%, var(--mantine-color-cyan-filled) 100%);--button-color:var(--mantine-color-white);--button-bd:none" class="mantine-focus-auto mantine-active m_77c9d27d mantine-Button-root m_87cf2631 mantine-UnstyledButton-root" data-variant="gradient" data-size="xs" href="/u/new"><span class="m_80f1301b mantine-Button-inner"><span class="m_811560b9 mantine-Button-label">Зарегистрироваться</span></span></a></div></div></div></div></div><div class="paywalled m_d08caa0 mantine-Typography-root"><p>В этом уроке мы поработаем с таблицами: будем создавать их, добавлять, модифицировать и удалять данные. Также разберем типы данных таблицы.</p>
<h2 id="heading-2-1">Создание базы данных</h2>
<p>Прежде чем создать таблицу, создадим базу данных <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">hexlet</code> с помощью SQL (если вы еще этого не сделали). Для этого подключитесь к СУБД через <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">psql</code>. При этом не указывайте базу данных, чтобы подключиться к базе по умолчанию. Далее выполните следующие запросы:</p>
<div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlight-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlight-controls"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlight-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlight-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlight-pre" style="padding:0"><code class="m_5caae6d3 mantine-CodeHighlight-code">DROP DATABASE hexlet;
CREATE DATABASE hexlet;</code></pre></div></div></div><button class="mantine-focus-auto m_c9378bc2 mantine-CodeHighlight-showCodeButton m_87cf2631 mantine-UnstyledButton-root" data-hidden="true" type="button">Expand code</button></div>
<p>В примере выше два SQL запроса:</p>
<ul>
<li>
<p><code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">DROP DATABASE hexlet</code> — удаляет базу данных с именем <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">hexlet</code></p>
</li>
<li>
<p><code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">CREATE DATABASE hexlet</code> — создает базу данных с таким же именем</p>
</li>
</ul>
<p>Базовые правила построения запросов:</p>
<ul>
<li>
<p>Каждый запрос должен заканчиваться точкой с запятой. Иначе <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">psql</code> будет думать, что вы продолжаете вводить команды</p>
</li>
<li>
<p>Регистр не важен. Можно было написать <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">drop database hexlet;</code>. По традиции принято использовать верхний регистр для ключевых слов самого SQL. Это позволяет визуально разделять структуру запроса от данных внутри него. Последнее в примере — это имя базы данных, которое может быть произвольным</p>
</li>
</ul>
<p>Если подключиться к той же базе данных, которую вы хотите удалить или пересоздать, то во время попытки удаления СУБД будет ругаться, что к базе есть активное соединение — ваше соединение. Поэтому важно подключиться к любой другой базе данных.</p>
<p>Команды <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">createdb</code> и <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">createuser</code>, которые мы разобрали в прошлых уроках, выполняют SQL-запросы внутри СУБД. Их сделали ради удобства первоначальной настройки, и чтобы использовать в скриптах автоматизации.</p>
<p>SQL поддерживает <strong>комментарии</strong> — строчка, которая начинается с двух дефисов. Комментарии игнорируются СУБД при построении запросов:</p>
<div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlight-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlight-controls"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlight-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlight-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlight-pre" style="padding:0"><code class="m_5caae6d3 mantine-CodeHighlight-code">hexlet=> -- i am comment
hexlet=></code></pre></div></div></div><button class="mantine-focus-auto m_c9378bc2 mantine-CodeHighlight-showCodeButton m_87cf2631 mantine-UnstyledButton-root" data-hidden="true" type="button">Expand code</button></div>
<p>Нам удалось создать базу данных <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">hexlet</code>, поэтому можно переходить к созданию таблицы. Подключитесь к созданной базе данных</p>
<h2 id="heading-2-2">Создание таблиц</h2>
<p>Таблица создается с помощью запроса <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">CREATE TABLE</code>:</p>
<div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlight-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlight-controls"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlight-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlight-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlight-pre" style="padding:0"><code class="m_5caae6d3 mantine-CodeHighlight-code">-- Это один запрос, хоть и многострочный.
-- Описание запроса заканчивается символом ;
CREATE TABLE courses (
name varchar(255),
slug varchar(255),
lessons_count integer,
body text
);</code></pre></div></div></div><button class="mantine-focus-auto m_c9378bc2 mantine-CodeHighlight-showCodeButton m_87cf2631 mantine-UnstyledButton-root" data-hidden="true" type="button">Expand code</button></div>
<p>Чтобы создать таблицу, необходимо указать ее имя, набор полей и их типы. В примере выше названия полей — это <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">name</code>, <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">slug</code>, <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">lessons_count</code> и <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">body</code>, а <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">varchar(255)</code>, <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">integer</code> и <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">text</code> — их типы.</p>
<h3 id="heading-3-3">Типы данных</h3>
<p>У каждого поля в PostgreSQL определенный тип, который задается на этапе создания таблицы. Это значит, что значением этого поля могут быть только определенные данные. Если поле имеет числовой тип, то в него невозможно вставить строку, и наоборот. База данных выдаст ошибку при попытке выполнить подобный запрос.</p>
<div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlight-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlight-controls"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlight-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlight-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlight-pre" style="padding:0"><code class="m_5caae6d3 mantine-CodeHighlight-code">-- Выполняем запрос на вставку передавая в lessons_count строку вместо числа
ERROR: invalid input syntax for type integer: "wrong value"</code></pre></div></div></div><button class="mantine-focus-auto m_c9378bc2 mantine-CodeHighlight-showCodeButton m_87cf2631 mantine-UnstyledButton-root" data-hidden="true" type="button">Expand code</button></div>
<p>В PostgreSQL встроено много различных типов данных, но на практике используются не все. Ниже мы разбираем только самые популярные типы.</p>
<h4 id="heading-4-4">Строки</h4>
<p>Для строк в базах данных в основном используются два типа:</p>
<ul>
<li><em>varchar</em> — для строк с ограничением максимальной длины</li>
<li><em>text</em> — для строк без ограничения. Как правило, это полноценные тексты</li>
</ul>
<p>В базах данных нельзя оставить первый тип без указания длины. Это связано с производительностью и эффективностью. Данные в базах данных физически хранятся на дисках в файлах. Быстрый доступ к этим данным возможен только тогда, когда у данных фиксированный размер. Это позволяет быстро перемещаться по ним и считать смещения.</p>
<p>Если размер данных не известен, то придется просматривать весь файл в поисках нужного значения. Чтобы избежать подобной ситуации, тип <em>text</em> хранится отдельно. Это тоже негативно влияет на скорость, но уже не так сильно. Если размер строки известен или он меньше какого-то значения, то предпочтительнее использовать <em>varchar</em>.</p>
<div style="--table-min-width:calc(50rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_a100c15 mantine-TableScrollContainer-scrollContainer m_d57069b5 mantine-ScrollArea-root"><div style="overflow-x:hidden;overflow-y:hidden" class="m_c0783ff9 mantine-ScrollArea-viewport" data-offset-scrollbars="x" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><div class="m_62259741 mantine-TableScrollContainer-scrollContainerInner"><table><thead><tr><th>Имя</th><th>Описание</th></tr></thead><tbody><tr><td>character varying(n), varchar(n)</td><td>строка ограниченной переменной длины</td></tr><tr><td>text</td><td>строка неограниченной переменной длины</td></tr></tbody></table></div></div></div></div>
<ul>
<li>
<p><em>varchar</em>. Полное название типа <em>character varying</em> (<em>varchar</em> может использоваться как псевдоним). Размер строки с таким типом указывается в скобках после названия типа, например, <em>varchar(10)</em>. Это значит, что в поле с таким типом можно записать строку длиной до 10 символов.</p>
</li>
<li>
<p><em>text</em>. Не требует указания размера и может содержать текст произвольной длины</p>
</li>
</ul>
<p>Пример создания таблицы с такими типами:</p>
<div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlight-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlight-controls"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlight-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlight-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlight-pre" style="padding:0"><code class="m_5caae6d3 mantine-CodeHighlight-code">CREATE TABLE blog_posts (
name varchar(80),
body text
);</code></pre></div></div></div><button class="mantine-focus-auto m_c9378bc2 mantine-CodeHighlight-showCodeButton m_87cf2631 mantine-UnstyledButton-root" data-hidden="true" type="button">Expand code</button></div>
<h4 id="heading-4-5">Числа</h4>
<p>Для чисел в основном используются два типа данных: <em>integer</em> и <em>bigint</em>. Какой конкретно указывать тип, зависит от потенциального потолка значения. Ниже указаны диапазоны, допустимые в рамках этих типов:</p>
<div style="--table-min-width:calc(50rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_a100c15 mantine-TableScrollContainer-scrollContainer m_d57069b5 mantine-ScrollArea-root"><div style="overflow-x:hidden;overflow-y:hidden" class="m_c0783ff9 mantine-ScrollArea-viewport" data-offset-scrollbars="x" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><div class="m_62259741 mantine-TableScrollContainer-scrollContainerInner"><table><thead><tr><th>Имя</th><th>Описание</th><th>Диапазон</th></tr></thead><tbody><tr><td>integer</td><td>типичный выбор для целых чисел</td><td>-2147483648 .. +2147483647</td></tr><tr><td>bigint</td><td>целое в большом диапазоне</td><td>-9223372036854775808 .. 9223372036854775807</td></tr></tbody></table></div></div></div></div>
<p>Пример создания таблицы с такими типами:</p>
<div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlight-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlight-controls"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlight-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlight-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlight-pre" style="padding:0"><code class="m_5caae6d3 mantine-CodeHighlight-code">CREATE TABLE users (
id bigint,
age integer
);</code></pre></div></div></div><button class="mantine-focus-auto m_c9378bc2 mantine-CodeHighlight-showCodeButton m_87cf2631 mantine-UnstyledButton-root" data-hidden="true" type="button">Expand code</button></div>
<h4 id="heading-4-6">Даты</h4>
<p>Типы для хранения дат отличаются друг от друга очень сильно, в первую очередь по решаемой задаче. Нам надо хранить день без конкретного времени? Это тип <em>date</em>. Нужно конкретный момент времени, тогда <em>timestamp</em>. Просто время без даты? Тогда <em>time</em>.</p>
<div style="--table-min-width:calc(50rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_a100c15 mantine-TableScrollContainer-scrollContainer m_d57069b5 mantine-ScrollArea-root"><div style="overflow-x:hidden;overflow-y:hidden" class="m_c0783ff9 mantine-ScrollArea-viewport" data-offset-scrollbars="x" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><div class="m_62259741 mantine-TableScrollContainer-scrollContainerInner"><table><thead><tr><th>Имя</th><th>Описание</th><th>Наименьшее значение</th><th>Наибольшее значение</th><th>Точность</th></tr></thead><tbody><tr><td>timestamp</td><td>дата и время (без часового пояса)</td><td>4713 до н. э.</td><td>294276 н. э.</td><td>1 микросекунда</td></tr><tr><td>date</td><td>дата (без времени суток)</td><td>4713 до н. э.</td><td>5874897 н. э.</td><td>1 день</td></tr><tr><td>time</td><td>время суток (без даты)</td><td>00:00<div></div></td><td>24:00<div></div></td><td>1 микросекунда</td></tr></tbody></table></div></div></div></div>
<p>Пример создания таблицы с такими типами:</p>
<div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlight-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlight-controls"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlight-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlight-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlight-pre" style="padding:0"><code class="m_5caae6d3 mantine-CodeHighlight-code">CREATE TABLE events (
start_date date,
-- имя поля может называться как тип данных
time time,
updated_at timestamp,
created_at timestamp
);</code></pre></div></div></div><button class="mantine-focus-auto m_c9378bc2 mantine-CodeHighlight-showCodeButton m_87cf2631 mantine-UnstyledButton-root" data-hidden="true" type="button">Expand code</button></div>
<p>Хорошей практикой считается добавление и заполнение полей <em>created_at</em> и <em>updated_at</em> в каждую таблицу базы данных. С их помощью всегда можно узнать, когда запись создалась и обновилась.</p>
<p>Значения даты и времени принимаются практически в любом известном формате. Вот несколько примеров того, как можно задавать дату:</p>
<div style="--table-min-width:calc(50rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_a100c15 mantine-TableScrollContainer-scrollContainer m_d57069b5 mantine-ScrollArea-root"><div style="overflow-x:hidden;overflow-y:hidden" class="m_c0783ff9 mantine-ScrollArea-viewport" data-offset-scrollbars="x" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><div class="m_62259741 mantine-TableScrollContainer-scrollContainerInner"><table><thead><tr><th>Пример</th><th>Описание</th></tr></thead><tbody><tr><td>1999-01-08</td><td>ISO 8601 (рекомендуемый формат)</td></tr><tr><td>January 8, 1999</td><td></td></tr></tbody></table></div></div></div></div>
<h4 id="heading-4-7">Логический тип</h4>
<p>Содержит всего два значения: <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">true</code> и <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">false</code>. Этот тип используется для флагов:</p>
<div style="--table-min-width:calc(50rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_a100c15 mantine-TableScrollContainer-scrollContainer m_d57069b5 mantine-ScrollArea-root"><div style="overflow-x:hidden;overflow-y:hidden" class="m_c0783ff9 mantine-ScrollArea-viewport" data-offset-scrollbars="x" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><div class="m_62259741 mantine-TableScrollContainer-scrollContainerInner"><table><thead><tr><th>Имя</th><th>Описание</th></tr></thead><tbody><tr><td>boolean</td><td>true или false (истина или ложь)</td></tr></tbody></table></div></div></div></div>
<p>Пример создания таблицы с такими типами:</p>
<div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlight-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlight-controls"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlight-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlight-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlight-pre" style="padding:0"><code class="m_5caae6d3 mantine-CodeHighlight-code">CREATE TABLE blog_posts (
-- флаг: опубликован?
published boolean
);</code></pre></div></div></div><button class="mantine-focus-auto m_c9378bc2 mantine-CodeHighlight-showCodeButton m_87cf2631 mantine-UnstyledButton-root" data-hidden="true" type="button">Expand code</button></div>
<p>Состояние «true» может задаваться следующими значениями:</p>
<code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">TRUE
't'
'true'
'y'
'yes'
'on'
'1'</code>
<p>Для состояния «false» можно использовать следующие варианты:</p>
<code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">FALSE
'f'
'false'
'n'
'no'
'off'
'0'</code>
<h4 id="heading-4-8">NULL</h4>
<p>Помимо типов данных для реальных значений, в базе существует специальное значение <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">NULL</code>, чтобы обозначать пустоту. Оно используется, когда у конкретного поля нет значения. Тип поля при этом не важен. Подробнее с <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">NULL</code> мы разберемся в следующих уроках.</p>
<h2 id="heading-2-9">Анализ структуры базы данных</h2>
<p>Чтобы исследовать структуру таблиц в визуальном режиме, используется <em>PgAdmin</em>:</p>
<p><img style="--image-object-fit:contain;width:auto" class="m_9e117634 mantine-Image-root" src="/rails/active_storage/blobs/proxy/eyJfcmFpbHMiOnsiZGF0YSI6NjA4OSwicHVyIjoiYmxvYl9pZCJ9fQ==--1a8e7f81df07b5829af6bef1238847390360dfde/pgadmin-create-table.png" alt="PgAdmin" loading="lazy"/></p>
<p>SQL для анализа структуры базы данных не существует. Если вы хотите посмотреть список таблиц и их структуру в базе данных, то придется использовать команды самого <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">psql</code>:</p>
<p><strong>Просмотр списка таблиц базы данных hexlet</strong></p>
<div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlight-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlight-controls"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlight-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlight-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlight-pre" style="padding:0"><code class="m_5caae6d3 mantine-CodeHighlight-code">hexlet=> \d
List of relations
Schema | Name | Type | Owner
--------+------------+-------+---------
public | courses | table | vagrant
public | events | table | vagrant
public | blog_posts | table | vagrant</code></pre></div></div></div><button class="mantine-focus-auto m_c9378bc2 mantine-CodeHighlight-showCodeButton m_87cf2631 mantine-UnstyledButton-root" data-hidden="true" type="button">Expand code</button></div>
<p>Здесь мы видим список таблиц в базе данных <em>hexlet</em>. Все что здесь отображается, было создано в этом уроке выше.</p>
<p>В первом столбце видим новое для нас понятие — <em>schema</em>. Это пространство имен, которое позволяет группировать таблицы в различных ситуациях. На практике эта возможность используется редко, поэтому мы не обращаем на нее внимание. По умолчанию все таблицы публикуются в общей схеме <em>public</em>, которую можно не указывать.</p>
<p><strong>Просмотр структуры таблицы courses</strong></p>
<div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlight-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlight-controls"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlight-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlight-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlight-pre" style="padding:0"><code class="m_5caae6d3 mantine-CodeHighlight-code">hexlet=> \d courses
# public - обозначает схему по умолчанию
Table "public.courses"
Column | Type | Modifiers
---------------+------------------------+-----------
name | character varying(255) |
slug | character varying(255) |
lessons_count | integer |
body | text |</code></pre></div></div></div><button class="mantine-focus-auto m_c9378bc2 mantine-CodeHighlight-showCodeButton m_87cf2631 mantine-UnstyledButton-root" data-hidden="true" type="button">Expand code</button></div>
<p>В этом выводе показана структура таблицы <em>courses</em>. Здесь мы видим все имена полей и их типы.</p>
<p>Кроме перечисленных полезными могут оказаться следующие команды:</p>
<ul>
<li><code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">\l</code> — список всех баз данных</li>
<li><code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">\dt</code> — список всех таблиц</li>
<li><code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">\?</code> — вывод справки</li>
</ul>
<h2 id="heading-2-10">Удаление таблиц</h2>
<p>Чтобы удалить таблицу, выполняется запрос <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">DROP</code>:</p>
<div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlight-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlight-controls"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlight-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlight-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlight-pre" style="padding:0"><code class="m_5caae6d3 mantine-CodeHighlight-code">DROP TABLE courses;</code></pre></div></div></div><button class="mantine-focus-auto m_c9378bc2 mantine-CodeHighlight-showCodeButton m_87cf2631 mantine-UnstyledButton-root" data-hidden="true" type="button">Expand code</button></div>
<p>Будьте внимательны, так как удаление таблицы приводит к безвозвратной потере данных.</p>
<h2 id="heading-2-11">Выводы</h2>
<p>В этом уроке мы разобрали работу с таблицами: создавали базу данных и таблицу, устанавливали типы данных и анализировали структуру базы. Еще мы показали, как удалять таблицу. Попрактикуйтесь создавать таблицы — проходите каждый шаг, описанный в уроке, и со временем для вас это станет легкой задачей.</p></div></div></div></div><style data-mantine-styles="inline">.__m__-_R_1bdub_{--col-flex-grow:auto;--col-flex-basis:8.333333333333334%;--col-max-width:8.333333333333334%;}@media(min-width: 48em){.__m__-_R_1bdub_{--col-flex-grow:auto;--col-flex-basis:16.666666666666668%;--col-max-width:16.666666666666668%;}}</style><div style="min-width:0rem;height:100%;min-height:0rem" class="m_96bdd299 mantine-Grid-col __m__-_R_1bdub_"><div style="margin-inline:var(--mantine-spacing-xs)" class="mantine-visible-from-sm"><a style="--button-color:var(--mantine-color-white);margin-bottom:var(--mantine-spacing-lg);text-decoration:none" class="mantine-focus-auto m_849cf0da mantine-focus-auto m_77c9d27d mantine-Button-root m_87cf2631 mantine-UnstyledButton-root m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="/courses/rdb-basics/lessons/sql-ddl/finish_unit?unit=theory" data-disabled="true" data-block="true" disabled=""><span class="m_80f1301b mantine-Button-inner"><span class="m_811560b9 mantine-Button-label"><span style="margin-inline-end:var(--mantine-spacing-xs)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Дальше</span>→</span></span></a><a style="padding-inline:0rem" class="mantine-focus-auto m_f0824112 mantine-NavLink-root m_87cf2631 mantine-UnstyledButton-root"><span class="m_690090b5 mantine-NavLink-section" data-position="left"><div style="--ti-size:var(--ti-size-sm);--ti-bg:transparent;--ti-color:var(--mantine-color-indigo-light-color);--ti-bd:calc(0.0625rem * var(--mantine-scale)) solid transparent;color:inherit" class="m_7341320d mantine-ThemeIcon-root" data-variant="transparent" data-size="sm"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-list-numbers "><path d="M11 6h9"></path><path d="M11 12h9"></path><path d="M12 18h8"></path><path d="M4 16a2 2 0 1 1 4 0c0 .591 -.5 1 -1 1.5l-3 2.5h4"></path><path d="M6 10v-6l-2 2"></path></svg></div></span><div class="m_f07af9d2 mantine-NavLink-body"><span class="m_1f6ac4c4 mantine-NavLink-label">Навигация по теме</span><span class="m_57492dcc mantine-NavLink-description">Теория</span></div><span class="m_690090b5 mantine-NavLink-section" data-position="right"></span></a><div style="margin-block:var(--mantine-spacing-lg)" class="m_3eebeb36 mantine-Divider-root" data-orientation="horizontal" role="separator"></div><div style="margin-block:var(--mantine-spacing-lg)" class=""><div style="justify-content:space-between;margin-bottom:calc(0.1875rem * var(--mantine-scale));color:var(--mantine-color-dimmed);font-size:var(--mantine-font-size-xs)" class="m_8bffd616 mantine-Flex-root __m__-_R_qimrbdub_"><p style="font-size:var(--mantine-font-size-xs)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Завершено</p><p style="font-size:var(--mantine-font-size-xs)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">0 / 24</p></div><div style="--progress-size:var(--progress-size-sm)" class="m_db6d6462 mantine-Progress-root" data-size="sm"><div style="--progress-section-size:0%;--progress-section-color:var(--mantine-color-gray-filled)" class="m_2242eb65 mantine-Progress-section" role="progressbar" aria-valuemax="100" aria-valuemin="0" aria-valuenow="0" aria-valuetext="0%"></div></div></div><button style="padding-inline:0rem" class="mantine-focus-auto m_f0824112 mantine-NavLink-root m_87cf2631 mantine-UnstyledButton-root" type="button"><span class="m_690090b5 mantine-NavLink-section" data-position="left"><div style="--ti-size:var(--ti-size-sm);--ti-bg:transparent;--ti-color:var(--mantine-color-indigo-light-color);--ti-bd:calc(0.0625rem * var(--mantine-scale)) solid transparent;color:inherit" class="m_7341320d mantine-ThemeIcon-root" data-variant="transparent" data-size="sm"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-message "><path d="M8 9h8"></path><path d="M8 13h6"></path><path d="M18 4a3 3 0 0 1 3 3v8a3 3 0 0 1 -3 3h-5l-5 3v-3h-2a3 3 0 0 1 -3 -3v-8a3 3 0 0 1 3 -3h12"></path></svg></div></span><div class="m_f07af9d2 mantine-NavLink-body"><span class="m_1f6ac4c4 mantine-NavLink-label">Обсуждения (архив)</span><span class="m_57492dcc mantine-NavLink-description"></span></div></button><div style="--toc-bg:var(--mantine-color-blue-light);--toc-color:var(--mantine-color-blue-light-color);--toc-size:var(--mantine-font-size-sm);--toc-radius:var(--mantine-radius-sm);margin-top:var(--mantine-spacing-xl)" class="m_bcaa9990 mantine-TableOfContents-root" data-variant="light" data-size="sm"></div></div><div class="mantine-hidden-from-sm"><div style="--stack-gap:0rem;--stack-align:stretch;--stack-justify:flex-start" class="m_6d731127 mantine-Stack-root"><a style="--button-color:var(--mantine-color-white);margin-bottom:var(--mantine-spacing-xs);padding:0rem;text-decoration:none" class="mantine-focus-auto m_849cf0da mantine-focus-auto m_77c9d27d mantine-Button-root m_87cf2631 mantine-UnstyledButton-root m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="/courses/rdb-basics/lessons/sql-ddl/finish_unit?unit=theory" data-disabled="true" data-block="true" disabled=""><span class="m_80f1301b mantine-Button-inner"><span class="m_811560b9 mantine-Button-label">→</span></span></a><button style="--ai-size:var(--ai-size-sm);--ai-bg:transparent;--ai-hover:var(--mantine-color-indigo-light-hover);--ai-color:var(--mantine-color-indigo-light-color);--ai-bd:calc(0.0625rem * var(--mantine-scale)) solid transparent;padding-block:var(--mantine-spacing-lg);color:inherit;width:100%" class="mantine-focus-auto m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="subtle" data-size="sm" data-disabled="true" type="button" disabled=""><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-list-numbers "><path d="M11 6h9"></path><path d="M11 12h9"></path><path d="M12 18h8"></path><path d="M4 16a2 2 0 1 1 4 0c0 .591 -.5 1 -1 1.5l-3 2.5h4"></path><path d="M6 10v-6l-2 2"></path></svg></span></button><button style="--ai-size:var(--ai-size-sm);--ai-bg:transparent;--ai-hover:var(--mantine-color-indigo-light-hover);--ai-color:var(--mantine-color-indigo-light-color);--ai-bd:calc(0.0625rem * var(--mantine-scale)) solid transparent;padding-block:var(--mantine-spacing-lg);color:inherit;width:100%" class="mantine-focus-auto mantine-active m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="subtle" data-size="sm" type="button"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-message "><path d="M8 9h8"></path><path d="M8 13h6"></path><path d="M18 4a3 3 0 0 1 3 3v8a3 3 0 0 1 -3 3h-5l-5 3v-3h-2a3 3 0 0 1 -3 -3v-8a3 3 0 0 1 3 -3h12"></path></svg></span></button></div></div></div></div></div></div></div>
</main>
<footer class="bg-dark fw-light text-light px-3 py-5">
<div class="row small">
<div class="col-12 col-sm-6 col-md-3">
<div class="h5 mb-3">Хекслет</div>
<ul class="list-unstyled">
<li>
<a class="nav-link link-light py-1 ps-0" href="/pages/about">О нас</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/testimonials">Отзывы</a>
</li>
<li>
<span class="nav-link link-light py-1 ps-0 external-link" data-href="https://b2b.hexlet.io" role="button">Корпоративное обучение</span>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/blog">Блог</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/qna">Вопросы и ответы</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/glossary">Глоссарий</a>
</li>
<li>
<span class="nav-link link-light py-1 ps-0 external-link" data-href="https://help.hexlet.io" data-target="_blank" role="button">Справка</span>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" target="_blank" rel="noopener noreferrer" href="/map">Карта сайта</a>
</li>
</ul>
</div>
<div class="col-12 col-sm-6 col-md-3">
<div class="h5 fw-normal mb-3">Направления</div>
<ul class="list-unstyled">
<li>
<a class="nav-link link-light py-1 ps-0" href="/courses_devops">DevOps
</a></li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/courses_data_analytics">Аналитика
</a></li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/courses_backend_development">Бэкенд
</a></li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/courses_programming">Программирование
</a></li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/courses_testing">Тестирование
</a></li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/courses_front_end_dev">Фронтенд
</a></li>
</ul>
</div>
<div class="col-12 col-sm-6 col-md-3">
<div class="h5">Профессии</div>
<ul class="list-unstyled">
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/devops-engineer-from-scratch">DevOps-инженер с нуля</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/go">Go-разработчик</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/java">Java-разработчик</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/python">Python-разработчик </a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/data-analytics">Аналитик данных</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/qa-engineer">Инженер по ручному тестированию</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/php">РНР-разработчик</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/frontend">Фронтенд-разработчик</a>
</li>
</ul>
</div>
<div class="col-12 col-sm-6 col-md-3">
<div class="h5">Навыки</div>
<ul class="list-unstyled">
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/python-django-developer">Django</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/docker">Docker</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/php-laravel-developer">Laravel</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/postman">Postman</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/js-react-developer">React</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/js-rest-api">REST API в Node.js</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/spring-boot">Spring Boot</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/typescript">Typescript</a>
</li>
</ul>
</div>
</div>
<hr>
<div class="row">
<div class="col-12 col-sm-4 col-md-2">
<div class="fs-4">
<ul class="list-unstyled d-flex">
<li class="me-3">
<a aria-label="Telegram" target="_blank" class="link-light" rel="noopener noreferrer nofollow" href="https://t.me/hexlet_ru"><span class="bi bi-telegram"></span>
</a></li>
<li>
<a aria-label="Youtube" target="_blank" class="link-light" rel="noopener noreferrer nofollow" href="https://www.youtube.com/user/HexletUniversity"><span class="bi bi-youtube"></span>
</a></li>
</ul>
</div>
<div class="mb-2 d-flex flex-column">
<a class="link-light text-decoration-none" rel="nofollow" href="mailto:support@hexlet.io">support@hexlet.io</a>
<a class="link-light text-decoration-none py-2" target="_blank" href="https://t.me/hexlet_help_bot">t.me/hexlet_help_bot</a>
</div>
<ul class="list-unstyled d-flex">
<li class="me-3">
<span class="link-light text-decoration-none opacity-50 x-font-size-18 external-link" rel="nofollow" data-href="https://hexlet.io/locale/switch?new_locale=en" data-target="_self" role="button"><span class="my-auto">EN</span>
</span></li>
<li class="me-3">
<span class="link-light text-decoration-none opacity-50 x-font-size-18 opacity-100 external-link" rel="nofollow" data-href="https://ru.hexlet.io/locale/switch?new_locale=ru" data-target="_self" role="button"><span class="my-auto">RU</span>
</span></li>
<li class="me-3">
<span class="link-light text-decoration-none opacity-50 x-font-size-18 external-link" rel="nofollow" data-href="https://kz.hexlet.io/locale/switch?new_locale=kz" data-target="_self" role="button"><span class="my-auto">KZ</span>
</span></li>
</ul>
</div>
<div class="col-12 col-sm-4 col-md-3">
<ul class="list-unstyled fs-4">
<li class="mb-3">
<a class="link-light text-decoration-none" href="tel:8%20800%20100%2022%2047">8 800 100 22 47</a>
<span class="d-block opacity-50 small">бесплатно по РФ</span>
</li>
<li>
<a class="link-light text-decoration-none" href="tel:%2B7%20495%20085%2021%2062">+7 495 085 21 62</a>
<span class="d-block opacity-50 small">бесплатно по Москве</span>
</li>
</ul>
</div>
<div class="col-12 col-sm-4 col-md-3">
<div class="small mb-3">Образовательные услуги оказываются на основании Л035-01298-77/01989008 от 14.03.2025</div>
<ul class="list-unstyled small">
<li>
<a class="nav-link link-light py-1 ps-0" href="/pages/legal">Правовая информация</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/pages/offer">Оферта</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/pages/license">Лицензия</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/pages/contacts">Контакты</a>
</li>
</ul>
</div>
<div class="col-12 col-sm-12 col-md-4 small">
<div class="mb-2">
<div>ООО «<a href="/" class="text-decoration-none link-light">Хекслет Рус</a>»</div>
<div>108813 г. Москва, вн.тер.г. поселение Московский,</div>
<div>г. Московский, ул. Солнечная, д. 3А, стр. 1, помещ. 20Б/3</div>
<div>ОГРН 1217300010476</div>
<div>ИНН 7325174845</div>
</div>
<hr>
<div>АНО ДПО «<a href="/" class="text-decoration-none link-light">Учебный центр «Хекслет</a>»</div>
<div>119331 г. Москва, вн. тер. г. муниципальный округ</div>
<div>Ломоносовский, пр-кт Вернадского, д. 29</div>
<div>ОГРН 1247700712390</div>
<div>ИНН 7736364948</div>
</div>
</div>
</footer>
<div id="root-assistant-offcanvas"></div>
<script src="/vite/assets/assistant-Bukl1lYy.js" crossorigin="anonymous" type="module"></script><link rel="modulepreload" href="/vite/assets/chunk-DsPFFUou.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/init-BrRXra1y.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/ErrorFallbackBlock-naDSYSy9.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/MarkdownBlock-DbyKWoR_.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/gon-D3e4yh1x.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/mantine-CGMYrt2Y.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/shiki-V011pkdv.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/utils-DRqSHbQE.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/routes-CCH8ilKF.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/lib-XR8Qr8kR.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/dist-GCHh59xr.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Box-B5-OOzBf.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/notifications.store-C-3AFSMn.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/useIsomorphicEffect-HJ6VK0D3.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/lib-KSp6QbZ0.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/axios-BEvgo0ym.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/classnames-l6ipYlLR.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/dayjs.min-BkKovM-s.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/debounce-jMQ_Cf4f.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/i18next-BlSq9s7B.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/client-U9M77rxp.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/react-dom-DaLxUz_h.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/useTranslation-Bx1Cdrkz.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/compiler-runtime-6XxiPFnt.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/jsx-runtime-CwjcCKJi.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/react-CkL4ZRHB.js" as="script" crossorigin="anonymous">
<script defer src="https://static.cloudflareinsights.com/beacon.min.js/v67327c56f0bb4ef8b305cae61679db8f1769101564043" integrity="sha512-rdcWY47ByXd76cbCFzznIcEaCN71jqkWBBqlwhF1SY7KubdLKZiEGeP7AyieKZlGP9hbY/MhGrwXzJC/HulNyg==" data-cf-beacon='{"version":"2024.11.0","token":"d11015b65d11429ea6b4a2ef37dd7e0b","server_timing":{"name":{"cfCacheStatus":true,"cfEdge":true,"cfExtPri":true,"cfL4":true,"cfOrigin":true,"cfSpeedBrain":true},"location_startswith":null}}' crossorigin="anonymous"></script>
</body>
</html>