Rolf B: mysql: Error 1111 bei Verwendung von UPDATE und CONCAT

Beitrag lesen

Hallo Flo,

SUM ist eine Gruppierungsfunktion, genau, und kann als solche nur in einem SELECT verwendet werden. Ich frag mich nur was Du da eigentlich vorhast?

Ich versuche mal, den Select zu verstehen.

Da steht:

CONCAT('Anfangstext ', ...monster..., ' Endtext', Spalte)

Du baust also aus 4 Teilen einen String zusammen und gibst ihn als Ergebnis aus. Bzw. im Update-Statement möchtest Du daraus einen neuen Spaltenwert zusammenbauen.

Na gut, kann man machen - sollte man aber definitiv nur nach reiflicher Überlegung tun. Datenbanken haben die Aufgabe, Daten aufzubewahren und so zu speichern, dass man leicht damit hantieren kann. Die Aufbereitung für ein bestimmtes UI ist Sache der Anwendung, die die Datenbank nutzt. Genau das tust Du an dieser Stelle nicht. Hinzu kommt, dass Du auf diese Weise Redundanz erzeugst. Redundanz ist das Schmieröl der Datenbank, aber wehe, du vergisst dann diesen Schmiernippel irgendwann. Redundanzen baut man nur ein, wenn die DB andernfalls zu langsam wird. In deinem Fall wäre der redundante Wert das Ergebnis des Monsters, und die Einbettung in Text ist definitiv eine Aufgabe für die Anwendung, nicht für die Datenbank.

Und was tut das "Monster" im Concat? Es sieht so aus:

SUM(TRIM(LENGTH(Tore))-TRIM(LENGTH(REPLACE(Tore,',',''))))+1
               '----'                     '-----------'
        '------------'            '--------------------'
                           '----------------------------'
   '-----------------------------------------------------'

Dabei wird jedem respektablen SQL Server schlecht. Und dieser Ausdruck zeigt, dass Du Dich mit den Themen "Datentypen" dringend beschäftigen musst.

Tore
das ist mutmaßlich ein String. Und der kann Kommas enthalten. Nun gut. Du erwähntest den Konstruktionsfehler ja schon.
LENGTH(...)
das ist die Länge eines Strings, also eine Zahl. Du bestimmst einmal die Stringlänge und einmal die Stringlänge ohne die Kommas. Aha. Soso. Der Konstruktionsfehler beginnt, sein Wesen zu enthüllen 😉.
TRIM(...)
entfernt Leerstellen vom Anfang und Ende eines Strings. Aber Du wendest das auf eine Zahl an?! MySQL muss also die ermittelte Länge nun erstmal in einen String konvertieren, um davon dann die führenden und abschließenden Leerstellen zu amputieren. Die gibt's aber gar nicht. MYSQL setzt keine Spaces vor oder hinter eine Zahl, die es on the fly in einen String konvertiert.
TRIM(x) - TRIM(y)
TRIM liefert einen String. Aber für Strings ist der "-" Operator in SQL nicht definiert[1]. Der versteht nur Zahlen. MySQL hat also mühsam Zahlen in Strings verwandelt und nun werden wieder Zahlen draus, die Du dann subtrahierst.

Und das Ergebnis ist: Die Anzahl der Kommata in "Tore".

Erster Schritt zum Verständnis wäre also: Die TRIMs sind weder Handwerks- noch schöne Kunst und können ersatzlos weg.

SUM(LENGTH(Tore) - LENGTH(REPLACE( Tore, ',', '' ))) + 1,

Nun steht da noch SUM. Das ist eine Aggregatfunktion, und sie ergibt nur dann einen Sinn, wenn die Query (ohne das SUM) mehr als einen Satz liefern kann. Ist das bei Dir so? Du fragst nämlich SpieleID=... ab. Ist die SpieleId in deiner Table ein Primär- oder ein Fremdschlüssel?

Wenn sie Primärschlüssel ist (d.h. es gibt zu jeder SpieleId genau eine Zeile in table), dann kann auch der SUM weg.

Wenn sie ein Fremdschlüssel ist (d.h. table enthält pro SpieleId keinen, einen oder auch mehrere Sätze mit Tore-Angaben), dann ergibt SUM schon einen Sinn, aber dann würde ich fragen, ob das "+1" an der richtigen Stelle steht. Was willst Du da bestimmen? Die Anzahl der kommagetrennten Einträge in "Tore", über alle Sätze dieser SpieleId hinweg? Dann müsste das +1 innerhalb des SUM() stehen.

Allerdings ergibt der UPDATE dann keinen Sinn mehr. Wenn SpieleId nämlich ein Fremdschlüssel ist, dann ist es in einer einzelnen Zeile von table nicht unbedingt sinnvoll, die Anzahl von Tore-Angaben über alle Zeilen mit dieser SpieleId hinweg zu vermerken.

Dieser Vermerk ist - wie eingangs erwähnt - in der DB ohnehin nicht sinnvoll. Es ist eine redundante Information, und Du müsstest den Inhalt von "Spalte" ständig mühsam aktuell halten, sobald sich irgendwo in "Tore" die Anzahl der Werte ändert.

Und wenn der Konstruktionsfehler "Tore" behoben wird - der da lautet: Eklatante Verletzung der ersten Normalform, die ein "Array-Feld" verbietet - dann ist das Problem eh keins mehr, weil Du dann nämlich einfach die Sätze mit Tore-Angaben zählst.

Wenn dann auch noch der Konstruktionsfehler "Datenaufbereitung in der DB" behoben wird, entfällt auch der Update.

Es sei denn, ich habe das alles grob mistverstanden.

Rolf

--
sumpsi - posui - obstruxi

  1. Die einzige mir bekannte Sprache, die ein "-" für Strings definiert hat, war dBase. Eine Stringverkettung mit "-" hat die Spaces am Ende des ersten Operanden hinter den zweiten Operanden geschoben. "A " - "B " ergab "AB ". Hilfreich, wenn man mit einem Monospace-Font Tabellen erzeugt hat und darin Spalten aus Strings zusammengesetzt werden mussten. Ah, die 80er... ↩︎