Есть такая проблема, что при определенных больших SQL запросах, excel падает в ошибку при попытке получить oRS.RecordCount или .CopyFromRecordset oRS. В других приложениях данный sql запрос отрабатывает без ошибок. Так же, если в запросе указать limit 0 (т.е. ограничить количество выводимых строк нулем), то ответ вставляется корректно, а именно его шапка и пустая соответственно таблица. Код подключения:[vba]
Код
Set oConn = CreateObject("ADODB.Connection") Set oRS = CreateObject("ADODB.Recordset") oConn.Open "ххххххххххххх" oRS.CursorType = 3 oRS.Open strSql, oConn -------- cl = oRS.RecordCount cf = oRS.Fields.Count -------- For Each fld In oRS.Fields Workbooks(sql_range.Parent.Parent.Name).Worksheets(sql_range.Parent.Name).Cells(sql_range.Row, nCol).Value = fld.Name nCol = nCol + 1 Next
[/vba] При определении размеров ответа cl и cf, ошибка возникает только в cl, cf отрабатывает отлично. Так же пробовал вызвать свойство oRS.EOF, тоже возникает ошибка. Если строку cl = oRS.RecordCount закомментировать, то ошибка вылазит на .CopyFromRecordset oRS Прошу помощи, как обойти эту ошибку.
Уважаемые гуру, всем, доброго дня.
Есть такая проблема, что при определенных больших SQL запросах, excel падает в ошибку при попытке получить oRS.RecordCount или .CopyFromRecordset oRS. В других приложениях данный sql запрос отрабатывает без ошибок. Так же, если в запросе указать limit 0 (т.е. ограничить количество выводимых строк нулем), то ответ вставляется корректно, а именно его шапка и пустая соответственно таблица. Код подключения:[vba]
Код
Set oConn = CreateObject("ADODB.Connection") Set oRS = CreateObject("ADODB.Recordset") oConn.Open "ххххххххххххх" oRS.CursorType = 3 oRS.Open strSql, oConn -------- cl = oRS.RecordCount cf = oRS.Fields.Count -------- For Each fld In oRS.Fields Workbooks(sql_range.Parent.Parent.Name).Worksheets(sql_range.Parent.Name).Cells(sql_range.Row, nCol).Value = fld.Name nCol = nCol + 1 Next
[/vba] При определении размеров ответа cl и cf, ошибка возникает только в cl, cf отрабатывает отлично. Так же пробовал вызвать свойство oRS.EOF, тоже возникает ошибка. Если строку cl = oRS.RecordCount закомментировать, то ошибка вылазит на .CopyFromRecordset oRS Прошу помощи, как обойти эту ошибку.TD_MElec
Сообщение отредактировал TD_MElec - Суббота, 30.10.2021, 01:23
doober, а каким образом все это происходит?)) Как кладете результат во временную?
Причем, я так понимаю, это не зависит от количества строк. Я пробовал указать limit 1, и все равно выходит ошибка. Видимо проблема в типах данных, но в чем конкретно не могу разобраться. Среди прочих, есть данные с большим количеством символов после запятой, может в этом проблема...
doober, а каким образом все это происходит?)) Как кладете результат во временную?
Причем, я так понимаю, это не зависит от количества строк. Я пробовал указать limit 1, и все равно выходит ошибка. Видимо проблема в типах данных, но в чем конкретно не могу разобраться. Среди прочих, есть данные с большим количеством символов после запятой, может в этом проблема...TD_MElec
Методом исключения, определил поля, которые вызывают ошибку. Все эти поля временные/расчетные, пользователи естественно не задают им определенный тип. Сторонний софт показывает тип данных: numeric(131089,0). Но значения есть не целые, а как я понимаю, numeric(131089,0) - означает ноль знаков после запятой, т.е. целочисленные значения. Если результат вычислений имеет не больше двух знаков после запятой, то ошибки не возникает. Возвращается корректное значение с двумя знаками. Довольно странно, но если результат меньше 1, но больше 0 и имеет большое количество знаков после запятой, то тоже не возникает ошибки! А вот если результат больше единицы и знаков больше двух, то происходит ошибка.
Методом исключения, определил поля, которые вызывают ошибку. Все эти поля временные/расчетные, пользователи естественно не задают им определенный тип. Сторонний софт показывает тип данных: numeric(131089,0). Но значения есть не целые, а как я понимаю, numeric(131089,0) - означает ноль знаков после запятой, т.е. целочисленные значения. Если результат вычислений имеет не больше двух знаков после запятой, то ошибки не возникает. Возвращается корректное значение с двумя знаками. Довольно странно, но если результат меньше 1, но больше 0 и имеет большое количество знаков после запятой, то тоже не возникает ошибки! А вот если результат больше единицы и знаков больше двух, то происходит ошибка.TD_MElec
Сообщение отредактировал TD_MElec - Суббота, 30.10.2021, 13:35
Где то так.Это пример.Могут быть ошибки, писал в нотепаде
[vba]
Код
sql="IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[T]') AND type in (N'U')) " & vbCrLf & _ " DROP TABLE [dbo].[T]; " oConn.Execute sql sql = "SELECT и т.д ваш запрос into T FROM [таблица] " oConn.Execute sql sql = "ALTER TABLE T " & vbCrLf & _ "ADD ct [int] IDENTITY(1,1) PRIMARY KEY; " oConn.Execute sql Set Rs = oConn.Execute("SELECT max([ct]) FROM [T]") If Rs.EOF = False Then Count = Rs(0) Else Count = 0 End If Set Sh = ActiveSheet For n = 1 To Count Step 100000 Set Rs = oConn.Execute(" SELECT * from T where ct>=" & n & " and ct<=" & (n + 100000 - 1)) If Not Rs.EOF Then If n = 1 Then For i = 0 To Rs.Fields.Count - 1 Sh.Cells(1, i + 1) = Rs.Fields(i).Name Next Sh.Range("a2").CopyFromRecordset Rs Else LastRow = Sh.Cells(Sh.Rows.Count, 2).End(xlUp).Row + 1 Sh.Range("a" & LastRow).CopyFromRecordset Rs
End If
End If Next
sql = "IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[T]') AND type in (N'U')) " & vbCrLf & _ " DROP TABLE [dbo].[T]; " oConn.Execute sql
[/vba]
Где то так.Это пример.Могут быть ошибки, писал в нотепаде
[vba]
Код
sql="IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[T]') AND type in (N'U')) " & vbCrLf & _ " DROP TABLE [dbo].[T]; " oConn.Execute sql sql = "SELECT и т.д ваш запрос into T FROM [таблица] " oConn.Execute sql sql = "ALTER TABLE T " & vbCrLf & _ "ADD ct [int] IDENTITY(1,1) PRIMARY KEY; " oConn.Execute sql Set Rs = oConn.Execute("SELECT max([ct]) FROM [T]") If Rs.EOF = False Then Count = Rs(0) Else Count = 0 End If Set Sh = ActiveSheet For n = 1 To Count Step 100000 Set Rs = oConn.Execute(" SELECT * from T where ct>=" & n & " and ct<=" & (n + 100000 - 1)) If Not Rs.EOF Then If n = 1 Then For i = 0 To Rs.Fields.Count - 1 Sh.Cells(1, i + 1) = Rs.Fields(i).Name Next Sh.Range("a2").CopyFromRecordset Rs Else LastRow = Sh.Cells(Sh.Rows.Count, 2).End(xlUp).Row + 1 Sh.Range("a" & LastRow).CopyFromRecordset Rs
End If
End If Next
sql = "IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[T]') AND type in (N'U')) " & vbCrLf & _ " DROP TABLE [dbo].[T]; " oConn.Execute sql
doober, Спасибо. Я сначала подумал, что создаете временную в vba и с ней работаете. А я обнаружил, что если отключить .CursorLocation = 3, то .CopyFromRecordset отрабатывает! Но при этом у меня есть подозрения на достоверность выводимых данных, именно в тех полях, которые вызывали ошибку :-/
PS Да действительно, значение конкретно этих полей совсем не соответствует действительности. один и тот же запрос с одной и той же сортировкой Так из альтернативной программы я получаю результат: field_name_1 field_name_2 27637961673,9986 403116,824005105 27637961673,9986 121252,175044491 27637961673,9986 91841,8608386193 27637961673,9986 509919,595871232
а этот мне приходит из запроса с отключенным .CursorLocation = 3 field_name_1 field_name_2 13,63541093 0,00137972008613245 13,63541093 0,000225865529070376 13,63541093 0,00525719558035457 13,63541093 0,000170514345006219
Остальные поля идентичны друг другу
Что за мистика????
PPS Если я использую .CursorType = 3, а .CursorLocation = 3, не использую. То в других запросах .RecordCount отрабатывает корректно, а в этом возвраащает -1.
Err.Description Поставщик данных или другая служба вернули состояние E_FAIL. Err.Number -2147467259 Err.Source Microsoft Cursor Engine
doober, Спасибо. Я сначала подумал, что создаете временную в vba и с ней работаете. А я обнаружил, что если отключить .CursorLocation = 3, то .CopyFromRecordset отрабатывает! Но при этом у меня есть подозрения на достоверность выводимых данных, именно в тех полях, которые вызывали ошибку :-/
PS Да действительно, значение конкретно этих полей совсем не соответствует действительности. один и тот же запрос с одной и той же сортировкой Так из альтернативной программы я получаю результат: field_name_1 field_name_2 27637961673,9986 403116,824005105 27637961673,9986 121252,175044491 27637961673,9986 91841,8608386193 27637961673,9986 509919,595871232
а этот мне приходит из запроса с отключенным .CursorLocation = 3 field_name_1 field_name_2 13,63541093 0,00137972008613245 13,63541093 0,000225865529070376 13,63541093 0,00525719558035457 13,63541093 0,000170514345006219
Остальные поля идентичны друг другу
Что за мистика????
PPS Если я использую .CursorType = 3, а .CursorLocation = 3, не использую. То в других запросах .RecordCount отрабатывает корректно, а в этом возвраащает -1.
Err.Description Поставщик данных или другая служба вернули состояние E_FAIL. Err.Number -2147467259 Err.Source Microsoft Cursor EngineTD_MElec
Сообщение отредактировал TD_MElec - Воскресенье, 31.10.2021, 17:06
Я полностью не разобрался ни в вашем sql запросе, ни в коде в целом :-(, просто скопировать я не могу, т.к. используется субд на основе PostgreSQL и там отличается синтаксис. и эта строка, уже вызвала ошибку [vba]
Код
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[T]') AND type in (N'U')) DROP TABLE [dbo].[T];
[/vba] А в общих чертах, вы создаете временную таблицу с постоянным именем "Т" - тут у меня сразу возникает вопрос, а если несколько пользователей будут делать запрос в одно время, не возникнет ли ошибок? А правильно ли я думаю, что если мы сделаем вот так то это не вызовет ошибок: [vba]
Код
sql = "IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[T]') AND type in (N'U')) DROP TABLE [dbo].[T]; " & vbCrLf & _ "SELECT и т.д ваш запрос into T FROM [таблица]; " & vbCrLf & _ "ALTER TABLE T ADD ct [int] IDENTITY(1,1) PRIMARY KEY; " oConn.Execute sql
[/vba] В эту таблицу "Т" вы всегда помещаете результат всего вашего запроса, а потом из этой временной вы наполняете Rs. И если после первого наполнения, Rs.OEF вызывает ошибку, то вы очищаете Rs и... дальше я не могу понять. Вы кладете только одну строку из таблицы "T" в Rs?
Я полностью не разобрался ни в вашем sql запросе, ни в коде в целом :-(, просто скопировать я не могу, т.к. используется субд на основе PostgreSQL и там отличается синтаксис. и эта строка, уже вызвала ошибку [vba]
Код
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[T]') AND type in (N'U')) DROP TABLE [dbo].[T];
[/vba] А в общих чертах, вы создаете временную таблицу с постоянным именем "Т" - тут у меня сразу возникает вопрос, а если несколько пользователей будут делать запрос в одно время, не возникнет ли ошибок? А правильно ли я думаю, что если мы сделаем вот так то это не вызовет ошибок: [vba]
Код
sql = "IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[T]') AND type in (N'U')) DROP TABLE [dbo].[T]; " & vbCrLf & _ "SELECT и т.д ваш запрос into T FROM [таблица]; " & vbCrLf & _ "ALTER TABLE T ADD ct [int] IDENTITY(1,1) PRIMARY KEY; " oConn.Execute sql
[/vba] В эту таблицу "Т" вы всегда помещаете результат всего вашего запроса, а потом из этой временной вы наполняете Rs. И если после первого наполнения, Rs.OEF вызывает ошибку, то вы очищаете Rs и... дальше я не могу понять. Вы кладете только одну строку из таблицы "T" в Rs?TD_MElec
Я кладу по 10 000 Для PG такие команды Можно выбирать через OFFSET [vba]
Код
DROP TABLE IF EXISTS T; create table T as select .............; ALTER TABLE T ADD COLUMN ct SERIAL PRIMARY KEY; SELECT * FROM T ORDER BY ct LIMIT 10000 OFFSET 0; ...... LIMIT 10000 OFFSET 10000;
[/vba]Почитайте мануалы.Если Вы тянете через инет, то там есть ограничения в длине пакета
Я кладу по 10 000 Для PG такие команды Можно выбирать через OFFSET [vba]
Код
DROP TABLE IF EXISTS T; create table T as select .............; ALTER TABLE T ADD COLUMN ct SERIAL PRIMARY KEY; SELECT * FROM T ORDER BY ct LIMIT 10000 OFFSET 0; ...... LIMIT 10000 OFFSET 10000;
[/vba]Почитайте мануалы.Если Вы тянете через инет, то там есть ограничения в длине пакетаdoober
doober, доброго дня. Создал временную, заполнил ее результатом выборки, и без E_FAIL перенес в excel (через запрос из excel средствами vba: select * from temp_table). НО есть проблемы с данными. Так dbeaver в тех самых полях при выполнении того же запроса select * from temp_table выводит одни данные, а excel другие. Сейчас у временной таблицы тип всех проблемных полей numeric. Что вообще происходит ?!?! Я совсем не понимаю как такое может быть...
doober, доброго дня. Создал временную, заполнил ее результатом выборки, и без E_FAIL перенес в excel (через запрос из excel средствами vba: select * from temp_table). НО есть проблемы с данными. Так dbeaver в тех самых полях при выполнении того же запроса select * from temp_table выводит одни данные, а excel другие. Сейчас у временной таблицы тип всех проблемных полей numeric. Что вообще происходит ?!?! Я совсем не понимаю как такое может быть...TD_MElec
Временная таблица-это одно, а первоисточник совсем другое. Надо скрипт создания таблицы , сам запрос. Без первоисточника сказать ничего не могу. Сделайте выборку на пару строк, посчитайте руками и сравните У Вас нет никакой программы для работой с базой данных? Сомневаюсь, что база и таблицы создавались с командной строки.
Временная таблица-это одно, а первоисточник совсем другое. Надо скрипт создания таблицы , сам запрос. Без первоисточника сказать ничего не могу. Сделайте выборку на пару строк, посчитайте руками и сравните У Вас нет никакой программы для работой с базой данных? Сомневаюсь, что база и таблицы создавались с командной строки.doober
С бд работаем через dbeaver. Чем там она строится, я не знаю. Скрипт создания и сам запрос, во вложенном txt, (сюда не поместилось по количеству символов) xls надо переименовать в txt. TXT не смог загрузить.
Теперь запрос select * from odb.tmp_nb_table в excel выводит одни данные, а в DBeaver другие Поля с разными данными: coeff_w_ctg_pk total_ver_ctg_pk ver_sku_tren_pk
С бд работаем через dbeaver. Чем там она строится, я не знаю. Скрипт создания и сам запрос, во вложенном txt, (сюда не поместилось по количеству символов) xls надо переименовать в txt. TXT не смог загрузить.
Теперь запрос select * from odb.tmp_nb_table в excel выводит одни данные, а в DBeaver другие Поля с разными данными: coeff_w_ctg_pk total_ver_ctg_pk ver_sku_tren_pkTD_MElec
Теперь запрос select * from odb.tmp_nb_table в excel выводит одни данные, а в DBeaver другие
Я Вас понимаю, но этого не может быть, чтобы один и тот же запрос к таблице возвращал разные данные Первый раз такое встречаю.Если база крутиться на хостинге, могу скрипт php написать и вывести результат в текстовик для сравнения. Реально чудеса.
Теперь запрос select * from odb.tmp_nb_table в excel выводит одни данные, а в DBeaver другие
Я Вас понимаю, но этого не может быть, чтобы один и тот же запрос к таблице возвращал разные данные Первый раз такое встречаю.Если база крутиться на хостинге, могу скрипт php написать и вывести результат в текстовик для сравнения. Реально чудеса.doober
Да, база в облаке. Думается мне, что проблема в том, что vba не правильно интерпретирует тип данных, поэтому получается так. Сейчас в excel, из odb.tmp_nb_table приходят те же значения, что приходили, когда я отключал .CursorLocation = 3 и делал прямой запрос, только тогда .RecordCount отрабатывал -1, а сейчас он возвращает точное значение.
Да, база в облаке. Думается мне, что проблема в том, что vba не правильно интерпретирует тип данных, поэтому получается так. Сейчас в excel, из odb.tmp_nb_table приходят те же значения, что приходили, когда я отключал .CursorLocation = 3 и делал прямой запрос, только тогда .RecordCount отрабатывал -1, а сейчас он возвращает точное значение.TD_MElec
Использую драйвера со страницы postgresql.org Версия драйвера psqlodbc_13_01_0000 Но доступна уже psqlodbc_13_02_0000 Попробую обновиться в ближайшее время.
Использую драйвера со страницы postgresql.org Версия драйвера psqlodbc_13_01_0000 Но доступна уже psqlodbc_13_02_0000 Попробую обновиться в ближайшее время.TD_MElec
Может быть кто-то еще знает причины. Почему при одном и том же запросе select * from odb.tmp_nb_table в excel выводит одни данные, а в DBeaver другие.
Обновил драйвера, проблема не исчезла.
Может быть кто-то еще знает причины. Почему при одном и том же запросе select * from odb.tmp_nb_table в excel выводит одни данные, а в DBeaver другие.TD_MElec