Имя: Пароль:
1C
1C 7.7
v7: ПроUPDATEить кучу элементов одним запросом (прямые запросы)
0 monsterZE
 
24.04.14
12:57
Возможен сабж, если у элементов разные значения свойств?
Сейчас апдейчу - 1 элемент-1 запрос.. медленновато =(
Элемент - например товар, свойства - цена, остаток
1 Ёпрст
 
24.04.14
12:58
запросто
2 monsterZE
 
24.04.14
13:00
ТекстЗапроса = "
|    UPDATE "+ТекСКЛТаб+"
|    SET
|      [бла-бла-бла]
|   IF @@ROWCOUNT = 0
|      BEGIN
|            INSERT INTO "+ТекСКЛТаб+"
|      [бла-бла-бла]
|            VALUES
|      [бла-бла-бла]
|      END
|";
3 monsterZE
 
24.04.14
13:01
(1) Запихать все в виртуальную табличку?
4 Ёпрст
 
24.04.14
13:02
да просто апдейт из селекта
5 Ёпрст
 
24.04.14
13:02
т.е значения для set получать из таблички.. усё.
6 Ёпрст
 
24.04.14
13:04
ну, так например (смотри примеры с from внизу)
http://msdn.microsoft.com/ru-ru/library/ms177523.aspx

а можешь и коррелированный подзапрос в set пихать еще..
7 monsterZE
 
24.04.14
13:05
(5) а пример можно? =) самой конструкции
еще такой момент - апдейчу я внешнюю табличку из 1сы
8 monsterZE
 
24.04.14
13:05
(6) ок, спс, смотрю =)
9 Ёпрст
 
24.04.14
13:07
тип того

update table1
set column1 = ( select max(a) from table2 ) ,
    column1 = ( select max(b) from table3 )
WHERE column3 = c
10 Ёпрст
 
24.04.14
13:08
или ... иннер джоин и значения со второй таблички..
Ну, вариантов масса
11 monsterZE
 
24.04.14
13:25
фак =)
а если часть товара присутствует в табличке (и ее надо проапдейтить)
а части нет и ее надо заинсертить
Чет я не совсем понимаю - у меня WHERE column3 = c
в с будет множество объектов
т.е. мне надо как-то цикл что-ли =) который бы перебирал объекты и апдейтил их или инсертил
12 monsterZE
 
24.04.14
13:28
Допустим у меня есть таблица значений, строки которой надо проапдейтить
я чет не совсем представляю - мне надо в текст запроса запихать каждый объект с его свойствами?
13 Ёпрст
 
24.04.14
13:30
я ж не знаю, откуда ты поля для апдейта тащить собираешься
14 Ёпрст
 
24.04.14
13:32
если запрос на sqlite, то там есть insert or replase, для обычного скуля..нужно проверять
15 Ёпрст
 
24.04.14
13:34
или, как trad писал:
делать ли if exist или сразу update?
см 3 пост
16 monsterZE
 
24.04.14
13:36
(15) да я так тогда и переписывал
17 monsterZE
 
24.04.14
13:43
(13) если из тз
18 Ёпрст
 
24.04.14
13:44
(17) ну и ?
А по какому признаку различать, кому и что ?..Или в тзз есть ссылка на объект и значение для реквизита ?
19 monsterZE
 
24.04.14
13:46
угу. вот ИД надо обновить остальные поля
    ТабТовараКОбновлению.НоваяКолонка("РодИД");
    ТабТовараКОбновлению.НоваяКолонка("ИД");
    ТабТовараКОбновлению.НоваяКолонка("Назван");
    ТабТовараКОбновлению.НоваяКолонка("Цена");
    ТабТовараКОбновлению.НоваяКолонка("ЕдИзм");
    ТабТовараКОбновлению.НоваяКолонка("УпКол");
    ТабТовараКОбновлению.НоваяКолонка("Ост");
    ТабТовараКОбновлению.НоваяКолонка("Рез");
сейчас я каждый раз подставляю в текст-запроса нужное и
Запрос.ВыполнитьСкалярный(ТекстЗапроса);
20 monsterZE
 
24.04.14
13:46
(19) по ИД
21 Ёпрст
 
24.04.14
13:47
тогда ТЗ во временную табличку, а далее примитивно

update t
   set t.a = vrem.b
from table as t inner join #tmptable as vrem on vrem.id = t.id
22 Ёпрст
 
24.04.14
13:50
на счет укладки тз, тут пример:
http://www.1cpp.ru/forum/YaBB.pl?num=1170322440/7#7
23 monsterZE
 
24.04.14
13:52
такой еще вопрос - текст запроса (для 1с++) по размеру имеет какие-то ограничения? если все значения сразу в него запихать.
24 Ёпрст
 
24.04.14
13:55
Попробуй, только смысл ?
25 Ёпрст
 
24.04.14
13:56
и ограничение есть, только не помню, какое.
26 monsterZE
 
24.04.14
14:00
(24) не, ну чтобы заполнить временную табличку - это-ж тоже время (если также в цикле ее заполнять)
а для меня как раз самое главное время сэкономить
27 Ёпрст
 
24.04.14
14:01
ну, не больше времени займёт, чем заполнение текста запроса.
28 Ёпрст
 
24.04.14
14:02
и это, Ост ты же откуда то получаешь ?
И наверняка, тоже с запроса, вот и клади в нём сразу или сразу апдейт..
29 КонецЦикла
 
24.04.14
14:03
30 monsterZE
 
24.04.14
14:03
(28) спасибо за инфу, буду пробывать =)
31 monsterZE
 
24.04.14
14:04
(29) благодарю! =)
32 ADirks
 
24.04.14
14:33
что касается вставить только то, чего нет, то например так

insert into  dest_table
   ...
from src_table
   ...
where
   src_table.ID not in (select ID from dest_table)
33 Ёпрст
 
24.04.14
14:34
(32) как в (15) красившее и быстрее..
34 Ёпрст
 
24.04.14
14:34
по идее :)
35 ADirks
 
24.04.14
14:44
типа того?

insert into  dest_table
   ...
from src_table
   ...
where
   not exists (select * from dest_table where dest_table.ID = src_table.ID)


да, как минимум не медленее.
просто не люблю коррелированные запросы. эстет, панимаишь :)
36 Ёпрст
 
24.04.14
14:47
(35) не-не-не, никаких коррелированных!



trad :

обычно пишу так

|UPDATE ...
|IF @@ROWCOUNT = 0
|   INSERT ...

и не парюсь
37 Ёпрст
 
24.04.14
14:48
тупо проверка на количество проапдейтенных строк..
:)
красиво
38 Ёпрст
 
24.04.14
14:50
Хотя.. если не надо апдейтить, то что есть, тогда да..тогда проверка селектом
39 ADirks
 
24.04.14
14:52
Так это если одна строка, или все строки из src отсутствуют в dest. А если часть строк из src уже есть в dest?
40 Ёпрст
 
24.04.14
14:53
(39) тады ой :)
41 Ёпрст
 
24.04.14
14:54
хотя непонятно, чего не реализовать было как в sqlite конструкцию insert or replace в скуле
42 monsterZE
 
24.04.14
16:04
собрал все, что мне надо запросом теперь апдейтить =)
    ТекстЗапроса = "
    |SELECT
    |     LTRIM(СпрРод.Code) as РодКод
    |    ,LTRIM(СпрТов.Code) as Код
    //|    ,СпрТов.ID as [Товар $Справочник.Товары]
    |    ,СпрТов.Descr as Имя
    |    ,$СпрТов.Опт_Цена as Цена
    |    ,$СпрТов.БазоваяЕдиница as [БазЕд $Перечисление.ЕдиницыИзмерения]
    |    ,$СпрТов.СтоимостьСборки as УпКол
    |    ,ТОст.Ост as Остаток
    |    ,ТРез.Рез as Резерв
    |FROM
    |    $Справочник.Товары as СпрТов (NOLOCK)
    |LEFT JOIN
    |(SELECT
    |     РегОст.Товар as ТовИД
    |    ,РегОст.ОстатокТовараОстаток as Ост
    |FROM
    |    $РегистрОстатки.ОстаткиТоваров(,,
    |                                   Склад = :ВыбСклад AND Товар IN (SELECT Val FROM #Группа),
    |                                   (Товар),(ОстатокТовара)) as РегОст) as ТОст ON ТОст.ТовИД = СпрТов.ID
    |LEFT JOIN
    |(SELECT
    |     РегРез.Товар as ТовИД
    |    ,РегРез.РезервТовараОстаток as Рез
    |FROM
    |    $РегистрОстатки.РезервыТоваров(,,
    |                                   Склад = :ВыбСклад AND Товар IN (SELECT Val FROM #Группа),
    |                                   (Товар),(РезервТовара)) as РегРез) as ТРез ON ТРез.ТовИД = СпрТов.ID
    |LEFT JOIN
    |    $Справочник.Товары as СпрРод (NOLOCK) ON СпрРод.ID = СпрТов.PARENTID
    |WHERE
    |    СпрТов.ID IN (SELECT Val FROM #Группа)
    |";
43 Serginio1
 
24.04.14
16:13
44 monsterZE
 
24.04.14
16:16
как теперь еще в один селект обернуть? =)
типа иф екзист в дест_таб.ид подзапрос.ид
then апдейт
else инсерт
45 monsterZE
 
24.04.14
16:25
(43) о! =)
что-то типа
MERGE Target AS T
USING (Подзапрос) AS S
ON (Target.Код = S.Код)
WHEN NOT MATCHED BY TARGET  
    THEN INSERT(цена, остаток) VALUES(S.Цена, S.Остаток)
WHEN MATCHED
    THEN UPDATE SET T.Цена = S.Цена, T.Остаток = S.Остаток
46 Serginio1
 
24.04.14
16:25
47 Ёпрст
 
24.04.14
16:26
(43) ага, только вот с кокой версии то оно появилось ? :)
48 Serginio1
 
24.04.14
16:27
(47) 2008
49 monsterZE
 
24.04.14
16:27
(47) умеешь поддержать =)
50 monsterZE
 
24.04.14
16:28
а.. не 2008 тоже есть!
51 Ёпрст
 
24.04.14
16:29
(48) во-во.. а у аутора поди 2000 или 2005 :)
52 monsterZE
 
24.04.14
16:30
(51) 2008R2 8-P
53 Ёпрст
 
24.04.14
16:32
повезло значит
54 Ёпрст
 
24.04.14
16:33
там кстати, есть и инсерт через новый синтаксис.. и ранжирующие функции и .. много еще чего :)
55 Serginio1
 
24.04.14
16:41
(54) Да вкусненьки этот 2008.
Ну и уже 6 лет прошло. А 2005 это вообще переходный вариант.
56 monsterZE
 
24.04.14
17:16
факардо! =) у меня целевая табличка лежит в отдельной бд
57 monsterZE
 
24.04.14
17:20
дописал путь.. в инсерте и апдейте его тож надо дописать?
пока просто, чтобы проверить как оно вобще =)

    ТекстЗапроса = "
    |MERGE [Magazin].[dbo].["+ТекСКЛТаб+"] AS Целевая
    |USING (SELECT
    |         LTRIM(СпрРод.Code) as РодКод
    |        ,LTRIM(СпрТов.Code) as Код
    //|        ,СпрТов.ID as [Товар $Справочник.Товары]
    |        ,СпрТов.Descr as Имя
    |        ,$СпрТов.Опт_Цена as Цена
    |        ,$СпрТов.БазоваяЕдиница as [БазЕд $Перечисление.ЕдиницыИзмерения]
    |        ,$СпрТов.СтоимостьСборки as УпКол
    |        ,ТОст.Ост as Остаток
    |        ,ТРез.Рез as Резерв
    |    FROM
    |        $Справочник.Товары as СпрТов (NOLOCK)
    |    LEFT JOIN
    |    (SELECT
    |         РегОст.Товар as ТовИД
    |        ,РегОст.ОстатокТовараОстаток as Ост
    |    FROM
    |        $РегистрОстатки.ОстаткиТоваров(,,
    |                                       Склад = :ВыбСклад AND Товар IN (SELECT Val FROM #Группа),
    |                                       (Товар),(ОстатокТовара)) as РегОст) as ТОст ON ТОст.ТовИД = СпрТов.ID
    |    LEFT JOIN
    |    (SELECT
    |         РегРез.Товар as ТовИД
    |        ,РегРез.РезервТовараОстаток as Рез
    |    FROM
    |        $РегистрОстатки.РезервыТоваров(,,
    |                                       Склад = :ВыбСклад AND Товар IN (SELECT Val FROM #Группа),
    |                                       (Товар),(РезервТовара)) as РегРез) as ТРез ON ТРез.ТовИД = СпрТов.ID
    |    LEFT JOIN
    |        $Справочник.Товары as СпрРод (NOLOCK) ON СпрРод.ID = СпрТов.PARENTID
    |    WHERE
    |        СпрТов.ID IN (SELECT Val FROM #Группа)) AS Источник
    |ON (Целевая.id = Источник.Код)
    |WHEN NOT MATCHED BY TARGET  
    |    THEN INSERT(parent_id,id,nazvan,cena,up_ed,up_kol,ostatok,rezerv,izmenost)
    |            VALUES(Источник.РодКод
    |                  ,Источник.Код
    |                  ,Источник.Имя
    |                  ,Источник.Цена
    |                  ,Источник.БазЕд
    |                  ,Источник.УпКол
    |                  ,Источник.Остаток
    |                  ,Источник.Резерв
    |                  ,:Маркер)
    |WHEN MATCHED
    |    THEN UPDATE SET
    |        parent_id = Источник.РодКод
    |        ,nazvan    = Источник.Имя
    |        ,cena      = Источник.Цена
    |        ,up_ed     = Источник.БазЕд
    |        ,up_kol    = Источник.УпКол
    |        ,ostatok   = Источник.Остаток
    |        ,rezerv    = Источник.Резерв
    |       ,izmenost  = :Маркер
    |;
    |";
58 Serginio1
 
24.04.14
17:27
Я Ну можно еще проверить на изменение полей

|MERGE into dbo."+СтрРегПрайсов.ИмяТаблицыХранения+" as ИзменяемыеПрайсы
     |Using #TempPrice as Источник";
     Стр=Стр+"
     |   ON Источник.Артикул=ИзменяемыеПрайсы."+РегПрайсовПоля.Артикул+"
     |   and @Прайс=ИзменяемыеПрайсы."+РегПрайсовПоля.ТипЦен+"
     |   and Источник.Мейк = ИзменяемыеПрайсы."+РегПрайсовПоля.Мейк+"
     |   When MATCHED AND (@Импорт<>ИзменяемыеПрайсы."+РегПрайсовПоля.Импорт+СтрРавнения+") Then
     |   Update Set ИзменяемыеПрайсы."+РегПрайсовПоля.Импорт+"=@Импорт"+СтрУстановки+"
     | When NOT MATCHED THEN
     |INSERT("
59 monsterZE
 
24.04.14
17:29
(58) да пока ругается на
State 42000, native 1038, message [Microsoft][ODBC SQL Server Driver][SQL Server]Имя объекта или столбца отсутствует или пусто. Убедитесь, что каждый из столбцов в инструкции SELECT INTO имеет имя. Для других инструкций проверьте наличие пустых имен-псевдонимов. Не допускаются псевдонимы,
60 Serginio1
 
24.04.14
17:38
,IsNull(ТОст.Ост,0) as Остаток
    |        ,IsNull(ТРез.Рез,0) as Резерв
61 monsterZE
 
24.04.14
17:38
косячу =)
62 monsterZE
 
24.04.14
17:38
имя таблички закоментил
63 monsterZE
 
24.04.14
17:48
теперь чем-то не нравится имя столбца
Недопустимое имя столбца "БазЕд".
64 Ёпрст
 
24.04.14
17:53
(63)
$СпрТов.БазоваяЕдиница as [БазЕд $Перечисление.ЕдиницыИзмерения]

выкини типизацию на ..х
65 monsterZE
 
24.04.14
17:55
выкинул - заработало
но нах мне там абра-кадабра =) как ее к нормальному виду привести?
66 monsterZE
 
24.04.14
18:01
не джойнить же справочник единиц и выдерать из него дескр =\\\
67 Serginio1
 
24.04.14
18:02
Из метаданных сделай табличку соотвествия ID и Наименования
мд=СоздатьОбъект("MetaDataWork");
68 monsterZE
 
24.04.14
18:09
(67) ок, завтра продолжу =)
куясе оно работает.. быстрее минимум раз в 10, чем старый вариант
69 Serginio1
 
24.04.14
18:11
70 monsterZE
 
24.04.14
18:16
(69) угу, спасибо! =)
такой еще вопрос - это если я пользую 1с под Sa я могу любую табличку прямым запросом править? в том смысле - раньше я сначала подключался к ней, потом возвращался к текущей.
Запрос.УстБД(ОДБЦ_ДБ);
[...]
ОДБЦ_ДБ.Закрыть();
Запрос.УстБД1С();
71 Serginio1
 
24.04.14
18:16
Уже не помню но где то 10 тичный а где то и 36 значчный ID используется
ИД36=мд.ЧислоВСтроку(мд.ИДОбъекта(МДПеречисление),36);
72 Serginio1
 
24.04.14
18:17
Да можешь.
73 monsterZE
 
24.04.14
18:21
(72) прост у меня возникла мысль, что возможно еще из-за соединения медленно работало.. а достаточно было имя бд указать
74 Serginio1
 
24.04.14
18:33
(73) Ну при записи по одной строке у тебя идет поиск по номеру каждый раз, при MERGE используется индекс в двух таблицах и проходят по индексам двух таблиц.
Это аналогично алгоритму сортировки слиянием. Плюс все в одной транзакции
75 monsterZE
 
24.04.14
18:37
(74) завтра из интереса попробую без организации соединения
просто по имяБД.Табличка
а в целом - кароч надо все переписывать потихоньку =)

зы. очередной раз спасибо за помощь!
76 spock
 
24.04.14
19:26
Когда же вы на v8х перейдете?
77 monsterZE
 
25.04.14
09:31
(76) чтобы "нам" перейти на 8 - надо нанимать штат программеров и писак кфкг с нуля.. и желательно еще скрестить ее с бухией =) (и потом еще переучивать 100 чел операторов.. которые как роботы с одной программой) а это будет стоить дорого.. а дорого платить никто не хочет. тут давятся из-за процентов перевоплощения ип в ооо, а ты говоришь "когда перейдете" =) ..немного оффтопика
78 monsterZE
 
25.04.14
09:32
*писать
79 Serginio1
 
25.04.14
10:36
(76) Кстати эта ветка показывает то чего нельзя сделать в v8х. В 1С++ можешь использовать всю мощь T-SQL. А в 8ке нужно извращаться как v8: Подзапросы с Выбрать Первые либо писать прямые запросы.
80 monsterZE
 
25.04.14
10:41
(75) проверил, использование соединения видимых ограничений в скорости не накладывает. запросы пуляются ровно такое-же количество времени.
*продолжаю наблюдения* =))
81 monsterZE
 
25.04.14
11:51
собрал табличку соответ.
чтобы пользовать ее в запросе, это надо временную создавать и заполнять ее значениями?

    ТабСоотЕдИзм = СоздатьОбъект("ТаблицаЗначений");
    ТабСоотЕдИзм.Очистить();
    ТабСоотЕдИзм.НоваяКолонка("Ид36");
    ТабСоотЕдИзм.НоваяКолонка("Ед");
    ТабСоотЕдИзм.НоваяКолонка("Пред");
    
    Для ъ=1 По Метаданные.Перечисление("ЕдиницыИзмерения").Значение() Цикл
        МетаЗнач = Метаданные.Перечисление("ЕдиницыИзмерения").Значение(ъ);
        
        ТабСоотЕдИзм.НоваяСтрока();
        ТабСоотЕдИзм.Ид36 = МД.ЧислоВСтроку(МД.ИДОбъекта(МетаЗнач),36);
        ТабСоотЕдИзм.Ед   = МетаЗнач.Идентификатор;
        ТабСоотЕдИзм.Пред = МетаЗнач.Представление;
    КонецЦикла;
--- добавил еще один джойн по Единицам, чтобы забрать Descr..
    |    LEFT JOIN
    |        $Справочник.Единицы as СпрЕд (NOLOCK) ON (СпрЕд.PARENTEXT = СпрТов.ID) AND ($СпрЕд.Единица = $СпрТов.БазоваяЕдиница)