Имя: Пароль:
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.
Проблемы невозможно решaть нa том же уровне компетентности, нa котором они возникaют. Альберт Эйнштейн