Это вторая часть статьи, в которой изложен опыт работы со списком адресообразующих элементов ФИАС, загруженным в базу данных под управлением PostgreSQL. С первой частью статьи можно ознакомиться здесь.



Полный текст статьи состоит состоит из 4 частей. В первой половине этой части статьи изложены комментарии к реализации функции. Во второй — исходный текст функции. Тем из читателей, кого интересуют только исходные тексты, предлагаем сразу перейти к Приложению.

Полное наименование адресообразующего элемента


Основная идея функции fsfn_AddressObjects_TreeActualName в том, чтобы возвратить соединенные в одну строку название элемента вместе с названиями всех его предков. Например, пусть функции поиска родословной элемента (fstf_AddressObjects_AddressObjectTree) возвращает следующий список значений.

Таблица 5. результат выполнения функции fstf_AddressObjects_AddressObjectTree('bfc1236d-b5d2-4734-a238-3b1e4830e963')
AOGUID CurrStatus ActStatus AOLevel ShortName FormalName ObjectGroup
db9c4f8b-b706-40e2-b2b4-d31b98dcd3d1 0 1 1 край Красноярский Region
625497d3-22de-4390-b4b4-2febfbfc15ce 0 1 3 р-н Балахтинский Territory
39da6405-b3e6-4baf-b332-d47b73b4d5fb 0 1 6 п Могучий Locality
bfc1236d-b5d2-4734-a238-3b1e4830e963 0 1 7 ул Новая Street

Тогда fsfn_AddressObjects_TreeActualName('bfc1236d-b5d2-4734-a238-3b1e4830e963') должна возвратить:

«Красноярский край, Балахтинский р-н, п Могучий, ул Новая»

У функции есть еще одни необязательный параметр массив масок (a_MaskArray), с помощью которого можно включать в результат не все названия элементов, а только те, которые нужны.

Текст функции приведен в разделе Приложения «Создание функции fsfn_AddressObjects_TreeActualName».

Как это работает


Основу реализации функции составляет вызов fstf_AddressObjects_AddressObjectTree (описанная в первой части статьи) и цикл по возвращаемым ей записям, в теле которой формируется полное наименование адресообразующего элемента путем сцепления (конкатенации) всех наименований в одну строку. Эта строка в конце концов будет возвращения функцией fsfn_AddressObjects_TreeActualName.

Далее будут поясняться детали.

Во-первых, порой нет необходимости в том, чтобы результат функции обязательно включал наименования всех предков текущего элемента. Например, в пределах Красноярского края вместо «Красноярский край, Балахтинский р-н, п Могучий, ул Новая», чаще используют укороченную форму «Балахтинский р-н, п Могучий, ул Новая». А внутри города Красноярска вместо адреса «Красноярский край, г Красноярск, д Песчанка, ул Сергея Лазо» чаще используют «д Песчанка, ул Сергея Лазо».

Для того чтобы иметь возможность управлять разными формами написания полного наименования адресообразующего элемента введен параметр массив масок (a_MaskArray), который содержит последовательность указателей (масок) на группы элементов.

Таблица 6. Список масок функции
Значение Примечание
{ST} Маска — улица
{ZC} Маска — почтовый индекс
{DT} Маска — городской район
{LP} Маска — подчиненный населенный пункт
{LM} Маска — основной населенный пункт
{TP} Маска — района субъекта федерации
{TM} Маска — субъект федерации (регион)
{CY} Маска — страна

Во-вторых, для того чтобы реализовать построение полного наименования в соответствии с массивом масок создана вспомогательная функция fsfn_AddressObjects_ObjectGroup, которая относит каждый адресообразующий элемент к определенной группе.

Таблица 7. Значения, возвращаемые функцией fsfn_AddressObjects_ObjectGroup
Значение Примечание
Country Признак группы — Страна
Region Признак группы — Регион
City Признак группы — Основной населенный пункт
Territory Признак группы — район
Locality Признак группы — населенный пункт подчиненный основному
MotorRoad Признак группы — автомобильная дорога
RailWayObject Признак группы — железная дорога
VillageCouncil Признак группы — сельсовет
Street Признак группы — улица в населенном пункте
AddlTerritory Признак группы — дополнительная территория
PartAddlTerritory Признак группы — часть дополнительной территории

Список значений, возвращаемых функцией fsfn_AddressObjects_ObjectGroup, приведен в Таблица 5.

Цель создания этой функции в том чтобы собрать в одном месте все особенности (если хотите, то «костыли») определения группы элемента. С детальной реализацией этой функции можно ознакомиться в разделе Приложения «Создание функции fsfn_AddressObjects_ObjectGroup».

Комбинация значений функции и поля AOLevel (уровень адресообразующего элемента) вместе с проверкой на присутствие маски группы массиве масок позволяет определять должно ли название текущего элемента включаться в строку результата.

Например, признаком того, что название основного населенного пункта должно включаться в полное наименование элемента, является истинность следующего выражения:

          v_ObjectGroup='City' AND '{LM}' <@ a_MaskArray AND v_AOLevel =4

ПРИЛОЖЕНИЕ



Создание функции fsfn_AddressObjects_ObjectGroup


BEGIN TRANSACTION;
DROP FUNCTION IF EXISTS fsfn_AddressObjects_ObjectGroup(a_AOGUID VARCHAR(36),a_CurrStatus INTEGER);
/*****************************************************************************/
/* Возвращает признак группы адресообразующего элемента по его идентификатору */
/* fias_AddressObjects                                                    */
/*****************************************************************************/
CREATE OR REPLACE FUNCTION fsfn_AddressObjects_ObjectGroup(
	a_AOGUID  VARCHAR(36), /* Глобальный уникальный идентификатор */
                                                     /* адресообразующего элемента*/
	a_CurrStatus INTEGER default NULL /* Статус актуальности КЛАДР 4: */
                                                     /* 0 - актуальный, */
                                                     /* 1-50 - исторический, */
                                                     /*     т.е. элемент был переименован, */
                                                     /*      в данной записи приведено одно */
                                                     /*       из прежних его наименований, */
                                                     /* 51 - переподчиненный */
)
RETURNS VARCHAR(50) /* Группа адресообразующего элемента */
AS
$BODY$
DECLARE
	c_CountryGroupValue   CONSTANT VARCHAR(50):='Country';
	c_RegionGroupValue	    CONSTANT VARCHAR(50):='Region';
	c_CityGroupValue          CONSTANT VARCHAR(50):='City';
	c_TerritoryGroupValue  CONSTANT VARCHAR(50):='Territory';
	c_LocalityGroupValue   CONSTANT VARCHAR(50):='Locality';
	c_MotorRoadValue        CONSTANT VARCHAR(50):='MotorRoad';
	c_RailWayObjectValue  CONSTANT VARCHAR(50):='RailWayObject';
	c_VillageCouncilValue  CONSTANT VARCHAR(50):='VillageCouncil';
	c_StreetGroupValue       CONSTANT VARCHAR(50):='Street';
	c_AddlTerritoryValue    CONSTANT VARCHAR(50):='AddlTerritory';
	c_PartAddlTerritoryValue CONSTANT VARCHAR(50):='PartAddlTerritory';
	v_ShortTypeName         VARCHAR(10);   /* Тип адресообразующего элемента */ 
	v_AddressObjectName  VARCHAR(100); /* Название адресообразующего элемента */ 
	v_AOLevel                     INTEGER;    /* Уровень адресообразующего элемента*/	
	v_CurrStatus                  INTEGER;    /* Текущий статус адресообразующего элемента*/
	v_ObjectGroup              VARCHAR(50);   /* Группа адресообразующего элемента	*/
 	v_Return_Error		Integer :=0;	/* Код возврата */
--**************************************************************************       
--**************************************************************************
 BEGIN
     SELECT INTO v_CurrStatus COALESCE(a_CurrStatus,MIN(addrobj.currstatus)) 
                     FROM fias_AddressObjects addrobj WHERE addrobj.AOGUID=a_AOGUID;
     SELECT INTO v_ShortTypeName,v_AddressObjectName,v_AOLevel
                                 ShortName,FormalName,AOLevel 
                     FROM fias_AddressObjects addrobj   
                     WHERE addrobj.AOGUID=a_AOGUID AND addrobj.currstatus = v_CurrStatus 	
                     LIMIT 1;
     IF v_AOLevel = 1 AND UPPER(v_ShortTypeName) <> 'Г' THEN /*  уровень региона */ 
          v_ObjectGroup:=c_RegionGroupValue;
     ELSIF v_AOLevel = 1 AND UPPER(v_ShortTypeName) =  'Г' THEN /*  уровень города */
                                                     /* как региона  */ 
          v_ObjectGroup:=c_CityGroupValue;
     ELSIF v_AOLevel = 3 THEN /* уровень района */
          v_ObjectGroup:=c_TerritoryGroupValue;
      ELSIF (v_AOLevel = 4 AND UPPER(v_ShortTypeName) NOT IN ('С/С','С/А','С/О','С/МО')) 
                OR (v_AOLevel = 1 AND UPPER(v_ShortTypeName) <> 'Г')  THEN /* уровень города */ 
          v_ObjectGroup:=c_CityGroupValue;
      ELSIF v_AOLevel IN (4,6)  AND UPPER(v_ShortTypeName) IN ('С/С','С/А','С/О','С/МО') 
               AND UPPER(v_ShortTypeName) NOT LIKE ('Ж/Д%') THEN /* уровень сельсовета */ 
          v_ObjectGroup:=c_VillageCouncilValue;	
      ELSIF v_AOLevel = 6 AND UPPER(v_ShortTypeName) NOT IN ('С/С','С/А','С/О','С/МО',
                                                      'САД','СНТ','ТЕР',
                                                      'АВТОДОРОГА',
                                                      'ПРОМЗОНА',
                                                     'ДП','МКР')
               AND UPPER(v_ShortTypeName) NOT LIKE ('Ж/Д%') THEN   /* уровень населенного */
                                                      /* пункта */ 
           v_ObjectGroup:=c_LocalityGroupValue;
       ELSIF  UPPER(v_ShortTypeName) IN ('АВТОДОРОГА') THEN /* уровень */
                                                     /* автомобильной дороги */ 
           v_ObjectGroup:=c_MotorRoadValue;
       ELSIF  v_AOLevel IN (6,7) AND UPPER(v_ShortTypeName) LIKE ('Ж/Д%') THEN 
                                                     /* уровень элемент */
                                                     /* на железной дороге */ 
           v_ObjectGroup:=c_RailWayObjectValue;	
       ELSIF v_AOLevel = 7 AND UPPER(v_ShortTypeName) NOT LIKE ('Ж/Д%') 
                    AND UPPER(v_ShortTypeName) NOT IN ('УЧ-К','ГСК','ПЛ-КА','СНТ','ТЕР') 
                    OR (v_AOLevel = 6 AND UPPER(v_ShortTypeName) IN ('МКР') )  THEN 
                                                      /* уровень улицы */
          v_ObjectGroup:=c_StreetGroupValue;
      ELSIF v_AOLevel = 90 OR v_AOLevel = 6 AND UPPER(v_ShortTypeName) IN ('САД',
                                                      'СНТ','ТЕР','ПРОМЗОНА','ДП')
                  OR v_AOLevel = 7 
                 AND UPPER(v_ShortTypeName) IN ('УЧ-К','ГСК','ПЛ-КА','СНТ','ТЕР')  THEN
                                                      /*  уровень дополнительных */
                                                      /* территорий */
           v_ObjectGroup:=c_AddlTerritoryValue;
      ELSIF v_AOLevel = 91 THEN  /* уровень подчиненных дополнительным территориям */
                                                 /* объектов */ 
           v_ObjectGroup:=c_PartAddlTerritoryValue;
     END IF;	
     RETURN v_ObjectGroup;
  END;
  $BODY$
 LANGUAGE plpgsql;
COMMENT ON FUNCTION fsfn_AddressObjects_ObjectGroup(a_AOGUID VARCHAR(36),
                                                      a_CurrStatus INTEGER)
     IS 'Возвращает  признак группы адресного объекта по его идентификатору в таблице fias_AddressObjects';

--ROLLBACK TRANSACTION;
COMMIT TRANSACTION;

SELECT fsfn_AddressObjects_ObjectGroup('719b789d-2476-430a-89cd-3fedc643d821',51);
SELECT fsfn_AddressObjects_ObjectGroup('db9c4f8b-b706-40e2-b2b4-d31b98dcd3d1');
SELECT fsfn_AddressObjects_ObjectGroup('625497d3-22de-4390-b4b4-2febfbfc15ce');
SELECT fsfn_AddressObjects_ObjectGroup('39da6405-b3e6-4baf-b332-d47b73b4d5fb');
SELECT fsfn_AddressObjects_ObjectGroup('bfc1236d-b5d2-4734-a238-3b1e4830e963');

Создание функции fsfn_AddressObjects_TreeActualName


BEGIN TRANSACTION;
DROP FUNCTION IF EXISTS fsfn_AddressObjects_TreeActualName(a_AOGUID VARCHAR(36),a_MaskArray VARCHAR(2)[10]) CASCADE;
/*****************************************************************************/
/* Возвращает строку с полным названием адресообразующего элемента  */
/*****************************************************************************/	
CREATE OR REPLACE FUNCTION fsfn_AddressObjects_TreeActualName(
	    a_AOGUID		VARCHAR(36) DEFAULT NULL,  /* Идентификтор */
                                                      /* адресообразующего  элемента */
	    a_MaskArray		VARCHAR(2)[10] default '{TP,LM,LP,ST}'	/* Массив масок, */
                                                       /* управляющий содержанием строки */ 
                                                      /* с адресом дома*/
)
RETURNS VARCHAR(1000) AS
$BODY$
DECLARE
	c_CountryGroupValue	 CONSTANT VARCHAR(50):='Country'; /* Признак группы - Страна*/	
	c_RegionGroupValue	 CONSTANT VARCHAR(50):='Region'; /* Признак группы - Регион*/	
	c_CityGroupValue	 CONSTANT VARCHAR(50):='City';	/* Признак группы - Основной */
                                                                /* населенный пункт*/	
	c_TerritoryGroupValue CONSTANT VARCHAR(50):='Territory';/* Признак группы - район */	
	c_LocalityGroupValue   CONSTANT VARCHAR(50):='Locality';/* Признак группы - */
                                                                /* населенный  пункт, */
                                                                /* подчиненный основному */	
	c_MotorRoadValue      CONSTANT VARCHAR(50):='MotorRoad';/* Признак группы - */
                                                                /* автомобильная дорога */	
	c_RailWayObjectValue	 CONSTANT VARCHAR(50):='RailWayObject';/* Признак группы - */
                                                                /* железная дорога */	
	c_VillageCouncilValue	 CONSTANT VARCHAR(50):='VillageCouncil';
                                                                /* Признак группы - сельсовет */
	c_StreetGroupValue	  CONSTANT VARCHAR(50):='Street';
                                                                 /* Признак группы - */
                                                                /* улица в населенном пункте */	
	c_AddlTerritoryValue	 CONSTANT VARCHAR(50):='AddlTerritory';/* Признак группы - */
                                                                /* дополнительная территория*/	
	c_PartAddlTerritoryValue CONSTANT VARCHAR(50):='PartAddlTerritory';/* Признак группы */
                                                      /* - часть дополнительной территории*/	
	c_StreetMask	 	CONSTANT  VARCHAR(2)[1] :='{ST}';/* Маска улица */
	c_PostIndexMask	CONSTANT  VARCHAR(2)[1] :='{ZC}';/* Маска почтовый индекс */
	c_DistrictMask		CONSTANT  VARCHAR(2)[1] :='{DT}';/* Маска городской район*/
	c_PartLocalityMask	CONSTANT  VARCHAR(2)[1] :='{LP}';/* Маска подчиненный */
                                                                /* населенный пункт*/
	c_MainLocalityMask	CONSTANT  VARCHAR(2)[1] :='{LM}';/* Маска основной */
                                                                /* населенный пункт*/
	c_PartTerritoryMask	CONSTANT  VARCHAR(2)[1] :='{TP}';/* Маска района */
                                                                /* субъекта федерации*/
	c_MainTerritoryMask	CONSTANT  VARCHAR(2)[1] :='{TM}';/* Маска субъект федерации */
                                                                /* (регион)*/
	c_CountryMask		CONSTANT  VARCHAR(2)[1] :='{CY}';/* Маска страна*/
	v_ShortTypeName	VARCHAR(10);	/* Тип адресообразующего элемента */ 
	v_AddressObjectName VARCHAR(100); /* Название адресообразующего элемента */
	v_AOLevel                INTEGER;         /* Уровень адресообразующего элемента*/	
	v_MinCurrStatus       INTEGER;		/* Минимальное значение текущего статуса */
                                                                 /* адресообразующего элемента*/	
	v_TreeAddressObjectName	VARCHAR(1000); /* Полное в иерархии название элемента*/ 
	v_ObjectGroup         VARCHAR(50); /* Группа адресообразующего элемента */
	v_TreeLeverCount    INTEGER;		/* Счетчик цикла*/
	v_Return_Error_i     Integer := 0;     /* Код возврата*/
	cursor_AddressObjectTree RefCURSOR;  /* курсор по иерархии адреса*/
	v_Return_Error       Integer :=0;	/* Код возврата */
--******************************************************************************  
--******************************************************************************
 BEGIN
	SELECT INTO v_MinCurrStatus MIN(addrobj.currstatus) 
          FROM fias_AddressObjects addrobj
          WHERE aoguid=a_AOGUID;
	OPEN cursor_AddressObjectTree FOR SELECT rtf_ShortTypeName,
                        REPLACE(rtf_AddressObjectName,'  ',' '),
                       rtf_AOLevel,fsfn_AddressObjects_ObjectGroup(rtf_AOGUID )
          FROM fstf_AddressObjects_AddressObjectTree(a_AOGUID) 
          ORDER BY rtf_AOLevel;
	v_TreeLeverCount:=0;
	v_TreeAddressObjectName:='';
	FETCH FIRST FROM cursor_AddressObjectTree INTO v_ShortTypeName,v_AddressObjectName,
                        v_AOLevel,v_ObjectGroup;
	WHILE FOUND
	LOOP
		v_TreeLeverCount:=v_TreeLeverCount+1;	
		IF v_ObjectGroup=c_CountryGroupValue AND c_CountryMask <@ a_MaskArray 
                                     AND v_AOLevel =0 THEN
			v_TreeAddressObjectName:=v_TreeAddressObjectName||
                               CASE WHEN v_TreeAddressObjectName='' THEN ''  
                                  ELSE ', ' END ||
                               v_AddressObjectName||' '||v_ShortTypeName;
		ELSIF v_ObjectGroup=c_RegionGroupValue 
                                     AND c_MainTerritoryMask <@ a_MaskArray
                                     AND v_AOLevel <=2 THEN
			v_TreeAddressObjectName:=v_TreeAddressObjectName||
                                CASE WHEN v_TreeAddressObjectName='' THEN ''
                                         ELSE ', ' END ||
                                CASE WHEN UPPER(v_ShortTypeName) LIKE 
                                               UPPER('%Респ%') THEN 'Республика ' ||
                               v_AddressObjectName ELSE v_AddressObjectName||
                                              ' '||v_ShortTypeName END;
		ELSIF v_ObjectGroup=c_TerritoryGroupValue 
                                     AND c_PartTerritoryMask <@ a_MaskArray 
                                     AND v_AOLevel =3 THEN
			v_TreeAddressObjectName:=v_TreeAddressObjectName||
                                CASE WHEN v_TreeAddressObjectName='' THEN ''
                                         ELSE ', ' END ||
                                v_AddressObjectName||' '||v_ShortTypeName;
		ELSIF v_ObjectGroup=c_CityGroupValue
                                     AND c_MainLocalityMask <@ a_MaskArray AND v_AOLevel =4 THEN
			v_TreeAddressObjectName:=v_TreeAddressObjectName||
                                    CASE WHEN v_TreeAddressObjectName='' THEN ''
                                          ELSE ', ' END ||
                                     CASE WHEN UPPER(LEFT(v_AddressObjectName,6+
                                         LENGTH(v_ShortTypeName)))='ЗАТО '||
                                         UPPER(TRIM(v_ShortTypeName))||'.'  THEN
                                             v_AddressObjectName
                                       ELSE v_ShortTypeName ||' '|| v_AddressObjectName END;
		ELSIF v_ObjectGroup=c_LocalityGroupValue 
                                     AND c_DistrictMask <@ a_MaskArray AND v_AOLevel =5 THEN
			v_TreeAddressObjectName:=v_TreeAddressObjectName||
                                    CASE WHEN v_TreeAddressObjectName='' THEN '' 
                                        ELSE ', ' END ||
                                    v_AddressObjectName||' '||v_ShortTypeName ;
		ELSIF v_ObjectGroup=c_LocalityGroupValue 
                                    AND c_PartLocalityMask <@ a_MaskArray 
                                    AND v_AOLevel =6 THEN
			v_TreeAddressObjectName:=v_TreeAddressObjectName||
                                   CASE WHEN v_TreeAddressObjectName='' THEN ''
                                        ELSE ', ' END ||
                                   v_ShortTypeName ||' '|| v_AddressObjectName;
		ELSIF v_ObjectGroup=c_StreetGroupValue 
                                   AND c_StreetMask <@ a_MaskArray 
                                   AND v_AOLevel =7  THEN
			v_TreeAddressObjectName:=v_TreeAddressObjectName||
                                   CASE WHEN v_TreeAddressObjectName='' THEN '' 
                                        ELSE ', ' END ||
                                   v_ShortTypeName ||' '|| v_AddressObjectName;
		END IF;
		FETCH NEXT  FROM cursor_AddressObjectTree INTO v_ShortTypeName,
                                                                                            v_AddressObjectName,
                                                                                            v_AOLevel,v_ObjectGroup;
	END LOOP;
	CLOSE cursor_AddressObjectTree;
 	RETURN 	v_TreeAddressObjectName;
  END;
  $BODY$
LANGUAGE plpgsql ;
COMMENT ON FUNCTION fsfn_AddressObjects_TreeActualName(a_AOGUID VARCHAR(36),
                                                     a_MaskArray VARCHAR(2)[10])
    IS 'Возвращает  строку с полным названием адресообразующего элемента';
--ROLLBACK TRANSACTION;
COMMIT TRANSACTION;
SELECT fsfn_AddressObjects_TreeActualName('bfc1236d-b5d2-4734-a238-3b1e4830e963','{TM,TP,LM,LP,ST}');
SELECT fsfn_AddressObjects_TreeActualName('bfc1236d-b5d2-4734-a238-3b1e4830e963');

Спасибо за внимание!
Поделиться с друзьями
-->

Комментарии (8)


  1. kxl
    01.12.2016 14:35

    Я для своих проектов сделал базу на основе КЛАДР версии ФИАС. Получилось, как мне кажется, намного проще. Всего две таблицы — Socrs и AddressElements. Первая повторяет исходную в КЛАДР, а вторая:

    --MS  SQL
    CREATE TABLE [dbo].[AddressElements](
    	[Code] [decimal](19, 0) NOT NULL PRIMARY KEY,
    	[ElementType] [tinyint] NOT NULL,
    	[IsCityOrPlace] [bit] NOT NULL,
    	[Name] [varchar](40) NULL,
    	[Socr] [varchar](10) NULL,
    	[AltName] [varchar](200) NULL,
    	[RegionCode] [smallint] NOT NULL,
    	[RayonCode] [smallint] NOT NULL,
    	[CityCode] [smallint] NOT NULL,
    	[PlaceCode] [smallint] NOT NULL,
    	[StreetCode] [smallint] NOT NULL,
    	[Actuality] [tinyint] NOT NULL,
    	[PostIndex] [varchar](6) NULL,
    	[Ifns] [varchar](4) NULL,
    	[Ocato] [varchar](11) NULL,
    	[FullRegion] [varchar](160) NULL
    ) 
    


    1. gladkovs
      01.12.2016 17:01

      Ваш вопрос требует развернутого ответа. Я, обязательно, отвечу Вам завтра на свежую голову.


    1. gladkovs
      02.12.2016 06:03

      Степень простоты или сложности решения оценивается в зависимости от задачи. Я принимаю неявный упрек в том, что в публикации не описал решаемую задачу, а лишь ограничился тем, что использую структуру справочника ADDROBJ.DBF.
      Задача состоит в том, чтобы по адресу, поступившему откуда-то извне (например, от заказчика), найти соответствующий адрес в справочнике ФИАС. При этом, внешний адрес может содержать устаревшие названия улиц и населенный пунктов. Как Вы знаете, переименование названий адресообразующих элементов не такое уж редкое явление.
      Поэтому в структуре таблицы, созданной из справочника, были сохранены записи об истории переименования каждого элемента. Я надеялся, что смогу по устаревшему названию элемента находить актуальное. К сожалению, эта надежда не оправдалась. Как написано в первой части статьи лишь в 6,8% от числа элементов, имеющих записи об истории переименования, присутствуют различия в названиях одного и того же элемента. Да и в этих случаях, речь идет скорее об исправлении ошибок, чем об истории переименования адресообразующих элементов. Поэтому, мне не удалось использовать ФИАС, как базовый справочник для решения поставленной задачи. Сейчас он используется как один из источников данных для моего внутреннего справочника адресов.
      Подробнее проблемы связанные и использованием адресов ФИАС изложены: .
      Описанная задача решается как часть основной задачи – задачи геопривязки, т.е. по предоставленному извне адресу найти объект на карте. Но объектами на карте не обязательно являются дома в населенных пунктах. Такими объектами могут быть, например, дома в дачных или садовых товариществах, или здания цехов на территории промышленной зоны.
      Вот как выглядят адреса таких и подобных мест:
      «Республика Хакасия, г Абакан, пр-кт Дружбы Народов, дворовая территория домов 15 17 19 тер»
      «Республика Хакасия, г Абакан, ул Пушкина, дворовая территория дома 21 тер»
      Для идентификации таких мест код ФИАС расширен полями:

      • PLANCODE nvarchar(4) Код элемента планировочной структуры
      • EXTRCODE nvarchar(4) Код дополнительного адресообразующего элемента
      • SEXTCODE nvarchar(3) Код подчиненного дополнительного адресообразующего элемента


      Смотри документ «Сведения о составе информации государственного адресного реестра федеральной информационной адресной системы» на сайте .
      Не буду обманывать, задача геопривязки дополнительных территорий еще не решена, но она стоит в ближайших планах компании, в которой я работаю. Поэтому и эти поля я не убирал из структуры таблицы.


      1. gladkovs
        02.12.2016 06:35

        Извините. В ответе не отобразились ссылки на сайты. Документ который упоминается в ответе, можно найти запросу ФИАС (ФЕДЕРАЛЬНАЯ ИНФОРМАЦИОННАЯ АДРЕСНАЯ СИСТЕМА) на сайте налоговой службы.
        Мое описание проблем с адресами ФИАС можно найти по названию публикации «Эх, ФИАС, ФИАС… Почему ты не адресный реестр?».


      1. kxl
        02.12.2016 19:52

        Я не думал упрекать. Структура ФИАС слишком замудрена. Кстати у меня тоже можно найти предыдущие наименования — они будут с другим кодом Actuality (также содержится в Code). Таблица для переименований мне не нужна, если, конечно, не придется искать реорганизованные пункты. Тогда можно будет и добавить её.


        1. gladkovs
          03.12.2016 05:37

          Я сам себя упрекаю…


  1. heleo
    01.12.2016 16:15

    Я смотрю у Вас в правилах создание объектов бд с использованием begin\commit блоков. При генерации таблиц так же пользуетесь транзакцией или всяческие constraint внутрь create table (..) вместо alter table…?


    1. gladkovs
      01.12.2016 17:00

      Да, при создании таблиц я особенно часто использую транзакции. Сначала begin\rollback, а когда уверен, что ничего не забыл, использую begin\commit блоков.