DO $$ DECLARE r RECORD; keep_id UUID; dup_id UUID; BEGIN -- Loop through duplicates: groups of (name, regiao) where generic lower(trim(nome)) matches FOR r IN SELECT lower(trim(nome)) as norm_name, regiao FROM tipos_eventos GROUP BY lower(trim(nome)), regiao HAVING count(*) > 1 LOOP RAISE NOTICE 'Processing duplicate group: % in %', r.norm_name, r.regiao; -- Identify the "Keeper" (Capitalized preferred) -- We order by nome ASC so 'Baile' < 'baile' (ASCII 66 < 98). 'Baile' comes first. SELECT id INTO keep_id FROM tipos_eventos WHERE lower(trim(nome)) = r.norm_name AND regiao = r.regiao ORDER BY nome ASC LIMIT 1; -- Process all others as duplicates to be merged FOR dup_id IN SELECT id FROM tipos_eventos WHERE lower(trim(nome)) = r.norm_name AND regiao = r.regiao AND id != keep_id LOOP RAISE NOTICE ' Merging % -> %', dup_id, keep_id; -- 1. Update Agenda UPDATE agenda SET tipo_evento_id = keep_id WHERE tipo_evento_id = dup_id; -- 2. Update Precos -- Check if target price already exists to avoid unique constraint if any UPDATE precos_tipos_eventos SET tipo_evento_id = keep_id WHERE tipo_evento_id = dup_id AND NOT EXISTS ( SELECT 1 FROM precos_tipos_eventos p2 WHERE p2.tipo_evento_id = keep_id AND p2.funcao_profissional_id = precos_tipos_eventos.funcao_profissional_id AND p2.regiao = precos_tipos_eventos.regiao ); -- If conflicting prices existed, just delete the old ones (duplicate) since we prefer the kept type's prices usually DELETE FROM precos_tipos_eventos WHERE tipo_evento_id = dup_id; -- 3. Delete the Type DELETE FROM tipos_eventos WHERE id = dup_id; END LOOP; END LOOP; END $$;