Поиск повторяющихся идентификаторов

Материал из GedeminWiki
(Различия между версиями)
Перейти к: навигация, поиск
(Новая страница: «Идеология платформы Гедымин требует уникальности идентификаторов объектов в пределах фа…»)
 
 
(не показаны 3 промежуточные версии 1 участника)
Строка 1: Строка 1:
 
Идеология платформы Гедымин требует уникальности идентификаторов объектов в пределах файла базы данных. Дублирующиеся идентификаторы являются следствием физического повреждения базы данных или логических сбоев в программном обеспечении.  
 
Идеология платформы Гедымин требует уникальности идентификаторов объектов в пределах файла базы данных. Дублирующиеся идентификаторы являются следствием физического повреждения базы данных или логических сбоев в программном обеспечении.  
 +
 +
===Поиск дубликатов с использованием временной таблицы===
  
 
Для поиска дубликатов создадим временную таблицу TEMP:
 
Для поиска дубликатов создадим временную таблицу TEMP:
Строка 63: Строка 65:
 
   count(t.id) > 1
 
   count(t.id) > 1
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
 +
===Поиск дубликатов с использованием битовых массивов===
 +
 +
На сервере должна быть установлена библиотека GUDF.DLL. Используются два битовых массива. База данных сканируется дважды. На первом проходе, первый массив заполняется всеми ИД из БД, второй -- только повторяющимися. На втором проходе выводится список повторяющихся ИД с именами таблиц.
 +
 +
<syntaxhighlight lang="SQL">
 +
EXECUTE BLOCK
 +
  RETURNS(ID INTEGER, RN CHAR(31))
 +
AS
 +
  DECLARE VARIABLE DUMB INTEGER;
 +
BEGIN
 +
  g_his_create(0, 0);
 +
  g_his_create(1, 0);
 +
 +
  FOR
 +
    SELECT DISTINCT
 +
      r.rdb$relation_name
 +
    FROM
 +
      rdb$relation_fields rf JOIN rdb$relations r
 +
        ON r.rdb$relation_name = rf.rdb$relation_name
 +
      LEFT JOIN
 +
        (
 +
          SELECT relc.rdb$relation_name
 +
          FROM
 +
            rdb$relation_constraints relc JOIN rdb$ref_constraints refc
 +
              ON refc.rdb$constraint_name = relc.rdb$constraint_name
 +
            JOIN rdb$index_segments iseg
 +
              ON iseg.rdb$index_name = relc.rdb$index_name
 +
                AND iseg.rdb$field_name = 'ID'
 +
        ) constr ON constr.rdb$relation_name = r.rdb$relation_name
 +
    WHERE
 +
      rf.rdb$field_name = 'ID' AND r.rdb$relation_name <> 'TEMP'
 +
        AND r.rdb$relation_name <> 'GD_RUID'
 +
        AND r.rdb$view_source IS NULL
 +
        AND constr.rdb$relation_name IS NULL
 +
    INTO :RN
 +
  DO BEGIN
 +
    EXECUTE STATEMENT
 +
      'SELECT SUM(g_his_include(1, id)) ' ||
 +
      '  FROM ' || :RN ||
 +
      '  WHERE g_his_has(0, id) <> 0 '
 +
    INTO :DUMB;
 +
 +
    EXECUTE STATEMENT
 +
      'SELECT SUM(g_his_include(0, id)) ' ||
 +
      '  FROM ' || :RN
 +
    INTO :DUMB;
 +
  END
 +
 +
  FOR
 +
    SELECT DISTINCT
 +
      r.rdb$relation_name
 +
    FROM
 +
      rdb$relation_fields rf JOIN rdb$relations r
 +
        ON r.rdb$relation_name = rf.rdb$relation_name
 +
      LEFT JOIN
 +
        (
 +
          SELECT relc.rdb$relation_name
 +
          FROM
 +
            rdb$relation_constraints relc JOIN rdb$ref_constraints refc
 +
              ON refc.rdb$constraint_name = relc.rdb$constraint_name
 +
            JOIN rdb$index_segments iseg
 +
              ON iseg.rdb$index_name = relc.rdb$index_name
 +
                AND iseg.rdb$field_name = 'ID'
 +
        ) constr ON constr.rdb$relation_name = r.rdb$relation_name
 +
    WHERE
 +
      rf.rdb$field_name = 'ID' AND r.rdb$relation_name <> 'TEMP'
 +
        AND r.rdb$relation_name <> 'GD_RUID'
 +
        AND r.rdb$view_source IS NULL
 +
        AND constr.rdb$relation_name IS NULL
 +
    INTO :RN
 +
  DO BEGIN
 +
    FOR
 +
      EXECUTE STATEMENT
 +
        'SELECT id ' ||
 +
        '  FROM ' || :RN ||
 +
        '  WHERE g_his_has(1, id) <> 0 '
 +
      INTO :id
 +
    DO BEGIN
 +
      SUSPEND;
 +
    END
 +
  END
 +
 
 +
  g_his_destroy(0);
 +
  g_his_destroy(1);
 +
END
 +
</syntaxhighlight>
 +
 +
====См. также====
 +
 +
* [[ID і RUID]]
  
 
[[Category:Школа системного администратора]]
 
[[Category:Школа системного администратора]]

Текущая версия на 20:42, 24 июля 2014

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

[править] Поиск дубликатов с использованием временной таблицы

Для поиска дубликатов создадим временную таблицу TEMP:

CREATE TABLE temp (
  id dintkey, 
  relid dintkey
)

Заполним ее:

EXECUTE BLOCK
AS
  DECLARE VARIABLE RN CHAR(31);
  DECLARE VARIABLE RID INTEGER;
BEGIN
  FOR
    SELECT DISTINCT
      r.rdb$relation_name, r.rdb$relation_id
    FROM
      rdb$relation_fields rf JOIN rdb$relations r
        ON r.rdb$relation_name = rf.rdb$relation_name
      LEFT JOIN
        (
          SELECT relc.rdb$relation_name
          FROM
            rdb$relation_constraints relc JOIN rdb$ref_constraints refc
              ON refc.rdb$constraint_name = relc.rdb$constraint_name
            JOIN rdb$index_segments iseg
              ON iseg.rdb$index_name = relc.rdb$index_name
                AND iseg.rdb$field_name = 'ID'
        ) constr ON constr.rdb$relation_name = r.rdb$relation_name
    WHERE
      rf.rdb$field_name = 'ID' AND r.rdb$relation_name <> 'TEMP'
        AND r.rdb$relation_name <> 'GD_RUID'
        AND r.rdb$view_source IS NULL
        AND constr.rdb$relation_name IS NULL
    INTO :RN, :RID
  DO BEGIN
    EXECUTE STATEMENT
      'INSERT INTO TEMP (id, relid) ' ||
      '  SELECT id, ' || :RID || ' FROM ' || :RN ||
      '  WHERE id > 32 '
      WITH AUTONOMOUS TRANSACTION;
  END
END

Теперь, получить список ИД, встречающихся более одного раза можно так:

SELECT
  t.id, COUNT(t.id), list(TRIM(r.rdb$relation_name))
FROM
  temp t JOIN rdb$relations r
    ON t.relid = r.rdb$relation_id
GROUP BY
  t.id
HAVING
  COUNT(t.id) > 1

[править] Поиск дубликатов с использованием битовых массивов

На сервере должна быть установлена библиотека GUDF.DLL. Используются два битовых массива. База данных сканируется дважды. На первом проходе, первый массив заполняется всеми ИД из БД, второй -- только повторяющимися. На втором проходе выводится список повторяющихся ИД с именами таблиц.

EXECUTE BLOCK
  RETURNS(ID INTEGER, RN CHAR(31))
AS
  DECLARE VARIABLE DUMB INTEGER;
BEGIN
  g_his_create(0, 0);
  g_his_create(1, 0);
 
  FOR
    SELECT DISTINCT
      r.rdb$relation_name
    FROM
      rdb$relation_fields rf JOIN rdb$relations r
        ON r.rdb$relation_name = rf.rdb$relation_name
      LEFT JOIN
        (
          SELECT relc.rdb$relation_name
          FROM
            rdb$relation_constraints relc JOIN rdb$ref_constraints refc
              ON refc.rdb$constraint_name = relc.rdb$constraint_name
            JOIN rdb$index_segments iseg
              ON iseg.rdb$index_name = relc.rdb$index_name
                AND iseg.rdb$field_name = 'ID'
        ) constr ON constr.rdb$relation_name = r.rdb$relation_name
    WHERE
      rf.rdb$field_name = 'ID' AND r.rdb$relation_name <> 'TEMP'
        AND r.rdb$relation_name <> 'GD_RUID'
        AND r.rdb$view_source IS NULL
        AND constr.rdb$relation_name IS NULL
    INTO :RN
  DO BEGIN
    EXECUTE STATEMENT
      'SELECT SUM(g_his_include(1, id)) ' ||
      '  FROM ' || :RN ||
      '  WHERE g_his_has(0, id) <> 0 '
    INTO :DUMB;
 
    EXECUTE STATEMENT
      'SELECT SUM(g_his_include(0, id)) ' ||
      '  FROM ' || :RN
    INTO :DUMB;
  END
 
  FOR
    SELECT DISTINCT
      r.rdb$relation_name
    FROM
      rdb$relation_fields rf JOIN rdb$relations r
        ON r.rdb$relation_name = rf.rdb$relation_name
      LEFT JOIN
        (
          SELECT relc.rdb$relation_name
          FROM
            rdb$relation_constraints relc JOIN rdb$ref_constraints refc
              ON refc.rdb$constraint_name = relc.rdb$constraint_name
            JOIN rdb$index_segments iseg
              ON iseg.rdb$index_name = relc.rdb$index_name
                AND iseg.rdb$field_name = 'ID'
        ) constr ON constr.rdb$relation_name = r.rdb$relation_name
    WHERE
      rf.rdb$field_name = 'ID' AND r.rdb$relation_name <> 'TEMP'
        AND r.rdb$relation_name <> 'GD_RUID'
        AND r.rdb$view_source IS NULL
        AND constr.rdb$relation_name IS NULL
    INTO :RN
  DO BEGIN
    FOR
      EXECUTE STATEMENT
        'SELECT id ' ||
        '  FROM ' || :RN ||
        '  WHERE g_his_has(1, id) <> 0 '
      INTO :id
    DO BEGIN
      SUSPEND;
    END
  END
 
  g_his_destroy(0);
  g_his_destroy(1);
END

[править] См. также

Персональные инструменты
Пространства имён

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