Быстрое обновление данных в клиент-серверном варианте (SQL)
В статье рассматривается инструкция UPDATE языка запросов SQL.
- Описание
- Подробнее
Описание
Как мы обычно меняем записи регистров сведений?
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.
