2016-10-21 1 views
0

Ich habe eine einfache Abfrage, um eine Zwischentabelle mit einigen Werten aus einer VB NET-Anwendung zu aktualisieren. Ich bin nur die BinLength Tabelle zu aktualisieren und ich diese Fehlermeldung erhalten, wenn ich versuche, das zu tun:Fremdschlüssel existiert und ich bekomme MySQL Error: 1452: Hinzufügen oder Aktualisieren einer untergeordneten Zeile: eine Fremdschlüsseleinschränkung schlägt fehl

MySQL Error: 1452: Cannot add or update a child row: a foreign key constraint fails. 

Was ich weiß, es sagt mir, dass der damit verbundene FK Id existiert nicht in die übergeordneten Tabelle.

[Doch es existiert!]. Ich habe es ein paar Wege zum Sonnenschein angefragt und sie sind alle da - jede der FK-Spalten in meiner Tabelle hat eine entsprechende ID in ihrer fremden Tabelle!

Also, welche Art von Fehler ist dies ..

ich auch InnoDb in allen meine Tabellen verwendet, damit ich es weiß, unterstützt Einschränkung FK.

Mit Blick auf die Daten und die unten angegebenen Informationen kann mir jemand in die richtige Richtung zeigen, um dieses Problem zu lösen. Ich knalle meinen Kopf auf SO und MySQL, um eine Antwort für 4 oder 5 Stunden jetzt zu finden, und ich bin jetzt näher an der Lösung.

Im Folgenden habe ich meine Befehle zum Einfügen und Aktualisieren, die vom Befehlsgenerator bereitgestellt werden. SQL VON MYSQL COMMAND BUILDER

UPDATE `binlength` SET `binID` = @p1, `lengthID` = @p2, `recipeID` = @p3, `IsSelected` = @p4 WHERE ((`ID` = @p5) AND (`binID` = @p6) AND (`lengthID` = @p7) AND (`recipeID` = @p8) AND ((@p9 = 1 AND `IsSelected` IS NULL) OR (`IsSelected` = @p10))) 

INSERT INTO `binlength` (`binID`, `lengthID`, `recipeID`, `IsSelected`) VALUES (@p1, @p2, @p3, @p4) 

Im Folgenden habe ich die 3 Tabellen von Interesse - Id der Primärschlüssel ist. TableNameId repräsentiert einen Fremdschlüssel.

TABELLE BINLENGTH Relevante Daten.

# ID, binID, lengthID, recipeID, IsSelected 
14,  1, 1, 1, 1 
15,  1, 2, 1, 1 
16,  1, 3, 1, 1 
17,  1, 4, 1, 1 
18,  1, 5, 1, 1 
19,  1, 6, 1, 1 
20,  1, 7, 1, 1 
21,  1, 8, 1, 1 
22,  1, 9, 1, 1 
23,  1, 10, 1, 1 
24,  1, 11, 1, 1 
25,  1, 12, 1, 1 
26,  1, 13, 1, 1 
27,  1, 14, 1, 1 
32,  8, 5, 1, 1 
33,  8, 6, 1, 1 
34,  8, 7, 1, 1 
35,  2, 5, 1, 1 
36,  25, 5, 1, 1 
37,  28, 6, 1, 1 
38,  20, 4, 1, 1 

TABLE BINS Relevante Daten

# Id, Name, Filling_Width, Filling_Pc, Filling_Mbf, Mbf_Calculate, DimensionID, RecipeID, BinSetupID 
1 BIN 1 0 0 0 0 1 1 1 
2 BIN 2 99.99 99 99.99 99 12 1 2 
3 BIN 3 0 0 0 0 1 1 3 
4 BIN 4 0 0 0 0 1 1 4 
5 BIN 5 0 0 0 0 12 1 5 
6 BIN 6 12 12 12 12 9 1 6 
7 BIN 7 0 0 0 0 2 1 7 
8 BIN 8 12 12 12 12 2 1 8 
9 BIN 9 0 0 0 0 17 1 9 
10 BIN 10 0 0 0 0 1 1 10 
11 BIN 11 0 0 0 0 24 1 11 
12 BIN 12 0 0 0 0 9 1 12 
13 BIN 13 0 0 0 0 1 1 13 
14 BIN 14 0 0 0 0 1 1 14 
15 BIN 15 0 0 0 0 1 1 15 
16 BIN 16 0 0 0 0 1 1 16 
17 BIN 17 0 0 0 0 1 1 17 
18 BIN 18 0 0 0 0 1 1 18 
19 BIN 19 0 0 0 0 1 1 19 
20 BIN 20 0 0 0 0 1 1 20 
21 BIN 21 0 0 0 0 1 1 21 
22 BIN 22 0 0 0 0 1 1 22 
23 BIN 23 0 0 0 0 1 1 23 
24 BIN 24 0 0 0 0 1 1 24 
25 BIN 25 0 0 0 0 1 1 25 
26 BIN 26 0 0 0 0 1 1 26 
27 BIN 27 0 0 0 0 1 1 27 
28 BIN 28 0 0 0 0 1 1 28 
29 BIN 29 0 0 0 0 1 1 29 
30 BIN 30 0 0 0 0 1 1 30 

Tischlängen Relevante Daten

# Id, Name, Min, Max, Nom, Actual_Real, Set_Default, Set_Enable, Visible, ndx 

1 LENGTH1  0.000 0.000 0.000 0.000 1 0 0 1 
2 LENGTH2  0.100 0.200 0.000 0.000 0 1 0 2 
3 LENGTH3  0.000 0.000 0.000 0.000 0 0 0 3 
4 LENGTH4  0.000 0.000 0.000 0.000 0 0 0 4 
5 LENGTH5  0.000 0.000 0.000 0.000 0 0 0 5 
6 LENGTH6  0.000 0.000 0.000 0.000 0 0 0 6 
7 LENGTH7  0.000 0.000 0.000 0.000 0 0 0 7 
8 LENGTH8  0.000 0.000 0.000 0.000 0 0 0 8 
9 LENGTH9  0.000 0.000 0.000 0.000 0 0 0 9 
10 LENGTH10 0.000 0.000 0.000 0.000 0 0 0 10 
11 LENGTH11 0.000 0.000 0.000 0.000 0 0 0 11 
12 LENGTH12 0.000 0.000 0.000 0.000 0 0 0 12 
13 LENGTH13 0.000 0.000 0.000 0.000 0 0 0 13 
14 LENGTH14 0.000 0.000 0.000 0.000 0 0 0 14 
15 LENGTH15 0.000 0.000 0.000 0.000 0 0 0 15 
16 LENGTH16 0.000 0.000 0.000 0.000 0 0 0 16 
17 LENGTH17 0.000 0.000 0.000 0.000 0 0 0 17 
18 LENGTH18 0.000 0.000 0.000 0.000 0 0 0 18 
19 LENGTH19 0.000 0.000 0.000 0.000 0 0 0 19 
20 LENGTH20 0.000 0.000 0.000 0.000 0 0 0 20 

Werte, die ich mit dem MySQL-Datenadapter einfügen versuchen:

Row, ID, binID, lengthID, recipeID, IsSelected 

0, 39, 6, 4, 1, 1 

1, 40, 6, 6, 1, 1 

Ich lief dieser SQL-Code gegen meine Tabellen zu versuchen, um festzustellen, was falsch war.

SELECT DISTINCT BLength.ID 
FROM binlength As BLength LEFT JOIN bins As bay 
ON BLength.BinId=bay.id 
WHERE bay.id IS NULL; 

SQL Tabellendefinitionen

CREATE TABLE `binlength` (
    `ID` int(11) NOT NULL AUTO_INCREMENT, 
    `binID` int(11) NOT NULL DEFAULT '0' COMMENT 'References the Bin.ID column of Table Bins', 
    `lengthID` int(11) NOT NULL DEFAULT '0' COMMENT 'References the Length.ID column of Table Lengths', 
    `recipeID` int(11) NOT NULL DEFAULT '0' COMMENT 'References the Recipe.ID column of Recipe Table.', 
    `IsSelected` int(1) DEFAULT '0' COMMENT 'Length is enabled for the selected bin.', 
    PRIMARY KEY (`ID`), 
    UNIQUE KEY `ID_UNIQUE` (`ID`), 
    KEY `FK_BINID_BINID_idx` (`binID`), 
    KEY `FK_LENID_LENID_idx` (`lengthID`), 
    KEY `NDX_RecipeID` (`recipeID`), 
    CONSTRAINT `FK_BINID_BINID` FOREIGN KEY (`binID`) REFERENCES `bins` (`Id`) ON DELETE CASCADE ON UPDATE CASCADE, 
    CONSTRAINT `FK_LENID_LENID` FOREIGN KEY (`lengthID`) REFERENCES `lengths` (`Id`) ON DELETE CASCADE ON UPDATE CASCADE 
) ENGINE=InnoDB AUTO_INCREMENT=44 DEFAULT CHARSET=utf8 COMMENT='Intermediary Table [aka Associative Table] for bins and length'; 



CREATE TABLE `bins` (
    `Id` int(11) NOT NULL AUTO_INCREMENT, 
    `Name` varchar(45) NOT NULL DEFAULT 'BIN UNDEFINED', 
    `Filling_Width` float NOT NULL DEFAULT '0', 
    `Filling_Pc` int(11) NOT NULL DEFAULT '0', 
    `Filling_Mbf` float NOT NULL DEFAULT '0', 
    `Mbf_Calculate` int(11) NOT NULL DEFAULT '0', 
    `DimensionID` int(11) DEFAULT NULL, 
    `RecipeID` int(11) NOT NULL DEFAULT '0', 
    `BinSetupID` int(11) DEFAULT '1', 
    PRIMARY KEY (`Id`), 
    UNIQUE KEY `Id_UNIQUE` (`Id`), 
    KEY `FK_RecipeID_BINS_idx` (`RecipeID`), 
    KEY `FK_BinRecipeID_Recipe_ID_idx` (`RecipeID`), 
    KEY `BinSetUpID_ndx` (`BinSetupID`), 
    CONSTRAINT `FK_BinRecipeID_Recipe_ID` FOREIGN KEY (`RecipeID`) REFERENCES `recipe` (`Id`) ON DELETE CASCADE ON UPDATE CASCADE 
) ENGINE=InnoDB AUTO_INCREMENT=1433 DEFAULT CHARSET=utf8; 


CREATE TABLE `lengths` (
    `Id` int(11) NOT NULL AUTO_INCREMENT, 
    `Name` varchar(82) DEFAULT '""', 
    `Min` decimal(11,3) DEFAULT '0.000', 
    `Max` decimal(11,3) DEFAULT '0.000', 
    `Nom` decimal(11,3) DEFAULT '0.000', 
    `Actual_Real` decimal(11,3) DEFAULT '0.000', 
    `Set_Default` int(11) DEFAULT '0', 
    `Set_Enable` int(11) DEFAULT '0', 
    `Visible` int(11) DEFAULT '0', 
    `ndx` int(11) DEFAULT NULL, 
    PRIMARY KEY (`Id`) 
) ENGINE=InnoDB AUTO_INCREMENT=21 DEFAULT CHARSET=utf8; 

CREATE TABLE `recipe` (
    `Id` int(11) NOT NULL AUTO_INCREMENT, 
    `Name` varchar(80) NOT NULL DEFAULT 'UnAssigned', 
    `IsDefault` tinyint(1) DEFAULT '0', 
    PRIMARY KEY (`Id`), 
    UNIQUE KEY `Name_UNIQUE` (`Name`), 
    UNIQUE KEY `Id_UNIQUE` (`Id`) 
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8; 

EDIT

in meinem VB-Code zu laden ich die Daten in der MySQL-Tabelle Schließen der Verbindung und der Dataadapter angeordnet ist - ich Änderungen an die VB-Datentabelle. Ich rufe dann die SaveDataTable() Methode auf.

Mein relevanter VB-Code ist wie folgt: MySQLConector Version ist 6.98

Private Sub AddRows() 
datasTable = Load_Table("Select * From Where RecipeID= 1") 

' For the added rows 
         Dim drow As DataRow = dt.NewRow() 
' Iam not setting the Id field in my code - I do not need to the addrow method magically adds it - based on MissingSchemaAction addwithkey 
         drow("Id") = 41 ' This is the next sequence number - it was grabbed from the load. 
         drow("binID") = 13 
         drow("lengthId") = 1 
         drow("recipeID") = 1 
         drow("IsSelected") = 1 
         drow.EndEdit() 
         dt.Rows.Add(drow) 


End Sub 

ORIGINAL Last

Private Function Load_Table(query As String) As DataTable 

    Dim table As DataTable = New DataTable 

    Using Conn As MySqlConnection = New MySqlConnection(DatabaseConnection) 

     Using Comm As MySqlCommand = New MySqlCommand(query, Conn) 

      Comm.CommandType = CommandType.Text 

      Using SDA As MySqlDataAdapter = New MySqlDataAdapter(Comm) 

       Try 

        Conn.Open() 

        SDA.MissingSchemaAction = MissingSchemaAction.AddWithKey 

        SDA.Fill(table) 

       Catch sqlError As MySqlException 

        Dim exErr As String = String.Format("{0}: {1}", sqlError.Number, sqlError.Message) 
        MessageBox.Show(exErr, "Error While Loading Table", MessageBoxButtons.OK, MessageBoxIcon.Error) 

       Catch ex As Exception 

        MessageBox.Show(ex.Message, "Error While Loading Table", MessageBoxButtons.OK, MessageBoxIcon.Error) 

       Finally 

        Conn.Close() 

       End Try 

      End Using 

     End Using 

    End Using 

    Return table 

End Function 

SAVE DATA

Private Sub SaveDataTable(datasTable As DataTable, query As String) 

     Using con As MySqlConnection = New MySqlConnection(DatabaseConnection) 

      Using comm As MySqlCommand = New MySqlCommand(query, con) 

       comm.CommandType = CommandType.Text 

       Using mySDA As MySqlDataAdapter = New MySqlDataAdapter(comm) 

        Try 

         con.Open() 

         Dim dt As DataTable = New DataTable 

      ' tried both with and with out this MissingSchemaAction 
        ' mySDA.MissingSchemaAction = MissingSchemaAction.AddWithKey 

         mySDA.Fill(dt) 

      ' Tried Both of these .. 

         dt.Merge(datasTable, True) 

        ' dt.Merge(datasTable, False) 

         Dim cmdBuild As MySqlCommandBuilder = New MySqlCommandBuilder(mySDA) 

      ' Tried Building my own commands as well - same results. 

      cmdBuild.GetInsertCommand() 
         cmdBuild.GetUpdateCommand() 
         cmdBuild.GetDeleteCommand() 

         mySDA.Update(dt) 


        Catch sqlError As MySqlException 

         Dim exErr As String = String.Format("MySQL Error: {0}: {1}", sqlError.Number, sqlError.Message) 
         MessageBox.Show(exErr, "Error While Saving Table", MessageBoxButtons.OK, MessageBoxIcon.Error) 

        Catch concurrencyError As DBConcurrencyException 

         MessageBox.Show(concurrencyError.Message.ToString(), "Error While Saving Table", MessageBoxButtons.OK, MessageBoxIcon.Error) 

        Catch ex As Exception 

         MessageBox.Show(ex.Message.ToString(), "Error While Saving Table", MessageBoxButtons.OK, MessageBoxIcon.Error) 

        Finally 

         con.Close() 

        End Try 

       End Using 

      End Using 

     End Using 

End Sub 

In MySqlException ich bekommen kann nicht hinzugefügt oder ein Kind Zeile aktualisieren: a. Fremdschlüssel fehlschlägt (mydatabasebinlength, CONSTRAINT FK_BINID_BINID FREMDSCHLÜSSEL (binID) REFERENZEN bins (Id) ON LÖSCHEN CASCADE ON UPDATE CASCADE)

Wenn ich meine eigene Abfrage erstellen, wo ich den Primärschlüssel mit den Werten einschließen - ich bekomme binId kann nicht null sein - aber es ist nicht null!

Wenn ich das Ding massiere und die hinzugefügten Zeilen auf "modifiziert" setze, gibt der SQL Adapter keinen Fehler aus, aber er update die Datenbank auch nicht.

Wenn sie in einem unveränderten Zustand sind - passiert natürlich nichts und ich bekomme auch keinen Fehler.

Bilder hinzugefügt

Bins BinLengthRows Lengths

+0

Sie haben vergessen, den kritischsten Teil, die tatsächlichen Tabellendefinitionen. Bilder der Tabellen/Daten sind schön, aber grundsätzlich nutzlos. Sie müssen die Feld- und FK-Definitionen anzeigen. –

+0

@MarcB Ich veröffentlichte die Create Table Statements - sollte alles zeigen, was benötigt wird. – Ken

+0

Sie verwenden Variablen in Ihren updates/insert-Anweisungen. Das könnte dumm und offensichtlich sein, aber Sie sind sicher, dass sie eingestellt sind, bevor Sie die Befehle ausführen, ja? (Kann nicht weh tun, um die kleinen Dinge zu überprüfen ...) – jhaagsma

Antwort

0

WOW 2 Tage hämmern und ich fand schließlich die Antwort. Ich poste dies hier zugunsten anderer, die vielleicht mit einem ähnlichen Problem kämpfen.

In meinem Szenario wurde die Datentabelle an eine Bindungsquelle gebunden - die ich gefiltert habe. Ich brauchte nur die gefilterte Liste - also klonte ich meine Tabelle und importierte dann die gefilterten Zeilen. Ich habe diese neue Tabelle an meine Speichermethode übergeben.

Meine Speichermethode verwendet den MySqlDataAdapter, um eine Datentabelle [dt] mit den Tabellendaten zu füllen. Ich füge das dann mit meiner Tabelle zusammen, die die importierten Zeilen enthält.

So war, dass mein Szenario das Problem in der SaveDataTable Verfahren ist durch diese Codezeile verursacht:

Dim dt As DataTable = New DataTable

mySDA.Fill(dt)

Wenn ich diese Zeile dazu geändert:

Dim dt As DataTable = datasTable.Clone()

mySDA.Fill(dt)

Der Code, wie es funktioniert sollte haben. Ich kann nicht erklären, warum das funktionierte und die anderen nicht aus derselben Tabelle stammen. aber wenn ich das Original klonen und es füllen, dann füge ich es wieder mit Original zusammen - es funktioniert. Vielleicht hat jemand, der liest, die Antwort darauf und würde nichts dagegen haben, einen Kommentar zu schreiben.

Ich hoffe, dass dies jemand anderen hilft, der ein ähnliches Problem hat.

Arbeits-Code unten:

Private Sub SaveDataTable(datasTable As DataTable, query As String) 

     Using con As MySqlConnection = New MySqlConnection(DatabaseConnection) 

      Using comm As MySqlCommand = New MySqlCommand(query, con) 

       comm.CommandType = CommandType.Text 

       Using mySDA As MySqlDataAdapter = New MySqlDataAdapter(comm) 

        Try 

         con.Open() 

         Dim dt As DataTable = datasTable.Clone() 

         mySDA.Fill(dt) 

         dt.Merge(datasTable, False) 

         mySDA.AcceptChangesDuringUpdate = True 

         Dim cmdBuild As MySqlCommandBuilder = 
             New MySqlCommandBuilder(mySDA) 

         cmdBuild.GetDeleteCommand() 

         cmdBuild.GetInsertCommand() 

         cmdBuild.GetUpdateCommand() 

         mySDA.Update(dt) 

         Success = True 

        Catch sqlError As MySqlException 

         Dim exErr As String = String.Format("MySQL Error: 
         {0}: {1}", sqlError.Number, sqlError.Message) 
         MessageBox.Show(exErr, "Error While Saving Table", 
         MessageBoxButtons.OK, MessageBoxIcon.Error) 

        Catch concurrencyError As DBConcurrencyException 

         MessageBox.Show(concurrencyError.Message.ToString(), 
         "Error While Saving Table", MessageBoxButtons.OK, 
         MessageBoxIcon.Error) 

        Catch ex As Exception 

         MessageBox.Show(ex.Message.ToString(), "Error While 
         Saving Table", MessageBoxButtons.OK, 
         MessageBoxIcon.Error) 

        Finally 

         con.Close() 

        End Try 

       End Using 

      End Using 

     End Using 

End Sub 
Verwandte Themen

 Verwandte Themen