Seite 1 von 2

SQL 2 Varianten Welche ist sinnvoller?

Verfasst: 6. Juni 2010 19:13
von Nvidia
Ich für ein Problem zwei Varianten, welche ist sinnvoller?
Kleines Beispiel:
Ich habe 100 Personen. (a 10 Personen in 10 Gruppen).
Variante a):
ich erstelle einen Table mit den Gruppenamen und eine Tabelle mit dem Personen, wobei eine Spalte den Gruppennamen trägt.
2 Tables erstellen. Fertig.
Beim Auslesen einer Gruppe, müsste er ~ 100x vergleichen und einlesen.
Variante b)
ich erstelle einen Table mit den Gruppenamen und für jeden Gruppennamen eine eigenen Table.
Beim Auslesen einer Gruppe, müsste er ~10x einlesen. Das vergleichen, fiele dann weg.
Allerdings habe ich einige Tabellen mehr. Bei dieser Größenordnung spielt das keine Rolle ist nur ein Beispiel.
Welche ist sinnvoller?
nvidia

Verfasst: 6. Juni 2010 20:31
von upsala
Variante a)
Variante b macht man nicht, außer über Partionierung.

Verfasst: 6. Juni 2010 20:52
von Nvidia
warum

Verfasst: 6. Juni 2010 20:54
von franzf
Jein zu a). Nicht den Gruppenname sondern die ID der jeweiligen Gruppe solltest du eintragen. Das kann böse enden, wenn du mal eine Gruppe umbenennen willst und dann auch noch alle alten Einträge aus der "Personen"-Tabelle ändern darfst.

Häufig (dann wenn du nicht nur diese viele-zu-eine-Verknüpfung hast) nimmt man auch eine eigene Lookup-Tabelle für die Verknüpfungen. In der werden dann jeweils die ID der Gruppe und die der Person in einer Reihe eingetragen. Solltest du später noch andere Gruppierungen deiner Personen einfügen wollen, ist das so einfacher zu handhaben.

Verfasst: 6. Juni 2010 21:36
von FaS
Und wenn du die Gruppen-Spalte in der Personen-Tabelle indizierst, muss die SQL-Engine auch nicht 100 Einträge durchgehen, um alle Personen einer bestimmten Gruppe zu liefern.
Gruß,
FaS

Verfasst: 7. Juni 2010 18:07
von Nvidia
ok ich hab das jetzt versucht an einem beispiel mit dem primery key, aber das haut nicht so ganz hin.

Code: Alles auswählen

#include "mainwindow.h"

#include <QtGui>
#include <QtSql>


MainWindow::MainWindow()
{

    w = new QWidget;
    button = new QPushButton;
    button->setText("Push me");
    line = new QLineEdit;
    show2 = new QLabel;
    connect(button,SIGNAL(clicked()),this,SLOT(Methode1()));

    QHBoxLayout *layout2 = new QHBoxLayout;
    layout2->addWidget(line);
    layout2->addWidget(button);
    layout2->addWidget(show2);
    w->setLayout(layout2);

    setCentralWidget(w);
}


void MainWindow::Methode1()
{
    QString k = line->text();
    QSqlQuery query("INSERT into person (name)"
                    "VALUES ("+line->text()+")");
    query.exec();

    QSqlQuery query2("SELECT last_insert_rowid();");
    QString k2 = query2.value(0).toString();
    show2->setText(k2);
}


Ich erhalte als Antwort QSqlQuery::value: not positioned on a valid record.
ich hab ein bisschen mit dem record rumprobiert, aber ich erhalte immer als ergebnis -1. was ja nicht sein kann

Verfasst: 7. Juni 2010 18:23
von FaS
Du executest dein 2. Query garnicht.
Und nebenbei erwähnt, gibt es QSqlQuery::lastInsertId().
Gruß,
FaS

Verfasst: 7. Juni 2010 18:48
von Nvidia
ok das hat mich auch gewundert. Weil unter diesem Beispiel
http://doc.trolltech.com/4.6/qsqlquery.html
QSqlQuery query("SELECT country FROM artist");
while (query.next()) {
QString country = query.value(0).toString();
doSomething(country);
}
wird er auch nicht executed.
ok ich versuchs mal damit.
also so sieht das nun aus:

Code: Alles auswählen

void MainWindow::Methode1()
{
    QString k = line->text();
    QSqlQuery query("INSERT into person (name)"
                    "VALUES ("+k+")");

    query.exec();
    QString k2 = query.lastInsertId().toString();
    qDebug() << query.lastError();
    show2->setText(k2);
}
Als Fehler meint er QSqlError(-1,"Unable to fetch row","no query");

Verfasst: 7. Juni 2010 19:03
von upsala
Doch, die 2. Query wird schon ausgeführt. Die 1. wird sogar 2x ausgeführt.

Nur wenn man ein Ergebnis will, sollte man den Datenzeiger auch positionieren. Z.B. mit next().

Verfasst: 7. Juni 2010 19:04
von FaS
Sorry du hast Recht:
Konstruktor-mit-Query-String-Doku hat geschrieben:[...] If query is not an empty string, it will be executed. [...]
Das heißt dein 1. exec() ist auch überflüssig bzw. fügt deine Person ein zweites Mal hinzu.
Dann fehlt jetzt nur noch query2.next(), wie im Beispiel ;-)

Verfasst: 7. Juni 2010 19:24
von Nvidia
???
Wozu und wo brauch ich nun next()?

Verfasst: 7. Juni 2010 19:37
von upsala
Versuch einfach mal die Doku zu lesen.

Verfasst: 7. Juni 2010 20:03
von Nvidia
check das nicht, wofür ich nun next brauch.
ich weiß, dass bei next() er die tabelle immer weiter durch geht.
Aber wofür brauch ich das denn?
Wenn ich doch grat was eingefügt habe und dannach die letzte Id abfrage, warum muss ich dann next aufrufen?!

Verfasst: 7. Juni 2010 20:21
von upsala
bool QSqlQuery::next ()
Retrieves the next record in the result, if available, and positions the query on the retrieved record. Note that the result must be in the active state and isSelect() must return true before calling this function or it will do nothing and return false.
The following rules apply:
If the result is currently located before the first record, e.g. immediately after a query is executed, an attempt is made to retrieve the first record.
If the result is currently located after the last record, there is no change and false is returned.
If the result is located somewhere in the middle, an attempt is made to retrieve the next record.
If the record could not be retrieved, the result is positioned after the last record and false is returned. If the record is successfully retrieved, true is returned.
Was ist daran nicht verständlich?

Verfasst: 7. Juni 2010 20:49
von Nvidia

Code: Alles auswählen

void MainWindow::Methode1()
{
    QString k = line->text();
    QSqlQuery query("INSERT into person (name)"
                    "VALUES ("+line->text()+")");
    while (query.next())
    {
    QString k2 = query.lastInsertId().toString();
    show2->setText(k2);
    }
}
Da krieg ich einen leeren String.