Удаление из GD RUID записей для несуществующих объектов
Материал из GedeminWiki
Между таблицей GD_RUID и таблицами с объектами нет жесткой связи. Т.е. объект может быть удален из базы, а его RUID останется.
Очистка GD_RUID с использованием функций из GUDF.DLL
EXECUTE BLOCK AS DECLARE VARIABLE rn VARCHAR(31); DECLARE VARIABLE fn VARCHAR(31); DECLARE VARIABLE d INTEGER; BEGIN IF (g_his_create(0, 0) = 0) THEN EXCEPTION gd_e_exception 'Can''t create huge array'; FOR SELECT rf.rdb$relation_name, LIST(TRIM(rf.rdb$field_name)) FROM rdb$relation_fields rf JOIN rdb$relations r ON r.rdb$relation_name = rf.rdb$relation_name JOIN rdb$index_segments idxs ON idxs.rdb$field_name = rf.rdb$field_name JOIN rdb$indices idx ON idx.rdb$index_name = idxs.rdb$index_name JOIN rdb$relation_constraints rc ON rc.rdb$index_name = idx.rdb$index_name AND rc.rdb$relation_name = rf.rdb$relation_name WHERE rc.rdb$constraint_type = 'PRIMARY KEY' AND rf.rdb$relation_name <> 'GD_RUID' /* Тут должно быть условие на таблицы, в которых не соблюдается уникальность ИД по аналогии с GD_RUID (см выше). */ AND r.rdb$system_flag = 0 AND COALESCE(r.rdb$relation_type, 0) = 0 GROUP BY 1 HAVING LIST(TRIM(rf.rdb$field_name)) = 'ID' INTO :rn, :fn DO BEGIN EXECUTE STATEMENT 'SELECT SUM(g_his_include(0, id)) FROM ' || :rn || ' WHERE id >= 147000000' INTO :d; END DELETE FROM gd_ruid WHERE g_his_has(0, id) = 0 AND id >= 147000000; g_his_destroy(0); END
Очистка с использованием временного поля
Данную задачу можно выполнить следующим образом:
1) Создадим в таблице GD_RUID временное поле FLAG:
ALTER TABLE gd_ruid ADD flag INTEGER
2) Пробежимся по всем таблицам в базе данных и для существующих ИД пометим флагом соответствующие записи в GD_RUID:
EXECUTE BLOCK AS DECLARE VARIABLE RN VARCHAR(31); BEGIN FOR SELECT rf.rdb$relation_name FROM rdb$relation_fields rf JOIN rdb$fields f ON rf.rdb$field_source = f.rdb$field_name WHERE rf.rdb$field_name = 'ID' AND f.rdb$field_name = 'DINTKEY' /* укажите здесь условие, если в обработку необходимо включить только некоторые таблицы AND rf.rdb$relation_name IN (...) */ INTO :RN DO BEGIN EXECUTE STATEMENT 'MERGE INTO gd_ruid r ' || ' USING (SELECT id FROM ' || :RN || ' WHERE id >= 147000000) i ' || ' ON (i.id = r.id) ' || ' WHEN MATCHED THEN ' || ' UPDATE SET flag = 1 '; END END
3) Удалим из GD_RUID записи, которые остались непомеченными:
DELETE FROM gd_ruid WHERE flag IS NULL
4) Избавимся от временного поля FLAG:
ALTER TABLE gd_ruid DROP flag