2016-09-13 1 views
-1

Ich habe eine Verarbeitungs-Engine in C geschrieben, die 40k Datensätze aus einer Tabelle extrahiert, die Daten verarbeitet und Ergebnisse in eine andere Tabelle schreibt. Wenn ich die verarbeiteten Daten auf dem Bildschirm ausdrucke, sieht es perfekt aus, so dass alle Variablen die richtigen Werte enthalten. Ich muss die Daten in eine Tabelle schreiben, die 3 Spalten als Primärschlüssel hat. Ich schaffe die Tabelle wie folgt aus:Unerklärtes MySQL-Verhalten mit C libmysqlclient

CREATE TABLE halfcomp 
(
    MarketCode varchar(20) NOT NULL, 
    TRZNum varchar(20) NOT NULL, 
    origTRZNum varchar(20) NOT NULL, 
    PRIMARY KEY (MarketCode, TRZNum, origTRZNum) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

Wenn das C-Programm schreibt in die Datenbank, die Ergebnisse, die ich bekommen sind Müll. Ich bekomme Wiederholungswerte, wo ich nicht sollte, die Ergebnisse sind nicht in Ordnung, die Spalten sehen vertauscht aus usw. Ich spiele seit ein paar Tagen damit und ich denke, dass es etwas mit dem Primärschlüssel zu tun hat .

Der Grund, warum ich das glaube, ist, weil ich eine andere Tabelle mit einem automatisch inkrementierenden ganzzahligen Primärschlüssel gemacht habe, der meine anderen Werte freigab, um einfach alte Tabellenwerte zu sein. Ich habe die Tabelle wie folgt erstellt:

CREATE TABLE halfcomp 
(
    Ind int(11) auto_increment NOT NULL, 
    MarketCode varchar(20) DEFAULT NULL, 
    TRZNum varchar(20) DEFAULT NULL, 
    origTRZNum varchar(20) DEFAULT NULL, 
    PRIMARY KEY (Ind) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

Wenn ich den gleichen C-Code verwenden, um in diese Tabelle zu schreiben, sind die Ergebnisse perfekt. Keine wiederholten Werte, keine vertauschten Spalten. Aber hier ist die Sache, ich brauche die Spalten MarketCode, TRZNum und origTRZNum als Primärschlüssel. Erstelle ich meinen ersten Tisch unangemessen? Ich bin ratlos.

Ich habe über das C-Programm mit einem feinen Zahn Kamm und es sieht richtig aus, und der gleiche C-Code funktioniert auf anderen Tabellen. Aber mit dieser Tabelle funktioniert es nicht. Jede Einsicht würde sehr geschätzt werden! Vielen Dank!

Edit: Ich habe den Code aktualisiert. Ich benutze Malloc nicht mehr willkürlich oder sprintf, ich setze den Pufferwert direkt auf den Wert meiner String-Variablen. Ich habe versucht, ein "\ 0" am Ende meiner Saiten hinzuzufügen. Bisher hat nichts geholfen, ich bekomme das gleiche unberechenbare Verhalten. Dies geschieht nur, wenn die Werte Primärschlüssel sind, andernfalls werden sie korrekt geladen. Ich muss davon ausgehen, dass C am Ende der Strings einen Nullterminator hinzufügt, wenn es am Anfang die Datenbankinformationen an mich weitergibt, und ich benutze strcpy, um die Werte bei der Verarbeitung der Daten hin- und herzuübertragen, also muss ich glauben, dass Null-Terminatoren sind schon da. Irgendwelche anderen Gedanken ??

int writeDB(void) { 
    MYSQL *conn2; 
    MYSQL_STMT *stmt2; 
    MYSQL_BIND bind2[3]; 

    char *server = "localhost"; 
    char *user = "root"; 
    char *password = ""; 
    char *database = "thekeydb"; 
    int port = 3306; 

    int k; 
    int length = 15000; 
    unsigned long mc2_length, mn2_length, om2_length; 
    const char *insertStmt2 = "INSERT INTO tempcomp (MarketCode, TRZNum, origTRZNum) VALUES (?,?,?)"; 

    conn2 = mysql_init(NULL); 
    mysql_real_connect(conn2, server,user,password,database, port, NULL, 0); 
    stmt2 = mysql_stmt_init(conn2); 
    mysql_autocommit(conn2, 0); 
    mysql_query(conn2, "START TRANSACTION"); 

    for (k=0; k < length; k++) { 
     memset((void *) bind2, 0, sizeof(bind2)); 

     mc2_length = strlen(comps[k].marketCode); 
     mn2_length = strlen(comps[k].trzNum); 
     om2_length = strlen(comps[k].origTrzNum); 

     if (mysql_stmt_prepare(stmt2, insertStmt2, strlen(insertStmt2)) != 0) { 
      printf("Unable to create new session: Could not prepare statement\n"); 
     } 

     bind2[0].buffer_type = MYSQL_TYPE_STRING; 
     bind2[0].buffer = comps[k].marketCode; 
     bind2[0].buffer_length = STRING_SIZE; 
     bind2[0].is_null = 0; 
     bind2[0].length = &mc2_length; 

     bind2[1].buffer_type = MYSQL_TYPE_STRING; 
     bind2[1].buffer = comps[k].trzNum; 
     bind2[1].buffer_length = STRING_SIZE; 
     bind2[1].is_null = 0; 
     bind2[1].length = &mn2_length; 

     bind2[2].buffer_type = MYSQL_TYPE_STRING; 
     bind2[2].buffer = comps[k].origTrzNum; 
     bind2[2].buffer_length = STRING_SIZE; 
     bind2[2].is_null = 0; 
     bind2[2].length = &om2_length; 

     if (mysql_stmt_bind_param(stmt2, bind2) != 0) { 
      printf("Unable to create new session: Could not bind parameters"); 
     } 
     mysql_stmt_execute(stmt2); 
     printf("%s, %s, %s, %s\n", comps[k].marketCode, comps[k].trzNum, comps[k].origTrzNum, comps[k].address); 
    } 

    mysql_query(conn2, "COMMIT"); 
    mysql_autocommit(conn2, 1); 
    mysql_stmt_free_result(stmt2); 
    mysql_stmt_close(stmt2); 
    mysql_close(conn2); 

    return 1; 
} 

Antwort

0

Fast sicher sind Sie nicht null, die Ihre Zeichenketten beenden. Wenn Sie eine Zeichenfolge als Parameter an eine vorbereitete Anweisung in libmysqlclient übergeben, müssen Sie die Länge der Zeichenfolge angeben. Wenn die Saiten nicht null beendet und Sie verwenden strlen() die Länge der MYSQL_BIND Struktur zu übergeben oder sind Sie sie sprintf() oder ähnliche Bestehen der Abfrage zu erstellen, dann ein unerwartetes Verhalten wie das Verhalten Ihrer porgram erwartet wird .


Tun Sie dies nicht tun, wenn Sie es tatsächlich tun, verwenden Sie stattdessen vorbereitete Anweisungen.

+0

LOL Ich verwende sowohl strlen() als auch sprintf(), um Längen zu finden und Parameter an die Bindung zu übergeben. Wie kannst du sicher sein, dass du null bist, um deine Strings zu beenden? Ich bin auch neu in C, deshalb weiß ich nicht, wie ich meine Strings zwingen kann, null zu sein. – sax

+0

Ich habe den Code hinzugefügt, damit Sie sehen können, wie ich die Strings übergeben habe. Ich bekomme die Daten, um all dies von einem Anruf in die Datenbank zu tun. Ich bevölke ein 2D-Array (eine Struktur von Strukturen), um alle Daten zu halten. Mit diesem globalen Array übergebe ich die Zeichenfolge an die Bindung. Muss ich etwas irgendwie zum Ende meiner Saiten verketten? – sax

+0

Ich habe versucht, strcat() zu verwenden, um "\ 0" am Ende meiner Strings hinzuzufügen, bevor ich Funktionen wie sprintf und strlen verwende, aber ich bekomme immer noch das gleiche fehlerhafte Verhalten. Wenn ich die Abfrage ausgeführt habe, um alle meine Daten zu Beginn zu erhalten, hole ich jede Zeile und gebe dann die Zeilendaten an meine Variablen weiter. Ich würde denken, dass, wenn sie Strings wären, sie von der API mit Nullwerten übergeben worden wären, die bereits in den Strings enthalten sind, nicht wahr? Ich möchte wirklich glauben, dass Ihre Null-Termination-Theorie richtig ist, aber ich bin nicht überzeugt. Ich muss immer noch etwas falsch machen. – sax

0

Um der Gemeinschaft willen muss ich ehrlich auf dieses Problem antworten, obwohl ich zugeben muss, dass es mir sehr peinlich ist, dies zu tun. An dieser Stelle glaube ich, dass ich die Daten die ganze Zeit korrekt in die Datenbank geschrieben habe, aber die Datenbankdaten zum Vergleich falsch angezeigt habe. Als ich die Daten auf den Bildschirm druckte, betrachtete ich drei Spalten. Der erste war ein sich völlig wiederholender Marktcode, der zweite war ein ziemlich zufälliger Code und der dritte war ein Code, der sich in Gruppen von 5 oder 8 oder was auch immer wiederholte.Wenn ich ein "SELECT * FROM tempcomp" machen würde, um die Daten zu sehen, wäre es die zweite Spalte, die sich wiederholen würde, aber in kleineren Gruppen wie 2 oder 3, und die dritte Spalte sah zufällig aus. Ich glaube jetzt, dass MySQL Workbench die Daten irgendwie sortiert hat, bevor sie sie mir präsentiert haben. Daher unterschied sich die Datenbankanzeige von der Anzeige des Programms. Wenn ich eine automatisch_inkrementierende Ganzzahl als Primärschlüssel verwenden würde, zeigt die Datenbank die Daten in der gleichen Reihenfolge wie die Bildschirmanzeige an. Aber es sortiert die Ausgabe anders, wenn meine drei Spalten der Primärschlüssel waren. Es ist ein erbärmlicher 3 Tage lang versucht, dies herauszufinden, und herauszufinden, dass es tatsächlich keinen Fehler in meinem Code gibt, ist peinlich, um es gelinde auszudrücken.

Verwandte Themen