Java lernen

SQL-Statement MySQLSyntaxErrorException

Diskutiere MySQLSyntaxErrorException im Datenbankprogrammierung Forum; Damit schießt du dir irgendwann böse ins Bein... Sowas macht man einfach nicht. Nie niemals niocht hält man die gleichen Daten mehrfach...

  1. Thallius
    Thallius Bekanntes Mitglied
    Damit schießt du dir irgendwann böse ins Bein...

    Sowas macht man einfach nicht. Nie niemals niocht hält man die gleichen Daten mehrfach gespeichert....
     
  2. tommysenf
    tommysenf Aktives Mitglied
    Sag niemals nie. Im OLAP Bereich ist es sehr üblich und auch sinnvoll...
     
    mihe7 gefällt das.
  3. Thallius
    Thallius Bekanntes Mitglied
    Sinnvoll ist es nicht aber eben technisch im Moment noch nicht anders zu lösen.
    Aber hier reden wir nicht von BigData sondern von lächerliche. 1 mio datensätzen. Ein ganz typischer fallen POITROAE

    Claus
     
    mihe7 gefällt das.
  4. Ste3et_C0st
    Ste3et_C0st Neues Mitglied
    Hab nun nochmals die komplette Datenbank zurückgesetzt und von vorne angefangen und zwar erstell ich nun so eine Tabelle:

    Code (Text):

    CREATE TABLE IF NOT EXISTS `itemKurs` (
            `material` VARCHAR(255) NOT NULL,
            `materialID` MEDIUMINT NOT NULL AUTO_INCREMENT,
            `purchasePrice` DOUBLE NOT NULL DEFAULT 0,
            `retailPrice` DOUBLE NOT NULL DEFAULT 0,
            `amount` int NOT NULL DEFAULT 0,
            `action` VARCHAR(8) NOT NULL DEFAULT '—',
            `priceChange` DOUBLE NOT NULL DEFAULT 0,
            `lang` VARCHAR(255) NOT NULL,
            `time` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
             PRIMARY KEY (material,materialID)
    ) ENGINE=MyISAM;
     
    Ich bilde nun einen seperaten PRIMARY KEY für jedes material einzeln somit kann ich alles in eine Tabelle schreiben. Ich hoffe das war das was @Meniskusschaden meinte. Ich hab nur noch eine zentrale Tabelle in der die Werte eingefügt werden und ausgelesen werden. Ich hoffe das stimmt soweit. Eine frage hätte ich noch da ich gleich in die Arbeit musss, kann ich nun via executeBatch gleichzeitig einen INSERT machen und den LAST_INSERT_ID() - 1000 Löschen ? Ich möchte halt nur immer 1000 Transaktionen speichern pro material geht das ?
     
  5. Meniskusschaden
    Meniskusschaden Bekanntes Mitglied
    Nein, ich meinte nicht den Primary Key, sondern einen zusätzlichen Index über Material-ID und Zeitstempel, damit für ein gegebenes Material performant auf die neuesten Datensätze zugegriffen werden kann. Ich würde aber erst einmal austesten, wie schnell oder langsam es ohne den zusätzlichen Index überhaupt ist. Dann kannst du auch besser einordnen, ob der Index überhaupt etwas gebracht hat. Für den Primärschlüssel wäre die id ein Kandidat .
    Ja. Insert und Delete kann man mit einem gemeinsamen executeBatch-Aufruf ausführen. Man kann es aber nicht mit Select mischen.
     
  6. tommysenf
    tommysenf Aktives Mitglied
    Code (Text):
    CREATE TRIGGER insert_itemkurs
          AFTER INSERT
          ON itemkurs
          FOR EACH ROW BEGIN
          DELETE FROM itemkurs WHERE materialID=NEW.materialID - 1000;
        END;
     
     
    Meniskusschaden gefällt das.
  7. Meniskusschaden
    Meniskusschaden Bekanntes Mitglied
    Ich bemerke jetzt erst, dass die Material-ID in der neuen Tabelle offenbar nicht die Identifikation des Materials darstellen soll, sondern die Identifikation des Preis-Datensatzes. Deshalb könnte man hier
    doch den Index aus Post #14 des TE verwenden. Allerdings würde ich ihn dennoch nicht als Primary-Key verwenden. Ich würde die Spalte auch lieber anders benennen.

    Die zu löschenden Datensätze können jetzt natürlich nicht mehr über Differenzbildung der IDs ermittelt werden. Da wären dann ja auch die falschen Materialien enthalten. Das müsste in dem vorgeschlagenen Trigger von @tommysenf deshalb auch angepasst werden.
     
  8. Ste3et_C0st
    Ste3et_C0st Neues Mitglied
    Villeicht hab ich das nicht ganz so super rübergebracht. Ich möchte von meinem Server in die MySQL Tabelle die Daten Schreiben, es wird immer in die Datenbank geschrieben sobald sich der Preis eines Materials ändert mit einem Delay X.
    Ich habe insgesamt 786 Materialien somit wollte ich das Material als Primary Key setzen, da ich es vernünftig machen möchte, wollte ich nun die Datenbank euren Vorschlägen dementsprechend anpassen.
    Meine Idee war nun folgendes damit ich alles in eine Tabelle schreiben kann brauch ich ja zwingen nen Primary Key meine Überlegung war nun jeden Material eine eigene Id zu geben.

    material | materialId | purchasePrice ...
    STONE | 1 | 100.6
    STONE | 2 | 101.0
    STONE | 3 | 101.5
    GRASS | 1 | 50
    GRASS | 2 | 70

    So ist momentan die Tabelle aufgebaut.
    [​IMG]
    [​IMG]

    Ne normale Datenbank Struktur bekomm ich ja hin, da ist nichts dabei aber bei diesem "speziellen" Fall vergeht mir echt der Spaß. Ich möchte nunmal maximal 1000 Transaktionen eines Materials anzeigen, ich würde es echt gerne vernünftig machen. Den perfekten Weg hab ich leider noch nicht gefunden.
     
  9. mihe7
    mihe7 Aktives Mitglied
    Als erstes würde ich das Material mal separat darstellen. Die Anforderung, nur 1000 Sätze je Material zu speichern, lässt sich auf verschiedene Arten umsetzen. Hier mal eine Möglichkeit, die für Kurse eine bzgl. des Materials eindeutige ID verwendet:
    Code (SQL):

    CREATE TABLE IF NOT EXISTS material (
        id BIGINT NOT NULL AUTO_INCREMENT,
        description VARCHAR(255) NOT NULL,
        lastKursId BIGINT NOT NULL DEFAULT 0,
        PRIMARY KEY (id)
    );

    CREATE TABLE IF NOT EXISTS `itemKurs` (
            `materialID` BIGINT NOT NULL,
            `kursId` BIGINT NOT NULL,
            `purchasePrice` DOUBLE NOT NULL DEFAULT 0,
            `retailPrice` DOUBLE NOT NULL DEFAULT 0,
            `amount` INT NOT NULL DEFAULT 0,
            `action` VARCHAR(8) NOT NULL DEFAULT '—',
            `priceChange` DOUBLE NOT NULL DEFAULT 0,
            `lang` VARCHAR(255) NOT NULL,
            `time` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
             PRIMARY KEY (materialId, kursId),
             FOREIGN KEY (materialId) REFERENCES material(id)
    ) ENGINE=MyISAM;
    CREATE INDEX ix_itemKurs_time ON itemKurs(TIME);
     
    Dann kann so eingefügt werden:
    Code (SQL):

    SELECT @kid := lastKursId+1  FROM material WHERE id=@mid FOR UPDATE;
    INSERT INTO itemKurs(materialId, kursId, ...) VALUES (@mid, @kid, ...);
    DELETE FROM itemKurs WHERE materialID = @mid AND kursId < @kid - 1000;
    UPDATE material SET lastKursId = @kid WHERE id = @mid;
     
    Je nach Hintergrund der Forderung nach 1000 Einträge je Material kann man die veralteten Einträge auch verzögert (z. B. einmal je Tag) entfernen. Eine andere Überlegung wäre, über die Zeit zu gehen (alles, was älter als 24 h ist etc.).

    Die jüngsten zehn Einträge (je nach Reihenfolge des Einfügens kann es genügen, nur über ID zu sortieren):
    Code (SQL):

    SELECT * FROM itemKurs ORDER BY TIME DESC LIMIT 10;
     
     
    Meniskusschaden gefällt das.
  10. Thallius
    Thallius Bekanntes Mitglied
    Zunächst mal nur so als Tipp: speichere den Preis als int nicht als Double. Das ist schneller und erzeugt keine Rundungsfehler wenn du später mal damit rechnen willst.

    Zweitens: wozu denn die Material Id? Du hast doch das Datum. Ich würde mich hör auch nicht auf die 1000 festlegen sondern, wie Mihe schon schrieb, auf einen Zeitraum. Ich weis nicht in welchen Intervallen deine Datensätze kommen aber wenn z.b. Jede Sekunde einer kommenwürde, dann würde ich einfach alle Datensätze löschen die älter als eine stunde sind. Damit hast du dann immer 3600 Datensätze vorliegen, was dann etwa 3mio Rows in der DB wären. Ob das performanter genug ist hängt halt auch von der Hardware ab. Das Must du auf dem Server ausprobieren. Wenn es zu langsam wird setzt du das Intervall eben runter.

    Und selbst wenn du nur 1000 Datensätze haben wilst zum verwenden, Damm kannst du beim Select immer noch mit Limit 1000 arbeiten.

    Gruß

    Claus
     
  11. Hinweis: Du möchtest Java lernen? Vielleicht hilft dir diese Seite hier weiter.
Thema: MySQLSyntaxErrorException