Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: PK в PostgreSQL
Форум на CrossPlatform.RU > Библиотеки > Qt > Qt Разработка баз данных
Rocky
Всем привет!

Пытаюсь создать таблицу в PostgreSQL и одно из полей сделать PK.
Пробую так:
bRetVal = oQuery.exec(QString("CREATE TABLE tab (ID BIGSERIAL, "
":Pict_ID_1_1, :Pict_ID_1_2, :Pict_ID_1_3, "
"PRIMARY KEY (ID));"));
//bRetVal == true

bRetVal = oQuery.prepare(QString("INSERT INTO tab VALUES("
        ":Pict_ID_1_1, :Pict_ID_1_2, :Pict_ID_1_3, "
        ");"));
//bRetVal == true


//Потом
oQuery.bindValue(":Pict_ID_1_1", 1);
oQuery.bindValue(":Pict_ID_2_1", 2);
oQuery.bindValue(":Pict_ID_3_1", 3);

bRetVal =oQuery.exec();
//bRetVal == false


Пробовал через sequence:
bRetVal = oQuery.exec(QString("CREATE SEQUENCE tab_sq START WITH 1"));
//bRetVal == true

bRetVal = oQuery.exec(QString("CREATE TABLE BananasGoBahamas (ID DEFAULT NOT NULL nextval('tab_sq') PRIMARY KEY, "
        "Pict_ID_1_1 INTEGER, Pict_ID_1_2 INTEGER, Pict_ID_1_3 INTEGER);"));
//bRetVal == true

bRetVal = oQuery.prepare(QString("INSERT INTO tab VALUES(:ID, "
        ":Pict_ID_1_1, :Pict_ID_1_2, :Pict_ID_1_3, "
        ");"));
//bRetVal == true


//Потом
oQuery.bindValue(":ID", "tab_sq.nextval");
oQuery.bindValue(":Pict_ID_1_1", 1);
oQuery.bindValue(":Pict_ID_2_1", 2);
oQuery.bindValue(":Pict_ID_3_1", 3);

bRetVal =oQuery.exec();
//bRetVal == false


Как я понял, в постгрессе нету AUTOINCREMENT... Вобщем, никак не работает... (( Кто-нибудь знает в чем может быть проблема?

Спасибо)
DEADHUNT
Цитата(Rocky @ 4.3.2010, 17:09) *
Как я понял, в постгрессе нету AUTOINCREMENT... Вобщем, никак не работает... (( Кто-нибудь знает в чем может быть проблема?

тогда наверное придётся тригер на вставку делать, как это было в InterBase
Litkevich Yuriy
Есть в PostgreSQL понятие "Генератор"?
Если есть, то тогда точно, как в InterBase/Firebird - Генератор+Тригер
DEADHUNT
Цитата(Litkevich Yuriy @ 4.3.2010, 17:21) *
Если есть, то тогда точно, как в InterBase/Firebird - Генератор+Тригер

можно и без генератора обойтись, взять максимум по PK прибавить 1 и это будет новый PK.
Rocky
А можно маленький примерчик плиз? Я просто вот только-только взялся по-серьезному за базы данных =)
MoPDoBoPoT
Цитата(DEADHUNT @ 4.3.2010, 17:11) *
Как я понял, в постгрессе нету AUTOINCREMENT

Неправильно понял, точнее наделал ошибок и сделал неправильный вывод.
В PostgreSQL автоинкрементное поле осуществляется через тип SERIAL/BIGSERIAL (по сути это последовательность + "триггер").

В общем, по порядку:
1.
bRetVal = oQuery.exec(QString("CREATE TABLE tab (ID BIGSERIAL, "
":Pict_ID_1_1, :Pict_ID_1_2, :Pict_ID_1_3, "
"PRIMARY KEY (ID));"));

Я не понял эту конструкцию, так что создалась таблица?

2.
bRetVal = oQuery.prepare(QString("INSERT INTO tab VALUES(" 
        ":Pict_ID_1_1, :Pict_ID_1_2, :Pict_ID_1_3, "
        ");"));

Тут запрос неправильный, т.к. в таблице tab 4 поля, а не 3. Текст должен быть примерно такой:
"INSERT INTO tab(Pict_ID_1_1, Pict_ID_1_2, Pict_ID_1_3) VALUES(:Pict_ID_1_1, :Pict_ID_1_2, :Pict_ID_1_3);"

3.
oQuery.bindValue(":ID", "tab_sq.nextval");

Тут ты пытаешься в 1-е поле с числовым типом записать текстовую строку "tab_sq.nextval" (тем более в описании таблцы уже задан автоикремент).

4.
oQuery.bindValue(":Pict_ID_1_1", 1);
oQuery.bindValue(":Pict_ID_2_1", 2);
oQuery.bindValue(":Pict_ID_3_1", 3);

А в подготовленном запросе писал :Pict_ID_1_1, :Pict_ID_1_2, :Pict_ID_1_3

Вот попробуй так:
bRetVal = oQuery.exec(QString("CREATE TABLE tab (
                                              " ID BIGSERIAL,"
                                              " Pict_ID_1_1 INTEGER,"
                                              " Pict_ID_1_2 INTEGER,"
                                              " Pict_ID_1_3 INTEGER,"
                                              " CONSTRAINT tab_PK PRIMARY KEY (ID));"
                                              )
                                  );

bRetVal = oQuery.prepare("INSERT INTO tab(Pict_ID_1_1, Pict_ID_1_2, Pict_ID_1_3) VALUES(:Pict_1, :Pict_2, :Pict__3);");

//Потом
oQuery.bindValue(":Pict_1", 1);
oQuery.bindValue(":Pict_2", 2);
oQuery.bindValue(":Pict_3", 3);

bRetVal =oQuery.exec();
Rocky
Ого )

1. AUTOINCREMENT я имел ввиду именно ключевое слово, SERIAL я потом прочитал что это аналог этому AUTOINCREMENT... Ну да, таблица создалась )) А что в ней не так?

2. Блин, понял ( Я чето решил что из-за явного указания имен полей модуль QtSql при формировании запроса сам подставит по полям что куда нужно..

3. Упс, тут описался, на самом деле было так (просто за 3 часа уже устал туда-сюда все менять, вот не то и вписал под конец)
bRetVal = oQuery.exec(QString("CREATE TABLE BananasGoBahamas (ID INTEGER NOT NULL DEFAULT 
nextval('tab_sq') PRIMARY KEY,........


4. там все ок, просто у меня 32 поля, я все тут не стал писать (


Уря, заработало!!!

Тока в консоли пишет:
Цитата
NOTICE: CREATE TABLE will create implicit sequence "tab_id_seq" for serial column "tab.id"
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "tab_pk" for table "tab"

Это ничего страшного?
MoPDoBoPoT
Цитата(Rocky @ 4.3.2010, 18:17) *
Это ничего страшного?

Это просто уведомление о том, что неявно создаются объекты/конструкции (последовательность и индекс).
Rocky
А еще вопросик можно? А при указании имен столбцов в QSqlQuery::prepare важен порядок имен столбцов? Т.е. он должен быть такой же как и при создании таблицы, или без разницы?
Litkevich Yuriy
Цитата(DEADHUNT @ 4.3.2010, 20:26) *
PK прибавить 1 и это будет новый PK.
нет нельзя, т.к. могут существовать разные транзакции и значение может быть не уникальным. А генератор гарантирует уникальность
Во всяком случае в firebird/interbase, т.к. они версионники, а не блокировочники (как, например, MySQL)

Цитата(Rocky @ 4.3.2010, 21:42) *
в QSqlQuery::prepare важен порядок имен столбцов? Т.е. он должен быть такой же как и при создании таблицы, или без разницы?
зависит от типа подстановки, позиционная/именованная.
Для последней без разницы, подробности см. в описании класса
MoPDoBoPoT
Цитата(Litkevich Yuriy @ 4.3.2010, 18:50) *
зависит от типа подстановки, позиционная/именованная.

Мне кажется имелось в виду это:
INSERT INTO tab(Pict_ID_1_1, Pict_ID_1_2, Pict_ID_1_3) VALUES(:Pict_1, :Pict_2, :Pict_3);
INSERT INTO tab(Pict_ID_1_3, Pict_ID_1_2, Pict_ID_1_1) VALUES(:Pict_3, :Pict_2, :Pict_1);
Эти варианты равнозначны (такие вещи в стандарте SQL прописаны).
Litkevich Yuriy
Цитата(MoPDoBoPoT @ 4.3.2010, 22:00) *
Мне кажется имелось в виду это:
ну собственно и я про него же. В данном случае подстановка именованная (:Pict_3)
Rocky
Ага... а с при самом байндинге уже без разницы, так?

INSERT INTO tab(Pict_ID_1_1, Pict_ID_1_2, Pict_ID_1_3) VALUES(:Pict_1, :Pict_2, :Pict_3);

В смысле что я могу хоть так писать:
oQuery.bindValue(":Pict_3", ...);
oQuery.bindValue(":Pict_1", ...);
oQuery.bindValue(":Pict_2", ...);

Не обязательно так
oQuery.bindValue(":Pict_1", ...);
oQuery.bindValue(":Pict_2", ...);
oQuery.bindValue(":Pict_3", ...);
?
Litkevich Yuriy
Цитата(Rocky @ 4.3.2010, 22:50) *
В смысле что я могу хоть так писать:
Да, можно писать в любом порядке, т.к. ты используешь конкретные имена.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Форум IP.Board © 2001-2024 IPS, Inc.