powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / секционирование. как при update результат Affected rows: 0 изменить на Affected rows: 1
25 сообщений из 26, страница 1 из 2
секционирование. как при update результат Affected rows: 0 изменить на Affected rows: 1
    #39321310
Фотография Legushka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
подскажите плиз как можно изменить результат при изменении в партициях

сейчас при изменении срабатывает тригер на update
и там идет операция delete + insert вместо update (что бы данные могли попасть в нужную секцию, удаляем из текущей, и заново вставляем, при вставке работает тригер на insrt, который разруливает в какую секцию инсертить данные)

из бд все работает норм, но из hypername получаю ошибку:
Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1;
и все стопорится
...
Рейтинг: 0 / 0
секционирование. как при update результат Affected rows: 0 изменить на Affected rows: 1
    #39321328
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Legushka,

1)научится пользоватся гуглом
2)отключить эту проверку в настройках hibernate
3)?
4)profit

--
Maxim Boguk
www.postgresql-consulting.ru
...
Рейтинг: 0 / 0
секционирование. как при update результат Affected rows: 0 изменить на Affected rows: 1
    #39321337
Фотография Legushka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Maxim, отключить в настройках hibernate не дают.

для инсерта получилось сделать в postgres с помощью rule
для апдейта так же не получилось: в тригерной функции используется with а он с rule не работает.
...
Рейтинг: 0 / 0
секционирование. как при update результат Affected rows: 0 изменить на Affected rows: 1
    #39321380
Фотография vyegorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Legushka,

Можно в BEFORE триггере не возвращать NULL, что приведёт к вставке в мастер-таблицу.
На ту же таблицу вешается AFTER триггер, который сразу удаляет запись из мастер-таблицы.

Но это всё очень уж неповоротливо становиться...

Желательно убрать из мастер-таблицы индексы, установить fillfactor=50 (с потолка взял, надо смотреть по факту) и убедиться,
что достаточно autovacuum рабочих. Можно также понизить пороги срабатывания autovacuum'а для мастер-таблицы.
...
Рейтинг: 0 / 0
секционирование. как при update результат Affected rows: 0 изменить на Affected rows: 1
    #39321392
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
LegushkaMaxim, отключить в настройках hibernate не дают.
шампанское по утрам, хибернейт по утрам
короче, hibernate -- это дело либо дегенератов (99%), либо аристократов
в обоих случаях обходятся без вопросов на форумах, ага

Legushka в тригерной функции используется with а он с rule не работает.
вот с этого места подробно, с кодом, что делали, что не получилось

а то что вы всюду цте пихаете , то тоже не лучший паттерн (сам его пользую часто, грешен)

2егоров -- на апдейт оно не сработает -- там событие в партиции, а его и нет -- делет в одной и инсерт в другой вместо него --> надо вешать вьюху и инстеадить.
...
Рейтинг: 0 / 0
секционирование. как при update результат Affected rows: 0 изменить на Affected rows: 1
    #39321403
Фотография Legushka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
qwwq,qwwqнадо вешать вьюху и инстеадить.вот какрас так и пытаюсь сделать, но сейчас уходит в цикл:(
Код: sql
1.
2.
3.
4.
create or replace view master_table_view as select * from master_table;
CREATE or replace RULE use_right_updater_master_table AS
    ON UPDATE TO master_table
  DO INSTEAD UPDATE master_table_view SET id = new.id where id = new.id;


Код: sql
1.
2.
ERROR: infinite recursion detected in rules for relation "master_table"
ERROR: current transaction is aborted, commands ignored until end of transaction block
...
Рейтинг: 0 / 0
секционирование. как при update результат Affected rows: 0 изменить на Affected rows: 1
    #39321417
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Legushkaqwwq,qwwqнадо вешать вьюху и инстеадить.вот какрас так и пытаюсь сделать, но сейчас уходит в цикл:(
Код: sql
1.
2.
3.
4.
create or replace view master_table_view as select * from master_table;
CREATE or replace RULE use_right_updater_master_table AS
    ON UPDATE TO master_table
  DO INSTEAD UPDATE master_table_view SET id = new.id where id = new.id;


Код: sql
1.
2.
ERROR: infinite recursion detected in rules for relation "master_table"
ERROR: current transaction is aborted, commands ignored until end of transaction block



заведите 2 сущности:
1. мастер -- таблицу (наследование)
2. мастер-- представление (вьюха для обвески инстеадами)
наружу публикуйте мастер-- представление , а внутри руля пихайте (инсерттьте) в мастер--табличку, на которой висит старый добрый триггер разброски по партициям.

это общий мотив.


далее -- никогда не путайте рули с триггерами. -- рули недоступны к пониманию простыми смертными (там мухи и бутсы в головах отцов--основателей).

и собственно вместо руле, должен быть инстеад--офф триггер, который проверяет, что партиция меняется, и в этом случае (и только в нем) -- перекрывает обычный апдейт удалением из конкрентой партиции, и вставкой в мастер-- таблицу , на который висит обычный бефоре--триггер партицирования. Т.к. триггер на вьюхе инстеад -- то смело возвращаете NEW.

таким образом никаких циклов у вас в принципе нигде не появляется. а иначе -- мухи, и берцы, и ботфорты
...
Рейтинг: 0 / 0
секционирование. как при update результат Affected rows: 0 изменить на Affected rows: 1
    #39321425
Фотография Legushka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
qwwq,авторвместо руле, должен быть инстеад--офф триггер, попробовал создать получил:
Tables cannot have INSTEAD OF triggers.
...
Рейтинг: 0 / 0
секционирование. как при update результат Affected rows: 0 изменить на Affected rows: 1
    #39321430
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Legushkaqwwq,авторвместо руле, должен быть инстеад--офф триггер, попробовал создать получил:
Tables cannot have INSTEAD OF triggers.
не надо пробовать, надо понимать
ну или один раз таки убедиться
но дальше бестолковку подключить:

инстеад триггер вешается на вьюху (вьюха или форейгн тейбл могут иметь тольок инстеад офф триггера)
поэтому публичным "интерфейсом" может быть только вьюха в вашем случае.
а табличка д.б. спрятана за ней и обвешана обычными триггерами, returning NULL.
...
Рейтинг: 0 / 0
секционирование. как при update результат Affected rows: 0 изменить на Affected rows: 1
    #39321622
Фотография Legushka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
qwwq, сделал как вы сказали,
но результат возвращает все равно
Affected rows: 0
...
Рейтинг: 0 / 0
секционирование. как при update результат Affected rows: 0 изменить на Affected rows: 1
    #39321681
Фотография Legushka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
новое наблюдение причем довольно люопытное:
сейчас при обычном апдейте возвращает 1
но если партиция все таки меняется в результате апдейта то Affected rows: 0
...
Рейтинг: 0 / 0
секционирование. как при update результат Affected rows: 0 изменить на Affected rows: 1
    #39321736
Фотография Legushka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Maxim Boguk2)отключить эту проверку в настройках hibernate
Maxim, подскажите можно ли отключить в hibernate настройку проверки количества измененных строк только в конкретном запросе при сохранении/изменении конкретной записи (только на партицированных таблицах)?
устал я от танцов с бубном:
не используешь RULE, не возвращает 1
используешь RULE выходит ошибка там где апдейт идет в купе с CTE
круг замкнулся
...
Рейтинг: 0 / 0
секционирование. как при update результат Affected rows: 0 изменить на Affected rows: 1
    #39322002
Фотография Legushka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
исправил все хранимки которые были с with
теперь остался один шаг до реализации: когда меняется партиция при апдейте возвращает 0 -(
дело в том что при создании текущего документа (таблица NOT_MASTER_TABLE), изанчально сохраняется практически пустой запись в master_table
после всех расчетов в NOT_MASTER_TABLE идет апдейт в master_table, в том числе присваивается ГОРОД, из за чего партиция с master_table_other переходит в партицию master_table_tambov, но при этом RULE вернул Affected rows: 0

если получится сделать на Affected rows: 1, то исправлять и отключать в hybernate ничего не надо будет
...
Рейтинг: 0 / 0
секционирование. как при update результат Affected rows: 0 изменить на Affected rows: 1
    #39322037
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Legushka,

"вот с этого места подробно, с кодом, что делали, что не получилось"


напишите уже кратенький тест кейс, с минимумом ваших особостей, с табличкой с 3-мя полями (ключ, партицирующее, поле1) чтобы воспроизводилась ваша ситуация) и давайте играться на нём. минимальное кол--во кода в триггерах, только общее.
...
Рейтинг: 0 / 0
секционирование. как при update результат Affected rows: 0 изменить на Affected rows: 1
    #39322962
Фотография Legushka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
получилось сделать)
теперь правильно возвращает Affected rows: 1 если был апдейт

Код: sql
1.
create or REPLACE RULE use_right_updater_master_table AS ON UPDATE TO master_table DO INSTEAD update table_one set b = b where update_master_table_and_get_row(new, old) = 1;


логика такая:
table_one - это таблица с 1 записью! сделана просто что бы был какой то апдейт

в условии стоит функция update_master_table_and_get_row(new, old)
в ней реально происходит апдейт, причем сразу участвуют в условиях все поля которые есть в разрезах партиций, поэтому даже если вы апдейтите в условии только по одному ИД, все равно сработают все check и мы сразу в нужную партицию попадаем-)
после апдейта проверяем сколько строк апдейтилось и возвращаем результат

и потом в исполнении правила идет проверка update_master_table_and_get_row(new, old) = 1


минус подхода: апдейты нельзя будет использовать совместно с with, придется смирится
...
Рейтинг: 0 / 0
секционирование. как при update результат Affected rows: 0 изменить на Affected rows: 1
    #39322984
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Legushkaполучилось сделать)
теперь правильно возвращает Affected rows: 1 если был апдейт

Код: sql
1.
create or REPLACE RULE use_right_updater_master_table AS ON UPDATE TO master_table DO INSTEAD update table_one set b = b where update_master_table_and_get_row(new, old) = 1;


логика такая:
table_one - это таблица с 1 записью! сделана просто что бы был какой то апдейт

в условии стоит функция update_master_table_and_get_row(new, old)
в ней реально происходит апдейт, причем сразу участвуют в условиях все поля которые есть в разрезах партиций, поэтому даже если вы апдейтите в условии только по одному ИД, все равно сработают все check и мы сразу в нужную партицию попадаем-)
после апдейта проверяем сколько строк апдейтилось и возвращаем результат

и потом в исполнении правила идет проверка update_master_table_and_get_row(new, old) = 1


минус подхода: апдейты нельзя будет использовать совместно с with, придется смирится

Безумству храбрых поем мы песню!
Делать вам нечего.
И ради чего главное то???

--
Maxim Boguk
www.postgresql-consulting.ru
...
Рейтинг: 0 / 0
секционирование. как при update результат Affected rows: 0 изменить на Affected rows: 1
    #39322992
Фотография Legushka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Maxim, ради того что бы не делать поддержку всех зависимых таблиц которые ссылаются на мастер_таблицу
на разных серверах может быть сколь угодно много внешних FK (а это ограничение для создания партиций)

отключать FK в нашем случае нерезонно: поддерживать целостность данных там где мы не имеем никакой дейятельности не резонно
покупатели сами решают делать им FK или еще чтото на своих таблицах, нам не важно, мы ведем поддержку только своей таблицы

правда для того что бы заработало FK это уже другая история, в данном случае важно было сделать так что бы зависимые внешние данные не удалялись тогда когда мы изменяем партиции (из одной удалили, в другую вставили, и в этот момент при делеете не удалились все зависимые данные)

вот ради чего все и затевалось.
...
Рейтинг: 0 / 0
секционирование. как при update результат Affected rows: 0 изменить на Affected rows: 1
    #39322994
Фотография Legushka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
яcreate or REPLACE RULE use_right_updater_master_table AS ON UPDATE TO master_table DO INSTEAD update table_one set b = b where update_master_table_and_get_row(new, old) = 1;думаю можно ли сделать так: заменить апдейт в table_one на select 1
Код: sql
1.
create or REPLACE RULE use_right_updater_master_table AS ON UPDATE TO master_table DO INSTEAD select 1 where update_master_table_and_get_row(new, old) = 1;


что бы не было блоков на одной таблице если одновременно много пользователей совершают апдейты

селект так же вернет Affected rows: 1 если внутри в update_master_table_and_get_row() произойдет изменение.
...
Рейтинг: 0 / 0
секционирование. как при update результат Affected rows: 0 изменить на Affected rows: 1
    #39323055
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Legushkaполучилось сделать)
теперь правильно возвращает Affected rows: 1 если был апдейт

Код: sql
1.
create or REPLACE RULE use_right_updater_master_table AS ON UPDATE TO master_table DO INSTEAD update table_one set b = b where update_master_table_and_get_row(new, old) = 1;



тьху, блин

дай северному варвару нефритовый стержень...

так тест кейс с 3-мя полями, БЕЗ РУЛЕЙ но с инстеад--триггерами варвар ниасилил
печалька
вычёркиваю (тм)
...
Рейтинг: 0 / 0
секционирование. как при update результат Affected rows: 0 изменить на Affected rows: 1
    #39323056
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
пысы:
задача -- отапдейтить одним стейтментм 2 записи. и получить 2, а не 1.
...
Рейтинг: 0 / 0
секционирование. как при update результат Affected rows: 0 изменить на Affected rows: 1
    #39323084
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
таки надумал сам откейсить :
Код: 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.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
--DROP TABLE t_t ;
BEGIN;
CREATE TABLE t_t 
(part integer NOT NULL 
,t_id serial primary key
,fld text 
,CHECK (part is null ) no inherit 
);

CREATE TABLE t_1
(
 CHECK (part =1 ) no inherit 
)
inherits (t_t)
;
CREATE TABLE t_2
(
 CHECK (part = 2 ) no inherit 
)
inherits (t_t)
;
CREATE VIEW t AS select * from t_t;
ALTER TABLE t ALTER t_id SET DEFAULT nextval('t_t_t_id_seq'::regclass); -- удобства на улице

CREATE OR REPLACE FUNCTION part_insert_trigger()
RETURNS TRIGGER AS $body$
BEGIN
	IF (NEW.part= 1) THEN
		INSERT INTO t_1 VALUES (NEW.*);
	ELSIF (NEW.part = 2) THEN
		INSERT INTO t_2 VALUES (NEW.*);
	ELSE
		--RAISE EXCEPTION 'partition key is out of range.  Fix the trigger function';
		INSERT INTO t_t VALUES (NEW.*);
	END IF;
	RETURN NEW; -- RETURN NEW in this case, typically you'd return NULL from this trigger, but for views we return NEW
END;
$body$
LANGUAGE plpgsql;

CREATE TRIGGER ins
INSTEAD OF INSERT ON t
FOR EACH ROW EXECUTE PROCEDURE part_insert_trigger(); -- create "INSTEAD OF" trigger
--tests

	--INSERT INTO t (part,t_id,fld) values (0,default,'0-error-chk');
	INSERT INTO t (part,t_id,fld) values (1,default,'1-chk');
	SELECT tableoid::regclass,* FROM t_t;
	INSERT INTO t (part,t_id,fld) values (2,default,'2-chk');
	SELECT tableoid::regclass,* FROM t_t;
	--UPDATE t SET part = 1 + (part %2);
---UPDATE---
CREATE OR REPLACE FUNCTION part_update_trigger()
RETURNS TRIGGER AS $body$
BEGIN
	
	IF (NEW.part= OLD.part) THEN
		UPDATE t_t SET	part	=NEW.part
				,t_id	=NEW.t_id
				,fld = 	NEW.fld
		WHERE 	
			t_t.part	=NEW.part
			AND t_t.t_id	=NEW.t_id;
	ELSE
		DELETE FROM t_t WHERE t_id = OLD.t_id;
		INSERT INTO t VALUES (NEW.*);
	END IF;
	RETURN NEW; -- RETURN NEW in this case, typically you'd return NULL from this trigger, but for views we return NEW
END;
$body$
LANGUAGE plpgsql;

CREATE TRIGGER upd
INSTEAD OF UPDATE ON t
FOR EACH ROW EXECUTE PROCEDURE part_update_trigger(); -- create "INSTEAD OF" trigger
/*
-- check moving end not moving cases 
	UPDATE t SET part = 1 + (part %2);
	SELECT tableoid::regclass,* FROM t_t;
	UPDATE t SET fld = fld||' check ';
	SELECT tableoid::regclass,* FROM t_t;
--*/
-- finally tests^
--
	UPDATE t SET fld = fld ||' recheck 0'
	RETURNING t.*;
--
	UPDATE t SET	part = 1 + (part %2)
			, fld = fld ||' recheck1'
	RETURNING t.*;
--
	UPDATE t SET	part = 1 + (part %2)
		, fld = fld ||' recheck2'
	RETURNING t.*;
	
ROLLBACK ;

...
Рейтинг: 0 / 0
секционирование. как при update результат Affected rows: 0 изменить на Affected rows: 1
    #39323690
Фотография Legushka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
qwwq, спасибо за ваш кейс, попробовал поюзать
нашел такой минус: изменение на вью количество измененных дает верно
но на основной таблице при изменении :
Код: sql
1.
UPDATE t_t SET part = 2 WHERE T_ID = 1


Affected rows: 0
...
Рейтинг: 0 / 0
секционирование. как при update результат Affected rows: 0 изменить на Affected rows: 1
    #39323724
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ну вы ж блин и дерево:

qwwqинстеад триггер вешается на вьюху (вьюха или форейгн тейбл могут иметь тольок инстеад офф триггера)
поэтому публичным "интерфейсом" может быть только вьюха в вашем случае.
а табличка д.б. спрятана за ней и обвешана обычными триггерами, returning NULL.

вы поменяйте десяток ззапись-писей одним апдейттом в своём "решении" и опубликуйте, сколько же роу у вас таки аффектед
...
Рейтинг: 0 / 0
секционирование. как при update результат Affected rows: 0 изменить на Affected rows: 1
    #39323741
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
я ещё дя тупых хотел не t_t обозвать, а t_hidden or t_Stealth or t_phantom, кактотаг

проблема с вьюхой вместо таблички -- не видно системных столбцов
и приходится апдейт по полям расписывать (и ключи по полям равнять)
обобщенных трггерных ф--й (если не через динамику-- что тормозно) не предвидится
нужен обьект "враппер", частный случай вьюхи ровно к одной таблице, с системными полями, и спец--кляузой для апдейта текущей строки "фоновой таблички" в таких делах.
...
Рейтинг: 0 / 0
секционирование. как при update результат Affected rows: 0 изменить на Affected rows: 1
    #39323759
Фотография Legushka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
qwwq, спрятать не получится: она используется уже энцать лет, ее все знают. Эта таблица используется уже во многих кейсах, зашито глубоко в hibernate, вообще одна из первых таблиц с которых все началось. так что не быть ей stealth fantom и тд.

rule в общем помогли разрулить это, но сейчас update однострочной таблицы не вариант, нужно придумать альтернативу, как без блоков изменять пустышку.
...
Рейтинг: 0 / 0
25 сообщений из 26, страница 1 из 2
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / секционирование. как при update результат Affected rows: 0 изменить на Affected rows: 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]