Не правильно работает функция

Mblp
Дата: 03.02.2015 14:37:50
вот код функции
CREATE OR REPLACE FUNCTION common.gent(in_mode text,exclusion int)
  RETURNS integer AS
$BODY$
declare --объЯвлЯем переменные
  i_res bigint;
  i bigint;
 
  rec1 record;
  rec2 record;
    rec3 record;
  curs1 refcursor;
  curs2 refcursor;
  sql_array text[];
  pk_array text[];
  pk_str text;
  the_sql text;
  a_cprop bigint;
   a_cpropb bigint;
hranim text[];
  i_res2 bigint;
  needed_i_res2 bigint;
begin

  for rec1 in
   select pgn.nspname::text as col_schema, pgcl.relname::text as col_table, pga.attname::text as col_cprops, pgcon.conkey::bigint[] as col_pk_nums,
    ARRAY(
      select pga2.attname
      from pg_attribute as pga2
      where (pga2.attrelid = pgcl.oid)
       and (pga2.attnum > 0)
      order by pga2.attnum
    )::text[] as col_all_columns,
	  --select *
    (
        select pgcon2.conkey::text
	from pg_constraint as pgcon2
	where  (pgcon2.contype = 'p')
	and (pgcon2.conrelid=pgcl.oid)
	)::bigint[] as pk_num 
	--выборка первичных ключей таблицы с которой работаем
    from pg_class as pgcl, pg_namespace as pgn, pg_attribute as pga, pg_constraint as pgcon ,pg_class as pgcl2
    where (pgcl.relkind = 'r')
    and (pgcl.relnamespace = pgn.oid)
    and (pgn.nspname = 'common')
    and (pga.attrelid = pgcl.oid)
    and (pgcl2.relname=in_mode)
    and (pga.attnum=pgcon.conkey[1]) 
    and (pgcon.conrelid = pgcl.oid)
    and (pgcon.confrelid = pgcl2.oid)
    order by pgcl.relname
/*название таблицы к которой все обращаютсЯ
если номер столбца равен номеру вторичного ключа
 находим название таблицы с помощью номера в pgcl и conrelid( показывает к какой таблице относитсЯ)
 внешний ключ ссылаетсЯ на какую таблицу*/
 loop

   

    sql_array := ARRAY[]::text[];
    pk_array := ARRAY[]::text[];
    pk_str := '';
    
    for i in 1..coalesce(array_upper(rec1.pk_num, 1), 0) loop
      pk_array := array_append(pk_array, rec1.col_all_columns[rec1.pk_num[i]]);   
    end loop;
	-- заносим в массив первичные ключи
    pk_str := array_to_string(pk_array, ', ');             
	-- делаем из массива строку

    sql_array := array_append(sql_array, 'select ARRAY[' || pk_str || ']::text[] as col_pk_vals, ' || rec1.col_cprops || '::text as col_cprops_vals');
    sql_array := array_append(sql_array, 'from ' || (rec1.col_schema || '.' || rec1.col_table));
    sql_array := array_append(sql_array, 'order by ' || pk_str);
    --sql_array := array_append(sql_array, 'group by ' || rec1.col_cprops || 'count(*)');
    sql_array := array_append(sql_array, ';');               
    the_sql := array_to_string(sql_array, ' ');               
	--запрос на выборку, сортируем по первичным ключам
	-- делаем из массива строку
	
  open curs1 for execute the_sql;
      open curs2 for execute the_sql;
    while true loop
      fetch curs1 into rec2;
      if (rec2 is null) then
        exit;
      end if;
     -- a_cprop := rec2.col_cprops_vals;
     -- hranim =rec2.col_pk_vals;
	while true loop
      fetch curs2 into rec3;
    if (rec3 is null) then
      exit;
     end if;
     a_cprop := rec2.col_cprops_vals;
      hranim =rec2.col_pk_vals;
       a_cpropb := rec3.col_cprops_vals;

        --if(a_cprop=a_cprop1)  then

          if (a_cprop=exclusion) then
                         -- делаем так чтоб не выводились числа для которых разрешены многочисленные ссылки
		continue;
          end if;
            raise notice '_("%"); //%.%.%[%] . PK_table: %  ', a_cprop, rec1.col_schema, rec1.col_table, rec1.col_cprops, rec2.col_pk_vals::text, rec3.col_pk_vals::text;
      -- end if;
      
     end loop;
     
    end loop;

   close curs1;
   close curs2;
  end loop;
    return 0;
end;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
ALTER FUNCTION common.gent(text,int)
  OWNER TO postgres;


пытаюсь сделать так что если в БД больше 1 раза обращается FK к PK выбраной таблицы, но получается так что выводит не все значения, и по каким-то причинам rec2 знает только о значениях 1,11,129,48 что за бред, прошу помощи, не догоняю сам

также если будут другие варианты как сделать предлагайте!
Это сложно
Дата: 05.02.2015 15:48:31
Mblp
вот код функции
CREATE OR REPLACE FUNCTION common.gent(in_mode text,exclusion int)
  RETURNS integer AS
$BODY$
declare --объЯвлЯем переменные
  i_res bigint;
  i bigint;
 
  rec1 record;
  rec2 record;
    rec3 record;
  curs1 refcursor;
  curs2 refcursor;
  sql_array text[];
  pk_array text[];
  pk_str text;
  the_sql text;
  a_cprop bigint;
   a_cpropb bigint;
hranim text[];
  i_res2 bigint;
  needed_i_res2 bigint;
begin

  for rec1 in
   select pgn.nspname::text as col_schema, pgcl.relname::text as col_table, pga.attname::text as col_cprops, pgcon.conkey::bigint[] as col_pk_nums,
    ARRAY(
      select pga2.attname
      from pg_attribute as pga2
      where (pga2.attrelid = pgcl.oid)
       and (pga2.attnum > 0)
      order by pga2.attnum
    )::text[] as col_all_columns,
	  --select *
    (
        select pgcon2.conkey::text
	from pg_constraint as pgcon2
	where  (pgcon2.contype = 'p')
	and (pgcon2.conrelid=pgcl.oid)
	)::bigint[] as pk_num 
	--выборка первичных ключей таблицы с которой работаем
    from pg_class as pgcl, pg_namespace as pgn, pg_attribute as pga, pg_constraint as pgcon ,pg_class as pgcl2
    where (pgcl.relkind = 'r')
    and (pgcl.relnamespace = pgn.oid)
    and (pgn.nspname = 'common')
    and (pga.attrelid = pgcl.oid)
    and (pgcl2.relname=in_mode)
    and (pga.attnum=pgcon.conkey[1]) 
    and (pgcon.conrelid = pgcl.oid)
    and (pgcon.confrelid = pgcl2.oid)
    order by pgcl.relname
/*название таблицы к которой все обращаютсЯ
если номер столбца равен номеру вторичного ключа
 находим название таблицы с помощью номера в pgcl и conrelid( показывает к какой таблице относитсЯ)
 внешний ключ ссылаетсЯ на какую таблицу*/
 loop

   

    sql_array := ARRAY[]::text[];
    pk_array := ARRAY[]::text[];
    pk_str := '';
    
    for i in 1..coalesce(array_upper(rec1.pk_num, 1), 0) loop
      pk_array := array_append(pk_array, rec1.col_all_columns[rec1.pk_num[i]]);   
    end loop;
	-- заносим в массив первичные ключи
    pk_str := array_to_string(pk_array, ', ');             
	-- делаем из массива строку

    sql_array := array_append(sql_array, 'select ARRAY[' || pk_str || ']::text[] as col_pk_vals, ' || rec1.col_cprops || '::text as col_cprops_vals');
    sql_array := array_append(sql_array, 'from ' || (rec1.col_schema || '.' || rec1.col_table));
    sql_array := array_append(sql_array, 'order by ' || pk_str);
    --sql_array := array_append(sql_array, 'group by ' || rec1.col_cprops || 'count(*)');
    sql_array := array_append(sql_array, ';');               
    the_sql := array_to_string(sql_array, ' ');               
	--запрос на выборку, сортируем по первичным ключам
	-- делаем из массива строку
	
  open curs1 for execute the_sql;
      open curs2 for execute the_sql;
    while true loop
      fetch curs1 into rec2;
      if (rec2 is null) then
        exit;
      end if;
     -- a_cprop := rec2.col_cprops_vals;
     -- hranim =rec2.col_pk_vals;
	while true loop
      fetch curs2 into rec3;
    if (rec3 is null) then
      exit;
     end if;
     a_cprop := rec2.col_cprops_vals;
      hranim =rec2.col_pk_vals;
       a_cpropb := rec3.col_cprops_vals;

        --if(a_cprop=a_cprop1)  then

          if (a_cprop=exclusion) then
                         -- делаем так чтоб не выводились числа для которых разрешены многочисленные ссылки
		continue;
          end if;
            raise notice '_("%"); //%.%.%[%] . PK_table: %  ', a_cprop, rec1.col_schema, rec1.col_table, rec1.col_cprops, rec2.col_pk_vals::text, rec3.col_pk_vals::text;
      -- end if;
      
     end loop;
     
    end loop;

   close curs1;
   close curs2;
  end loop;
    return 0;
end;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
ALTER FUNCTION common.gent(text,int)
  OWNER TO postgres;


пытаюсь сделать так что если в БД больше 1 раза обращается FK к PK выбраной таблицы, но получается так что выводит не все значения, и по каким-то причинам rec2 знает только о значениях 1,11,129,48 что за бред, прошу помощи, не догоняю сам

также если будут другие варианты как сделать предлагайте!


Вы что в ручную отлаживаете?
Возмите дбфорж может дело побыстрее пойдет?
Mblp
Дата: 05.02.2015 16:47:43
нужна помощь! эта функция, которая выше, поидее должна искать FK которые обращаются к PK
но сама суть мне надо найти значения FK обращающихся к PK более 1 раза
т.е есть таблицы допустим
t1
t2
t3
вот в t1 есть значение 14
в t2 есть значение 14
в t3 есть значение 11
так вот они все ссылаются на таблицу t4 в которой первичный ключ 14 и 11 так вот надо вывести значения t1 t2 а t3 нет

если больше 1 раза то выводим нет оставляем
vyegorov
Дата: 05.02.2015 17:08:28
Mblp,

Как-то так?

SELECT s.id,
       count(*), -- сколько вообще повторений
       count(DISTINCT s.tabname) -- в скольки таблицах
  FROM (
    SELECT 't1'::text AS tabname, id FROM t1
    UNION SELECT 't2'::text, id FROM t2
    UNION SELECT 't3'::text, id FROM t3) s
  JOIN t4 USING (id)
HAVING count(DISTINCT s.tabname)>1;
Mblp
Дата: 05.02.2015 17:42:50
select pgn.nspname::text as col_schema, pgcl.relname::text as col_table, pga.attname::text as col_cprops, pgcon.conkey::bigint[] as col_pk_nums,
ARRAY(
select pga2.attname
from pg_attribute as pga2
where (pga2.attrelid = pgcl.oid)
and (pga2.attnum > 0)
order by pga2.attnum
)::text[] as col_all_columns,
--select *
(
select pgcon2.conkey::text
from pg_constraint as pgcon2
where (pgcon2.contype = 'p')
and (pgcon2.conrelid=pgcl.oid)
)::bigint[] as pk_num
--выборка первичных ключей таблицы с которой работаем
from pg_class as pgcl, pg_namespace as pgn, pg_attribute as pga, pg_constraint as pgcon ,pg_class as pgcl2
where (pgcl.relkind = 'r')
and (pgcl.relnamespace = pgn.oid)
and (pgn.nspname = 'common')
and (pga.attrelid = pgcl.oid)
and (pgcl2.relname='название таблицы')
and (pga.attnum=pgcon.conkey[1])
and (pgcon.conrelid = pgcl.oid)
and (pgcon.confrelid = pgcl2.oid)
order by pgcl.relname

таким запросом я нахожу, название схемы,таблицы,столбца в таблице, номер FK, и PK вот, как мне сделать так чтобы сделать как я описал выше, т.е вывести если встречается более 1 раза, то что указали вы "vyegorov" почему-то не работает, мб я криворук?