Каталог решений - Быстрое обновление данных в клиент-серверном варианте (SQL)

Быстрое обновление данных в клиент-серверном варианте (SQL)

Быстрое обновление данных в клиент-серверном варианте (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 данная проблема решается за минуты примерно вот так:

 

Дано:

  1. Документ «КакойТоДокумент», таблица SQL «_Document55»;
  2. Поле, в которую нужно записать сумму «_Fld12507»;
  3. Табличная часть «_Document55_VT172″;
  4. Поле табличной части, содержащее сумму «_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

Собственно, все.

 

Что мы тут написали?

  1. Мы указали UPDATE для таблицы «_Document55″, т.е. мы будем именно эту таблицу обновлять.
  2. Мы указали, что поле «_Fld12507″ мы будем заполнять результатом агрегатной функции SUM — сумма — для поля «_Fld749» таблицы t2 («_Document55_VT172″).
  3. Стандартное FROM (ИЗ) и имя таблицы нашего документа.
  4. LEFT JOIN (ЛЕВОЕ СОЕДИНЕНИЕ) — соединяемся с табличной частью по (ON) ссылке.
  5. GROUP BY (ГРУППИРОВАТЬ ПО) — группируем по ссылке.


Заключение.

В качестве заключения могу сказать, что SQL не так сложен, как его малюют. На нем вполне реально реализовать не только операции замены каких-то данных, но и весьма существенные процессы, такие, например, как обмен данными между базами. У нас в компании SQL-скрипты применяются весьма часто. В частности, для сравнения данных между многочисленными базами с разнородным содержимым (например, между УТ и БП КОРП).


Также стоит отметить, что в качестве источника можно использовать не только ту же самую базу, но и любую другую. Скажу больше — даже базу данных с другого сервера SQL (для нас это обычная практика, когда сравниваются базы данных, расположенные на разных серверах, разнесенных территориально). Для этого есть соответствующие инструкции языка запросов SQL.

has been added to your cart:
Оформление заказа