Общие реквизиты. Опыт использования и жестокий "косяк"

Потребовалось объединять данные двух независимых баз в одной. Решение лежащее на поверхности — использование общего реквизита в режиме "Разделять" и использование разделяемых данных "Независимо и совместно". Для создания базы использовалась "Библиотека стандартных подсистем", где уже присутствовал общий реквизит рекомендованного 1С типа "Число". К чему это привело будет ниже.

Платформа 8.2.18.96

Механизм общих реквизитов расписывать не буду, т.к. это сделано неоднократно. Просто напомню, что при включении в состав общего реквизита какого-либо объекта в его таблице на сервере добавляется поле.

Итак, общий реквизит «ОбластьДанных» автоматически распространялся на все объекты метаданных.
Добавил свой реквизит «ИсточникДанных»  — тип СправочникСсылка (о рекомендациях 1С на тот момент не знал), в файловой базе доделал всё, что надо, проверил, работает «замечательно» (почему в кавычках напишу в самом низу). Перенес в рабочую серверную базу и оказалось, что при установке параметров сеанса все разделенные данные «пропадают».

Оказалось, при наличии двух общих реквизитов у объекта в его таблице на сервере добавляется вычисляемое поле «_DataSeparationHash» формула:

(CONVERT([int],substring(hashbytes('MD5',CONVERT([varchar],[_Fld164],0)),(1),(4)),0)#k8SjZc9Dxkchecksum([_Fld2260RRef]))


где [_Fld164] — это общий реквизит «ОбластьДанных» типа число(7,0)
а [_Fld2260RRef] — это мой общий реквизит.

Устанавливаем параметры сеанса (только мой общий реквизит, «ОбластьДанных» не используем), выполняем запрос «Первые 333» к справочнику без условий, который должен вернуть 333 строки, но запрос оказывается пустым. На сервере видим:

SELECT TOP 333
T1._IDRRef,
T1._Version,
T1._Marked,
T1._IsMetadata,
T1._ParentIDRRef,
CASE WHEN (T1._Folder = 0x00) THEN 0x01 ELSE 0x00 END,
T1._Code,
T1._Description,
T1._Fld2088,
T1._Fld2089RRef,
T1._Fld2136RRef,
T1._Fld2154RRef,
T1._Fld2157RRef,
T1._Fld2260RRef
FROM _Reference2046 T1 WITH(NOLOCK)
WHERE (T1._Fld164 = 0.0
AND T1._Fld2260RRef = ?
AND T1._DataSeparationHash = CAST(SUBSTRING(HASHBYTES('MD5',CONVERT(VARCHAR,0.0)),1,4) AS INT) #k8SjZc9Dxk CHECKSUM(?))
p_0: 0x82F80025902DD79811E2CA0032A150E6
p_1: 0x82F80025902DD79811E2CA0032A150E6

Итак, платформой, несмотря на отключенное использование разделения по реквизиту «ОбластьДанных», накладывается условие по полю «_Fld164″, впрочем, это никак не влияет, проблема оказалась в условии по полю «_DataSeparationHash» CAST(SUBSTRING(HASHBYTES(‘MD5’,CONVERT(VARCHAR,0.0)),1,4) AS INT) #k8SjZc9Dxk CHECKSUM(?))

, тогда как в формуле

CONVERT([int],substring(hashbytes(‘MD5’,CONVERT([varchar],[_Fld164],0)),(1),(4)),0)#k8SjZc9Dxkchecksum([_Fld2260RRef])

Решение — не использовать два общих реквизита у одного объекта.

З.Ы.
Возможно, если использовать общие реквизиты нерекомендованного 1С типа, т.е. не число, то такой «косяк» и не всплывет.

И коротко про документы и их движения (досконально не разбирался, но в объяснение «замечательно» в кавычках).

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

В файловой базе можно было «задвоить» движения, сначала провести при выключенном разделении, потом при установленном разделителе.
 в серверном варианте возникает ошибка вставки неуникального индекса.
Так что, если пришли к необходимости использования общего реквизита, то придется распроводить документы, устанавливать разделитель и проводить. Или напрямую обновлять таблицы регистров (хотя сам я не решился на такое).

Надеюсь, эта информация кому-нибудь да пригодится.

11 Comments

  1. Ксакеп

    Пригодилась, огромное спасибо.

    Вопрос — как вы получили текст запроса на сервере?

    Reply
  2. alex_sh2008

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

    Reply
  3. coch

    (1) Ксакеп, точный рецепт зависит от сервера БД. Я даже точно сейчас сказать не могу какой сервер БД используется на базе. Толи MSSQL 2005, толи 2008. В мониторе активности вроде по номеру сеанса запрос смотрел. «Выбрать первые 333» использовал специально, чтобы легче найти было. MSSQL 2000 там отдельно запускается трассировщик, опять же давно с ним не работал, но вроде там всё понятно было, настраиваются фильтры, запускается трассировка, выполняется запрос на клиенте, останавливаем трассировку и ищем текст запроса.

    Если нужен точный рецепт то завтра на работе могу посмотреть.

    Reply
  4. coch

    (2) alex_sh2008, а обновление как у типовых в поставке было? Я-то только из хранилища свою базу обновляю.

    Reply
  5. alex_sh2008

    (4) качал с сайта 1С

    Reply
  6. alex_sh2008

    (3) Вряд ли версия SQL сервера даст какой то результат, это скорее всего зависит от версии платформы 1С. Я пока что не вижу преимуществ в этих реквизитах, разве что уменьшение размера конфигурации за счет потери производительности

    Reply
  7. Ксакеп

    Что удалось выяснить:

    — Запросы отслеживаются профайлером. Только в нем нужно настроить фильтр по базе данных, иначе заколебешься искать нужный запрос.

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

    — При изменении типа поля основого разделителя на текстовый — формула упрощается до (checksum([_Fld14444RRef])#k8SjZc9Dxkchecksum([_Fld658])), что в принципе позволяет избавиться от ошибки. К сожалению у нас не принято менять объекты типовой конфигурации, только добавлять новые.

    — Что интересно: На Postgre ошибка не вопроизводится, работает нормально.

    — В 2012 MSSQL добавлена функция Format, которая позволяет отразить число с требуемым кол-вом знаков после запятой. М.б. платформа читает версию скуля, и в зависимости от этого использует доступный набор функций.

    Reply
  8. Elisy

    Написал статью на схожую тему: разделители в БСП.

    http://infostart.ru/public/290219/

    Тоже остался негативный осадок.

    Вы не сталкивались с проблемами:

    1. Можно ли получить СКД-отчет по всем объектам без учета разделителей?

    2. Есть ли штатные средства загрузить БД в определенную область данных, если база была создана без использования разделителей?

    Reply
  9. coch

    (8) Elisy, статью прочитаю позже, сейчас предотпускной завал.

    по вопросам

    1. Если стоит «независимо и совместно» у общего реквизита, то при отключении в параметрах сеанса использования разделителя, любой отчет/запрос вернёт все данные по установленным отборам/условиям.

    2. Только если через конвертацию, перед загрузкой данных установить разделитель в сеансе (я так данные Москвы гружу.)

    Reply
  10. acanta

    Возможно ли добавление общего реквизита без разделения данных и как он будет выглядеть в запросах и реквизитах?

    Reply
  11. coch

    (10) Да возможно. в составе общего реквизита можно указать объекты, у которых он будет.

    И в запросах и на формах и «через точку» общие реквизиты доступны как и индивидуальные реквизиты.

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *