Имя: Пароль:
1C
1С v8
Не срабатывает UPDATE через ADO
0 RobinBobinCom
 
24.02.19
15:50
Добрый день
Подключаюсь к MS SQL базе через ADO. Делаю UPDATE:

ТекстЗапроса = "UPDATE PERSON
        |SET
        |    ID_1C ='" +  СокрЛП(ВыборкаКарт.Код) + "'
        |WHERE
        |    TAB_NUM ='" + СокрЛП(ТабельныйНомер) + "'";

Соединение.Execute(ТекстЗапроса,,128);

У меня в цикле 3000 таких запросов, срабатывает только 300-500 шт.
Если этот же запрос выполнить в Managemen Studio - все прекрасно апдейтится

Что характерно - останавливаюсь в отладчике после строки Соединение.Execute(ТекстЗапроса,,128); т.е. когда запрос уже выполнился - смотрю запись в скуле - она не проапдейтилась, тут же беру этот текст запроса из отладчика, ничего не корректируя - вставляю в студию, выполняю в студии - запись апдейтится. Чудеса.

Ошибок никаких нет. Кто знает в чем может быть дело?
Заранее всем спасибо!
1 bolero
 
24.02.19
16:01
COMMIT где?
2 RobinBobinCom
 
24.02.19
16:08
(1) Раньше всегда делал без COMMIT, все работало. Как должно с коммитом выглядеть?
3 ДенисЧ
 
24.02.19
16:24
А сразу пакетом сделать?
4 GreyMen
 
24.02.19
16:32
(3)  можно и пакетом, но почему апдейт через раз срабатывает?
5 bolero
 
24.02.19
16:42
(4) если ты не указал драйверу, где должен быть COMMIT, то драйвер сам решит за тебя, без выдачи ошибок. Это может быть после выполнения каждого запроса (sql studio по-умолчанию), при корректном закрытии курсора (большинство драйверов), либо допустим каждые n секунд, что привносит элемент "через раз работает".

При любом раскладе автор сам должен знать, где COMMIT.
6 GreyMen
 
24.02.19
16:52
(5) а как явно указать? Просто после каждого update делать commit?
7 bolero
 
24.02.19
18:44
(6) можно и после каждого update, но это очень по-одинэсному

лучше create temporary table; insert into ...; update ... using ...; commit; - четыре запроса вместо 3000.
8 NorthWind
 
24.02.19
20:26
(5) если нет явно простартованной транзакции, то COMMIT делается после каждой атомарной операции. Здесь дело явно не в этом. То что делается это адский тормоз, я бы Batch Updates заюзал на месте ТС, но работать должно.
9 NorthWind
 
24.02.19
20:31
(0) посмотрите в сторону преобразования чисел в строки в 1С. Скорее всего, где-то там строка с пробелом преобразуется и из-за этого команда не отрабатывает. А лучше уберите порнографию ID_1C ='" +  СокрЛП(ВыборкаКарт.Код) + "'  и передавайте через ADO параметры.
10 NorthWind
 
24.02.19
20:33
имею в виду разделители триад пробелы
11 RobinBobinCom
 
24.02.19
21:47
добавил после каждого запроса commit. Ситуация в целом не изменилась. Да, я понимаю что не правильно делать 3000 апдейтов и есть масса способов сделать это более правильно, изящно и т.д. Сейчас вопрос не в этом. Вопрос в том, что я 3000 раз вызываю UPDATE, а исполняется он только несколько сотен раз за цикл. Т.е. при каждом запуске цикла в таблице остается меньше незатронутых записей. такое ощущение, что часть запросов игнорируется скулем.
Опять же, если бы были какие-то проблемы с преобразованием, с правильностью написания запроса и т.д. - он не бы не отрабатывал в студии. А так - я беру запрос прямо из отладчика, вставляю в студию - и он апдейтит запись в базе.
12 NorthWind
 
24.02.19
21:51
(11) а как выглядит строка соединения с сервером?
13 RobinBobinCom
 
24.02.19
21:52
Попытка
        Соединение  = Новый COMОбъект("ADODB.Connection");
        Команда     = Новый COMОбъект("ADODB.Command");
        Выборка     = Новый COMОбъект("ADODB.RecordSet");
        Соединение.ConnectionString =
            "driver={SQL Server};" +
            "server="+ИмяСервераSQL+";"+
            "uid="+ПользовательSQL+";"+
            "pwd="+ПарольSQL+";"+
            "database="+БазаДанныхSQL+";";
        Соединение.ConnectionTimeout = 60;
        Соединение.CommandTimeout = 600;
        Соединение.Open();
        Команда.ActiveConnection   = Соединение;
    Исключение
        Сообщить(ОписаниеОшибки());
        Возврат;
    КонецПопытки;
14 NorthWind
 
24.02.19
21:58
Таймауты зачем? Без них не работает?
15 NorthWind
 
24.02.19
22:02
Хотя в принципе они тут вряд ли на что-то влияют, они довольно велики
16 NorthWind
 
24.02.19
22:07
Непонятно. А другой ole db провайдер попробовать не хотите? На connectionstrings.com есть много вариантов для mssql...
17 vde69
 
24.02.19
22:10
Execute - асинхронная команда.... от сюда свистгопляска... кроме того следует учитывать, что текст запроса подвергается оптимизации...

по этому
1. делай по блочно в транзакции (например по 100 элементов)
2. используй параметр а не формирование текста
3. используй контроль (возвращаемый параметр) количества выполненых апдейтов

ну и напоследок- апдейт не умеет добавлять записи, по этому следует использовать проверку и чередовать инсерт с апдейтом
18 vde69
 
24.02.19
22:12
ну и еще - неразрывный пробел учел? а то ведь если в табельном номере болше 4 символов - то беда
19 RobinBobinCom
 
24.02.19
22:12
(17) а что понимается под вторым пунктом?
20 vde69
 
24.02.19
22:16
21 RobinBobinCom
 
24.02.19
22:25
(18) а почему именно 4 символа? У меня в табельном номере 8-10 символов, неразрывного пробела в табельных номерах нет, табельный номер - строка
Почему беда, если он больше 4-х символов?
22 vde69
 
24.02.19
22:30
(21) если тексттовый - то не страшно, просто обычно он числовой
23 SSSSS_AAAAA
 
25.02.19
09:31
(11) Что сделано для выявления причины разной работы запросов? Чем сработавший запрос отличается от несработавшего?
24 NorthWind
 
25.02.19
10:39
(21) посмотрите (16). Дело в том что у вас провайдер какой-то странный. Когда я выбираю у себя OLE DB провайдера для Microsoft SQL Server, у меня в строке соединения прописывается что-то вроде Provider=SQLOLEDB.1, а у вас не так. Может быть, ваш провайдер работает не совсем правильно и из-за этого запросы плохо выполняются. Попробуйте разные доступные варианты и почитайте connectionstrings.com в разделе по MS SQL.
25 vitkhv
 
25.02.19
11:06
(0) а профайлер открыть и посмотреть, что там отправляется от 1С к MSSQL?
26 trad
 
25.02.19
11:06
(24) у тебя оледб провайдер
У ТС одбц драйвер - это норм
27 Вафель
 
25.02.19
11:10
(17) делать поблочно в транзакции - это наследие 77, когда транзакции кэшировались в памяти.
в скл такого делать не нужно.
Когда будет происходить реальный чекпойнт (сброс на диск) решит сам сервер
28 NorthWind
 
25.02.19
11:37
(26) так может не стоит чесать левое ухо правой ногой, вызывая сначала ole db провайдер, который затем стукнется в ODBC, а ODBC наконец соединится с MS SQL?
и использование как можно более нативного ole db провайдера решит проблему?
29 MM
 
25.02.19
11:51
(17) Но ведь есть более интересный оператор https://docs.microsoft.com/ru-ru/sql/t-sql/statements/merge-transact-sql?view=sql-server-2017 вместо update. К сожалению не довелось использовать.
(18) Если региональные настройки американские, то там разделителем групп будет запятая, а бывают и более экзотичные разделители. Так что только функция Формат решает проблему.
30 NorthWind
 
25.02.19
12:02
(29) интересно, почему люди так ADO Parameters не любят? Офигенная ведь вещь и даже работает...
31 Жан Пердежон
 
25.02.19
12:14
(17) >> ну и на последок...
это называется merge
32 trad
 
25.02.19
12:26
(28) Мне не понятно почему ты взаимодействие через ODBC называешь "чесать левое ухо правой ногой"
Мне не понятно почему ты считаешь oledb нативнее чем odbc.
33 NorthWind
 
25.02.19
13:31
(32) потому что взаимодействие в данном случае идет через две прослойки вместо одной. Нативнее клиентская либа, которая линкуется к приложению и обращается к серверу напрямую безо всяких ODBC и OLE DB, но речь не об этом.
34 NorthWind
 
25.02.19
13:41
еще вопрос, что там за драйвер ODBC и какая версия SQL. Механизму ODBC черт-те сколько лет, может, драйвер, который у него на клиентской машине, не работает нормально со свежим MSSQL. Мы сами толком не знаем, чего починяем так-то :)
35 MM
 
25.02.19
14:04
(30) Может потому, что они разные на разных СУБД, где то не именованные только или разные префиксы для параметров. Но в целом параметры это верный подход.
(32) Разве oledb не может работать напрямую с нативной библиотекой, вместо odbc, если правильно задать строку соединения?
36 trad
 
25.02.19
14:17
(33) "в данном случае идет через две прослойки вместо одной."
О каких прослойках речь? (для понимания) в случаях:
1) driver=SQL Server
2) Provider=SQLOLEDB
37 NorthWind
 
25.02.19
15:25
(36) 1. вы обращаетесь к ADO, который является облегченной для пользователя надстройкой над OLEDB. OLEDB, в свою очередь, дергает функции ODBC, а ODBC через свой драйвер обращается к серверу БД. В процессе этого неизбежно происходит конвертация передаваемой информации, потому что вызовы и типы данных ADO и ODBC наверняка не на 100% совместимы между собой хотя бы потому, что механизмы эти разных поколений. В процессе этого могут иметь место ошибки.
.
2. Вы обращаетесь к ADO, который с помощью OLEDB провайдера напрямую, без ODBC, соединится с сервером. Тем самым ускорив работу (что по нынешним временам вряд ли существенно) и уменьшив вероятность ошибок (а вот это существенно).
38 trad
 
25.02.19
15:55
(37) хм, имею несколько иные представления об этих абстракциях.
Но не буду настаивать - возможно заблуждаюсь
39 NorthWind
 
25.02.19
22:01
(38) Ну они не совсем абстракции. Это вполне реальные движки для доступа к БД, реальный код. Оба они не новые, но ODBC насчитывает около 30 лет от роду, тогда как OLEDB всего около 20.
Есть два вида языков, одни постоянно ругают, а вторыми никто не пользуется.