Проверка на дубликаты уникальных идентификаторов

Материал из GedeminWiki
(Различия между версиями)
Перейти к: навигация, поиск
Строка 19: Строка 19:
 
     FROM
 
     FROM
 
       rdb$relation_fields rf
 
       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$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$indices idx ON idx.rdb$index_name = idxs.rdb$index_name
Строка 27: Строка 28:
 
       AND
 
       AND
 
       rf.rdb$relation_name <> 'GD_RUID'
 
       rf.rdb$relation_name <> 'GD_RUID'
 +
      /*
 +
     
 +
      Тут должно быть условие на таблицы, в которых не соблюдается
 +
      условие уникальности ИД.
 +
     
 +
      */
 +
      AND
 +
      r.rdb$system_flag = 0
 +
      AND
 +
      COALESCE(r.rdb$relation_type, 0) = 0
 
       AND
 
       AND
 
       NOT EXISTS(
 
       NOT EXISTS(

Версия 20:16, 22 декабря 2017

Идеология платформы требует чтобы у каждого бизнес-объекта был свой уникальный в пределах базы данных целочисленный идентификатор. Данное правило достигается с помощью использования единого генератора GD_G_UNIQUE. Однако, в результате программных сбоев могут возникнуть дубликаты ИД. Для их отыскания следует использовать запрос, приведенный ниже. Запрос выводит название таблицы и количество записей с ИД, встречающимся в других таблицах, в данной базе данных.

EXECUTE BLOCK
  RETURNS(tbl VARCHAR(31), cnt INTEGER)
AS
  DECLARE VARIABLE rn VARCHAR(31);
  DECLARE VARIABLE fn VARCHAR(31);
  DECLARE VARIABLE id INTEGER;
  DECLARE VARIABLE s INTEGER;
  DECLARE VARIABLE c 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'
      /*
 
      Тут должно быть условие на таблицы, в которых не соблюдается
      условие уникальности ИД.
 
      */
      AND
      r.rdb$system_flag = 0
      AND
      COALESCE(r.rdb$relation_type, 0) = 0
      AND
      NOT EXISTS(
        SELECT * 
        FROM 
          rdb$index_segments idxs_fk 
          JOIN rdb$indices idx_fk ON idxs_fk.rdb$index_name = idx_fk.rdb$index_name
        WHERE
          idxs_fk.rdb$field_name = rf.rdb$field_name
          AND        
          idx_fk.rdb$relation_name = rf.rdb$relation_name
          AND
          idx_fk.rdb$index_name <> idx.rdb$index_name          
      )
    GROUP BY
      1
    HAVING
      LIST(TRIM(rf.rdb$field_name)) = 'ID'
  INTO
    :rn, :fn
  DO BEGIN
    s = 0;
    c = 0;
    EXECUTE STATEMENT
      'SELECT SUM(g_his_include(0, id)), COUNT(*) FROM ' || :rn || ' WHERE id > 147000000'
    INTO :s, :c;
 
    s = COALESCE(:s, 0);
    c = COALESCE(:c, 0);
 
    IF (:c <> :s) THEN
    BEGIN
      tbl = :rn;
      cnt = :c - :s;
      SUSPEND;
    END  
  END
 
  g_his_destroy(0);
END
Персональные инструменты
Пространства имён

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