Как мы обычно меняем записи регистров сведений?
1С с записями баз данных работает вполне сносно, особенно если это набор записей того или иного регистра. Если записей немного, то для их изменения вполне годится чтение набора записей, заполнение нужной колонки и запись изменившихся данных. Т.е. примерно так:
Набор = РегистрыСведений.КакойТоРегистрСведений.СоздатьНаборЗаписей();
Набор.Отбор.Реквизит.Значение = ЗначениеФильтра;
Набор.Отбор.Реквизит.Использование = Истина;
Набор.Прочитать();
Для Каждого Ст ИЗ Набор Цикл
Набор.НужнаяКолонка = НужноеЗначение;
Набор.НоваяКлонка = Набор.КолонкаСоСтанымЗначением;
КонецЦикла;
Набор.Записать();
При существенном размере таблицы такой подход будет неоправдан. Для решения подобных задач программист часто пишет запрос, выбирая нужные записи для изменения, а потом через менеджер записи меняет оные в цикле. Как-то так:
Запрос = Новый Запрос(
"ВЫБРАТЬ
| НужнаяКолонка КАК НужнаяКолонка,
| КолонкаСоСтанымЗначением КАК НоваяКлонка,
| Реквизит,
| Реквизит1,
| Реквизит2
|ИЗ
| РегистрыСведений.КакойТоРегистрСведений
|ГДЕ
| Реквизит = &ЗначениеОтбора");
Запрос.УстановитьПараметр("ЗначениеОтбора");
Для Каждого Ст ИЗ Запрос.Выполнить().Выгрузить() Цикл
Запись = РегистрыСведений.КакойТоРегистрСведений.СоздатьМенеждерЗаписи();
ЗаполнитьЗначенияСвойств(Запись, Ст);
Запись.Записать();
КонецЦикла;
Это уже работает куда медленнее. Можно, конечно, распараллелить процесс с помощью фоновых заданий, но тут уже трудоемкость становится неадекватна решаемой задаче (хотя, если у вас есть подсистема мультипоточного вычисления, то трудоемкость оказывается не сильно выше).
Как можно поменять записи колонок таблиц в SQL, не трогая остальное?
Данный вопрос можно очень быстро решить с помощью инструкции UPDATE языка запросов SQL.
Сделать это можно так:
UPDATE [MyBase].[dbo]._InfoReg1234 SET _Fld5678 = 1 WHERE _Active = 0
Собственно, здесь мы просто заполняем поле _Fld5678 таблицы _InfoReg1234 значением "1". Если тип поля _Fld5678 булево, то считайте, что вы проставили "ИСТИНА" во всех активных записях регистра.
Как понять, в каком поле какой таблицы SQL что хранится?
Для того, чтобы узнать, какое поле какой таблицы как называется на SQL-сервере, можно использовать функцию встроенного языка 1С "ПолучитьСтруктуруХраненияБазыДанных", которая возвращает таблицу значений, содержащую в себе структуру базы данных.
Для Каждого Стр ИЗ ПолучитьСтруктуруХраненияБазыДанных(,Истина) Цикл
НовСтр = ТаблицаБазДанных.Добавить();
ЗаполнитьЗначенияСвойств(НовСтр,Стр);
Для Каждого стр1 ИЗ Стр.Поля Цикл
НовСтр = Поля.Добавить();
ЗаполнитьЗначенияСвойств(НовСтр,Стр1);
КонецЦикла;
КонецЦикла;
После выполнения данного кода у вас в таблице значений "ТаблицаБазДанных" будет находится список таблиц, а в таблице значений "Поля" - список полей. Если для каждого элемента первой таблицы добавить некий индекс и прописать его для всех элементов второй таблицы, то будет достаточно просто искать во второй таблице поля для нужной таблицы базы данных. Сама по себе структура этих таблиц подробно описана в справке по 1С.
Рабочий пример:
Допустим, мы решили добавить в документ сумму для того, чтобы отображать ее в журналах и отчетах без необходимости лезть за ней каждый раз в табличную часть. При стандартном подходе мы можем собрать суммы по всем документам с помощью хзапроса, а потом в цикле установить данную сумму в нужный реквизит документа, после чего придется этот документ записать. Возможно из-за этого программисты и не спешат производить такие изменения. С помощью SQL данная проблема решается за минуты примерно вот так:
Дано:
- Документ "КакойТоДокумент", таблица SQL "_Document55";
- Поле, в которую нужно записать сумму "_Fld12507";
- Табличная часть "_Document55_VT172";
- Поле табличной части, содержащее сумму "_Fld749"
Итак, давайте напишем скриптик для SQL, который все, что нам нужно, сделает за считанные минуты даже если у нас не одна сотня тысяч документов:
UPDATE _Document55 SET _Fld12507 = SUM(t2._Fld749) FROM _Document55 AS t1 LEFT JOIN _Document55_VT172 AS t2 ON t1._IDRef = t2._Document55_IDRRef GROUP BY t1._IDRef
Собственно, все.
Что мы тут написали?
- Мы указали UPDATE для таблицы "_Document55", т.е. мы будем именно эту таблицу обновлять.
- Мы указали, что поле "_Fld12507" мы будем заполнять результатом агрегатной функции SUM - сумма - для поля "_Fld749" таблицы t2 ("_Document55_VT172").
- Стандартное FROM (ИЗ) и имя таблицы нашего документа.
- LEFT JOIN (ЛЕВОЕ СОЕДИНЕНИЕ) - соединяемся с табличной частью по (ON) ссылке.
- GROUP BY (ГРУППИРОВАТЬ ПО) - группируем по ссылке.
Заключение.
В качестве заключения могу сказать, что SQL не так сложен, как его малюют. На нем вполне реально реализовать не только операции замены каких-то данных, но и весьма существенные процессы, такие, например, как обмен данными между базами. У нас в компании SQL-скрипты применяются весьма часто. В частности, для сравнения данных между многочисленными базами с разнородным содержимым (например, между УТ и БП КОРП).
Также стоит отметить, что в качестве источника можно использовать не только ту же самую базу, но и любую другую. Скажу больше - даже базу данных с другого сервера SQL (для нас это обычная практика, когда сравниваются базы данных, расположенные на разных серверах, разнесенных территориально). Для этого есть соответствующие инструкции языка запросов SQL.