gifts2017

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

Опубликовал Николай (coch) в раздел Программирование - Практика программирования

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

Платформа 8.2.18.96

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

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

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

(CONVERT([int],substring(hashbytes('MD5',CONVERT([varchar],[_Fld164],0)),(1),(4)),0)^checksum([_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) ^ CHECKSUM(?))
p_0: 0x82F80025902DD79811E2CA0032A150E6
p_1: 0x82F80025902DD79811E2CA0032A150E6

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

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

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

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

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

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

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

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

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

См. также

Вознаграждение за ответ
Сумма: 0 $m
Добавили:
Павел Медведев (Ксакеп) (5.00 $m)
Подписаться Добавить вознаграждение
Комментарии
1. Павел Медведев (Ксакеп) 28.11.13 16:09
Пригодилась, огромное спасибо.
Вопрос - как вы получили текст запроса на сервере?
2. alex_sh2008 alex_2h2008 (alex_sh2008) 28.11.13 16:55
Я сталкивался с тем что при очередном обновлении конфигурации все общие реквизиты сбрасывать приходилось, в противном случае программа не запускалась, как потом выяснил, что конфигурацию готовили в другой версии программы, так что пока не использую их, и головной боли нет
3. Николай (coch) 28.11.13 19:32
(1) Ксакеп, точный рецепт зависит от сервера БД. Я даже точно сейчас сказать не могу какой сервер БД используется на базе. Толи MSSQL 2005, толи 2008. В мониторе активности вроде по номеру сеанса запрос смотрел. "Выбрать первые 333" использовал специально, чтобы легче найти было. MSSQL 2000 там отдельно запускается трассировщик, опять же давно с ним не работал, но вроде там всё понятно было, настраиваются фильтры, запускается трассировка, выполняется запрос на клиенте, останавливаем трассировку и ищем текст запроса.
Если нужен точный рецепт то завтра на работе могу посмотреть.
Ксакеп; +1 Ответить 1
4. Николай (coch) 28.11.13 19:36
(2) alex_sh2008, а обновление как у типовых в поставке было? Я-то только из хранилища свою базу обновляю.
5. alex_sh2008 alex_2h2008 (alex_sh2008) 28.11.13 19:54
6. alex_sh2008 alex_2h2008 (alex_sh2008) 29.11.13 09:10
(3) coch, Вряд ли версия SQL сервера даст какой то результат, это скорее всего зависит от версии платформы 1С. Я пока что не вижу преимуществ в этих реквизитах, разве что уменьшение размера конфигурации за счет потери производительности
7. Павел Медведев (Ксакеп) 29.11.13 12:13
Что удалось выяснить:
- Запросы отслеживаются профайлером. Только в нем нужно настроить фильтр по базе данных, иначе заколебешься искать нужный запрос.
- Ситуацию описанную автором воспроивел, ощущение что разрабы вместо запятой поставили точку, в результате хеш считается не правильно. изменил формулу расчета в хеше - все заработало как надо.. но это не вариант. При каждой реструктуризации менять формулы полей в сотнях таблиц...
- При изменении типа поля основого разделителя на текстовый - формула упрощается до (checksum([_Fld14444RRef])^checksum([_Fld658])), что в принципе позволяет избавиться от ошибки. К сожалению у нас не принято менять объекты типовой конфигурации, только добавлять новые.
- Что интересно: На Postgre ошибка не вопроизводится, работает нормально.
- В 2012 MSSQL добавлена функция Format, которая позволяет отразить число с требуемым кол-вом знаков после запятой. М.б. платформа читает версию скуля, и в зависимости от этого использует доступный набор функций.

8. Сергей Карташев (Elisy) 09.07.14 07:04
Написал статью на схожую тему: разделители в БСП.
http://infostart.ru/public/290219/
Тоже остался негативный осадок.

Вы не сталкивались с проблемами:
1. Можно ли получить СКД-отчет по всем объектам без учета разделителей?
2. Есть ли штатные средства загрузить БД в определенную область данных, если база была создана без использования разделителей?
9. Николай (coch) 09.07.14 22:04
(8) Elisy, статью прочитаю позже, сейчас предотпускной завал.
по вопросам
1. Если стоит "независимо и совместно" у общего реквизита, то при отключении в параметрах сеанса использования разделителя, любой отчет/запрос вернёт все данные по установленным отборам/условиям.
2. Только если через конвертацию, перед загрузкой данных установить разделитель в сеансе (я так данные Москвы гружу.)