просмотр таблицы с меняющимися данными, запоминание и выделение тек строки |
Здравствуйте, гость ( Вход | Регистрация )
просмотр таблицы с меняющимися данными, запоминание и выделение тек строки |
Tonal |
9.2.2012, 9:45
Сообщение
#11
|
Активный участник Группа: Участник Сообщений: 452 Регистрация: 6.12.2007 Из: Новосибирск Пользователь №: 34 Спасибо сказали: 69 раз(а) Репутация: 17 |
Про Т2 и прзиционирование:
Что-то я не очень понял, если для Т2 используется та же структура, то почему не использовать ID для позиционирования. В противном случае не ясно что делать при наличии 2х и более одинаковых (или очень близких) значений PARAM в массиве. Как-то ты же должна задавать на этом массиве порядок/сортировку для выборки. Иначе можно получить данные совершенно не в том порядке и позиционирование будет бессмысленно, потому что в "уже просмотренные" попадут совсем ни те данные. Если порядок таки задан - то и запоминать позицию нужно ориентируясь на него. Пример: Цитата Поступает 1-й раз массив со значениями PARAM (1.23, 2.34, 300.45, 445.00), оператор начинает его просмотр, делает текущей запись со значением 300.45, Куда позиционироватся, если следующий запрос вернёт: PARAM (445.00, 2.34, 300.45, 1.23) или PARAM (1.23, 2.34, 300.45, 300.45, 300.45, 300.45, 445.00) или PARAM (3.38, 1.32, 300.45001, 455.01, 300.44999) И что это будет значить для оператора? Про способы использования: 1. Я имел в виду, что ты всё оставляешь как сейчас, но при генерации текста запроса вместо данных подставляешь заполнители (например символы "?"). После этого биндишь переменные (как в справке по QSqlQuery) В этом случае данные в сервер попадают минуя преображение в строку у тебя в коде и обратно на сервере. Меньше преобразований - меньше накапливается ошибок. Причём объект QSqlQuery после prepare можно не удалять, а сохранить где-то, и для следующего запроса только подставить (забиндить) новые параметры. В случае Т3 можно сделать кеширование. Например QMap где ключом будет состав изменяемых полей а значением - препарированный запрос. 2. В триггере перед изменением можно проверить - если поле опциональное, восстановить предыдущее значение, например:
3. Всё то же самое - определение состава обновляемых полей и выбор варианта запроса. Или его можно собрать в процедуре и выполнить через execute statiment. Практически тот же вариант 1, но перенесённый на сервер. Кстати, что делается в случае если param == null_double для записи с новым ID? Ну и я бы стал делать вариант 2 и 3 только в том случае, если данные в базу могут поступать из разных приложений. В противном случае это дополнительное усложнение схемы данных. |
|
|
Steklova Olga |
9.2.2012, 21:04
Сообщение
#12
|
Участник Группа: Участник Сообщений: 198 Регистрация: 27.9.2011 Из: Санкт-Петербург Пользователь №: 2912 Спасибо сказали: 5 раз(а) Репутация: 4 |
Привет! Пишу на этот раз сразу несколько сообщений.
09.02.2012 часть 1 уточнения про Т2 1) не ясно что делать при наличии 2х и более одинаковых (или очень близких) значений PARAM в массиве У меня для Т2 предполагается, что в одном и том же массиве не могут приходить одинаковые значения.Близкими значения могут быть, но при этом они все равно будут разными. 2) Как-то ты же должна задавать на этом массиве порядок/сортировку для выборки. Сортировка Т2 установлена всегда по возрастанию значения PARAM.3) Цитата - на 300.45, так как массив с моей точки зрения не изменился, ведь он всегда сортируется по возрастанию,Поступает 1-й раз массив со значениями PARAM (1.23, 2.34, 300.45, 445.00), оператор начинает его просмотр, делает текущей запись со значением 300.45, Куда позиционироватся, если следующий запрос вернёт: PARAM (445.00, 2.34, 300.45, 1.23) или - такой массив не может поступить,PARAM (1.23, 2.34, 300.45, 300.45, 300.45, 300.45, 445.00) или - на 1.32 (на min значение), так как значение 300.45 с моей точки зрения изменилось.PARAM (3.38, 1.32, 300.45001, 455.01, 300.44999) 09.02.2012 часть 2 ----------------------------------------------------------------------------- уточненная постановка задачи !!! 4) Пока разбиралась с программой, уточнила постановку задачи. Она оказалась проще, чем я рассчитывала. Поняла ее так. Есть цикл работы, например, 5 сек. Он может измениться. Есть "анализатор" и несколько "устройств". Со всеми устройствами анализатор работает одинаково. Анализатор (с каким-то своим внутренним циклом) собирает данные от устройства, на основе этих данных рассчитывает массив значений параметра PARAM этого устройства и посылает этот массив мне (не чаще раза в цикл работы 5 сек) для сохранения в БД. (Поэтому, в Т2 у меня есть еще поле с номером устройства TO_OBJ_ID, внешний ключ.) Передача массива для устройства в каждом рабочем цикле не является обязательной. Если анализатор насчитал новые значения параметра для устройства, то он передает массив. Если массив для устройства "устаканился" (определился с нужной точностью, а данные от устройства в последнее время резко не менялись), то анализатор приостанавливает для этого устройства передачу массива в БД. Получается, что массив для Т2 будет поступать ко мне только при его изменении. И я была не права, когда сказала, что Данные разных массивов: - могут полностью совпадать, И тогда логичнее, как мне кажется, был бы следующий вариант А. А) Вариант для случая, когда массив будет поступать ко мне только при его изменении. При поступлении очередного массива - удалить старый массив, добавить новый массив, сделать текущей первую запись. (Не "отлавливать блох", проверяя, осталось ли в новом массиве значение PARAM, бывшее текущим. Тогда и оператор сразу увидит, что массив изменился, а не будет пребывать в неведении.) Что-то я не очень понял, если для Т2 используется та же структура, то почему не использовать ID для позиционирования. - Когда я раньше, при поступлении очередного массива проверяла, какая запись была до этого текущей, я не могла проверять ID, так как я удаляю старый массив вместе со всеми этими ID и добавляю новый. Ведь ID - автоинкрементное поле. - Теперь, в варианте А, в соотв. с новым пониманием постановки задачи, можно будет для позиционирования использовать ID вместо PARAM. ID - автоинкрементное поле. - В Т1 можно позиционироваться по ID, так как там записи не удаляются. Б) Вариант для случая, когда массив будет поступать ко мне каждый цикл, даже если массив не изменился. Этот вариант для моей программы, получается, не нужен, но остается интерен мне теоретически, на будущее. При поступлении очередного массива - отсортировать новый массив по возрастанию PARAM (?), - сравнить новый массив со старым (?), - если они абсолютно совпадают, то оставить все как было, - если массивы хоть немного отличаются, то удалить старый массив, добавить новый массив, сделать текущей первую запись. Здесь тоже можно будет для позиционирования использовать ID вместо PARAM. ID - автоинкрементное поле. Сообщение отредактировал Steklova Olga - 10.2.2012, 10:15 |
|
|
Steklova Olga |
10.2.2012, 10:14
Сообщение
#13
|
Участник Группа: Участник Сообщений: 198 Регистрация: 27.9.2011 Из: Санкт-Петербург Пользователь №: 2912 Спасибо сказали: 5 раз(а) Репутация: 4 |
09.02.2012 часть 3
5) Кстати, что делается в случае если param == null_double для записи с новым ID? Если для записи в Т3 поступит структурас id, которого еще не было в таблице, и с param == null_double, то в Т3 будет добавлена запись. В INSERT я укажу поле ID, равное id, и не укажу поле PARAM. Неуказанное поле, насколько я понимаю, по умолчанию окажется == NULL. 6) Про способы использования: Это ясно (для Т1).1. Я имел в виду, что ты всё оставляешь как сейчас, но при генерации текста запроса вместо данных подставляешь заполнители (например символы "?"). После этого биндишь переменные (как в справке по QSqlQuery) В этом случае данные в сервер попадают минуя преображение в строку у тебя в коде и обратно на сервере. Меньше преобразований - меньше накапливается ошибок. Причём объект QSqlQuery после prepare можно не удалять, а сохранить где-то, и для следующего запроса только подставить (забиндить) новые параметры. 7) уточняющий вопрос про prepare и addBindValue Поля таблицы T2: ID INTEGER NOT NULL (PK, автоинкрементное поле), N записи, TO_OBJ_ID INTEGER NOT NULL (FK), N устройства, PARAM DOUBLE PRECISION NOT NULL, значение параметра. Таблица Т2 может содержать [0..200] значений PARAM для каждого TO_OBJ_ID. А для обработки поступившего массива со значениями PARAM для одного конкретного TO_OBJ_ID вариант а) лучше, чем б) и в)? (TO_OBJ_ID здесь одно и то же, PARAM - разные)
8 ) В случае Т3 можно сделать кеширование. Вы предлагаете использовать QMap<K, T>, структуру данных, которая содержит пары ключ-значение,Например QMap где ключом будет состав изменяемых полей а значением - препарированный запрос. упрядоченные по возрастанию ключей? Я понимаю так, что это будет QMap<QString, QVariant> map; где QString - наименование поля таблицы, QVariant - значения поля таблицы. Вставляем в map только поступившие в Rec значения полей и их наименования, для чего для каждого поля проверяем, равно ли его значение константе null_... для соотв. типа поля. Из полученного списка keys получаем часть строки запроса с названиями полей, дополняем строку соотв. кол-вом символов '?', потом в цикле делаем addBindValue, занося в запрос значения полей из полученного списка values. 9) То, что Вы написали нужно проверять в триггере, понятно. Только я пока не создавала таких триггеров в базе, а делала проверки в тексте Qt. 10) С хранимками еще совсем не разбиралась. 11) Ну и я бы стал делать вариант 2 (с триггерами) и 3 (с хранимками) только в том случае, Уф, успокоили, что это необязательно для моего случая.если данные в базу могут поступать из разных приложений. В противном случае это дополнительное усложнение схемы данных. Мне еще не доводилось писать базы, данные в которые прямо записываются из разных приложений. Сама из Qt-программы пишу данные в БД, выдаю результаты запросов к БД другим людям, модули которых вместе с моими находятся в одном приложении. Уважаю за терпение дочитавших до конца! Простите студента за многословие. Сообщение отредактировал Steklova Olga - 10.2.2012, 10:16 |
|
|
Tonal |
10.2.2012, 12:00
Сообщение
#14
|
Активный участник Группа: Участник Сообщений: 452 Регистрация: 6.12.2007 Из: Новосибирск Пользователь №: 34 Спасибо сказали: 69 раз(а) Репутация: 17 |
Т. е. с позиционированием ты разобралась.
Могу только добавить, что раз есть порядок, то можно позиционироваться на первый элемент больший или равный текущему или на последний меньший или равный, на выбор. 5. Неуказанное в insert-е поле заполняется значением по умолчанию для этого поля, которое можно указать при создании таблицы (или при создании домена). Если значение по умолчанию не указано, подставляется null. 6. Тут возможны варианты с транзакциями: сохраняется ли препарированность между транзакциями или для новой транзакции нужно препарить запросы по новой? Если мне склероз не изменяет, Firebird в последних версиях не требовал переподготавливать запросы каждый раз, но не знаю как к этому относится драйвер в Qt. 7. Есть ещё вариант а' - использовать биндинг по имени или номеру. Тогда obj_id можно забиндить 1 раз перед циклом. Я бы выбрал его. 8. Ну, если совсем втупую то примерно так (псевдокод на псевдопитоне):
Хотя можно вместо списка с QVariant использовать словарь и биндить по именам. Главная идея, что сам запрос для конкретной конфигурации полей ты создаёшь только если она появилась и лишь один раз. |
|
|
Steklova Olga |
10.2.2012, 17:01
Сообщение
#15
|
Участник Группа: Участник Сообщений: 198 Регистрация: 27.9.2011 Из: Санкт-Петербург Пользователь №: 2912 Спасибо сказали: 5 раз(а) Репутация: 4 |
Привет!
6. Цитата сохраняется ли препарированность запроса между транзакциями (Firebird, Qt) я тоже не знаю.7. Цитата Есть ещё вариант а' - использовать биндинг по имени или номеру. Тогда obj_id можно забиндить 1 раз перед циклом. Я бы выбрал его. То, что надо! Нашла тут примеры разных вариантов для prepare и bindValue.
//Заодно поняла, как забиндить значения NULL в поля разного типа.
8. Спасибо, Tonal, за пример. Еще разбираюсь с ним... |
|
|
Текстовая версия | Сейчас: 26.11.2024, 1:48 |