Форум программистов, компьютерный форум, киберфорум
PostgreSQL
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
0 / 0 / 0
Регистрация: 12.11.2016
Сообщений: 10

Триггер plpgsql

19.01.2023, 09:17. Показов 433. Ответов 1

Author24 — интернет-сервис помощи студентам
Добрый день, подскажите пожалуйста, необходимо автоматически генерировать запись в колонку id_doc следующим форматом:
Р XXXXXX XXX ,
где 2-7 символы - число, месяц, год текущей даты
8-10 - порядковый номер на текущую дату (т.е. 001, 002 и т.д.)
При этом каждый день соответственно из-за смены даты, у нас запись должна меняться, как это можно реализовать? Весь вывод добавил, осталось только это реализовать (синим выделил какой кусок кода надо изменить):

SQL Скопировано
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
-- Function: ins_n()
 
-- DROP FUNCTION ins_n();
 
CREATE OR REPLACE FUNCTION ins_n()
  RETURNS TRIGGER AS
$BODY$
BEGIN
 
--insert into out (
--  id_doc,с_pt,doc_creation_time,id,
--  name,number,
--  e,
--  start,end
--)
INSERT INTO OUT (
  id_doc,c_pt,doc_creation_time,id,
  e,
  START,END
)
[COLOR="Blue"]SELECT 'P'||SUBSTRING(e.code FROM 2) AS id_doc[/COLOR],'1234' AS c_pt,
       now() AS doc_creation_time,i.id AS id,
f.e AS e,
(f.dt_range).start AS START,(f.dt_range).final AS final
FROM fr a
LEFT OUTER JOIN m b ON a.m_id=b.id
LEFT OUTER JOIN ta_an c ON b.t_id=c.t_id
LEFT OUTER JOIN ta_pa e ON b.t_id=e.id
LEFT OUTER JOIN res f ON b.t_id=f.t_id
INNER JOIN s_con h ON e.num=h.p_num[1]
INNER JOIN rks.p_ut i ON i.id_in=h.plan_in_num AND i.id_doc IS NOT NULL
WHERE a.id=NEW.id;
 
INSERT INTO out_p (
  id_doc,
  fr,ba,bad,
  den,DEC,ng,
  mg,pl,
  s,s_r,
  m_t,e_c,
  dn,m_d,
  s_t
)
[COLOR="blue"]SELECT 'P'||SUBSTRING(e.code FROM 2) AS id_doc[/COLOR],
(fr).fr AS fr,(fr).ba AS ba,(fr).bad AS bad,
a.den AS den, a.dec AS DEC, a.ng AS ng,
a.mg AS mg, a.pl AS pl,
a.s AS s, a.s_r AS s_r,
a.m_t AS m_t, a.e_c AS e_c,
a.dn AS dn, a.m_d AS m_d,
a.s_t AS s_t
FROM fr a
LEFT OUTER JOIN m b ON a.m_id=b.id
LEFT OUTER JOIN ta_an c ON b.t_id=c.t_id
LEFT OUTER JOIN ta_pa e ON b.t_id=e.id
LEFT OUTER JOIN res f ON b.t_id=f.t_id
INNER JOIN s_con h ON e.num=h.p_num[1]
INNER JOIN p_ut i ON i.id_in=h.p_num AND i.id_doc IS NOT NULL
WHERE a.id=NEW.id;
 
RETURN NEW;
END;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
ALTER FUNCTION ins_n()
  OWNER TO adm;
COMMENT ON FUNCTION ins_n() IS 'Тест';
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
19.01.2023, 09:17
Ответы с готовыми решениями:

Запрос по plpgsql с курсором
Здравствуйте! Как и все студенты, делаю курсовую работу в последнюю ночь :) Но с этим запросом, если честно, 3 день мучаюсь, и чет...

Plpgsql как пользоваться
в общем, парсю значение посредством плпскл, получилось пока такое. синатксис нов, чувссвтую что пишу чушь (правда работает) кто подскажет...

commit внутри функции plpgsql
Доброго времени суток! Столкнулся с проблемой промежуточного commit внутри функции. Есть функция внутри которой огромный цикл по...

1
55 / 50 / 5
Регистрация: 30.06.2022
Сообщений: 251
19.01.2023, 16:54
Не надо придавать идентификаторам записи таблиц дополнительные функции! Они не для этого применяются.
Пользуйтесь либо последовательностями и целыми числами, либо UUID и генераторами уникальных значений.
В таблицу добавьте поле строку num_doc и пишите туда что угодно.

Добавлено через 7 минут
Ещё вам нужно поле типа timestamp со значением по умолчанию now() и NOT NULL
по этому полю создаётся индекс.
Далее пишете функцию простановки поля num_doc для записи,
в ней блокируете все строки за день, который берётся из текущей записи, затем запросом вычисляете
ваш порядковый номер на текущую дату
Далее формируете строку, записываете в поле num_doc и возвращаете управление.
Минимум блокировок и реализуется то, что вам нужно.

Добавлено через 13 минут
SQL Скопировано
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
-- структура тестовой таблицы
CREATE SEQUENCE sh_test.tbl_docs_id_seq;
ALTER SEQUENCE sh_test.tbl_docs_id_seq
 INCREMENT BY 1
 MINVALUE 1
 MAXVALUE 9223372036854775807
 START WITH 1
 NO CYCLE;
ALTER SEQUENCE sh_test.tbl_docs_id_seq OWNER TO postgres;
CREATE TABLE sh_test.tbl_docs (
    id BIGINT NOT NULL,
    name_doc text NOT NULL,
    body_doc text,
    num_doc text,
    date_doc TIMESTAMP
);
COMMENT ON TABLE sh_test.tbl_docs IS 'Документы и номера.';
ALTER TABLE sh_test.tbl_docs ALTER id 
SET DEFAULT NEXTVAL('sh_test.tbl_docs_id_seq'::regclass);
ALTER TABLE sh_test.tbl_docs ALTER name_doc SET DEFAULT ''::text;
ALTER TABLE sh_test.tbl_docs ALTER date_doc SET DEFAULT now();
ALTER TABLE sh_test.tbl_docs ADD 
CONSTRAINT tbl_docs_pkey PRIMARY KEY (id);
CREATE INDEX tbl_docs_date_doc_idx ON sh_test.tbl_docs USING btree (date_doc);
ALTER TABLE sh_test.tbl_docs OWNER TO postgres;
Добавлено через 35 минут
SQL Скопировано
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
CREATE OR REPLACE FUNCTION sh_test.fn_test_set_num(in_id BIGINT)
 RETURNS BIGINT
 LANGUAGE plpgsql
 SECURITY DEFINER
AS $function$
DECLARE
    v_rec RECORD; 
    v_date_doc TIMESTAMP;
    v_num_doc TEXT;
    v_num_row INTEGER;
BEGIN
    SELECT date_doc INTO v_date_doc
    FROM sh_test.tbl_docs
    WHERE id = in_id;
    FOR v_rec IN
        SELECT
            id,
            date_doc,
            num_doc
        FROM sh_test.tbl_docs
        WHERE date_doc::DATE = v_date_doc::DATE 
        ORDER BY date_doc ASC 
        FOR UPDATE
    LOOP
        v_num_row = COALESCE(v_num_row,0)+1;
        IF v_rec.id = in_id THEN -- тут получаем тот номер
            v_num_doc = v_date_doc::DATE::TEXT||' '||v_num_row::TEXT;
        END IF;
    END LOOP;
    UPDATE sh_test.tbl_docs SET num_doc=v_num_doc WHERE id = in_id;
    RETURN in_id;
END;
$function$;
ALTER FUNCTION sh_test.fn_test_set_num(BIGINT) OWNER TO postgres;
GRANT EXECUTE ON FUNCTION sh_test.fn_test_set_num(BIGINT) TO PUBLIC;
GRANT EXECUTE ON FUNCTION sh_test.fn_test_set_num(BIGINT) TO postgres WITH GRANT OPTION;
Добавлено через 1 минуту
SQL Скопировано
1
2
3
4
5
6
SELECT                                    
id,
date_doc,
num_doc
FROM sh_test.tbl_docs
ORDER BY date_doc ASC;
И результат
Code Скопировано
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 id |          date_doc          |   num_doc    
----+----------------------------+--------------
  1 | 2022-01-19 16:18:57.261306 | 2022-01-19 1
  2 | 2022-01-19 16:19:02.233629 | 2022-01-19 2
  3 | 2022-01-19 16:19:06.659471 | 2022-01-19 3
  4 | 2023-01-17 16:19:11.177813 | 2023-01-17 1
  5 | 2023-01-17 16:19:15.231224 | 2023-01-17 2
  6 | 2023-01-17 16:19:19.581022 | 2023-01-17 3
  7 | 2023-01-17 16:19:25.18139  | 2023-01-17 4
  8 | 2023-01-17 16:19:32.850095 | 2023-01-17 5
  9 | 2023-01-17 16:19:37.03092  | 2023-01-17 6
 10 | 2023-01-17 16:19:43.100864 | 2023-01-17 7
 11 | 2023-01-19 16:19:47.409317 | 2023-01-19 1
 12 | 2023-01-19 16:19:51.77682  | 2023-01-19 2
 13 | 2023-01-19 16:19:55.670734 | 2023-01-19 3
 14 | 2023-01-19 16:20:02.174263 | 2023-01-19 4
(14 строк)
Добавлено через 7 минут
Обратите внимание на нюансы
1)было бы неплохо в код добавить проверки на корректность и чтоб при изменении даты-времени записи не было одинаковых значений в таблице, может, вообще стоит уникальный ключ на это поле добавить в табличку и date_doc сделать NOT NULL.
Иначе корректность работы не будет гарантирована.
2) Если реализовать п.1, то не будет сюрпризов при параллельной работе, и при этом блокируется не вся таблица и тормозов скорее всего будет меньше, чем если реализовывать вашим методом.
Сорри, если не очень понятно пишу.

Добавлено через 7 минут
3)Эту функцию наверное стоит вызывать в триггере после добавления и обновления(но триггер должен срабатывать только, если меняется поле date_doc), тогда он не будет вызываться при каждом обновлении записей
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
19.01.2023, 16:54
Помогаю со студенческими работами здесь

Plpgsql . вставка данных из файла
Добрый день! Подскажите пожалуйста, как можно выбрать значение из файла (excel), чтобы заинсёртить в БД?

Триггер для добавления к строке название таблицы, в которой содержится триггер
Есть таблицы База_Практик. В неё добавляю предприятие, и автоматически нужно добавить это предприятие с именем таблицы База практик в...

Триггер для добавления к строке название таблицы, в которой содержится триггер
Есть таблицы База_Практик. В неё добавляю предприятие, и автоматически нужно добавить это предприятие с именем таблицы База практик в...

Не срабатывает триггер после вставки внутри триггера в таблицу, для которой реализован триггер
Добрый день. Есть таблица A. Для таблицы A сделан триггер A_T, срабатывающий AFTER INSERT в таблицу A. Внутри триггера A_T может...

Триггер, вызывающий процедуру, в которой выполняется select к этой таблице (откуда был вызван триггер)
есть тригерр create or replace trigger quickstart.quickstart.ACRIONS_COMMIT_TR after update on quickstart.actions for each...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
2
Ответ Создать тему
Новые блоги и статьи
Оптимизация производительности Node.js с помощью кластеризации
run.dev 04.04.2025
Масштабирование приложений для обработки тысяч и миллионов запросов — обыденная задача для многих команд. Node. js, благодаря своей асинхронной событийно-ориентированной архитектуре, стал популярной. . .
Управление зависимостями в Python с Poetry
py-thonny 04.04.2025
Стандартный инструмент для установки пакетов в Python - pip - прекрасно справляется с базовыми сценариями: установил пакет командой pip install и используешь его. Но что произойдёт, когда разные. . .
Мониторинг с Prometheus в PHP
Jason-Webb 04.04.2025
Prometheus выделяется среди других систем мониторинга своим подходом к сбору и хранению метрик. В отличие от New Relic, который использует агентный подход и отправляет данные во внешнее хранилище,. . .
Пакет Context в Golang: Управление потоками и ресурсами
golander 04.04.2025
Работа с горутинами в Go часто напоминает управление непослушными детьми - они разбегаются кто куда, делают что хотят и не всегда завершаются вовремя. К счастью, в Go 1. 7 появился пакет context,. . .
Контейнеризация React приложений с Docker
Reangularity 03.04.2025
Контейнеризация позволяет упаковать приложение со всеми его зависимостями в автономный контейнер, который можно запустить на любой платформе с установленным Docker. Это существенно упрощает процессы. . .
Свой попап в SwiftUI
mobDevWorks 03.04.2025
SwiftUI, как декларативный фреймворк от Apple, предоставляет множество инструментов для создания пользовательских интерфейсов. В нашем распоряжении есть такие API как alerts, popovers, action sheets. . .
Антипаттерны микросервисной архитектуры
ArchitectMsa 03.04.2025
Хорошо спроектированная микросервисная система может выдержать испытание временем, оставаясь гибкой, масштабируемой и устойчивой к большинству проблем. Такая архитектура обладает высоким уровнем. . .
std::mutex в C++: Советы и примеры использования
bytestream 03.04.2025
std::mutex - это механизм взаимного исключения, который гарантирует, что критический участок кода выполняется только одним потоком в каждый момент времени. Это простое, но могущественное средство. . .
Не удержался от оценки концепции двигателя Стирлинга.
Hrethgir 03.04.2025
Сколько не пытался - она выдавала правильные схемы, причём случайно рисовала горячие области в середине, холодные по краям, трубки с краёв в низ и магнит в соединяющей, но при этой выдавала описание. . .
Метод с двумя буферами (или double buffering) или ping-pong buffering
Hrethgir 02.04.2025
Из ответов LM модели. Метод, который предполагает использование двух массивов для хранения промежуточных результатов сложения векторов, обычно применяется в сценариях, где необходимо минимизировать. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru
Выделить код Копировать код Сохранить код Нормальный размер Увеличенный размер