The target table tab of the UPDATE is not updatable bei MySQL-Kommando

stefanva

Mitglied
Hallo alle zusammen,

ich bekomme immer diese eine Fehlermeldung:
Code:
#1288 - The target table tab of the UPDATE is not updatable
Wenn ich dieses MySQL-Kommando ausführe:
Code:
UPDATE 
(SELECT missing.excused, missing.studentID, missing.minlate FROM `missing` LEFT JOIN (SELECT education.educationID, education.date, education.schoolhour FROM education WHERE education.date='2017-07-21') AS edu ON missing.educationID=edu.educationID INNER JOIN excusable ON edu.date=excusable.date AND edu.schoolhour >= excusable.hour WHERE missing.excused='0' AND missing.studentID='1' AND missing.minlate > 20 ORDER BY edu.schoolhour ASC LIMIT 1) AS tab 
SET missing.excused='1'

Ich komme nicht mehr weiter. Ich wäre jede Art von Hilfe dankbar.

Mit freundlichen Grüßen Stefan
 
Moin Stefan,

Der Alias ist doch auch tab und nicht missing.
Versuche SET tab.excused='1'

Grüße
Biber
 
Hallo Biber,

Danke für deine rasche Antwort.
Ich habe es ausprobiert.
Code:
UPDATE (SELECT missing.excused, missing.studentID, missing.minlate FROM `missing` LEFT JOIN (SELECT education.educationID, education.date, education.schoolhour FROM education WHERE education.date='2017-07-21') AS edu ON missing.educationID=edu.educationID INNER JOIN excusable ON edu.date=excusable.date AND edu.schoolhour >= excusable.hour WHERE missing.excused='0' AND missing.studentID='1' AND missing.minlate > 20 ORDER BY edu.schoolhour ASC LIMIT 1) AS tab SET tab.excused='1'
Es kommt jedoch noch immer die selbe Fehlermeldung. :-/

Grüße
Stefan
 
Moin Stefan,

tja, schade eigentlich.

Ein Versuch vielleicht noch mit
SQL:
UPDATE
 `missing` m LEFT JOIN
   (SELECT education.educationID, education.date, education.schoolhour
     FROM education
     WHERE education.date='2017-07-21'
     ) AS edu ON m.educationID=edu.educationID
     INNER JOIN excusable ON edu.date=excusable.date AND edu.schoolhour >= excusable.hour
     WHERE m.excused='0'
       AND m.studentID='1'
       AND m.minlate > 20
       ORDER BY edu.schoolhour ASC LIMIT 1
SET m.excused='1'

Wenn auch das nicht geht, dann liegt es evtl an der "ORDER BY...LIMIT 1" Klausel. Da bin ich unsicher, ob das bei einem UPDATE erlaubt.
Das liesse sich ggf. umformulieren mit "WHERE NOT EXISTS (irgendein Datensatz mit kleinerer edu.schoolhour)".

Grüße
Biber
 
Hallo Biber,

Dieser Befehl geht leider auch nicht:
SQL:
#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'WHERE m.excused='0'
       AND m.studentID='1'
       AND m.minlate > 20
    ' at line 8

Ohne diesen ORDER BY LIMIT Klausen geht es auch nicht.

Ich schildere mal kurz das Anfangsproblem, vielleicht hast du dann einen bessere Idee als meine.
Ich möchte die ersten Einträge an diesen Tag auf excused=1 setzten. Es sollen aber nicht alle Datensätze von dieser studentID betroffen sein sondern nur die ersten x Anzahl. Das habe ich oben mit LIMIT x versuch.

Vielleicht hat jetzt jemand einen besseren Lösungsansatz.

Grüße
Stefan
 
Zuletzt bearbeitet:
Moin Stefan,

sorry, mein Fehler.
Die WHERE-Klausel gehört natürlich bei dieser Variante definitiv nach die Zeile mit dem SET.
Allerdings sieht dann der ORDER BY..LIMIT-Krams so abstrus aus... das brauchen wird nicht versuchen.

Vielleicht so:
SQL:
UPDATE
 `missing` as m LEFT JOIN
   (SELECT education.educationID, education.date, education.schoolhour
     FROM education
     WHERE education.date='2017-07-21'
     ) AS edu ON m.educationID=edu.educationID
     INNER JOIN excusable ON edu.date=excusable.date AND edu.schoolhour >= excusable.hour

SET m.excused='1'
     WHERE m.excused='0'
       AND m.studentID='1'
       AND m.minlate > 20
 --     and edu.schoolhour in (select min(schoolhour) from education e
 --        where e.educationId=edu.educationID
 --                 and e.date=education.date )

Die letzten drei auskommentierten Zeilen könnten sinngemäß die noch fehlende Einschränkung auf "die letzten x" bilden, also das, was du mit dem LIMIT machen wolltest.

Das habe ich allerdings nicht ganz durchdrungen, was da nun alles für den Studenten "1" in der Missing-Tabelle stehen kann und was gleichzeitig in education und excusable steht.
Vielleicht postest du mal eine Beispiel-Konstellation (also ein paar Beispielsätze aus den 3 Tabellen plus der Ausssage "Updaten will ich DIESEN Satz hier")

Oder du tastest dich selbst heran... du kannst ja die Zeile "Set m.excused='1' ändern auf "Set m.excused=m.excused".
Dann machst du nix kaputt, siehst aber, ob und wie viele Datensätze von UPDATE betroffen sind.

Grüße
Biber
 
Hallo Biber,

Danke für deine Bemühungen.

missing:
studentID | educationID | exused | minlate
1 | 1 | 0 | 50
1 | 2 | 0 | 50
1 | 3 | 0 | 50
2 | 1 | 1 | 50

education:
educationID | classID | date | schoolhour
1 | 1 | 2017-07-21 | 1
2 | 1 | 2017-07-21 | 2
3 | 1 | 2017-07-21 | 3

excusable:
studentID | date | hour
1 | 2017-07-21 | 1

Die roten Zahlen sollen auf 1 gestellt werden. Ich weiß das Datum, die studentID und die Anzahl der Stunden die an diesen Tag excused 1 gestellt werden sollen. In diesen Fall, die ersten zwei. Wobei nur die Stunden auf exused 1 gestellt werden können. An den auch ein Eintrag in excusable getätigt wurde. Diese hour muss aber früher bis gleich als die schoolhour sein.

Ich hoffe das ist verständlich.

Grüße
Stefan
 
Hallo,

ich habe es nach vielen herumprobieren geschafft.
Der Befehl schaut jetzt so aus:
SQL:
UPDATE
    `missing` AS mis LEFT JOIN education AS edu ON mis.educationID=edu.educationID
        INNER JOIN excusable ON edu.date=excusable.date AND edu.schoolhour>=excusable.hour AND mis.excused='0'
     SET `excused`='1'
     WHERE edu.schoolhour IN(SELECT * FROM (SELECT education.schoolhour FROM missing
                                                      LEFT JOIN education ON missing.educationID=education.educationID
                                                      INNER JOIN excusable ON education.date=excusable.date AND education.schoolhour>=excusable.hour AND missing.excused='0' AND missing.studentID='1' AND education.date='2017-07-21'
                                                      ORDER BY education.schoolhour ASC
                                                      LIMIT 1)
                                   AS t)
        AND edu.date='2017-07-21' AND mis.studentID='1'

Wobei ich nicht ganz verstehe wieso das LIMIT nur in einen SUB-Subquery geht und nicht nur in einen Subquery funktioniert. ??

Vielen Dank Biber für deine Hilfe.

Grüße Stefan
 
Moin Stefan,

ich denke, es liess sich wohl auch nur durch probieren lösen - da hatte ich mit meinen ungetesteten Statements wenig Chancen.

Zwei Details sind mir noch aufgefallen.
a) die Bedingung missing.minlate>20 hast du vergessen
b) wie ich in deinen Beispieldaten gesehen habe, gibt es auch in der excused-Tabelle ein Feld "StudentID"
Evtl muss auch da auf Gleichheit mit missing.studentID geprüft werden?

(Ist aber auch nur Bauchgefühl - ich kenne weder die PKs der Tabellen noch die Beziehungen)

Grüße
Biber
 
Hallo Biber,

a) die Bedingung missing.minlate>20 hast du vergessen
Da hast recht.
b) wie ich in deinen Beispieldaten gesehen habe, gibt es auch in der excused-Tabelle ein Feld "StudentID"
Stimmt, das habe ich auch übersehen. Gut erkannt von dir.

Jetzt, fertig schaut der Befehl so aus, für alle die es interessiert.
SQL:
UPDATE
    `missing` AS mis LEFT JOIN education AS edu ON mis.educationID=edu.educationID
        INNER JOIN excusable ON mis.studentID=excusable.studentID AND edu.date=excusable.date AND edu.schoolhour>=excusable.hour AND mis.minlate>20 AND mis.excused='0'
     SET `excused`='1'
     WHERE edu.schoolhour IN(SELECT * FROM (SELECT education.schoolhour FROM missing
                                                      LEFT JOIN education ON missing.educationID=education.educationID
                                                      INNER JOIN excusable ON education.date=excusable.date AND education.schoolhour>=excusable.HOUR AND missing.minlate>20 AND missing.excused='0' AND missing.studentID='1' AND education.DATE='2017-07-21' AND excusable.studentID=missing.studentID
                                                      ORDER BY education.schoolhour ASC
                                                      LIMIT 2)
                                   AS t)
        AND edu.date='2017-07-21' AND mis.studentID='1'

Nochmal vielen Dank für deine Hilfe.

Eine Frage noch, wieso machst du dir eigentlich so viel Arbeit und hilft allen so gut?

Grüße Stefan
 
Zurück