Как получить все поля Record'а

centur
Дата: 12.07.2004 22:17:18
Вопрос вот в чем - в процедуре динамически форммируется запрос, т.е. каждый раз выборка полей может отличаться, Далее необходимо по всем записям в цикле пройти и осуществить действия. Т.к. выборка каждый раз разная (кол-во полей) - жестко зашить не выходит. Вот вопрос - как получить список этих полей и их значений. Вернее получить список полей могу (запрос формирую сам), но как теперь получить значения этих полей которые в recordе . типа переменная fld_name=''kod_ved''
как получить значение rec.kod_ved. Или для триггера на таблице - зная названия полей, получить значения NEW.pole1 и OLD.pole1 НЕ зашивая жестко в триггерной функции pole1 и pole2.
4321
Дата: 24.01.2006 13:28:09
UP тему

в таком разрезе:
ХОЧУ перебрать все поля переменной типа рекорд по порядку (по числовому индексу). Как? (т.е. можно ли такое).

контекст: идет сравнение старой записи с NEW.* полей порядка 40. надо сравнить первые 37 (3 служебных) - и вынести вердикт об изменении. (что-то типа выгрузки удаленных данных с контролем реплик).

есТли есть идеи другого плана (помимо обращения к полю записи по числовому индексу) - тоже просьба поделицца. (я чел негордый - могу и все поля перебрать поименно - но просто уж вопрос слишком часто возникает)
фффф
Дата: 25.01.2006 03:46:08
IMHO на pl/pgsql никак. А так как на других динамических языках это делается запросто, то упросить добавить такой функционал в pl/pgsql сложно.

Остается либо писать на перле|пайтоне, либо использовать какое-нибудь средство моделирования (например PowerDesigner) с макроязыком для генерации pl/pgsql триггеров, либо написать генератор кода самому.

Можно гибридный вариант сделать: два триггера, один на перле делает только сравнение и ставит в вспомогательном поле или глобальной переменной true|false, а второй на pgsql разруливает всю бизнес-логику.
4321
Дата: 25.01.2006 10:39:17
фффф
Остается либо писать на перле|пайтоне, либо использовать какое-нибудь средство моделирования (например PowerDesigner) с макроязыком для генерации pl/pgsql триггеров, либо написать генератор кода самому.

ну есь и полуручные способы. (немножко аксесса + ворд с массовой заменой, табличными преобразованиями и т.п.)

С другой стороны в постгресс есть операторы сравения строк (RECORD) целиком, но кажется нет оператора сравнивания подстроки (как указать сравниваемую часть подстроки?). опять же проблема - нет (я не знаю, скажем так, ибо вероятно что таки есть) _удобного_ оператора, делающего проверку "неизменности" (а не равенства) как для строк, так и для _всех_ типов:
[|NOT] ((a=b) OR ((a IS NULL) AND (b IS NULL))
(что странно, ибо кажется что унутренне его проверить даже проще чем "="), а писать по ф-ии на каждый сравниваемый тип - слишком жирно.
ткните носом, если я неправ попо воду оператора.
Funny_Falcon
Дата: 26.01.2006 11:15:04
SELECT NULL IS DISTINCT FROM 'не нулл';
4321
Дата: 26.01.2006 12:54:13
Funny_Falcon
SELECT NULL IS DISTINCT FROM 'не нулл';
сенькаю. крутил я этот вариант, только с рядами (ROW)
SELECT
CASE WHEN ROW('Null','Null') IS DISTINCT FROM ROW('Null','Null')
THEN
	'изменен'
ELSE
	'неизменен'
END;
, но почему-то не принял на свой счет (поспешил видимо) -что-то на перший взгля не подошло. Наверное так и перепишу.
(а то ж с NOT вообше трехетажно получилось-
...IF NOT COALESCE((a=a1) OR ...),FALSE)
...
ELSIF NOT COALESCE((b=b1) OR ...),FALSE)


____
ЗЫ
-кстати, кажется придумал, как сравнивать части рядов _после вставки_, не переписывая всех атрибутофф - создать усеченный (на служебные поля) вью, и брать ряды запросами к нему. Но мне это нужно в триггере _до_. т.ч. там как обрезать new.* не перечисляя полей неясно (к тому же в 7.3. нельзя new положить в другой Record - запрос видите ли не рульный).
4321
Дата: 27.01.2006 17:46:19
вот кажется нашел, почему не надо пользовать IS DISTINCT FROM

...
RAISE NOTICE \'_lastold.okei %\', _lastold.okei;
RAISE NOTICE \'NEW.okei %\',  NEW.okei;
_isupdated := (select _lastold.okei  IS DISTINCT FROM  NEW.okei);
--_isupdated := tRUE;
RAISE NOTICE \'_isupdated %\',_isupdated;
...
читаю:
NOTICE:  _lastold.okei 123
NOTICE:  NEW.okei <NULL>
NOTICE:  _isupdated f
проверяю
SELECT  123 IS DISTINCT FROM null
t
сыршенно непонятный результатт. то ли я к вечеру тяпницы "никакой", то ли еще чего. (селект и скобицы я там, в присвоении, приписал позже, без них та же муть )
Т.ч. верну ка я гробики из коалкскав и прочей бодяги - оно канешно гробовидно, зато работаить.


ЗЫ. проверил на догадку о баге именно для plpg, нет - для констант то сравнивает:
--_isupdated :=  (_lastold.okei) IS DISTINCT FROM (NEW.okei);
_isupdated := 1 IS DISTINCT FROM NULL;
постгрес 7.3.4
4321
Дата: 30.01.2006 11:21:47
таки это баг 7.3.4
проверяем:
[src]CREATE OR REPLACE FUNCTION f_test_distinct()
RETURNS SETOF bool AS
'
declare
_res bool;
_tmp int4;
_tmp1 int4;
begin
_res := 1 IS DISTINCT FROM 2;
RAISE NOTICE \'1 IS DISTINCT FROM 2 %\' , _res;
RETURN NEXT _res;
_res := 1 IS DISTINCT FROM 1;
RAISE NOTICE \'1 IS DISTINCT FROM 1 %\' , _res;

_tmp:=1; _tmp1:=2;
RETURN NEXT _res;
_res := _tmp IS DISTINCT FROM _tmp1;
RAISE NOTICE \'_tmp:=1 IS DISTINCT FROM _tmp1:=2 %\' , _res;

_tmp:=1; _tmp1:=1;
RETURN NEXT _res;
_res := _tmp IS DISTINCT FROM _tmp1;
RAISE NOTICE \'_tmp:=1 IS DISTINCT FROM _tmp1:=1 %\' , _res;
RETURN NEXT _res;

_tmp:=1; _tmp1:=2;
_res := ROW(_tmp,1) IS DISTINCT FROM (_tmp1,1);
RAISE NOTICE \'ROW(_tmp:=1,1) IS DISTINCT FROM ROW(_tmp1:=2,1) %\' , _res;
RETURN NEXT _res;

_res := ROW(1,1) IS DISTINCT FROM (2,2);
RAISE NOTICE \'ROW(1,1) IS DISTINCT FROM (2,2) %\' , _res;
RETURN NEXT _res;
return;
end;
'
LANGUAGE 'plpgsql' VOLATILE;SRC]
возвраты соответственно:
7.3.4.
NOTICE: 1 IS DISTINCT FROM 2 t
NOTICE: 1 IS DISTINCT FROM 1 f
NOTICE: _tmp:=1 IS DISTINCT FROM _tmp1:=2 f
NOTICE: _tmp:=1 IS DISTINCT FROM _tmp1:=1 f
NOTICE: ROW(_tmp:=1,1) IS DISTINCT FROM ROW(_tmp1:=2,1) f
NOTICE: ROW(1,1) IS DISTINCT FROM (2,2) t
8.0.1
NOTICE: 1 IS DISTINCT FROM 2 t
NOTICE: 1 IS DISTINCT FROM 1 f
NOTICE: _tmp:=1 IS DISTINCT FROM _tmp1:=2 t
NOTICE: _tmp:=1 IS DISTINCT FROM _tmp1:=1 f
NOTICE: ROW(_tmp:=1,1) IS DISTINCT FROM ROW(_tmp1:=2,1) t
NOTICE: ROW(1,1) IS DISTINCT FROM (2,2) t
4321
Дата: 30.01.2006 11:23:35
таки это баг 7.3.4
проверяем:
CREATE OR REPLACE FUNCTION f_test_distinct()
  RETURNS SETOF bool AS
'
declare
	_res bool;
	_tmp int4;
	_tmp1 int4;
begin 
	_res := 1 IS DISTINCT FROM 2;
	RAISE NOTICE \'1 IS DISTINCT FROM 2 %\' , _res;
	RETURN NEXT _res;
	_res := 1 IS DISTINCT FROM 1;
	RAISE NOTICE \'1 IS DISTINCT FROM 1 %\' , _res;

	_tmp:=1; _tmp1:=2;
	RETURN NEXT _res;
	_res := _tmp  IS DISTINCT FROM _tmp1;
	RAISE NOTICE \'_tmp:=1  IS DISTINCT FROM _tmp1:=2 %\' , _res;

	_tmp:=1; _tmp1:=1;
	RETURN NEXT _res;
	_res := _tmp  IS DISTINCT FROM _tmp1;
	RAISE NOTICE \'_tmp:=1  IS DISTINCT FROM _tmp1:=1 %\' , _res;
	RETURN NEXT _res;

	_tmp:=1; _tmp1:=2;
	_res := ROW(_tmp,1)  IS DISTINCT FROM (_tmp1,1);
	RAISE NOTICE \'ROW(_tmp:=1,1)  IS DISTINCT FROM ROW(_tmp1:=2,1) %\' , _res;
	RETURN NEXT _res;

	_res := ROW(1,1)  IS DISTINCT FROM (2,2);
	RAISE NOTICE \'ROW(1,1)  IS DISTINCT FROM (2,2) %\' , _res;
	RETURN NEXT _res;
return;
end;
'
  LANGUAGE 'plpgsql' VOLATILE;
возвраты соответственно:
7.3.4.
NOTICE: 1 IS DISTINCT FROM 2 t
NOTICE: 1 IS DISTINCT FROM 1 f
NOTICE: _tmp:=1 IS DISTINCT FROM _tmp1:=2 f
NOTICE: _tmp:=1 IS DISTINCT FROM _tmp1:=1 f
NOTICE: ROW(_tmp:=1,1) IS DISTINCT FROM ROW(_tmp1:=2,1) f
NOTICE: ROW(1,1) IS DISTINCT FROM (2,2) t
8.0.1
NOTICE: 1 IS DISTINCT FROM 2 t
NOTICE: 1 IS DISTINCT FROM 1 f
NOTICE: _tmp:=1 IS DISTINCT FROM _tmp1:=2 t
NOTICE: _tmp:=1 IS DISTINCT FROM _tmp1:=1 f
NOTICE: ROW(_tmp:=1,1) IS DISTINCT FROM ROW(_tmp1:=2,1) t
NOTICE: ROW(1,1) IS DISTINCT FROM (2,2) t

(звиняюсь за форматирование - могабыть дропнуть пост выше?)
ВсеДуракииЯтоже
Дата: 31.05.2018 11:27:04
Сделай TO_JSON(record) и все сразу увидишь и поймешь.