Russian Qt Forum

Qt => Базы данных => Тема начата: Примерный ученик от Март 30, 2008, 22:42



Название: Поле SERIAL
Отправлено: Примерный ученик от Март 30, 2008, 22:42
Еще вопрос.
Почему-то не срабатывает индексное поле SERIAL.
Вставка записи просто не проводится, если только явно не указывать ожидаемый правильный номер!!!
Пришлось создать SEQUENCE, получать от него очередное число и явно его присваивать ключевому полю.
Может есть какая-то тонкость?   ???
Подключение к PostgreSQL 8.3 через ODBC3.
QT 3.3.8


Название: Re: Поле SERIAL
Отправлено: Примерный ученик от Март 31, 2008, 11:22
Неужели никто не встречался с подобной проблеммой ???


Название: Re: Поле SERIAL
Отправлено: Alex03 от Март 31, 2008, 12:46
Не знаю ни что такое SERIAL ни что такое PostgreSQL :) , но подозреваю что Вы пытаетесь явно вставить NULL?
Тада попробуйте убрать поле из списка полей вставляемой записи....


Название: Re: Поле SERIAL
Отправлено: Примерный ученик от Март 31, 2008, 14:46
SERIAL - это автоинкрементное поле, т.е. каждое новое значение на заданный шаг (как правило - шаг = 1) больше или меньше предыдущего - для обеспечения уникальности индекса. Поле должно получать значение автоматически. Однако этого почемуто не происходит.


Название: Re: Поле SERIAL
Отправлено: Mikhail от Март 31, 2008, 16:21
SERIAL - это автоинкрементное поле, т.е. каждое новое значение на заданный шаг (как правило - шаг = 1) больше или меньше предыдущего - для обеспечения уникальности индекса. Поле должно получать значение автоматически. Однако этого почемуто не происходит.


А проверить последнюю ошибку не пытался? Проверь что ему не нравится.

Еще один способ проверить с помощью sqlbrowser.exe из демок Qt. Он и ошибку укажет.


Название: Re: Поле SERIAL
Отправлено: Примерный ученик от Март 31, 2008, 16:30
Надо попробовать


Название: Re: Поле SERIAL
Отправлено: Примерный ученик от Март 31, 2008, 16:37
Попробовал - не фурычит...
Возможно проблема в ODBC3.
Раньше работал с PostgreSQL напрямую с DELPHI - проблем небыло >:(
А для QT3.3.8 построить плагин для PostgreSQL 8.3 не удалось.
В QT4.3 - строится без проблем...
WINDOWS XP + MSVC6.0 SP6


Название: Re: Поле SERIAL
Отправлено: Alex03 от Апрель 01, 2008, 06:41
SERIAL - это автоинкрементное поле, т.е. каждое новое значение на заданный шаг (как правило - шаг = 1) больше или меньше предыдущего - для обеспечения уникальности индекса. Поле должно получать значение автоматически. Однако этого почемуто не происходит.
tmikola
Я примерно догадывался что такое SERIAL...
По опыту работы с IB/FB....
Допустим есть таблица с полем ID на котором ограничение not null, и триггер который выставляет это поле в нужное значение.
Так вот
Код:
INSERT INTO mytable (id, field1, field2....) VALUES (NULL, f1val, f2val);
Матерится на то что ID IS NULL, ибо проверка ограничения выполняется до триггера который устанавливает это поле.
А
Код:
INSERT INTO mytable (field1, field2....) VALUES (f1val, f2val);
Работает как надо. Именно это я и имелл ввиду попробовать.
Впрочем в PostgreSQL я не спец, да и топик к Qt ИМХО не относится.


Название: Re: Поле SERIAL
Отправлено: SnowZmiY от Апрель 01, 2008, 09:27
Поле SERIAL в PostgreSQL очень часто работает некоректно, NULL здесь не причем (просто сериал почемуто может записывать иногда непонятно по какой причине уже существующие значение при добавлении записи, были случаи когда поле сериал записывало значения: 1,2,3,4,5,6 а потом опять 1,2,3,4,5,6 и так покругу хотя должно было бы быть 1,2,3,4,5,6,7,8,9,10,11,12....) поэтому в нашей конторе от него полностью отказались...
причем и через драйвер тоже. так что ODBC здесь ни при чем, так же возникают проблемы при снятии и востановлении дампа с этим типом данных. А если вам нужно поле с универсальным ключом используйте какую-нибудь свою функцию например(для Qt 3.3.6):
Код:
в .h
             // возвращает уникальный номер отсутствующий в данном поле в таблице (имя базы, имя таблицы, поле с кодом(int))
int zSerial(QString baseName, QString tableName, QString fieldName);


в .cpp
int ZDB::zSerial(QString baseName, QString tableName, QString fieldName)
{
int serial;
QSqlDatabase *db = QSqlDatabase::database( baseName, TRUE );
QSqlQuery query(db);
query.exec("SELECT min("+ fieldName +") FROM "+ tableName);
if(!query.next())
{
serial = 1;
return serial;
}
if (query.value(0).toInt() >1 )
{
serial = 1;
return serial;
}
else
{
bool MaX = true;
int first=0;
int next =0;
query.exec("SELECT "+ fieldName +" FROM "+ tableName +" ORDER BY "+ fieldName);
query.next();
first = query.value(0).toInt();
while (query.next())
{
next = query.value(0).toInt();
if (next - first > 1)
{
serial = first + 1;
MaX = false;
break;
}
first = next;
}
if (MaX)
{
query.exec("SELECT max("+ fieldName +") FROM "+ tableName);
if (query.next())
{
serial = query.value(0).toInt() + 1;
}
else
{
serial = 1;
}

}
return serial;
}
}
Написал сам вроде работает.


Название: Re: Поле SERIAL
Отправлено: Sergey B. от Апрель 03, 2008, 06:35
Поле SERIAL в PostgreSQL очень часто работает некоректно, NULL здесь не причем (просто сериал почемуто может записывать иногда непонятно по какой причине уже существующие значение при добавлении записи, были случаи когда поле сериал записывало значения: 1,2,3,4,5,6 а потом опять 1,2,3,4,5,6 и так покругу хотя должно было бы быть 1,2,3,4,5,6,7,8,9,10,11,12....) поэтому в нашей конторе от него полностью отказались...


Ни разу такого не было...
3 Промышленных проекта и все опираются на serial.
Может быть стоило отписать разработчикам и выяснить в чём дело?


Название: Re: Поле SERIAL
Отправлено: Примерный ученик от Апрель 03, 2008, 13:32
Я решил проблему, использовав последовательности

// создание последовательности
CREATE SEQUENCE _key_const
  INCREMENT 1
  MINVALUE 1
  MAXVALUE 2147483647
  START 1
  CACHE 1;
ALTER TABLE _key_const OWNER TO postgres;     

а в программе

   QSqlQuery sc("select nextval('_key_const')");  // новое значения последовательности
   sc.next();
   int i=sc.value(0).toInt();  // и его значение

Значение i присваиваю ключу создаваемой записи и ВСЕ.
Кстати, это позволяет у нескольких таблиц делать уникальные поля одной последовательностью.
Иногда это полезно...

все работает корректно.

P.S.
 Постгрис для каждого поля SERIAL создает свою последовательность.
Они реально были, но что-то не срослось.