create or replace function initkh() returns bigint as $$ declare rowcount bigint; pcode char(13); lvl int2; hrrh ltree; phrrh ltree; begin rowcount := 0; for hrrh,lvl in select hierarch,level from kladr where level > 1 loop case lvl when 2 then phrrh := subpath(hrrh,0,1); when 3 then if subpath(hrrh,1,1) = '000' then phrrh := subpath(hrrh,0,1); else phrrh := subpath(hrrh,0,2); end if; when 4 then if subpath(hrrh,1,2) = '000.000' then phrrh := subpath(hrrh,0,1); elsif subpath(hrrh,2,1) = '000' then phrrh := subpath(hrrh,0,2); else phrrh := subpath(hrrh,0,3); end if; end case; rowcount := rowcount+1; execute 'select code from kladr where hierarch = $1' into pcode using phrrh; execute 'update kladr set parent_code = $1 where hierarch = $2' using pcode,hrrh; end loop; return rowcount; end; $$ LANGUAGE plpgsql;
Изподвыподверта
kladr=> update kladr set parent_code = get_parent_code(hierarch,level) where level > 1; UPDATE 189598 Время: 22990,729 мс kladr=> select count(*) from kladr where parent_code is NULL; count ------- 0 (1 строка)
Время: 322,651 мс
Таки пошустрее, однако. Проверочные выборки я приводить не буду, чтобы сократить количество буковок повествования.
create or replace function get_parent_code(hrrh ltree, lvl int2, OUT pcode char(13)) as $$ declare phrrh ltree; begin case lvl when 2 then phrrh := subpath(hrrh,0,1); when 3 then if subpath(hrrh,1,1) = '000' then phrrh := subpath(hrrh,0,1); else phrrh := subpath(hrrh,0,2); end if; when 4 then if subpath(hrrh,1,2) = '000.000' then phrrh := subpath(hrrh,0,1); elsif subpath(hrrh,2,1) = '000' then phrrh := subpath(hrrh,0,2); else phrrh := subpath(hrrh,0,3); end if; else phrrh := ''::ltree; end case; if lvl = 1 then pcode := ''; else execute 'select code from kladr where hierarch = $1' into pcode using phrrh; end if; end; $$ LANGUAGE plpgsql;
Вот как-то так. База в наличии имеется. Имеется некоторое количество совершенно детских тестов из этой базы. Я с превеликим удовольствием погоняю более другие запросы, нежели мои (будут в следующем выпуске).