====== Задание 2 ====== Реализовать иерархический запрос create or replace type t_region_type is object (id integer, name varchar2(32000), pid integer); create or replace type t_region_tab is table of t_region_type; create or replace procedure MAIN_INS (pTab t_region_tab, pReg_name varchar2) is my_code NUMBER; my_errm VARCHAR2(32000); my_path VARCHAR2(100); begin select ltrim(SYS_CONNECT_BY_PATH(name,'/'), '/') into my_path from table(pTab) t where upper(t.name) = upper(pReg_name) start with pid is null connect by prior id = pid; dbms_output.put_line(my_path); exception when others then my_code := SQLCODE; my_errm := SQLERRM; dbms_output.put_line('Ошибка'); end; -- вызов declare t_reg_tab t_region_tab:= t_region_tab(); begin t_reg_tab.extend(6); t_reg_tab(1):= t_region_type(1, 'Россия', null); t_reg_tab(2):= t_region_type(2, 'Москва', 1); t_reg_tab(3):= t_region_type(3, 'Санкт-Петербург', 1); t_reg_tab(4):= t_region_type(4, 'Краснодарский край', 1); t_reg_tab(5):= t_region_type(5, 'Краснодар', 4); t_reg_tab(6):= t_region_type(6, 'Воронежская область', 1); MAIN_INS(t_reg_tab, 'Краснодар'); MAIN_INS(t_reg_tab, 'Стамбул'); end; ---- __**Решение**__ -- ----------------------------------------------------------------------- DO $$ BEGIN CREATE TYPE t_region_type AS (id INTEGER, name VARCHAR(32000), pid INTEGER); EXCEPTION WHEN duplicate_object THEN return; END $$; -- ----------------------------------------------------------------------- CREATE OR REPLACE FUNCTION get_region_tab() RETURNS VARCHAR AS $fun$ DECLARE t_name VARCHAR = 't_region_tab'; BEGIN EXECUTE('CREATE TEMPORARY TABLE ' || t_name || '( p1 t_region_type );'); EXCEPTION WHEN OTHERS THEN EXECUTE('TRUNCATE ' || t_name || ';'); RETURN t_name; END $fun$ LANGUAGE plpgsql; -- ----------------------------------------------------------------------- CREATE OR REPLACE PROCEDURE new_region (tt VARCHAR, d t_region_type) AS $proc$ BEGIN EXECUTE('INSERT INTO ' || tt || ' VALUES ($$' || d || '$$);'); END $proc$ LANGUAGE plpgsql; -- ----------------------------------------------------------------------- CREATE OR REPLACE PROCEDURE main_ins (tt VARCHAR, pReg_name VARCHAR) AS $proc$ DECLARE my_path VARCHAR(32000); BEGIN EXECUTE('WITH RECURSIVE temp1(id, name, pid, path) AS ( SELECT (t1.t_reg_tab).id AS id, (t1.t_reg_tab).name AS name, (t1.t_reg_tab).pid AS pid, CAST((t1.t_reg_tab).name AS VARCHAR(32000)) AS path FROM ' || tt || ' AS t1 WHERE UPPER((t1.t_reg_tab).name) = UPPER(''' || pReg_name || ''') UNION SELECT (t2.t_reg_tab).id AS id, (t2.t_reg_tab).name AS name, (t2.t_reg_tab).pid AS pid, CAST(temp1.path || ''/'' || (t2.t_reg_tab).name AS VARCHAR(32000)) AS path FROM t_region_tab AS t2 JOIN temp1 ON temp1.pid = (t2.t_reg_tab).id ) SELECT path my_path FROM temp1 WHERE pid IS NULL; ') INTO my_path; RAISE INFO '%',my_path; EXCEPTION WHEN OTHERS THEN RAISE INFO 'Ошибка'; END $proc$ LANGUAGE plpgsql; -- ----------------------------------------------------------------------- DO $$ DECLARE tt VARCHAR = get_region_tab(); BEGIN CALL new_region(tt,(1, 'Россия', NULL)); CALL new_region(tt,(2, 'Москва', 1)); CALL new_region(tt,(3, 'Санкт-Петербург', 1)); CALL new_region(tt,(4, 'Краснодарский край', 1)); CALL new_region(tt,(5, 'Краснодар', 4)); CALL new_region(tt,(6, 'Воронежская область', 1)); CALL main_ins(tt, 'Краснодар'); CALL main_ins(tt, 'Стамбул'); END $$; -- ----------------------------------------------------------------------- DO $$ BEGIN CREATE TYPE t_region_type AS (id INTEGER, name VARCHAR(32000), pid INTEGER); EXCEPTION WHEN duplicate_object THEN return; END $$; -- ----------------------------------------------------------------------- CREATE OR REPLACE PROCEDURE main_ins (tt t_region_type[], pReg_name VARCHAR(32000)) AS $proc$ DECLARE my_path VARCHAR; BEGIN WITH RECURSIVE temp1(id, name, pid, path) AS ( SELECT (t1).id AS id, (t1).name AS name, (t1).pid AS pid, CAST((t1).name AS VARCHAR) AS path FROM unnest(tt) AS t1 WHERE UPPER((t1).name) = UPPER(pReg_name) UNION SELECT (t2).id AS id, (t2).name AS name, (t2).pid AS pid, CAST(temp1.path || '/' || (t2).name AS VARCHAR) AS path FROM unnest(tt) AS t2 JOIN temp1 ON temp1.pid = (t2).id ) SELECT path INTO my_path FROM temp1 WHERE pid IS NULL; RAISE INFO '%',my_path; EXCEPTION WHEN OTHERS THEN RAISE INFO 'Ошибка'; END $proc$ LANGUAGE plpgsql; -- ----------------------------------------------------------------------- DO $$ DECLARE t_reg_tab t_region_type[]; BEGIN t_reg_tab[1] = (1, 'Россия', NULL); t_reg_tab[2] = (2, 'Москва', 1); t_reg_tab[3] = (3, 'Санкт-Петербург', 1); t_reg_tab[4] = (4, 'Краснодарский край', 1); t_reg_tab[5] = (5, 'Краснодар', 4); t_reg_tab[6] = (6, 'Воронежская область', 1); CALL main_ins2(t_reg_tab, 'Краснодар'); CALL main_ins2(t_reg_tab, 'Стамбул'); END $$;