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

Материал из GedeminWiki
(Различия между версиями)
Перейти к: навигация, поиск
(Новая страница: «Идеология платформы требует чтобы у каждого бизнес-объекта был свой уникальный в предел…»)
 
 
(не показаны 3 промежуточные версии 1 участника)
Строка 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(
Строка 66: Строка 77:
 
   g_his_destroy(0);
 
   g_his_destroy(0);
 
END
 
END
</sytaxhighlight>
+
</syntaxhighlight>
 +
 
 +
Процедура выводит все ИД из базы данных в привязке к ИД таблицы:
 +
 
 +
<syntaxhighlight lang="SQL">
 +
CREATE OR ALTER PROCEDURE gd_p_find_dupl_id
 +
  RETURNS(id INTEGER, relationkey INTEGER)
 +
AS
 +
  DECLARE VARIABLE rn VARCHAR(31);
 +
  DECLARE VARIABLE fn VARCHAR(31);
 +
  DECLARE VARIABLE rid INTEGER;
 +
BEGIN
 +
  FOR
 +
    SELECT
 +
      rf.rdb$relation_name, atr.id, 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
 +
      JOIN at_relations atr ON atr.relationname = r.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, 2
 +
    HAVING
 +
      LIST(TRIM(rf.rdb$field_name)) = 'ID'
 +
  INTO
 +
    :rn, :rid, :fn
 +
  DO BEGIN
 +
    relationkey = :rid;
 +
    FOR
 +
      EXECUTE STATEMENT 'SELECT id FROM ' || :rn
 +
      INTO :id
 +
    DO
 +
      SUSPEND;
 +
  END
 +
END
 +
</syntaxhighlight>
 +
 
 +
Используется для поиска дубликатов с помощью запроса:
 +
 
 +
<syntaxhighlight lang="SQL">
 +
select
 +
  id, list(relationkey), count(*)
 +
from
 +
  gd_p_find_dupl_id
 +
group by
 +
  1
 +
having
 +
  count(*) > 1
 +
</syntaxhighlight>
  
 
[[Category:База данных]]
 
[[Category:База данных]]

Текущая версия на 20:37, 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

Процедура выводит все ИД из базы данных в привязке к ИД таблицы:

CREATE OR ALTER PROCEDURE gd_p_find_dupl_id
  RETURNS(id INTEGER, relationkey INTEGER)
AS
  DECLARE VARIABLE rn VARCHAR(31);
  DECLARE VARIABLE fn VARCHAR(31);
  DECLARE VARIABLE rid INTEGER;
BEGIN
  FOR
    SELECT
      rf.rdb$relation_name, atr.id, 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
      JOIN at_relations atr ON atr.relationname = r.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, 2
    HAVING
      LIST(TRIM(rf.rdb$field_name)) = 'ID'
  INTO
    :rn, :rid, :fn
  DO BEGIN
    relationkey = :rid;
    FOR
      EXECUTE STATEMENT 'SELECT id FROM ' || :rn
      INTO :id
    DO
      SUSPEND;
  END
END

Используется для поиска дубликатов с помощью запроса:

SELECT 
  id, list(relationkey), COUNT(*) 
FROM 
  gd_p_find_dupl_id
GROUP BY 
  1
HAVING 
  COUNT(*) > 1
Персональные инструменты
Пространства имён

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