Запрос к базе данных из StarBasic возвращает неожиданный результат

Автор ost, 8 февраля 2017, 18:12

0 Пользователи и 1 гость просматривают эту тему.

ost

Доброго. Помогите, пожалуйста, разобраться.

Экспериментировал с цитируемым кодом и заметил что в случае использования

rowSet.First ' вернулись к первой записи. Теперь можно циклом перебрать 

результат некорректен: первая запись выборки теряется.
Если же rowSet.First не использовать, то выборка корректна.
Ощущений два =):
1) что rowSet.First устанавливает указатель на вторую строку объекта RowSet;
2) что после выполнения RowSet.execute() указатель установлен на "никуда" и только RowSet.next (или rowSet.First) устанавливает указатель на первую строку объекта RowSet.

Осталось решить вопрос о том, какое из них ближе к истине. Второе?


Перебор результата делал с помощью такой функции:

Function CreateResultArrayFromQuerry(ResultSet)
'ResultSet - результат запроса, получаемый по 'RowSet.execute()'

lRowCounter=-1

If Not IsNull(ResultSet) Then
iCols=ResultSet.Columns.Count 'iCols-Количесто полей в запросе/целевой таблице
While ResultSet.next 'перебираем значения результатов sql-запроса

Redim aCol(iCols-1) 'Создаем / 'Очищаем' массив перед получением данных следующей записи
For lColCounter=0 to iCols-1 '
aCol(lColCounter)=ResultSet.getString(lColCounter+1)
Next

lRowCounter=lRowCounter+1
redim preserve aStr(lRowCounter)
aStr(lRowCounter)=aCol()

Wend
CreateResultArrayFromQuerry=aStr()
End If
End Function 'CreateResultArrayFromQuerry


Цитата: economist от  9 февраля 2017, 11:36

В BASIC-коде лучше все данные из БД закачивать в динамический объект типа RecordSet, который по сути предоставляет самый быстрый и бесконфликтный способ подвыборки, изменения и удаления данных в базе.
Сейчас могу лишь копипастнуть свой код:


RowSet = createUnoService("com.sun.star.sdb.RowSet") ' создаем
RowSet.DataSourceName = "YourDataBase" ' указываем зарегистрированную базу данных, без *.odb!
RowSet.CommandType = com.sun.star.sdb.CommandType.COMMAND ' вызываем команду
RowSet.EscapeProcessing=FALSE
SQLSTR="SELECT * FROM СОТР"
RowSet.Command = SQLSTR 'задаем команду для набора строк
'On Error Goto ErrSQL
RowSet.execute() ' выполняем
rowSet.Last 'мотнули курсор к концу, чтобы узнать сколько строк
RowEND=(rowSet.RowCount()-1)
rowSet.First ' вернулись к первой записи. Теперь можно циклом перебрать 




rami

Цитата: ost от 25 февраля 2017, 05:47
Экспериментировал с цитируемым кодом и заметил что в случае использования

rowSet.First ' вернулись к первой записи. Теперь можно циклом перебрать

результат некорректен: первая запись выборки теряется.
Если же rowSet.First не использовать, то выборка корректна.
Ощущений два =):
1) что rowSet.First устанавливает указатель на вторую строку объекта RowSet;
2) что после выполнения RowSet.execute() указатель установлен на "никуда" и только RowSet.next (или rowSet.First) устанавливает указатель на первую строку объекта RowSet.

Осталось решить вопрос о том, какое из них ближе к истине. Второе?
Ближе к истине третье:rowSet.First ' вернулись к первой записи. Теперь можно циклом перебрать
действительно устанавливает первую запись, но дальше в функции CreateResultArrayFromQuerry(ResultSet) строка кодаWhile ResultSet.next 'перебираем значения результатов sql-запроса сразу переводит на вторую запись и с неё начинает перебор. Самое простое решение — заменить rowSet.First на rowSet.beforeFirst

ost

Спасибо. Уяснил.
Вот ссылочка. Там и примеры есть. Возможно, кому-нибудь поможет разобраться быстрее.
http://tutorials.jenkov.com/jdbc/resultset.html

economist

#18
Цитата: economist от  9 февраля 2017, 11:57SQL reserved words

Тот список SQL reserved words, которые нельзя использовать в именах полей - оказался неполным :-) Только что убил полдня на поиск причин ошибки.

Если использовать SQLite - можно быстро писать удобные "бескавычные" запросы, типа такие:  


SELECT Дата, N Номер, *, 5  FROM Table1

Тут вам и вывод столбца по номеру, и смесь * и имен полей, и необязательность GROUP BY для агрегирующих функций SUM MAX MIN... Другие движки заставят вас всё жестко обкавычить. А в с SQLite - нет, все здорово, кавычки не нужны, кириллица поддерживается везде и даже символы типа № в именах полей/псевдонимах.

Собирая запросы в Basic - не нужно лепить всяких """" итп. Но есть одно "но". Сам сдури придумал столбец номера с именем No. Так, вот, такое имя столбца без кавычек - тоже запрещено, и в Base, Basic - даст ошибку:

Синтаксическая ошибка в выражении SQL

Ошибка не возникает при .EscapeProcessing=FALSE в Basic.

Если вы используете самый быстрый способ затащить данные Base в Calc, а именно сервис Importer oDBRange.getReferredCells.doImport(oDesc())
то чтобы управлять макросом в Calc с DatabaseRanges, диапазоны баз данных вида "Импорт1", этот параметр придется подставить явно, как тут: https://lists.freedesktop.org/archives/libreoffice/2019-March/082286.html
Руб. за сто, что Питоньяк
Любит водку и коньяк!
Потому что мне, без оных, -
Не понять его никак...