|   |   | 
| 
 | Не срабатывает 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.     | 
 
 | Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |