Insert Into mit Subquery funktioniert nicht richtig

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 12 Antworten in diesem Thema. Der letzte Beitrag () ist von MemoAnMichSelbst.

    Insert Into mit Subquery funktioniert nicht richtig

    Hallo zusammen,

    nachdem ich hier in den Vergangenen Jahren immer ordentlich Hilfe bekommen habe und zum Glück alle Fragen meinerseits durch schon vorhandene Themen beantwortet werden konnten, bin ich nun soweit, dass ich nicht mehr weiter weiß ;(

    Ich habe für die Arbeit in VB ein Programm geschrieben, dass mit einer Datenbank zusammen arbeitet. Nun möchte ich einen "Insert Into" Query durchführen mit einem Subquery. Der CommandText wird im Quellecode so zusammen gesetzt:

    SQL-Abfrage

    1. "INSERT INTO Schichtplan (Datum, Schicht, Personalnummer, Arbeitsplatz, Gruppe) SELECT " _
    2. & Str(i) & ",'" & schicht & "',Mitarbeiter.Personalnummer AS persNr FROM Mitarbeiter WHERE Mitarbeiter.Name='" & name & "','" & arbeitsplatz & "'," & maxGruppe


    Der Befehl sieht mit eingesetzten Variablen dann so aus:

    SQL-Abfrage

    1. INSERT INTO Schichtplan (Datum, Schicht, Personalnummer, Arbeitsplatz, Gruppe) SELECT 42360,'Frühschicht',Mitarbeiter.Personalnummer AS persNr FROM Mitarbeiter WHERE Mitarbeiter.Name='Fischer','Mutal 1',2


    Jetzt bekomme ich immer wieder denselben Fehler:
    "Anzahl der Abfragewerte und Zielfelder stimmt nicht überein"

    Ich weiß aber nicht mehr wo ich gucken muss. Nach stundenlangem Googlen finde ich keinen Fehler mehr im Code. Die Syntax muss richtig sein und auch der Subquery, wenn ich ihn allein ausführe, liefert nur exakt eine Personalnummer. Da die Mitarbeiter mit ihren Personalnummern in einer Tabelle stehen, die Personalnummer als Schlüsselspalte festgelegt ist, und gleiche Nachnamen mit den Anfangsbuchstaben der Vornamen ergänzt werden, kann auch nur ein Eintrag beim Subquery herauskommen. ?(

    Ich wäre froh, wenn irgendjemand mir auf die Sprünge helfen könnte...

    Vielen Dank schon mal! :)
    Du möchtest in eine Tabelle mit 5 Feldern 3 Werte pro Zeile schreiben. 5 ist ungleich 3.

    Ausserdem ist dieser where-Clause richtig? Mir ist nicht bekannt, dass ich sowas schreiben könnte, wie: where field1='a', 'b'. Aber in dieser Hinsicht mag ich falsch liegen.
    Ich würd das Subselect mal ganz gewieft in Klammern setzen.

    EDIT:
    Wobei mir nen Rätsel ist, wieso man in VB.Net mit direkten SQL Statements arbeitet. Und der Code was SQL Injections angeht... Naja müssma nicht drüber reden.
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    ... Nun solltest es selber wissen. :'D
    Values muss man nicht übergeben, wenn man aus einer Tabelle in die Andere überträgt.
    Aber wie sich das verhält wenn man ein Select und manuelle Werte mischt, weiß ich nicht.
    Ich würd tatsächlich das Subselect erstmal in Klammern setzen, damit er weiß was zusammen gehört.
    Ggf. dann noch Values ergänzen. Aber nicht inner Echtumgebung hoffe ich.
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    ... Nun solltest es selber wissen. :'D
    Die Resonanz kommt ja ziemlich flott.

    @vb_fan: Es sollte sich genau um 5 Spalten handeln, die auch mit 5 Werten gefüllt werden. Sobald ich statt des Subquerys einen festen Wert eintrage, funktioniert der Code. So wie ich das verstanden habe endet der Where-Clause bei dem Komma. Dahinter steht der Wert für das nächste Feld.

    @MemoAnMichSelbst: Die Klammern bewirken nichts als einen Syntaxfehler. Nach meinen stundenlangen Google-Suchen bin ich aber auch auf genau die Form gekommen, die ich nutzen möchte. Was genau meinst du mit SQL-Injections? Ich kenne mich da leider nicht wirklich gut aus, da ich auch noch nicht lange programmiere und mir alles selbst beigebracht habe...

    der SQL-Code wird natürlich über das OleDB Modul weitergegeben. Eben einem OleDBCommand als CommandText zugewiesen.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „mapeli“ ()

    mapeli schrieb:

    (Datum, Schicht, Personalnummer, Arbeitsplatz, Gruppe)


    Das sind 5 Spalten.

    mapeli schrieb:

    Str(i) & ",'" & schicht & "',Mitarbeiter.Personalnummer AS persNr


    Und das sind 3 Werte.

    3 Werte passen in 5 Spalten nicht!

    Das sagt auch die Fehlermeldung:

    mapeli schrieb:

    Anzahl der Abfragewerte und Zielfelder stimmt nicht überein


    Wie ich sehe, hast du nicht die richtige Reihenfolge. Korrigiere mal.

    So müsste es gehen:

    mapeli schrieb:

    INSERT INTO Schichtplan (Datum, Schicht, Arbeitsplatz, Gruppe, Personalnummer) SELECT 42360,'Frühschicht','Mutal 1',2, Mitarbeiter.Personalnummer AS persNr FROM Mitarbeiter WHERE Mitarbeiter.Name='Fischer'



    Sql-Injection
    Hier wird das genau erklärt.

    @vb_fan
    Es gehören zu den 3 von dir genannten Spalten noch arbeitsplatz und maxGruppe (nicht Hartcodiert - EDIT)
    dazu.
    Und ich glaube hier ist das Problem. Das Statement erkennt nicht wo das Subselect endet...
    Es soll mit dem Subselect ja nur aufgefüllt werden.

    VB.NET-Quellcode

    1. "INSERT INTO Schichtplan (Datum, Schicht, Personalnummer, Arbeitsplatz, Gruppe) VALUES ((SELECT " _
    2. & i & ", '" & schicht & "', Mitarbeiter.Personalnummer FROM Mitarbeiter WHERE Mitarbeiter.Name='" & Name & "'), '" & arbeitsplatz & "', " & maxGruppe & ")"
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    ... Nun solltest es selber wissen. :'D

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „MemoAnMichSelbst“ ()

    Wow!

    So einfach kann es manchmal sein. Danke für den Gedankenanstoß. Nach erfolgreicher Umstellung der Werte funktioniert es endlich. Das SubSelect muss anscheinend am Ende stehen, damit er - wie du schon richtig vermutet hast - das Ende des SubSelects erkennt.

    Danke auch für den Hinweis auf SQL-Injection. In der Tat ein interessanter Punkt den ich mir mal genauer angucken sollte. Hier spielt das aber keine Rolle, da nichts von den Variablen händisch eingegeben werden kann. Ist aber wohl besser, immer mit Parametern zu arbeiten ...

    Danke Euch!

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „mapeli“ ()

    @MemoAnMichSelbst

    Ja, das habe ich später auch bemerkt. Wenn du das so machst (also mit VALUES), dann brauchst du aber noch mal zwei Klammern:

    SQL-Abfrage

    1. "INSERT INTO Schichtplan (Datum, Schicht, Personalnummer, Arbeitsplatz, Gruppe) VALUES ((SELECT " _
    2. & Str(i) & ", '" & schicht & "', Mitarbeiter.Personalnummer FROM Mitarbeiter WHERE Mitarbeiter.Name='" & name & "',) '" & arbeitsplatz & "', " & maxGruppe)


    oder so:

    SQL-Abfrage

    1. INSERT INTO Schichtplan (Datum, Schicht, Arbeitsplatz, Gruppe, Personalnummer) SELECT 42360,'Frühschicht','Mutal 1',2,
    2. Mitarbeiter.Personalnummer AS persNr FROM Mitarbeiter WHERE Mitarbeiter.Name='Fischer'
    Ich hab schon Parameterübergaben genutzt. Aber nur, weil es anders nicht ging. Irgendwas war da mit dem Datumsformat oder so... Dass es auf der sicherheitstechnischen Seite so wichtig ist, war mir allerdings nicht bewusst...

    Ich habe gerade auch mal probiert, mit Values und einem eingeklammerten Select zu arbeiten. Dabei gibt er allerdings einen Syntaxfehler aus...
    Wenn du die zwei Felder ins Select des Subselect schubbst, anstelle sie ans Ende zu setzen, machter das aber denk ich auch brav.
    Nichtsdestotrotz sind dbparameter ganz nett.
    Der Erfinder hat ja in dem verlinkten Beitrag auch einen Beitrag verlinkt wo er ne Extension hinterlegt hat, was die Verwendung der DBParameter vereinfacht.
    Sehr nützlich und damit nur wenig Code und weit übersichtlicher zu lesen.
    Du merkst ja selbst, wie man durcheinanderkommt bei den Ganzen & & & & & &...

    EDIT:
    Hier Tipp & Trick: DbParameter
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    ... Nun solltest es selber wissen. :'D