![]() |
Здравствуйте, гость ( Вход | Регистрация )
![]() |
Steklova Olga |
![]()
Сообщение
#1
|
![]() Участник ![]() ![]() Группа: Участник Сообщений: 198 Регистрация: 27.9.2011 Из: Санкт-Петербург Пользователь №: 2912 Спасибо сказали: 5 раз(а) Репутация: ![]() ![]() ![]() |
Всем привет!
![]() Есть у меня две таблицы БД: T1 и T2, в каждой есть поля ID INTEGER (PK, автоинкрементное) и PARAM FLOAT. Для работы с таблицами использую QSqlTableModel и QTableView. Во время работы программы в таблицу T1 записи только добавляются. Организую заполнение и просмотр следующим образом: - при поступлении первой записи добавляю ее в таблицу БД, выполняю select для модели, первую строку таблицы делаю текущей, запоминаю соотв. значение ID, - при поступлении следующей записи добавляю ее в таблицу БД, выполняю select для модели, строку с запомненным ID делаю текущей, делаю скроллинг отображения для обеспечения видимости текущей строки, - при изменении текущей строки оператором запоминаю значение ID. Тут все OK. А вот с таблицей T2 посложнее... Во время работы программы, периодически (вероятно, не чаще, чем 1 раз в 5 сек), для занесения в таблицу T2 приходит сразу целый массив записей (размер массива - от одной до 200 записей). Мне надо хранить в БД данные только последнего массива. Данные разных массивов: - могут полностью совпадать, - могут отличаться всеми значениями, - могут отличаться несколькими значениями, - могут отличаться количеством значений. Организую заполнение и просмотр следующим образом: - при поступлении первого массива добавляю поступившие записи в таблицу БД, выполняю select для модели, первую строку таблицы делаю текущей, - при поступлении следующего массива удаляю все записи из таблицы БД, добавляю поступившие записи в таблицу БД, выполняю select для модели, первую строку таблицы делаю текущей (пока так). Как здесь просматривать таблицу с запоминанием и выделением текущей строки? 1) Запоминать ID текущей строки? Здесь это не поможет, так как поле автоинкрементное. 2) Сделать поле ID не автоинкрементным, не удалять предыдущий массив и добавлять новый, а обновлять массив? Этот вариант мне совсем не нравится, по-моему, он очень сложный. 3) Запоминать PARAM текущей строки, а при поступлении следующего массива искать в нем запись с запомненным PARAM и делать ее текущей? А если такая не найдется, то делать текущей первую. Но для этого придется сравнивать значения типа FLOAT, видимо используя какую-то точность сравнения. Или так и надо? ![]() Других вариантов не придумала. У кого какие мысли есть по этому поводу? Спасибо. |
|
|
![]() |
ilyabvt |
![]()
Сообщение
#2
|
Активный участник ![]() ![]() ![]() Группа: Участник Сообщений: 297 Регистрация: 23.6.2011 Пользователь №: 2765 Спасибо сказали: 45 раз(а) Репутация: ![]() ![]() ![]() |
Цитата 3) Запоминать PARAM текущей строки, а при поступлении следующего массива искать в нем запись с запомненным PARAM и делать ее текущей? А если такая не найдется, то делать текущей первую. Но для этого придется сравнивать значения типа FLOAT, видимо используя какую-то точность сравнения. Или так и надо? Да так и надо. Насчет точности не надо париться, если значение другое то оно и должно восприниматься как другое. Сравнивайте также как вы бы сравнивали целочисленные значения. |
|
|
Steklova Olga |
![]()
Сообщение
#3
|
![]() Участник ![]() ![]() Группа: Участник Сообщений: 198 Регистрация: 27.9.2011 Из: Санкт-Петербург Пользователь №: 2912 Спасибо сказали: 5 раз(а) Репутация: ![]() ![]() ![]() |
Цитата Сравнивайте также как вы бы сравнивали целочисленные значения. А это во всех СУБД срабатывает? Я работаю сейчас с Firebird.
|
|
|
ilyabvt |
![]()
Сообщение
#4
|
Активный участник ![]() ![]() ![]() Группа: Участник Сообщений: 297 Регистрация: 23.6.2011 Пользователь №: 2765 Спасибо сказали: 45 раз(а) Репутация: ![]() ![]() ![]() |
Цитата Сравнивайте также как вы бы сравнивали целочисленные значения. А это во всех СУБД срабатывает? Я работаю сейчас с Firebird.С Firebird не работал, но честно говоря не представляю, почему оно должно вдруг не сработать. Может вы меня не так поняли? Я не имел ввиду что нужно конвертировать в целочисленные, я имел ввиду что принцип их сравнения одинаковый |
|
|
Steklova Olga |
![]()
Сообщение
#5
|
![]() Участник ![]() ![]() Группа: Участник Сообщений: 198 Регистрация: 27.9.2011 Из: Санкт-Петербург Пользователь №: 2912 Спасибо сказали: 5 раз(а) Репутация: ![]() ![]() ![]() |
Цитата Я не имел ввиду что нужно конвертировать в целочисленные, я имел ввиду что принцип их сравнения одинаковый Спасибо, я так и поняла.
|
|
|
Steklova Olga |
![]()
Сообщение
#6
|
![]() Участник ![]() ![]() Группа: Участник Сообщений: 198 Регистрация: 27.9.2011 Из: Санкт-Петербург Пользователь №: 2912 Спасибо сказали: 5 раз(а) Репутация: ![]() ![]() ![]() |
Однако не все так тривиально...
1) Зачем-то же написана функция qFuzzyCompare: пример
2) Оказалось, что точности FLOAT для поля PARAM в таблице БД мне не хватает, заменила на DOUBLE PRECISION. 3) После этого не могла понять, почему - из IBExpert получается добавить запись со значением PARAM, равным 15000.0000000151 (при этом в БД оказывается записанным 15000.0000000150994), - а из моей программы при добавлении записи со значением PARAM, равным 15000.0000000151 в БД оказывается записанным 15000. Дело было в том, что при формировании строки запроса на добавление записи в таблицу БД я переводила значение в строку с помощью setNum, но использовала prec = 6 (по умолчанию). Заменила s.setNum(d, 'f') на s.setNum(d, 'f', 10). Проверила работу, указав в Qt::DisplayRole для PARAM формат
4) Остался вопрос, какое "универсальное" (для любого поля типа DOUBLE PRECISION) значение prec лучше указать у меня в setNum при формировании запроса в общем случае, если таких параметров как PARAM у меня несколько, и я не знаю заранее их точный диапазон и точность, только знаю, что DOUBLE PRECISION подходит. prec = 15 что-ли? ![]() |
|
|
Tonal |
![]()
Сообщение
#7
|
![]() Активный участник ![]() ![]() ![]() Группа: Участник Сообщений: 452 Регистрация: 6.12.2007 Из: Новосибирск Пользователь №: 34 Спасибо сказали: 69 раз(а) Репутация: ![]() ![]() ![]() |
Дело было в том, что при формировании строки запроса на добавление записи в таблицу БД я переводила значение в строку с помощью setNum, но использовала prec = 6 (по умолчанию). Заменила s.setNum(d, 'f') на s.setNum(d, 'f', 10). Проверила работу, указав в Qt::DisplayRole для PARAM формат
4) Остался вопрос, какое "универсальное" (для любого поля типа DOUBLE PRECISION) значение prec лучше указать у меня в setNum при формировании запроса в общем случае, если таких параметров как PARAM у меня несколько, и я не знаю заранее их точный диапазон и точность, только знаю, что DOUBLE PRECISION подходит. prec = 15 что-ли? ![]() Используй параметризированные запросы и биндинг переменных. Тогда тебе не нужно будет руками форматировать данные и натыкатся на точность. ![]() Ну и почитай про числа с плавающей запятой - будешь лучше ориентироватся. ![]() По поводу стартового вопроса было бы неплохо уточнить, зачем нужна вообще выделенная строка в таблице T2, если данные там постоянно меняются. Какую она несёт функциональную нагрузку? Ежели это понять, можно дальше думаьт про механизм обеспечения постоянства этого выделения. |
|
|
Steklova Olga |
![]()
Сообщение
#8
|
![]() Участник ![]() ![]() Группа: Участник Сообщений: 198 Регистрация: 27.9.2011 Из: Санкт-Петербург Пользователь №: 2912 Спасибо сказали: 5 раз(а) Репутация: ![]() ![]() ![]() |
1)
Цитата Используйте биндинг переменных Понятно, как использовать биндинг, если надо добавить или обновить запись, а в запросе указать значения всех полей записи (конечно, кроме генератора).А вот другой случай... И как Вы здесь прикрутите биндинг? Например, есть таблица БД с полями ID (INTEGER, PK), PARAM (DOUBLE, необяз), FINT1 (INTEGER, необяз), FINT2 (INTEGER, необяз), FSTR (VARCHAR(20), необяз). Для записи или обновления данных таблицы поступает структура, содержащая значения полей записи.
Если поступает запись с новым id, то добавляем ее в таблицу. Если поступает запись со старым id, то обновляем соотв. запись в таблице. При формировании запросов из числа необязательных полей указываем только те, значения которых поступили в структуре, остальные значения полей должны остаться без изменения. Используем следующие признаки того, что необязательные поля не поступили: - для поля PARAM: param = null_double, - для поля FINT1: fint1 = null_qint32, - для поля FINT2: fint2 = null_qint32, - для поля FSTR: str.isEmpty(). Сейчас я использую функцию, формирующую часть строки запроса для записи или обновления данных любой таблицы БД. Эта часть строки запроса имеет вид: "(<список наименований полей записи, поступивших в структуре>) VALUES (<список соотв. значений полей>)". Входным параметром функции является вектор. Элемент вектора - структура, содержащая информацию о поле таблицы, в том числе
2) Цитата По поводу стартового вопроса было бы неплохо уточнить, зачем нужна вообще выделенная строка в таблице T2, если данные там постоянно меняются. Дело в том, что - таблица предназначена для просмотра текущего массива оператором, - для отображения таблицы на экране отведено не так много места, чтобы видеть сразу все записи, тем более, если их 200, - не каждые 5 сек все значения массива меняются, - Если оператор начнет скроллинг таблицы, а в это время, например, обновится массив только в одном значении (не в текущей строке), хочется, чтобы оператор спокойно остался на прежней текущей строке, а измененную строку он увидит, продолжив скроллинг. Если не запоминать текущую строку, то невозможно будет спокойно просматривать массив, при каждом обновлении массива текущей будет становится первая строка. Это будет даже в том случае, если данных разных массивов будут полностью совпадать, ведь я же удаляю старый массив и добавляю новый. Сообщение отредактировал Steklova Olga - 7.2.2012, 14:57 |
|
|
Tonal |
![]()
Сообщение
#9
|
![]() Активный участник ![]() ![]() ![]() Группа: Участник Сообщений: 452 Регистрация: 6.12.2007 Из: Новосибирск Пользователь №: 34 Спасибо сказали: 69 раз(а) Репутация: ![]() ![]() ![]() |
1)
Ты же вроде бы писала, что T2 ты очищаешь и вставляешь данные по новой. Т. е. в этом случае у тебя только 1 sql для удаления и 1 для вставки. Как использовать биндинг вроде очевидно ![]() Но даже если рассматривать более общий случай, который ты описываешь, то можно использовать биндинг несколькими способами: 1. Генерить параметрический sql (без данных) для каждого случая. 2. Использовать всегда полный insert/update с биндингом а в триггерах разбираться какие реально поля изменяются 3. Вынести логику разборок с данными на сервер - в сохранённую процедурку. Во всех 3х случаях кроме первого дополнительно к удобству работы с данными получаем ускорение на единственной генерации запроса клиентом и подготовке (препарации) запроса сервером. Да и в 1ом случае можно добавить систему кеширования позволяющую воспользоваться этими преимуществами. ![]() 2) Почему тогда просто не привязываться к порядковому номеру и верхней видимой строке? Других-то ориентиров у пользователя всё равно нету... |
|
|
Steklova Olga |
![]()
Сообщение
#10
|
![]() Участник ![]() ![]() Группа: Участник Сообщений: 198 Регистрация: 27.9.2011 Из: Санкт-Петербург Пользователь №: 2912 Спасибо сказали: 5 раз(а) Репутация: ![]() ![]() ![]() |
Таблицы Т1 и Т2 - это один пример,
таблица БД с полями ID, PARAM, FINT1, FINT2, FSTR - это таблица Т3, другой пример. В T1 записи только добавляются, в T2 удаляются старые записи и добавляются новые, в Т3 записи добавляются или обновляются в зависимости от поступившего ID (UPDATE OR INSERT INTO T3 ... MATCHING (ID)). Ты же вроде бы писала, что T2 ты очищаешь и вставляешь данные по новой. Т. е. в этом случае у тебя только 1 sql для удаления и 1 для вставки. ДаКак использовать биндинг вроде очевидно Так как в Т2 все поля обязательные, то для Т2 - да, очевидно.Если оператор начнет скроллинг таблицы, а в это время, например, обновится массив только в одном значении (не в текущей строке), хочется, чтобы оператор спокойно остался на прежней текущей строке, а измененную строку он увидит, продолжив скроллинг. Здесь я говорю о Т2. А под словом "обновится" я подразумеваю не то, что я делаю таблице UPDATE, а то, что меняются данные поступающего массива, например.Если не запоминать текущую строку, то невозможно будет спокойно просматривать массив, при каждом обновлении массива текущей будет становится первая строка. Это будет даже в том случае, если данных разных массивов будут полностью совпадать, ведь я же удаляю старый массив и добавляю новый. Поступает 1-й раз массив со значениями PARAM (1.23, 2.34, 300.45, 445.00), оператор начинает его просмотр, делает текущей запись со значением 300.45, поступает 2-й раз массив со значениями PARAM (1.23, 2.34, 300.45, 1888.00), <здесь я перерисовываю таблицу, но хочу, чтобы текущей осталась запись со значением 300.45>, поступает 3-й раз массив со значениями PARAM (1.23, 2.34, 300.45, 1888.00, 2001.45), <здесь я перерисовываю таблицу, но хочу, чтобы текущей осталась запись со значением 300.45>. Почему тогда просто не привязываться к порядковому номеру и верхней видимой строке? В соотв. с выше написанным, мне надо привязываться не к ID, а к PARAM, ориентир - это PARAM.Других-то ориентиров у пользователя всё равно нету... Но я-то хочу во всех случаях (для Т1, Т2, Т3 и любых других моих таблиц, в том числе с любым количеством необяз. полей) использовать одну функцию формирования запроса. Поэтому я и пишу s.setNum(d, 'f', 15). Читаю дальше Ваши предложения... Но даже если рассматривать более общий случай, который ты описываешь, то можно использовать биндинг несколькими способами: Если я Вас правильно поняла, то в этом случае для Т3, в которой четыре необяз. поля, придется писать 16 параметр. sql (все комбинации).1. Генерить параметрический sql (без данных) для каждого случая. 2. Использовать всегда полный insert/update с биндингом а в триггерах разбираться какие реально поля изменяются Я пока не настолько сильна в триггерах, чтобы такое написать. Пока что, использую триггеры только для генераторов.3. Вынести логику разборок с данными на сервер - в сохранённую процедурку. Очень хорошо, а что будет в этой хранимой процедуре? ![]() Да и в 1ом случае можно добавить систему кеширования позволяющую воспользоваться этими преимуществами. А эти слова для меня вообще пока как китайская грамота. ![]() |
|
|
Tonal |
![]()
Сообщение
#11
|
![]() Активный участник ![]() ![]() ![]() Группа: Участник Сообщений: 452 Регистрация: 6.12.2007 Из: Новосибирск Пользователь №: 34 Спасибо сказали: 69 раз(а) Репутация: ![]() ![]() ![]() |
Про Т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 |
![]()
Сообщение
#12
|
![]() Участник ![]() ![]() Группа: Участник Сообщений: 198 Регистрация: 27.9.2011 Из: Санкт-Петербург Пользователь №: 2912 Спасибо сказали: 5 раз(а) Репутация: ![]() ![]() ![]() |
Привет!
![]() 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 |
![]()
Сообщение
#13
|
![]() Участник ![]() ![]() Группа: Участник Сообщений: 198 Регистрация: 27.9.2011 Из: Санкт-Петербург Пользователь №: 2912 Спасибо сказали: 5 раз(а) Репутация: ![]() ![]() ![]() |
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 |
![]()
Сообщение
#14
|
![]() Активный участник ![]() ![]() ![]() Группа: Участник Сообщений: 452 Регистрация: 6.12.2007 Из: Новосибирск Пользователь №: 34 Спасибо сказали: 69 раз(а) Репутация: ![]() ![]() ![]() |
Т. е. с позиционированием ты разобралась.
![]() Могу только добавить, что раз есть порядок, то можно позиционироваться на первый элемент больший или равный текущему или на последний меньший или равный, на выбор. ![]() 5. Неуказанное в insert-е поле заполняется значением по умолчанию для этого поля, которое можно указать при создании таблицы (или при создании домена). Если значение по умолчанию не указано, подставляется null. 6. Тут возможны варианты с транзакциями: сохраняется ли препарированность между транзакциями или для новой транзакции нужно препарить запросы по новой? Если мне склероз не изменяет, Firebird в последних версиях не требовал переподготавливать запросы каждый раз, но не знаю как к этому относится драйвер в Qt. 7. Есть ещё вариант а' - использовать биндинг по имени или номеру. Тогда obj_id можно забиндить 1 раз перед циклом. Я бы выбрал его. ![]() 8. Ну, если совсем втупую то примерно так (псевдокод на псевдопитоне):
Хотя можно вместо списка с QVariant использовать словарь и биндить по именам. ![]() Главная идея, что сам запрос для конкретной конфигурации полей ты создаёшь только если она появилась и лишь один раз. |
|
|
Steklova Olga |
![]()
Сообщение
#15
|
![]() Участник ![]() ![]() Группа: Участник Сообщений: 198 Регистрация: 27.9.2011 Из: Санкт-Петербург Пользователь №: 2912 Спасибо сказали: 5 раз(а) Репутация: ![]() ![]() ![]() |
Привет!
![]() 6. Цитата сохраняется ли препарированность запроса между транзакциями (Firebird, Qt) я тоже не знаю.7. Цитата Есть ещё вариант а' - использовать биндинг по имени или номеру. Тогда obj_id можно забиндить 1 раз перед циклом. Я бы выбрал его. То, что надо! ![]()
//Заодно поняла, как забиндить значения NULL в поля разного типа. ![]()
8. Спасибо, Tonal, за пример. ![]() |
|
|
![]() ![]() ![]() |
![]() |
|
Текстовая версия | Сейчас: 4.5.2025, 22:29 |