Первинне завантаження даних реєстру (Initial load)
🌐 Цей документ доступний українською та англійською мовами. Використовуйте перемикач у правому верхньому куті, щоб змінити версію. |
Для первинного завантаження даних використовується БД-процедура PL/pgSQL, яка є мовою програмування, вбудованою в PostgreSQL для розширених процедур та функцій.
Перед виконанням процедури первинного завантаження даних, переконайтеся, що виконано всі передумови, описані в секції Підготовка даних до міграції. Це забезпечить гладке і безперебійне завантаження даних. |
1. Специфікація процедури PL/pgSQL для бази даних Платформи
Ця секція описує деталі процедури PL/pgSQL, яка дозволяє завантажувати дані з CSV-файлів до таблиць в базі даних Платформи.
CREATE OR REPLACE PROCEDURE p_load_table_from_csv(
p_table_name text,
p_file_name text,
p_table_columns text[],
p_target_table_columns text[] DEFAULT NULL::text[]
);
- Опис параметрів:
-
1 p_table_name
— назва цільової таблиці, в яку будуть завантажені дані.2 p_file_name
— повний шлях до CSV-файлу, з якого будуть завантажені дані.3 p_table_columns
— масив назв полів у файлі даних, який відповідає першому рядку CSV-файлу.4 p_target_table_columns
— масив полів цільової таблиці. Цей параметр є необов’язковим, якщо перелік полів у файлі даних збігається з полями в цільовій таблиці.Формати значень для параметра
p_target_table_columns
:-
<col_name>
: поле в цільовій таблиці отримує значення відповідного поля в CSV-файлі. -
<col_name>::<some_calculation_based_on_source_cols>
: поле отримує значення як результат обчислення, заснованого на джерельних полях.Більше інформації про цей підхід можна знайти в секції Складний сценарій 1. -
<col_name>::ref(lookup_col:<lookup_col_name>, ref_table:<ref_table_name>, ref_col:<ref_col_name>, ref_id:<ref_id_col_name>)
: Використовується для пошукуid
у довідниковій таблиці, коли вхідне значення представлено описовим полем, а не ідентифікатором, проте значення цього поля мають бути унікальними.SELECT <ref_id_col_name> INTO <col_name> FROM <ref_table_name> WHERE <ref_col_name> = <lookup_col_name>;
Докладніше про цей метод використання дивіться в секції Складний сценарій 2. -
<col_name>::ref_array(lookup_col:<lookup_col_name>, ref_table:<ref_table_name>, ref_col:<ref_col_name>, ref_id:<ref_col_name>, delim:<delimiter_character>)
: Аналогічно попередньому, але для випадків, коли поле<lookup_col_name>
у CSV-файлі містить масив описових значень, і потрібно повернути масив відповіднихid
.
-
2. Приклади виклику процедури
2.1. Базовий сценарій
Цей сценарій демонструє базове використання процедури для імпорту даних з CSV-файлу в таблицю бази даних. Особливістю є можливість імпорту значення ID сутності, яке унікально ідентифікує записи в таблиці.
CALL p_load_table_from_csv(
'research', 'D:\PostgreSQL\csv\uuid\01-Typy_doslidgen_uuid.csv',
array [ 'uuid', 'research_type' ],
array[ 'research_type' ]
);
- Опис параметрів:
-
1 uuid
— це статична (фіксована) назва, яка не залежить від назви ID сутності. Використовується для імпорту унікального ідентифікатора (UUID) з файлу. При імпорті,primaryKey
таблиці, в яку відбувається імпорт, повинен мати типUUID
.2 Стовпець з ID має бути першим у файлі імпорту та мати формат, що відповідає стандарту UUID, для забезпечення правильної обробки даних.
Цей приклад ілюструє імпорт даних з файлу 01-Typy_doslidgen_uuid.csv, розташованого за шляхом D:\PostgreSQL\csv\uuid\, в таблицю research
. Імпортовані поля включають uuid
як унікальний ідентифікатор та research_type
як тип дослідження.
2.2. Складний сценарій 1
Цей сценарій демонструє розширене використання процедури для імпорту даних, що включає обробку специфічних умов і формування додаткових полів з використанням розрахунків на основі даних, імпортованих з CSV-файлу. Такий підхід використовується для розв’язання специфічних потреб обробки та класифікації даних.
CALL p_load_table_from_csv(
'koatuu', '${dataLoadPath}03-KOATUU_simple.csv',
array[ 'code', 'category', 'name' ],
array[ 'code', 'category', 'name',
'level1::substring(code,1,2)||''00000000''',
'level2::substring(code,1,5)||''00000''',
'type::CASE WHEN code ~ ''[0-9]{2}0{8}'' AND code !~ ''(80|85)0{8}'' THEN ''О''
WHEN code ~ ''[0-9]{2}2[0-9]{2}0{5}'' AND code !~ ''[0-9]{2}20{7}'' THEN ''Р''
WHEN coalesce(category, ''Р'') != ''Р''
OR code IN (SELECT DISTINCT substring(code,1,5)||''00000'' FROM koatuu_csv k2 WHERE category = ''Р'') AND category IS NULL
OR code ~ ''(80|85)0{8}'' THEN ''НП''
ELSE NULL END' ]
);
- Опис параметрів та логіки:
-
1 code
,category
,name
— стандартні поля, що імпортуються безпосередньо з CSV-файлу.2 level1
— створює нове поле, яке витягує перші дві цифри з поляcode
та доповнює їх нулями до восьми знаків, формуючи унікальний ідентифікатор першого рівня.3 level2
— аналогічноlevel1
, але витягує перші п’ять цифр та доповнює нулями до п’яти знаків, створюючи унікальний ідентифікатор другого рівня.4 type
— визначає тип об’єкта на основі складного умовного виразу. Використовуючи регулярні вирази та умовну логіку, це поле класифікує записи на основі їх кодів та категорій.
Цей сценарій особливо корисний для обробки та класифікації географічних даних відповідно до КОАТУУ (Класифікатор об’єктів адміністративно-територіального устрою України), забезпечуючи автоматизоване створення ієрархічних рівнів та типів об’єктів на основі їх кодів.
2.3. Складний сценарій 2
Цей сценарій розкриває можливості імпорту даних для складної структури персоналу з використанням додаткових трансформацій для забезпечення відповідності даних зовнішнім ключам та ідентифікаторам у базі даних. Сценарій включає пошук у довідникових таблицях за допомогою описових значень для отримання відповідних ідентифікаторів, а також обробку масивів даних.
CALL p_load_table_from_csv('staff','D:\PostgreSQL\csv\staff.csv'
,array['uuid','laboratory','staff_status','researches','full_name','hygienist_flag','full_time_flag','salary','fixed_term_contract_flag','contract_end_date','specialization_date','specialization_end_date','dismissal_flag','dismissal_date']
,array['laboratory_id::ref(lookup_col:laboratory,ref_table:laboratory,ref_col:name,ref_id:laboratory_id)'
,'staff_status_id::ref(lookup_col:staff_status,ref_table:staff_status,ref_col:name,ref_id:staff_status_id)'
,'researches::ref_array(lookup_col:researches,ref_table:research,ref_col:research_type,ref_id:research_id,delim:#)'
,'full_name','hygienist_flag','full_time_flag','salary','fixed_term_contract_flag','contract_end_date','specialization_date','specialization_end_date','dismissal_flag','dismissal_date']
);
- Опис параметрів та логіки:
-
1 uuid
,full_name
,hygienist_flag
,full_time_flag
,salary
,fixed_term_contract_flag
,contract_end_date
,specialization_date
,specialization_end_date
,dismissal_flag
,dismissal_date
— стандартні поля, що імпортуються безпосередньо з CSV-файлу без змін.2 laboratory_id
— полеlaboratory
у CSV-файлі трансформується уlaboratory_id
шляхом пошуку відповідного ідентифікатора у таблиціlaboratory
за назвою лабораторії.3 staff_status_id
— аналогічно, полеstaff_status
трансформується уstaff_status_id
за допомогою пошуку ідентифікатора статусу персоналу в таблиціstaff_status
.4 researches
— це поле містить масив досліджень, які трансформуються у відповідніresearch_id
через пошук в таблиціresearch
. Спеціальний роздільник#
використовується для ідентифікації окремих елементів у масиві.
Цей сценарій показує, як можна ефективно імпортувати складні набори даних, що вимагають додаткових перетворень та пошуку в довідникових таблицях для забезпечення цілісності даних. Він особливо корисний для систем, де важливо забезпечити відповідність імпортованих даних до вже наявних сутностей у БД.
3. Процес завантаження даних до БД
Для завантаження даних до бази даних рекомендується використовувати стандартну функціональність Liquibase, інструменту для керування базами даних, що дозволяє вести версіонування схеми БД та управління змінами через XML-файли, SQL-скрипти, а також інші формати.
Використовуйте як приклад детальну практичну інструкцію з моделювання та завантаження структур даних до реєстру: Завдання 1. Моделювання структур бази даних реєстру. |
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.2.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog-ext.xsd">
<property name="dataLoadPath" value="D:\PostgreSQL\csv\"/>
<changeSet author="registry owner" id="load data to dictionaries">
<sql dbms="postgresql" endDelimiter=";" splitStatements="true" stripComments="true">
CALL p_load_table_from_csv('research','${dataLoadPath}01-Typy doslidgen.csv', array['code','research_type'], array['research_type']);
CALL p_load_table_from_csv('refusal_reason','${dataLoadPath}02-Prichiny vidmov.csv', array['code','document_type','name','constant_code'], array['document_type','name','constant_code']);
CALL p_load_table_from_csv('kopfg','${dataLoadPath}05-kopfg.csv', array['code','name']);
CALL p_load_table_from_csv('solution_type','${dataLoadPath}06-Typy rishen.csv', array['id','name','constant_code'], array['name','constant_code']);
CALL p_load_table_from_csv('factor','${dataLoadPath}14-Himichni_factory_OBRV.csv', array['code','name','col3','col4'], array['name','factor_type::''Хімічний: ОБРВ''']);
CALL p_load_table_from_csv('factor','${dataLoadPath}15-Himichni factory dovilni.csv', array['code','name'], array['name','factor_type::''Хімічний: довільні''']);
</sql>
</changeSet>
</databaseChangeLog>
- Опис XML-шаблону та його компонентів:
-
1 databaseChangeLog
— кореневий елемент, що визначає журнал змін бази даних. Він містить один або кілька елементівchangeSet
, кожен з яких представляє групу змін, які будуть застосовані до БД.2 property
— визначає зміннуdataLoadPath
, яка містить шлях до директорії з CSV-файлами, що будуть імпортовані.3 changeSet
— описує набір змін, які потрібно застосувати. Атрибутиauthor
таid
допомагають ідентифікувати та версіонувати кожен набір змін.4 sql
— використовується для виконання SQL-команд. Атрибутиdbms
,endDelimiter
,splitStatements
, таstripComments
дозволяють контролювати, як команди будуть виконані у контексті специфічної СКБД (у нашому випадку — PostgreSQL).
Цей приклад демонструє, як можна використовувати Liquibase для автоматизації процесу завантаження даних з зовнішніх файлів у визначені таблиці бази даних, забезпечуючи ефективне та контрольоване управління даними.
Читайте також про створення фізичної моделі даних реєстру на сторінці Розширення Liquibase для моделювання даних. |
4. Вимоги до файлів для імпорту даних до БД
4.1. Вимоги до імпорту
Важливо, щоб файли для завантаження даних до бази даних відповідали визначеним структурним та форматним вимогам. Нижче представлено детальний опис цих вимог з конкретними прикладами:
Вимога | Опис | Приклад |
---|---|---|
Формат файлу |
Використовуйте виключно CSV-формат. |
|
Назва файлу |
Назви файлів мають бути латиницею. |
|
Кодування |
Файли мають бути у кодуванні |
Файл збережений як |
Структура файлу |
Перший рядок містить назви полів. З другого рядка йдуть дані. |
|
Роздільник значень полів |
Використовуйте |
|
Відсутність значення ( |
Відсутнє значення представлене пропуском між двома роздільниками. |
|
Унікальність за бізнес-полем |
Забезпечте унікальність записів за ключовим бізнес-полем. |
У файлі |
Позначення масивів описових значень |
Використовуйте фігурні дужки для масивів описових значень. |
|
Ці вимоги забезпечують чіткість і консистентність даних, що імпортуються, та сприяють ефективному завантаженню інформації до бази даних без помилок та невідповідностей.
4.2. Приклад CSV
Розгляньмо приклад CSV-файлу, який містить чотири стовпці: name
, email
, age
, і specializations
, а також чотири записи з даними. Цей файл буде відповідати вказаним вимогам до структури та форматування даних.
name,email,age,specializations
John Doe,johndoe@example.com,30,{Data Analysis, Software Development}
Jane Smith,janesmith@example.com,28,{Project Management, User Experience Design}
Richard Roe,richardroe@example.com,35,{Network Administration, Technical Support}
Emily Davis,emilydavis@example.com,40,{Financial Planning, Market Research}
- У цьому прикладі:
-
1 name
— ім’я особи;2 email
— електронна пошта особи;3 age
— вік особи;4 specializations
— спеціалізації особи, представлені у вигляді масиву.
5. Рекомендації для завантаження великої кількості даних
За потреби завантаження великих обсягів даних (десятки чи сотні мегабайт) через CSV-файли, рекомендується використовувати прямий SQL код замість стандартних процедур. Використання SQL дозволяє не лише контролювати процес завантаження, але й забезпечує можливість створення історичних записів у таблиці _hst
та заповнення метаданих у полях, що починаються з ddm_
. Це важливо для забезпечення цілісності та коректної роботи реєстру, оскільки імітує дії, які зазвичай виконуються автоматично під час виклику процедури.
-- Створення тимчасової проміжної таблиці, яка відповідає структурі CSV-файлу
CREATE TABLE account_csv_stage (username text, bank_number text);
-- Завантаження даних з CSV-файлу в проміжну таблицю
COPY account_csv_stage (username, bank_number)
FROM
'${dataLoadPath}account.csv' WITH (HEADER, FORMAT CSV);
-- Вставка даних з проміжної таблиці в основну та історичну таблиці з одночасним заповненням метаданих
WITH main_table_cte AS (
INSERT INTO account (
username, bank_number, ddm_created_by,
ddm_updated_by
)
SELECT
username,
bank_number,
'admin',
'admin'
FROM
account_csv_stage RETURNING *
) INSERT INTO account_hst (
id, username, bank_number, ddm_created_by,
ddm_created_at, ddm_dml_op, ddm_system_id,
ddm_application_id, ddm_business_process_id
)
SELECT
id,
username,
bank_number,
ddm_created_by,
CURRENT_TIMESTAMP,
'I' as ddm_dml_op,
(
SELECT
ss.system_id
FROM
ddm_source_system ss
WHERE
ss.system_name = 'initial load'
) ddm_system_id,
(
SELECT
sa.application_id
FROM
ddm_source_application sa
WHERE
sa.application_name = 'initial load'
) ddm_application_id,
(
SELECT
sb.business_process_id
FROM
ddm_source_business_process sb
WHERE
sb.business_process_name = 'initial load process'
) ddm_business_process_id
FROM
main_table_cte;
-- Видалення тимчасової проміжної таблиці після завершення операцій
DROP
TABLE account_csv_stage;
Цей метод може бути використаний як альтернатива виклику процедури в XML-шаблоні для завантаження даних. Рекомендується створювати окремий changeSet
для кожного завантаження файлу за допомогою цього підходу, щоб забезпечити організоване управління версіями та змінами в базі даних.