Удаление из 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
Персональные инструменты
Пространства имён

Варианты
Действия
Навигация
Инструменты