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