Обновление MIS3 — различия между версиями
(→Обновление метаданных) |
Admin (обсуждение | вклад) (→Индекс) |
||
| (не показано 27 промежуточных версий 2 участников) | |||
| Строка 1: | Строка 1: | ||
| + | == Формат обновления == | ||
| + | Обновление представляет из себя архив 7z. Внтури архива: | ||
| + | |||
| + | * Набор файлов с расширением *.sql в кодировке win1251. Файл будут выполнены в порядке именоваия. | ||
| + | * файл readme.txt в кодировке win1251 с кратким описанием обновления. | ||
| + | |||
== Обновление метаданных == | == Обновление метаданных == | ||
| Строка 4: | Строка 10: | ||
Для этого достаточно написать небольшой блок кода. | Для этого достаточно написать небольшой блок кода. | ||
| + | === Схема === | ||
| + | Пример кода проверяющий схему | ||
| + | DO | ||
| + | $$ | ||
| + | BEGIN | ||
| + | IF NOT EXISTS( select schema_name | ||
| + | from information_schema.schemata | ||
| + | where schema_name = 'etl') -- вместо etl указать имя схемы | ||
| + | THEN | ||
| + | -- <<Далее скрипт что-то делающий>> | ||
| + | END IF ; | ||
| + | END; | ||
| + | $$ | ||
| + | |||
| + | === Таблица === | ||
Пример кода, проверяющий наличие таблицы в БД и при её отсутствии создающий её: | Пример кода, проверяющий наличие таблицы в БД и при её отсутствии создающий её: | ||
| + | |||
DO | DO | ||
$$ | $$ | ||
BEGIN | BEGIN | ||
IF NOT EXISTS(SELECT * | IF NOT EXISTS(SELECT * | ||
| − | FROM information_schema.tables where table_schema||'.'||table_name=''''audit'''.'''logged_actions'''') | + | FROM information_schema.tables where table_schema||'.'||table_name=''''''audit'''''.'''''logged_actions'''''') |
-- Вместо ''''audit'''.'''logged_actions'''' необходимо указать имя схемы БД в которой располагается объект | -- Вместо ''''audit'''.'''logged_actions'''' необходимо указать имя схемы БД в которой располагается объект | ||
-- и через точку указать имя проверяемой таблицы | -- и через точку указать имя проверяемой таблицы | ||
| Строка 18: | Строка 40: | ||
$$ | $$ | ||
| − | Пример кода, проверяющий наличие в БД | + | === Триггер === |
| + | Пример кода, проверяющий наличие в БД триггера и при его отсутствии создающий его: | ||
DO | DO | ||
$$ | $$ | ||
BEGIN | BEGIN | ||
| − | + | IF NOT EXISTS(SELECT * | |
FROM information_schema.triggers | FROM information_schema.triggers | ||
| − | WHERE event_object_table = 'warehouse_accounting_entry' | + | WHERE event_object_table = ''''''warehouse_accounting_entry'''''' -- вместо warehouse_accounting_entry необходимо указать имя таблицы за которой закреплён триггер |
| − | AND trigger_name = 'audit_trigger_row' ) | + | AND trigger_name = ''''''audit_trigger_row'''''' ) -- вместо audit_trigger_row указать имя тригера |
THEN | THEN | ||
| − | CREATE TRIGGER audit_trigger_stm | + | <<Далее скрипт создающий таблицу в БД. Например: CREATE TRIGGER audit_trigger_stm...>> |
| − | + | END IF ; | |
| − | + | END; | |
| − | + | $$ | |
| + | |||
| + | === Поле === | ||
| + | Пример кода, проверяющий наличие поля БД и при его отсутствии создающий его (mm.table-имя таблицы, куда добавляется поле, newcolumn-название нового поля, comment-описание поля): | ||
| + | DO | ||
| + | $$ | ||
| + | BEGIN | ||
| + | IF NOT EXISTS(SELECT * | ||
| + | FROM information_schema.columns where table_schema||'.'||table_name||'.'||column_name='mm.table.newcolumn') | ||
| + | THEN | ||
| + | <<Далее скрипт создающий поле в таблице, например:>> | ||
| + | ALTER TABLE mm.table ADD COLUMN newcolumn BOOLEAN; | ||
| + | ALTER TABLE mm.table ALTER COLUMN newcolumn SET DEFAULT false; | ||
| + | COMMENT ON COLUMN mm.table.newcolumn IS 'comment'; | ||
| + | END IF; | ||
| + | END; | ||
| + | $$ | ||
| − | + | === Пользователь === | |
| − | + | Пример кода, проверяющий наличие пользователя в БД и при его отсутствии создающий его: | |
| − | + | ||
| − | + | DO | |
| − | + | $$ | |
| + | begin | ||
| + | if not EXISTS(select usename from pg_user where usename = 'ИМЯ ПОЛЬЗОВАТЕЛЯ') then | ||
| + | -- Скрипт, создающий пользователя | ||
| + | end if; | ||
| + | END | ||
| + | $$ | ||
| + | |||
| + | === Индекс === | ||
| + | |||
| + | Пример кода, проверяющий наличие в БД индекса и при его отсутствии создающий его: | ||
| + | DO | ||
| + | $$ | ||
| + | BEGIN | ||
| + | -- Внимание! заменить в трех местах и DDL | ||
| + | IF EXISTS(SELECT * | ||
| + | FROM information_schema.tables | ||
| + | WHERE table_schema||'.'||table_name='pump.tarimu') -- заменить здесь 1 !!!! | ||
| + | THEN | ||
| + | -- если таблица существует | ||
| + | |||
| + | if not exists ( | ||
| + | select t.relname as "table_name", | ||
| + | i.relname as indname | ||
| + | FROM pg_index as idx | ||
| + | JOIN pg_class as i ON i.oid = idx.indexrelid | ||
| + | JOIN pg_am as am ON i.relam = am.oid | ||
| + | JOIN pg_namespace as ns ON ns.oid = i.relnamespace AND ns.nspname = | ||
| + | 'pump' -- заменить здесь 2 !!!! | ||
| + | join pg_class t on idx.indrelid = t.oid | ||
| + | where idx.indexprs is null -- исключаем функциональные индексы | ||
| + | and | ||
| + | i.relname = 'ix_tarimu$code' -- -- заменить здесь 3 !!!! | ||
| + | ) | ||
| + | then | ||
| + | ------------- DDL --------------------- | ||
| + | CREATE INDEX ix_tarimu$code ON pump.tarimu | ||
| + | USING btree (code COLLATE pg_catalog."default"); | ||
| + | end if; | ||
| + | ----------------------------------------- | ||
| + | END IF ; | ||
| + | END; | ||
| + | $$ | ||
| + | |||
| + | === FOREGN KEY === | ||
| + | |||
| + | <code lang="sql"> | ||
| + | |||
| + | DO | ||
| + | $$ | ||
| + | DECLARE | ||
| + | v_schema varchar; | ||
| + | v_table varchar; | ||
| + | v_contraint_name varchar; | ||
| + | BEGIN | ||
| + | v_schema := 'an'; | ||
| + | v_table := 'ds_sql_smart_field'; | ||
| + | v_contraint_name := 'fk_ds_sql_smart_field$ds_sql_smart$ds_sql_smart_id'; | ||
| + | |||
| + | IF NOT EXISTS( SELECT tc.constraint_name, | ||
| + | tc.table_schema, | ||
| + | tc.table_name, | ||
| + | kcu.column_name, | ||
| + | ccu.table_name AS foreign_table_name, | ||
| + | ccu.column_name AS foreign_column_name | ||
| + | FROM information_schema.table_constraints AS tc | ||
| + | JOIN information_schema.key_column_usage AS kcu ON tc.constraint_name = | ||
| + | kcu.constraint_name | ||
| + | JOIN information_schema.constraint_column_usage AS ccu ON | ||
| + | ccu.constraint_name = tc.constraint_name | ||
| + | WHERE constraint_type = 'FOREIGN KEY' and | ||
| + | tc.table_schema = v_schema and | ||
| + | tc.table_name = v_table | ||
| + | and tc.constraint_name=v_contraint_name ) -- вместо etl указать имя схемы | ||
| + | THEN | ||
| + | -- <<Далее скрипт добавляющий>> | ||
| + | ALTER TABLE an.ds_sql_smart_field | ||
| + | ADD CONSTRAINT fk_ds_sql_smart_field$ds_sql_smart$ds_sql_smart_id FOREIGN KEY (ds_sql_smart_id) | ||
| + | REFERENCES an.ds_sql_smart(id) | ||
| + | ON DELETE RESTRICT | ||
| + | ON UPDATE RESTRICT | ||
| + | NOT DEFERRABLE; | ||
| + | |||
| + | ELSE | ||
| + | -- TODO проверить на переименование | ||
| + | END IF ; | ||
| + | END; | ||
| + | $$ | ||
| + | </code> | ||
| + | |||
| + | == Добавление параметров в MM.ADJ для скриптов обновления БД == | ||
| + | Пример кода, проверяющий наличие параметра в mm.adj и при его отсутствии создающий его (SEC_NAME-имя секции, PARAM_NAME-название параметра, comment-описание параметра): | ||
| + | DO | ||
| + | $$ | ||
| + | BEGIN | ||
| + | IF NOT EXISTS (SELECT id from mm.adj where section='SEC_NAME' and "key"='PARAM_NAME' ) | ||
| + | THEN | ||
| + | INSERT INTO mm.adj ("section", "key", "value", "note") | ||
| + | VALUES ('SEC_NAME', 'PARAM_NAME', '0', 'comment'); | ||
| + | END IF; | ||
END; | END; | ||
$$ | $$ | ||
| + | |||
== Данные в таблицах, которые должны быть одинаковыми на всех БД == | == Данные в таблицах, которые должны быть одинаковыми на всех БД == | ||
| Строка 47: | Строка 186: | ||
* audit.table_conf - назначение мест аудита для таблиц | * audit.table_conf - назначение мест аудита для таблиц | ||
| − | == | + | == Проблема транзакции в регистратуре == |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | + | Следующие таблицы находятся в эксклюзивной блокировке: | |
| − | |||
| − | |||
| − | + | * ambticket | |
| − | + | * ambdoc | |
| + | * company_insur | ||
| + | * idoc | ||
| + | * idoc_tepe | ||
| + | * pay_type | ||
| + | * naz | ||
| + | * naz_dict | ||
| + | * mdoc | ||
| + | * mdoc_type | ||
| + | * people | ||
| + | * pinfo | ||
| + | * place_mdoc | ||
| + | * xpass | ||
| + | * sex | ||
| + | * type_programm | ||
| − | + | Любые изменения структуры (в том числе триггеры) будут висеть. Также будут висеть при измении таблиц, связанных constraint. | |
| − | |||
[[Категория:MIS3]][[Категория:Руководство программиста MIS3]] | [[Категория:MIS3]][[Категория:Руководство программиста MIS3]] | ||
Текущая версия на 14:42, 15 марта 2021
Содержание
Формат обновления
Обновление представляет из себя архив 7z. Внтури архива:
- Набор файлов с расширением *.sql в кодировке win1251. Файл будут выполнены в порядке именоваия.
- файл readme.txt в кодировке win1251 с кратким описанием обновления.
Обновление метаданных
При создании скриптов обновляющих объекты БД можно использовать проверку на существование обновляемых объектов БД. Для этого достаточно написать небольшой блок кода.
Схема
Пример кода проверяющий схему
DO
$$
BEGIN
IF NOT EXISTS( select schema_name
from information_schema.schemata
where schema_name = 'etl') -- вместо etl указать имя схемы
THEN
-- <<Далее скрипт что-то делающий>>
END IF ;
END;
$$
Таблица
Пример кода, проверяющий наличие таблицы в БД и при её отсутствии создающий её:
DO
$$
BEGIN
IF NOT EXISTS(SELECT *
FROM information_schema.tables where table_schema||'.'||table_name='audit.logged_actions')
-- Вместо 'audit.logged_actions' необходимо указать имя схемы БД в которой располагается объект
-- и через точку указать имя проверяемой таблицы
THEN
<<Далее скрипт создающий таблицу в БД. Например: CREATE TABLE audit.logged_actions... >>
END IF ;
END;
$$
Триггер
Пример кода, проверяющий наличие в БД триггера и при его отсутствии создающий его:
DO
$$
BEGIN
IF NOT EXISTS(SELECT *
FROM information_schema.triggers
WHERE event_object_table = 'warehouse_accounting_entry' -- вместо warehouse_accounting_entry необходимо указать имя таблицы за которой закреплён триггер
AND trigger_name = 'audit_trigger_row' ) -- вместо audit_trigger_row указать имя тригера
THEN
<<Далее скрипт создающий таблицу в БД. Например: CREATE TRIGGER audit_trigger_stm...>>
END IF ;
END;
$$
Поле
Пример кода, проверяющий наличие поля БД и при его отсутствии создающий его (mm.table-имя таблицы, куда добавляется поле, newcolumn-название нового поля, comment-описание поля):
DO
$$
BEGIN
IF NOT EXISTS(SELECT *
FROM information_schema.columns where table_schema||'.'||table_name||'.'||column_name='mm.table.newcolumn')
THEN
<<Далее скрипт создающий поле в таблице, например:>>
ALTER TABLE mm.table ADD COLUMN newcolumn BOOLEAN;
ALTER TABLE mm.table ALTER COLUMN newcolumn SET DEFAULT false;
COMMENT ON COLUMN mm.table.newcolumn IS 'comment';
END IF;
END;
$$
Пользователь
Пример кода, проверяющий наличие пользователя в БД и при его отсутствии создающий его:
DO $$ begin if not EXISTS(select usename from pg_user where usename = 'ИМЯ ПОЛЬЗОВАТЕЛЯ') then -- Скрипт, создающий пользователя end if; END $$
Индекс
Пример кода, проверяющий наличие в БД индекса и при его отсутствии создающий его:
DO
$$
BEGIN
-- Внимание! заменить в трех местах и DDL
IF EXISTS(SELECT *
FROM information_schema.tables
WHERE table_schema||'.'||table_name='pump.tarimu') -- заменить здесь 1 !!!!
THEN
-- если таблица существует
if not exists (
select t.relname as "table_name",
i.relname as indname
FROM pg_index as idx
JOIN pg_class as i ON i.oid = idx.indexrelid
JOIN pg_am as am ON i.relam = am.oid
JOIN pg_namespace as ns ON ns.oid = i.relnamespace AND ns.nspname =
'pump' -- заменить здесь 2 !!!!
join pg_class t on idx.indrelid = t.oid
where idx.indexprs is null -- исключаем функциональные индексы
and
i.relname = 'ix_tarimu$code' -- -- заменить здесь 3 !!!!
)
then
------------- DDL ---------------------
CREATE INDEX ix_tarimu$code ON pump.tarimu
USING btree (code COLLATE pg_catalog."default");
end if;
-----------------------------------------
END IF ;
END;
$$
FOREGN KEY
DO
$$
DECLARE
v_schema varchar;
v_table varchar;
v_contraint_name varchar;
BEGIN
v_schema := 'an';
v_table := 'ds_sql_smart_field';
v_contraint_name := 'fk_ds_sql_smart_field$ds_sql_smart$ds_sql_smart_id';
IF NOT EXISTS( SELECT tc.constraint_name,
tc.table_schema,
tc.table_name,
kcu.column_name,
ccu.table_name AS foreign_table_name,
ccu.column_name AS foreign_column_name
FROM information_schema.table_constraints AS tc
JOIN information_schema.key_column_usage AS kcu ON tc.constraint_name =
kcu.constraint_name
JOIN information_schema.constraint_column_usage AS ccu ON
ccu.constraint_name = tc.constraint_name
WHERE constraint_type = 'FOREIGN KEY' and
tc.table_schema = v_schema and
tc.table_name = v_table
and tc.constraint_name=v_contraint_name ) -- вместо etl указать имя схемы
THEN
-- <<Далее скрипт добавляющий>>
ALTER TABLE an.ds_sql_smart_field
ADD CONSTRAINT fk_ds_sql_smart_field$ds_sql_smart$ds_sql_smart_id FOREIGN KEY (ds_sql_smart_id)
REFERENCES an.ds_sql_smart(id)
ON DELETE RESTRICT
ON UPDATE RESTRICT
NOT DEFERRABLE;
ELSE
-- TODO проверить на переименование
END IF ;
END;
$$
Добавление параметров в MM.ADJ для скриптов обновления БД
Пример кода, проверяющий наличие параметра в mm.adj и при его отсутствии создающий его (SEC_NAME-имя секции, PARAM_NAME-название параметра, comment-описание параметра):
DO
$$
BEGIN
IF NOT EXISTS (SELECT id from mm.adj where section='SEC_NAME' and "key"='PARAM_NAME' )
THEN
INSERT INTO mm.adj ("section", "key", "value", "note")
VALUES ('SEC_NAME', 'PARAM_NAME', '0', 'comment');
END IF;
END;
$$
Данные в таблицах, которые должны быть одинаковыми на всех БД
- mm.app_tab - справочник закладок
- mm.rght - только первые 1000 записей, остальные все одинаковые
- mm.rsf_ref_column - колонки по реестру счетом
- audit.table_conf - назначение мест аудита для таблиц
Проблема транзакции в регистратуре
Следующие таблицы находятся в эксклюзивной блокировке:
- ambticket
- ambdoc
- company_insur
- idoc
- idoc_tepe
- pay_type
- naz
- naz_dict
- mdoc
- mdoc_type
- people
- pinfo
- place_mdoc
- xpass
- sex
- type_programm
Любые изменения структуры (в том числе триггеры) будут висеть. Также будут висеть при измении таблиц, связанных constraint.