Re: Daten reorganisieren: aus alt mach neu

Re: Daten reorganisieren: aus alt mach neu

am 30.10.2006 09:23:48 von Claus Reibenstein

Martin Lemke schrieb:

> SELECT alter_name, neuer_name, id , name
> FROM synonyme, grunddaten
> WHERE neuer_name,=name
> INSERT INTO neu_synonyme
> VALUES (NULL,alter_name,id,1)
>
> Leider versteht die Datenbank nicht was ich will. Die SQL-Anweisung enthält
> einen Fehler, den ich nicht finde.
>
> Allerdings lautet die Fehlermeldung von MySQL folgendermaßen:
>
> "#1064 - You have an error in your SQL syntax; check the manual that
> corresponds to your MySQL server version for the right syntax to use near
> 'INSERT INTO sb_synonyme VALUES ( NULL , alter_name , id , 1 )
> LIMIT 0, 30' at line 1 "
>
> "LIMIT 0, 30" hat anscheindend phpMyAdmin wohlmeinend hinzugefügt.
> Ausgeführt als php-Skript ergibt sich, dass die Zeile
>
> INSERT INTO sb_synonyme VALUES ( NULL , alter_name , id , 1 )
>
> Fehler enthält.

Du interpretierst die Fehlermeldung falsch. Diese Zeile _enthält_ nicht
den Fehler, sondern _ist_ der Fehler. Er _beginnt_ mit dem Schlüsselwort
INSERT. Dieses ist an dieser Stelle nicht zulässig.

Versuch's mal andersrum:

INSERT bla (x, y, z) SELECT a, b, c FROM blub

Gruß. Claus

Daten reorganisieren: aus alt mach neu

am 30.10.2006 09:58:21 von Martin Lemke

Ich möchte einige Desingfehler in meinen Tabellen ausbessern. Es geht
konkret um eine Datenbank von Artnamen von Tieren. Da sich die
wissenschaftlichen Namen gelegentlich ändern, gibt es eine Synonymtabelle
mit alten Namen.

Bisher sah das in etwa so aus:

Tabelle grunddaten:
name, autor, familie

Tabelle synonyme:
alter_name, neuer_name

Darüber hinaus gibt es Tabllen zu Angaben zu roten Listen einzelner
Bundesländer, die alle nach dem selben Prinzip aufgebaut sind.

Das hat sich als sehr nachteilig erwiesen, denn wenn sich erneut ein paar
Namen ändern, muss ich diverse Tabellen ändern. Deshalb soll der Name
künftig nur noch in der Grunddaten-Tabelle stehen und alle anderen Tabellen
sollen auf den Id verweisen.

Bitte nicht schlagen! Mir ist klar, dass ich das hätte von Anfang an so
mahen sollen. Ich bin nun aber auch kein Informatiker.

Neu sieht es nun so aus:

Tabelle neu_grunddaten
id, name, autor, familie

Num will ich die diue alte Synonymtabelle in die neue konvertieren:

Tabelle neu_synonyme
index
synonym
art_id
literatur_id

Um dies zu bewerkstelligen habe ihc mir folgende SQL-Konstruktion überlegt:

SELECT alter_name, neuer_name, id , name
FROM synonyme, grunddaten
WHERE neuer_name,=name
INSERT INTO neu_synonyme
VALUES (NULL,alter_name,id,1)

Leider versteht die Datenbank nicht was ich will. Die SQL-Anweisung enthält
einen Fehler, den ich nicht finde.

Allerdings lautet die Fehlermeldung von MySQL folgendermaßen:

"#1064 - You have an error in your SQL syntax; check the manual that
corresponds to your MySQL server version for the right syntax to use near
'INSERT INTO sb_synonyme VALUES ( NULL , alter_name , id , 1 )
LIMIT 0, 30' at line 1 "

"LIMIT 0, 30" hat anscheindend phpMyAdmin wohlmeinend hinzugefügt.
Ausgeführt als php-Skript ergibt sich, dass die Zeile

INSERT INTO sb_synonyme VALUES ( NULL , alter_name , id , 1 )

Fehler enthält.

Wie soll ich die Variablen denn ansonsten setzen?

Wenn jemand eine Anrregung hat, wie es es komplett anders besser hin
bekomme, bin ich auch für solche Tipps empfänglich.

Martin

Re: Daten reorganisieren: aus alt mach neu

am 30.10.2006 10:33:40 von Axel Schwenke

Martin Lemke wrote:

> Ich möchte einige Desingfehler in meinen Tabellen ausbessern.
....

> Bisher sah das in etwa so aus:
> Tabelle grunddaten: name, autor, familie
> Tabelle synonyme: alter_name, neuer_name
....

> Neu sieht es nun so aus:
> Tabelle neu_grunddaten: id, name, autor, familie
>
> Num will ich die diue alte Synonymtabelle in die neue konvertieren:
>
> Tabelle neu_synonyme
> index
> synonym
> art_id
> literatur_id
>
> Um dies zu bewerkstelligen habe ihc mir folgende SQL-Konstruktion überlegt:
>
> SELECT alter_name, neuer_name, id , name
> FROM synonyme, grunddaten
> WHERE neuer_name,=name
> INSERT INTO neu_synonyme
> VALUES (NULL,alter_name,id,1)
>
> Leider versteht die Datenbank nicht was ich will. Die SQL-Anweisung enthält
> einen Fehler, den ich nicht finde.



Du kannst dir nicht einfach neue SQL Konstrukte nach deinem Gusto
ausdenken und dann erwarten, daß MySQL die versteht. Die korrekte
Syntax ist:

INSERT INTO () SELECT FROM ...

ich nehme an, daß die `index` Spalte in synonyme_neu AUTO_INCREMENT
ist. Dann brauchst du der im INSERT gar keinen Wert zu geben:

INSERT INTO synonyme_neu (synonym, art_id, literatur_id)
SELECT synonyme.neuer_name, grunddaten.id, 1
FROM grunddaten, synonyme
WHERE synonyme.alter_name = grunddaten.name


Anmerkungen:

1. Es ist prinzipielle empfehlenswert, bei INSERT eine Spaltenliste
anzugeben. Zum einen macht das den INSERT für Menschen besser lesbar
(man muß nicht erst nachschlagen, welche Felder die Zieltabelle hat)
zum zweiten vermeidet man Ärger, wenn man die Tabellendefinition mal
ändert, aber vergißt das INSERT anzupassen

2. Bei der Benennung von Tabellen und Spalten sollte man vorher genau
nachdenken. Vermeiden sollte man reservierte Wörter (wie "index").
Auch keine Leerzeichen, Sonderzeichen und generell alles, was das
Quoten eines Bezeichners erzwingt.

3. Konsistenz ist schön. So könnte man einen numerischen PRIMARY KEY
jeder Tabelle id nennen. Und wenn man foo.id als FOREIGN KEY
verwendet, nennt man es foo_id. Eine Tabelle nennt man so, wie die
darin gespeicherten Dinge. Ob man die Einzahl- oder Mehrzahl-Form
verwendet, ist Geschmackssache. Ich bevorzuge ersteres.
Für dein Beispiel:

CREATE TABLE art
( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
name CHAR(20),
autor ... ,
familie ...
)

CREATE TABLE synonym
( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
art_id INT UNSIGNED,
name CHAR(20),
literatur_id ...
)

Anmerkung zur Anmerkung: AUTO_INCREMENT Spalten (bzw. generell IDs)
sollten UNSIGNED sein. Korrespondierende Spalten (z.B. art.id und
synonym.art_id, aber auch art.name und synonym.name) haben den
gleichen Typ.

Im Sinne der durchgängigen Normalisierung sollten autor und familie
natürlich auch eigene Tabellen bekommen und über ihre id referenziert
werden.


HTH, XL

Re: Daten reorganisieren: aus alt mach neu

am 30.10.2006 12:35:47 von Axel Schwenke

Martin Lemke wrote:
> Axel Schwenke schrieb:
>
>> Im Sinne der durchgängigen Normalisierung sollten autor und familie
>> natürlich auch eigene Tabellen bekommen und über ihre id referenziert
>> werden.
>
> Zumindest für die Familien werde ich das wohl machen. Das Problem ist das
> selbe wie oben, aber ich bekomme es noch immer nicht hin.
>
> Eine Liste der Familien bekomme ich mit (nun mit echten Tabellen- und
> Feldnamen)
>
> SELECT familie FROM sb_grunddaten
> GROUP BY familie
~~~~~~~~~~~~~~~~

Probier mal SELECT DISTINCT ...

> Nur das Füllen will wieder nicht funktionieren:
>
> a)
> INSERT INTO sb_familie
> VALUES (familie)
~~~~~~
> SELECT familie FROM sb_grunddaten
> GROUP BY familie
>
> b)
> INSERT INTO sb_familie (id, familie)
> VALUES (null, familie)
~~~~~~~~~~~~~~~~~~~~~~
> SELECT familie FROM sb_grunddaten
> GROUP BY familie

Ich hab dir die Fehler mal unterstrichen.

Wo in http://dev.mysql.com/doc/refman/5.0/en/insert-select.html
hast du eigentlich eine VALUES () Klausel gesehen?


XL

Re: Daten reorganisieren: aus alt mach neu

am 30.10.2006 13:00:07 von Martin Lemke

Axel Schwenke schrieb:

Vielen Dank für duie Tipps und Erläuterungen.

> Im Sinne der durchgängigen Normalisierung sollten autor und familie
> natürlich auch eigene Tabellen bekommen und über ihre id referenziert
> werden.

Zumindest für die Familien werde ich das wohl machen. Das Problem ist das
selbe wie oben, aber ich bekomme es noch immer nicht hin.

Eine Liste der Familien bekomme ich mit (nun mit echten Tabellen- und
Feldnamen)

SELECT familie FROM sb_grunddaten
GROUP BY familie

Eine neue Tabelle für die Familien ist angelegt:

CREATE TABLE `sb_familie` (
`id` int(10) unsigned NOT NULL auto_increment,
`familie` varchar(60) collate latin1_german1_ci NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_german1_ci
COMMENT='Familien der Arten' AUTO_INCREMENT=1 ;

Nur das Füllen will wieder nicht funktionieren:

a)
INSERT INTO sb_familie
VALUES (familie)
SELECT familie FROM sb_grunddaten
GROUP BY familie

b)
INSERT INTO sb_familie (id, familie)
VALUES (null, familie)
SELECT familie FROM sb_grunddaten
GROUP BY familie

Nichts davon funktioniert.

Martin

Re: Daten reorganisieren: aus alt mach neu

am 30.10.2006 13:52:54 von Martin Lemke

Axel Schwenke schrieb:

> Wo in http://dev.mysql.com/doc/refman/5.0/en/insert-select.html
> hast du eigentlich eine VALUES () Klausel gesehen?

Danke, jetzt hat es geklappt.

Mal sehen, ob das erworbene Wissen mir nun auch zum Lösen der restlichen
Aufgaben ausreicht.

Martin