Форум поддержки пользователей. LibreOffice, Apache OpenOffice, OpenOffice.org

Форум поддержки пользователей. LibreOffice, Apache OpenOffice, OpenOffice.org

23 Июнь 2017, 16:49 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
Новости: Часто задаваемые вопросы по LibreOffice и Apache OpenOffice.org
 
   Начало   Помощь Поиск Войти Регистрация    задать вопрос  
Страниц: 1 2 »   Вниз
  Печать  
Автор Тема: [РЕШЕНО] Трудности при обновлении (update) объекта RowSet  (Прочитано 684 раз)
0 Пользователей и 1 Гость смотрят эту тему.
ost
Пользователь
**
Offline Offline

Сообщений: 62


« Стартовое сообщение: 26 Март 2017, 17:15 »

Доброго.

Есть база данных SQLite, содержащая таблицу со многими полями среди значений которых встречаются пустые строки (''). Начитался, что это плохо и вместо них правильнее использовать NULL.

База доступна в LibreOffice Calc через ODBC.
Для решения задачи по замене всех пустых строк ('') на NULL написал такой макрос (здесь он упрощен за счет удаления цикла по перебору всех полей таблицы) на StarBasic, который не работает:
Код:
Sub Service3

RowSet = createUnoService("com.sun.star.sdb.RowSet") ' создаем
RowSet.DataSourceName = "SQLite_LO_test" ' указываем зарегистрированную базу данных, без *.odb!
RowSet.CommandType = com.sun.star.sdb.CommandType.COMMAND ' вызываем команду
RowSet.EscapeProcessing=FALSE

RowSet.Command = "SELECT uSumZ_VzOmsFF FROM U_tmp WHERE uSumZ_VzOmsFF=''"
RowSet.execute() ' выполняем

rowSet.Last 'мотнули курсор к концу
RowEND=(rowSet.RowCount())
rowSet.First ' вернулись к первой записи

If RowEND>0 Then
While RowSet.next() 'перебираем результат sql-запроса
RowSet.UpdateInt("uSumZ_VzOmsFF", NULL)
Wend
RowSet.Update()
End If

End Sub

Ругается на несовместимые типы в ходе выполнения строки внутри While -Wend . Понимаю, что "RowSet.UpdateInt", в данном случае, глупость, но как сделать правильно не знаю. Научите, пожалуйста.
Еще просьба. Поделитесь, пожалуйста, мнением о правильности/неправильности использования "пустой строки"/NULL для обозначения отсутствующих значений.
« Последнее редактирование: 28 Март 2017, 12:33 от ost » Записан
rami
Гуру
*******
Offline Offline

Пол: Мужской
Сообщений: 2 101


MacBook Pro, LibreOffice и Apache OpenOffice


« Ответ #1: 26 Март 2017, 17:46 »

Ругается на несовместимые типы в ходе выполнения строки внутри While -Wend . Понимаю, что "RowSet.UpdateInt", в данном случае, глупость, но как сделать правильно не знаю. Научите, пожалуйста.
Правильно ругается. В строке кода RowSet.UpdateInt("uSumZ_VzOmsFF", NULL) оба параметра должны быть числовые:
1. индекс столбца, а не его имя "uSumZ_VzOmsFF"
2. число, а не NULL

Попробуйте заменить RowSet.UpdateInt("uSumZ_VzOmsFF", NULL) на RowSet.updateNull(НомерСтолбца)

Я не совсем понимаю, зачем вы это делаете Непонимающий Отсутствующие значения всегда NULL.

Используйте тестовый файл.
« Последнее редактирование: 26 Март 2017, 18:00 от rami » Записан

economist
Ветеран
*****
Offline Offline

Сообщений: 561


« Ответ #2: 27 Март 2017, 10:34 »

Немного off про Null. Попробую от него отговорить в SQLite. И почему пустые строки это плохо?
SQLite вообще все хранит как текст, и Null вместо "" - тотально делать нет смысла.

Null - это полная неизвестность. "" - это известная пустота. Если рассуждать на примере ИНН физлица - то Null - это неизвестный ИНН (хотя с рождения он есть у всех), а ИНН="" - просто незаполненный. Смысл этой фразы в том, что Null - это большая пустота, чем "".

Настоящие проблемы возникнут при объединении таблиц с Null, ведь:

1) NULL не равно ни логическому значению FALSE, ни пустой строке "", ни 0 (нулю).
2) При сравнении NULL с любым значением будет получен результат NULL, а не FALSE и не 0.
3) NULL не равно NULL, а равно пустой строке "".

То есть вместо ="" и <>"" - нужно будет обрабатывать втрое больше сущностей.
Поэтому уж лучше везде пустые строки, чем Null. Они, эти Null, все равно будут попадаться в работе.
Например, во всех внешних соединениях таблиц - будут "дыры" (то есть поля набора данных, в которых нет соответствующей записи), и они заполнятся значением NULL. Это то же самое, что значение #Н/Д в функции =ВПР()/=VLOOKUP в Excel/Calc.

А еще если в поле есть хоть один Null - индекс по полю в SELECT-запросах использоваться не будет что означает 4-х кратное удлинение времени их выполнения.

И традиционный, от меня, камушек в огород ППО от MS. Многие не знают, а когда узнают - то сильно удивляются тому что движки Access 2000 и Access 2003 (JET/ACE) - по-разному отрабатывают Null, хотя расширение файла базы данных ОДИНАКОВО - *.mdb.

То есть один и то же запрос на разных компьютерах (в разных ОС) - может выполняться с одним и тем же файлом по-разному! Это апофеоз интероперабельности от Microsoft, который лично мне стоил нескольких суток нервотрепки.
Записан

Руб. за сто, что Питоньяк
Любит водку и коньяк!
Потому что мне, без оных, -
Не понять его никак...
ost
Пользователь
**
Offline Offline

Сообщений: 62


« Ответ #3: 27 Март 2017, 15:39 »

rami,
Спасибо. Пустые строки вместо NULL образовались в ходе импорта таблиц LO Calc в базу SQLite.

economist,
Благодарю за образность. Разница между NULL и пустой строкой теперь зрима. В этой связи подумаю, что оставить в базе.

Между тем макрос
Код:
Sub Service3

RowSet = createUnoService("com.sun.star.sdb.RowSet") ' создаем
RowSet.DataSourceName = "SQLite_LO_test" ' указываем зарегистрированную базу данных, без *.odb!
RowSet.CommandType = com.sun.star.sdb.CommandType.COMMAND ' вызываем команду
RowSet.EscapeProcessing=FALSE

RowSet.Command = "SELECT uSumZ_VzOmsFF FROM U_tmp WHERE uSumZ_VzOmsFF=''"
RowSet.execute() ' выполняем

rowSet.Last 'мотнули курсор к концу
RowEND=(rowSet.RowCount())
rowSet.First ' вернулись к первой записи

If RowEND>0 Then
While RowSet.next() 'перебираем результат sql-запроса
RowSet.UpdateNull(1)
Wend
RowSet.Update()
End If

End Sub
во время исполнения выдает ошибку на строке "RowSet.Update()" =(
Что же я делаю не так?
Записан
rami
Гуру
*******
Offline Offline

Пол: Мужской
Сообщений: 2 101


MacBook Pro, LibreOffice и Apache OpenOffice


« Ответ #4: 27 Март 2017, 16:12 »

во время исполнения выдает ошибку на строке "RowSet.Update()" =(
Что же я делаю не так?
Нужно указать что обновляем, попробуйте заменить на RowSet.updateRow()
Записан

ost
Пользователь
**
Offline Offline

Сообщений: 62


« Ответ #5: 27 Март 2017, 16:14 »

Получаю следующее сообщение:

Ошибка времени выполнения BASIC.
Вызвано исключение
Type: com.sun.star.sdbc.SQLException
Message: Ошибка функциональной последовательности..
Записан
rami
Гуру
*******
Offline Offline

Пол: Мужской
Сообщений: 2 101


MacBook Pro, LibreOffice и Apache OpenOffice


« Ответ #6: 27 Март 2017, 16:25 »

Пробуйте RowSet.refreshRow()
Записан

ost
Пользователь
**
Offline Offline

Сообщений: 62


« Ответ #7: 27 Март 2017, 16:37 »

Макрос отрабатывает без ошибок, но данные в базе не обновляются. =(
Записан
rami
Гуру
*******
Offline Offline

Пол: Мужской
Сообщений: 2 101


MacBook Pro, LibreOffice и Apache OpenOffice


« Ответ #8: 27 Март 2017, 16:45 »

Макрос отрабатывает без ошибок, но данные в базе не обновляются. =(
Какие данные должны обновиться? Сферические кони в вакууме Непонимающий Или хотите вместо пустой ячейки увидеть в ней надпись NULL Непонимающий
Записан

ost
Пользователь
**
Offline Offline

Сообщений: 62


« Ответ #9: 27 Март 2017, 16:51 »

В точности так. Только не кони и не в вакууме, а вместо пустой строки надпись NULL. Именно ее показывает менеджер SQLiteStudio, если "видит" NULL в базе.
Записан
rami
Гуру
*******
Offline Offline

Пол: Мужской
Сообщений: 2 101


MacBook Pro, LibreOffice и Apache OpenOffice


« Ответ #10: 27 Март 2017, 16:56 »

А если закрыть базу с сохранением и снова открыть? (Жаль, что я не могу сам всё проверить)
Записан

ost
Пользователь
**
Offline Offline

Сообщений: 62


« Ответ #11: 27 Март 2017, 17:11 »

Пробовал. Не помогает.
Возможно, как то поспособствует sql-предложение, формирующее тестовую базу (файл tmp.sql) или, собственно, база (файл test.sqlite3)

Макрос, который призван заменить все пустые строки на NULL в поле "oper1"

Код:
Sub Service3

RowSet = createUnoService("com.sun.star.sdb.RowSet") ' создаем
RowSet.DataSourceName = "SQLite_LO_test" ' указываем зарегистрированную базу данных, без *.odb!
RowSet.CommandType = com.sun.star.sdb.CommandType.COMMAND ' вызываем команду
RowSet.EscapeProcessing=FALSE

RowSet.Command = "SELECT oper1 FROM temp_table WHERE oper1=''"
RowSet.execute() ' выполняем

rowSet.Last 'мотнули курсор к концу
RowEND=(rowSet.RowCount())
rowSet.First ' вернулись к первой записи

If RowEND>0 Then
While RowSet.next() 'перебираем результат sql-запроса
RowSet.UpdateNull(1)
Wend
RowSet.RefreshRow()
End If

End Sub

Базу SQLite_LO_test.odb надо, конечно, создать, зарегистрировать ее в LibreOffice и прицепить к ней через odbc-драйвер (прямая ссылка на драйвер для win64 http://www.ch-werner.de/sqliteodbc/sqliteodbc_w64.exe) базу test.sqlite3.

Прошу прощения за сумбур.

UPD: а форум не дает прицеплять ни файлы *.sql, ни файлы *.sqlite3 =(
UPD: Выложил сюда https://yadi.sk/d/mvBk63kx3H4oVs архив 7zip с двумя этими файлами.

« Последнее редактирование: 17 Апрель 2017, 17:54 от ost » Записан
rami
Гуру
*******
Offline Offline

Пол: Мужской
Сообщений: 2 101


MacBook Pro, LibreOffice и Apache OpenOffice


« Ответ #12: 27 Март 2017, 17:18 »

...драйвер для win64...
Мне это не поможет, у меня Мак.


Записан

ost
Пользователь
**
Offline Offline

Сообщений: 62


« Ответ #13: 27 Март 2017, 17:25 »

Жаль. =) Спасибо за время. Буду потихоньку биться головой в интернеты. Глядишь, чего-нибудь накопаю.
Записан
economist
Ветеран
*****
Offline Offline

Сообщений: 561


« Ответ #14: 27 Март 2017, 17:39 »

А если сразу выполнить:
 
UPDATE U_tmp SET uSumZ_VzOmsFF=null WHERE uSumZ_VzOmsFF=''


Объекты RowSet/рекордсэты полезны, если нужно курсором ходить туда-сюда (т.е. seek-ать). Здесь же задача просто за-Null-ить всё пустое?   
« Последнее редактирование: 27 Март 2017, 17:42 от economist » Записан

Руб. за сто, что Питоньяк
Любит водку и коньяк!
Потому что мне, без оных, -
Не понять его никак...
Страниц: 1 2 »   Вверх
  Печать  
 
Перейти в:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.21 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!