Russian Qt Forum
Октябрь 01, 2024, 00:27 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: QSqlCursor и связанные таблицы. QT 3.3.6  (Прочитано 14462 раз)
TukiNov
Гость
« : Сентябрь 04, 2006, 14:00 »

Уф, наконец то зарегился на форуме Улыбающийся
есть две таблицы :
Код:

CREATE TABLE db_termin (
    `ID` int(11) NOT NULL auto_increment,
    `FULL_NAME` text,
    `SHORT_NAME` text,
    `RAZDEL` int(11) default NULL,
    `P_RAZDEL` int(11) default NULL,
    `OPREDELENIE` longblob default NULL,
   PRIMARY KEY (`ID`)
);

CREATE TABLE db_razdel (
`R_ID` int(11) NOT NULL auto_increment,
`R_NAME` text,
PRIMARY KEY (`R_ID`)
);

Они связаны так : db_termin.RAZDEL=db_razdel.R_ID
Мне нужно чтобы  вместо RAZDEL int(11) в таблице выводился R_NAME text
Можно так сделать при помощи QSqlCursor ?
p.s. Если делать выборку так :
Код:

QSqlSelectCursor *q = new QSqlSelectCursor("select * from db_termin, db_razdel where db_termin.RAZDEL=db_razdel.R_ID");

    QDataTable *t = new QDataTable(q, TRUE, &w);
    q->select();
    t->refresh();

то всё ок, но перестаёт работать terminTable->setFilter( "RAZDEL='" + QString::number(id) + "'" );  который мне очень нужен.
Помогите плиз.
Кто ничего не понял, говорю проще : Как с помощью QSqlCursor сделать выборку из двух связанных таблиц Улыбающийся
Записан
SLK
Гость
« Ответ #1 : Сентябрь 04, 2006, 14:27 »

попробуй в select оставить where пустым ... т.е. примерно так

select * from db_termin inner join db_razdel on db_termin.RAZDEL=db_razdel.R_ID
Записан
TukiNov
Гость
« Ответ #2 : Сентябрь 04, 2006, 14:40 »

Цитата: "SLK"
попробуй в select оставить where пустым ... т.е. примерно так

select * from db_termin inner join db_razdel on db_termin.RAZDEL=db_razdel.R_ID

не пашет.
У меня фильт базы происходит при выборе в ComboBox :
Код:

void main_form::filter_by_razdel()
{
    int id;
    mapRazdel( razdelCBox->currentText(), id, FALSE );
    if(id){
terminTable->setFilter( "RAZDEL='" + QString::number(id) + "'" );
    }
    terminTable->refresh();
}

При QSqlCursor, в designer вот что :
Код:

void main_form::polish()
{
    if ( terminTable ) {
        QSqlCursor* cursor = terminTable->sqlCursor();
        if ( !cursor ) {
            cursor = new QSqlCursor( "db_termin", TRUE, db_razdelConnection );      
            if ( terminTable->isReadOnly() )
                cursor->setMode( QSqlCursor::ReadOnly );    
            terminTable->setSqlCursor( cursor, FALSE, TRUE );    
        }
        if ( !cursor->isActive() )
            terminTable->refresh( QDataTable::RefreshAll );
    }
    QMainWindow::polish();
}
Записан
SLK
Гость
« Ответ #3 : Сентябрь 04, 2006, 16:25 »

дело в том, что текст установленный в setFilter, QT вставляет в раздел  WHERE ....  грубо пересобирая текст запроса примерно таким кодом ....
Код:
  
    QString fieldList = toString( d->nm );
    if ( fieldList.isEmpty() )
return FALSE;
    QString str= "select " + fieldList;
    str += " from " + d->nm;
    if ( !filter.isEmpty() ) {
d->ftr = filter;
str += " where " + filter;
    } else
d->ftr = QString::null;
    if ( sort.count() > 0 )
str += " order by " + sort.toString( d->nm );
    d->srt = sort;
    return exec( str );

По этому возможно, что при сложном запросе (с несколькими таблицами) фильтр в курсоре работать нормально не будет ...

попробуй использовать мой вариант запроса и поставить в код
такой вариант фильтра
Код:
terminTable->setFilter( "db_termin.RAZDEL='" + QString::number(id) + "'" );
 

если и это не сработает, придётся искать другие варианты решения ...
Записан
TukiNov
Гость
« Ответ #4 : Сентябрь 04, 2006, 17:43 »

не работает .... Грустный
Записан
SLK
Гость
« Ответ #5 : Сентябрь 05, 2006, 10:20 »

Ну ещё есть пару вариантов для курсора ..... к примеру
для твоего запроса
Код:
select * from db_termin, db_razdel where db_termin.RAZDEL=db_razdel.R_ID
попробовать использовать такой вот фильтр ...
Код:
terminTable->setFilter( "db_termin.RAZDEL=db_razdel.R_ID and db_termin.RAZDEL='" + QString::number(id) + "'" );

Ещё один вариант это создать VIEW на стороне SQL сервера .....
Код:
CREATE VIEW db_termin_razdel
AS select * from db_termin inner join db_razdel on db_termin.RAZDEL=db_razdel.R_ID

и в курсоре открывать этот view ....
Код:
QSqlSelectCursor *q = new QSqlSelectCursor("select * from db_termin_razdel");
Записан
TukiNov
Гость
« Ответ #6 : Сентябрь 06, 2006, 00:23 »

Цитата: "SLK"

Ещё один вариант это создать VIEW на стороне SQL сервера .....
Код:
CREATE VIEW db_termin_razdel
AS select * from db_termin inner join db_razdel on db_termin.RAZDEL=db_razdel.R_ID


при этом создаётся новая таблица ? или это что то вроде виртуальной таблицы ?
Записан
bigirbis
Гость
« Ответ #7 : Сентябрь 06, 2006, 08:40 »

При этом создается а-ля виртуальная таблица, данные которой нельзя редактировать. При чем, данные в столбцах могут быть реальными или вычисляемыми. Обычно это сджойненые таблицы.

А вообще, смотри http://www.sql.ru.
Записан
TukiNov
Гость
« Ответ #8 : Сентябрь 07, 2006, 01:15 »

Спасибо, работает, но не думаю что это устроит заказчиков, попробую ещё подумать Улыбающийся
Записан
TukiNov
Гость
« Ответ #9 : Сентябрь 08, 2006, 12:39 »

Цитата: "TukiNov"
Цитата: "SLK"

Ещё один вариант это создать VIEW на стороне SQL сервера .....
Код:
CREATE VIEW db_termin_razdel
AS select * from db_termin inner join db_razdel on db_termin.RAZDEL=db_razdel.R_ID


при этом создаётся новая таблица ? или это что то вроде виртуальной таблицы ?

Так и знал, у них этот запрос не выполняется, версия MySQL ниже 5, обновлять нельзя.
Вот терь х.з. чё делать Грустный
Записан
Grigory
Гость
« Ответ #10 : Сентябрь 13, 2006, 14:52 »

Может быть есть смысл попробовать использовать вычисляемые поля?  Это конечно уменьшит быстродействие, но позволит решить проблему. Нужно переопределить  функцию
Код:
QVariant QSqlCursor::calculateField ( const QString & name ) [virtual protected] 
и добавить вычисляемый столбец в курсор.
Записан
TukiNov
Гость
« Ответ #11 : Сентябрь 13, 2006, 20:47 »

Цитата: "Grigory"
Может быть есть смысл попробовать использовать вычисляемые поля?  Это конечно уменьшит быстродействие, но позволит решить проблему. Нужно переопределить  функцию
Код:
QVariant QSqlCursor::calculateField ( const QString & name ) [virtual protected] 
и добавить вычисляемый столбец в курсор.

эээ, чё то я ничего не понял Улыбающийся
Записан
Grigory
Гость
« Ответ #12 : Сентябрь 15, 2006, 16:10 »

Короче, читаешь вначале Ассистант на пример испоьлзования вычисляемых полей в SQL курсоре (там не очень много) Потом нужно будет переопределить функцию QSqlCursor::calculateField. Она объявлена как virtual protected, следовательно, придется создавать свой класс, отнаследовавшись от QSqlCursor. Дальше надо объявить и написать реализацию функции calculateField. Реализация примерно такая будет:
Код:

QVariant YourSqlSelectCursor::calculateField(const QString & name)
{
 QVariant res = QVariant::Invalid;
 if(name=="R_NAME")
 {
    QSqlQuery query("SELECT R_NAME from db_razdel  WHERE R_ID="+value("RAZDEL"));
     if(query.exec())
     {
           res = query.value(0);
     }
 }
 return res;
}


собственно при создании своего курсора q надо добавить в него вычисляемый столбец R_NAME. И при любом обращении к R_NAME будет выполняться функция  calculateField(); Добавление вычисляемого столбца можно сделать например так:
Код:
 q.addField(QSqlFieldInfo("R_NAME"));
 q.setCalculated ( "R_NAME", true );

Ну и саму таблицу заполнять только полями из db_termin
Код:
YourSqlSelectCursor *q = new YourSqlSelectCursor("select * from db_termin);


Вот как-то так. Код конечно не тестировал, так что могут быть ошибки.
Записан
TukiNov
Гость
« Ответ #13 : Сентябрь 27, 2006, 16:41 »

Такс, в простом случае получается. Посмотрел пример из qt/examples.
Но проблема вот терь какая, я всё делал в desiner'е и соответственно таблица уже есть.
вот что в примере (переделанный под мой случай):
Код:

InvoiceItemCursor::InvoiceItemCursor() :
    QSqlCursor( "db_termin" )
{
    QSqlFieldInfo productName( "razdel_name", QVariant::String );
    append( productName );
    setCalculated( productName.name(), TRUE );
}


QVariant InvoiceItemCursor::calculateField( const QString & name )
{
    if ( name == "razdel_name" ) {

QSqlQuery query( "SELECT R_NAME FROM db_razdel WHERE R_ID=" +
    field( "RAZDEL" )->value().toString() );
if ( query.next() ){
   return query.value( 0 );
}
        if(!query.isActive()){
query.lastError().showMessage();}
    }

    return QVariant( QString::null );
}

создаю класс :
Код:

class InvoiceItemCursor : public QSqlCursor
{
    public:
InvoiceItemCursor();
    protected:
QVariant calculateField( const QString & name );
};

далее в файле где дизайнер создал таблицу я прописываю :
Код:

InvoiceItemCursor invoiceItemCursor;
terminTable->setSqlCursor(&invoiceItemCursor);
terminTable->addColumn("FULL_NAME", "NAME");
terminTable->addColumn( "razdel_name", "R_NAME" );

Собирается всё на ура, а вот когда запускаю, всё падает с сегментацией. В чём дело ? как прикрутить всё это к уже существующей таблице ?
используемый пример лежит тут : qt/examples/sql/overview/subclass3/
Записан
bigirbis
Гость
« Ответ #14 : Сентябрь 27, 2006, 18:43 »

Похоже на то, что у тебя дохнет курсор, выходя из области видимости.
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.13 секунд. Запросов: 21.