MySQL Syntax in C++ (MFC)



  • estartu schrieb:

    Was macht das da:
    OPTION=2048

    daran liegts wahrscheinlich nich. hab es ganz weggelassen und gleiche ASSERT kommt trotzdem.

    hab folgendes gefunden: http://support.microsoft.com/?kbid=839782



  • Hats denn geholfen? Du hast doch gar kein Access?



  • ich kann es leider nicht machen.
    ehrlich gesagt, denke ich dass der fehler im code ist. irgendwo in View oder Doc oder sonstigen classe.
    ich bin schon soweit, dass ich mein backup lade und die ganze datenbank anbiendung von vorne anfange.

    daher würde ich dich estartu bieten mir eine kleine einführung zu posten. schritt für schritt. wo was ableiten, massegemaps ect.

    dieser link
    http://www.se.fh-heilbronn.de/usefulstuff/VCPLUS6/kap14.htm

    ist zwar gut, aber er behandelt ein projekt das zu sehr an die automatik von MFC gebunden ist. ich dagegen muss alles per hand machen, weil ich ein existierendes projekt an die datenbank anbinden muss. bisher habe ich auf textfiles geschrieben.

    falls es doch zu aufwendig wird, möchte ich mich an dieser stelle für deine hilfe 1000 mal bedanken.



  • Naja, du kannst auch so den Assistenten nutzen, keine Angst. 🙂

    Mach mal in der Klassenansicht rechte Maustaste auf dein Projekt, dann wähle "neue Klasse", dann MFC-Klasse und dann als Basisklasse CRecordset.
    Dann solltest dir schon einiges bekannt vorkommen.

    Das war jetzt aus dem Kopf geschrieben. Solltest du es nicht finden, suche ich es nochmal raus. 🙂

    (An einer Einführung arbeite ich fürs Magazin, komme aber nicht so oft dazu. 😞 )



  • hey danke,
    ich habs gleich ausprobiert, und ich kann tatsächlich den assistenten benutzen. man war ich blöd und hab alles per hand eingefügt, daher hats auch nicht funktioniert.

    ich starte nun mein backup und mache alles neu. melde mich dann ob es geklappt hat.

    danke nochmal



  • Ugene schrieb:

    man war ich blöd und hab alles per hand eingefügt, daher hats auch nicht funktioniert.

    Blöd ist der falsche Ausdruck.
    Eher ist es recht kompliziert, die Zusammenhänge zu erkennen - besonders, wenn man gerade mit dem Thema anfängt. 🙂

    Später ist es jedenfalls ohne grosse Probleme möglich, mal ein Feld von Hand nachzupflegen oder zu löschen. 😉



  • so, nun habe ich folgendes nach dem backup laden gemacht:

    1. eine neue klasse erstellt, abgeleitet von CRecordset, CRecordView und CDocument brauche ich nicht, da ich die daten nicht im fenster darstellen will.
    2. msdn bzgl. CRecordset durchgelesen

    nun mein code:

    CDatabase db;
    CString ODBC;
    CDatenBankSet rs;
    long datum = 0;
    long zeit = 0;
    
    ODBC = "DRIVER={MySQL ODBC 3.51 Driver};PORT=3306;SERVER=172.17.108.16;DATABASE=pruefmittel;USER=pm;PWD=pm25lh08";
    
    //DB öffnen
    db.OpenEx(_T(ODBC),db.noOdbcDialog); 
    
    if (!db.IsOpen())//falls öffnen fehlgeschlagen
    { 
    	AfxMessageBox("Fehler beim Verbinden mit Datenbank");
    
    }
    else 
    {
        	rs.AddNew( );
    	rs.m_SerNr = sSerNr;
    	rs.m_PersNr2 = Pnr;
    	rs.m_Vorname2 = Vorname;
    	rs.m_Name2 = Name;
    	rs.m_Datum3 = datum;
    	rs.m_Uhrzeit3 = zeit;
    
    	if( !rs.Update( ) )
    	{
    	   AfxMessageBox( "Record not added; no field values were set." );
    	}
    
    }
    db.Close();
    

    kompiliert, kein fehler, keine warnung.

    beim ausführen folgender assert bei AddNew();

    ASSERT(m_hstmt != SQL_NULL_HSTMT);
    // we can't construct an INSERT statement w/o any columns
    

    ich verstehe nicht warum ich so große problemme habe. eigentlich ist es nichts besonderes. verbinden->auslesen->schließen.

    wie macht ihr das?



  • Hmm, klingt als hättest du die Tabelle nicht sauber eingebunden. 😕

    Mir fehlt da auf jeden Fall ein

    rs.Open();
    

    sonst wird das Insert bald die nächste Meldung für dich haben.

    Versuchen wirs mal anders: Was steht in GetDefaultSQL und GetDefaultConnect vom Recordset?
    Was im DoFieldExchange?

    Hast du eigentlich die ODBC Datenquelle erstellt? Mich wundert dieser kryptische String für das OpenEx. 🙄



  • in der vom CRecordset abgeleiteten klasse steht das drin:

    /////////////////////////////////////////////////////////////////////////////
    // CDatenBankSet
    
    IMPLEMENT_DYNAMIC(CDatenBankSet, CRecordset)
    
    CDatenBankSet::CDatenBankSet(CDatabase* pdb)
    	: CRecordset(pdb)
    {
    	//{{AFX_FIELD_INIT(CDatenBankSet)
    	m_SerNr = _T("");
    	m_PersNr2 = _T("");
    	m_Vorname2 = _T("");
    	m_Name2 = _T("");
    	m_nFields = 6;
    	//}}AFX_FIELD_INIT
    	m_nDefaultType = dynaset;
    }
    
    CString CDatenBankSet::GetDefaultConnect()
    {
    	return _T("ODBC;DSN=pruefmittel");
    }
    
    CString CDatenBankSet::GetDefaultSQL()
    {
    	return _T("[personen]");
    }
    
    void CDatenBankSet::DoFieldExchange(CFieldExchange* pFX)
    {
    	//{{AFX_FIELD_MAP(CDatenBankSet)
    	pFX->SetFieldType(CFieldExchange::outputColumn);
    	RFX_Text(pFX, _T("[SerNr]"), m_SerNr);
    	RFX_Text(pFX, _T("[personen].[PersNr]"), m_PersNr2);
    	RFX_Text(pFX, _T("[personen].[Vorname]"), m_Vorname2);
    	RFX_Text(pFX, _T("[personen].[Name]"), m_Name2);
    	RFX_Date(pFX, _T("[personen].[Datum]"), m_Datum3);
    	RFX_Date(pFX, _T("[personen].[Uhrzeit]"), m_Uhrzeit3);
    	//}}AFX_FIELD_MAP
    }
    
    ////////////////////////////////////////////////////////////////////////////
    


  • also nun habe ich das halbe internet durchgesucht. und meiner verständnis nach habe ich keinen gravierenden fehler gemacht.
    die datenbankprogrammierung (mySQL) mittels MFC VC++ 6.0 verstehe ich von der theorie so:
    1. erzeuge ich die datenbank, ich nenne sie "pruefmittel".
    2. in der datenbank lege ich eine tabelle fest, diese nenne ich personen. sie beinhaltet 6 spalten (sSerNr, PersNr, Vorname, Name, Datum, Uhrzeit).
    3. ich erzeuge im datenquellen-administrator (Systemsteuerung->Verwaltung->Datenquellen) die ODBC datenquelle.
    4. im meinem existierenden projekt füge ich mit dem assistenen neue klasse hinzu. diese Klasse ist abgeleitet von CRecordset. und mache die angelegte datenquelle dieser klasse bekannt.(alles mittels assistent).
    5.ich stelle verbindung zu der datenquelle aus einer bieliebigen methode (z.B CPersonenDgl)

    CDatabase db;
    CString ODBC;
    CDatenBankSet rs;
    long datum = 0;
    long zeit = 0;
    
    ODBC = "DRIVER={MySQL ODBC 3.51 Driver};PORT=3306;SERVER=172.17.108.16;DATABASE=pruefmittel;USER=pm;PWD=pm25lh08";  
    //DB öffnen
    db.OpenEx(_T(ODBC),db.noOdbcDialog);
    

    6. nun übergebe ich meine variablen an die datenbank-variablen und speichere den inhalt mittel update()

    rs.AddNew( );
        rs.m_SerNr = sSerNr;
        rs.m_PersNr2 = Pnr;
        rs.m_Vorname2 = Vorname;
        rs.m_Name2 = Name;
        rs.m_Datum3 = datum;
        rs.m_Uhrzeit3 = zeit;
    
        rs.Update( )
    

    theoretisch müssen die daten ab hier in der db liegen.

    meine frage an euch wäre:
    ist mein gedankengang richtig? oder sieht jemand lücken, fehler, o.ä.



  • hier ist die lösung verboregen. mal schauen wie weit ich damit komme

    http://www.willemer.de/informatik/db/odbcmfc.htm



  • So grundlegend ist es richtig, nur dass du es mal so versuchen solltest:

    rs.Open();
        rs.AddNew( );
        rs.m_SerNr = sSerNr;
        rs.m_PersNr2 = Pnr;
        rs.m_Vorname2 = Vorname;
        rs.m_Name2 = Name;
        rs.m_Datum3 = datum;
        rs.m_Uhrzeit3 = zeit;
    
        rs.Update( )
    

    Oder so:

    CDatabase db;
    CString ODBC;
    long datum = 0;
    long zeit = 0;
    
    ODBC = "DRIVER={MySQL ODBC 3.51 Driver};PORT=3306;SERVER=172.17.108.16;DATABASE=pruefmittel;USER=pm;PWD=pm25lh08";  
    //DB öffnen
    db.OpenEx(_T(ODBC),db.noOdbcDialog);
    CDatenBankSet rs(db);
        rs.AddNew( );
        rs.m_SerNr = sSerNr;
        rs.m_PersNr2 = Pnr;
        rs.m_Vorname2 = Vorname;
        rs.m_Name2 = Name;
        rs.m_Datum3 = datum;
        rs.m_Uhrzeit3 = zeit;
    
        rs.Update( )
    

    So, wie du es bieher hast, existiert keine Verbindung zwischen dem Datenbankobjekt und dem Recordset.
    Zumindest das obere funktioniert eigentlich immer bei vom Assistenten erzeugten Klassen.



  • ich habe nun folgendes ausprobiert:

    db.OpenEx( NULL, CDatabase::forceOdbcDialog );
    

    programm gestartet und dann verbindung zur datenbank "per hand" mittels ODBC-fenster hergestellt.

    ich bekomme ein ASSERT in dbcore.cpp line 1580, habe ich shon vorher erwähnt:

    ASSERT(m_hstmt != SQL_NULL_HSTMT);
    // we can't construct an INSERT statement w/o any columns

    ich stelle fest: 1. es liegt nicht an OpenEx();
    2. Bug ist in der Tabelle: "man könne keinen Insert statement ohne spalten konstruieren"

    hier: http://db.apache.org/derby/docs/10.1/ref/rrefsqlj40774.html steht folgendens:

    An INSERT statement creates a row or rows and stores them in the named table. The number of values assigned in an INSERT statement must be the same as the number of specified or implied columns.

    folge: mein programm ist nicht in der lage spalten/reihen zu erzeigen
    ich stelle fest: 3. bug ist in INSERT



  • Es ist komisch, das AddNew ist es also.

    Mach bitte vor der Zeile mit AddNew mal:

    ASSERT(rs.IsOpen());
    

    und sag, ob der anschlägt.
    Hast du meine Vorschläge mal probiert? Dein Code von eben war ja wieder was anderes.



  • hi estartu,
    ja ich habe rs.Open(); eingefügt und ASSERT(rs.Open()) danach, um zu sehen ob rs öffnen konnte.

    rs.Open();
    	//...verbindung
    
    	ASSERT(rs.IsOpen());
        	rs.AddNew( );
    	rs.m_SerNr = sSerNr;
    	rs.m_PersNr = Pnr;
    	rs.m_Vorname = Vorname;
    	rs.m_Name = Name;
    	rs.m_Datum = datum;
    	rs.m_Uhrzeit = zeit;
    

    nun taucht ein ASSERT von timecore.cpp line 32,

    ASSERT(nDay >= 1 && nDay <= 31);
    

    da stimmt was mit dem datumformat nicht. mal sehen was ich da finde.



  • oh man, hab falsch abgetippt, verbindung ist natürlich ganz oben.
    sorry



  • Jaaaaaaaaaaaaaaaaaaaaaaaa!!!! 😮

    heute um 8:59uhr habe ich meinen ersten datensatz in die MySQL reingehauen!

    @estartu:
    um zu sehen ob es überhaupt geht, habe ich in der datenbanktabelle die zeitspalte und datumspalte gelöscht. und siehe da es geht!!

    danke dir viel mals.

    auch wenn ich lange gebraucht habe, ist es immer sehr sehr hilfreich, wenn dich einer unterstützt!! tausend dank an estartu! 👍



  • Das freut mich. 👍
    Wenns dann klappt macht auch das Helfen Spaß. 🙂

    Mit den Datum/Zeit Spalten musste mal rumprobieren. Das geht auch mit MySQL, ich hatte es mal. Leider habe ich den Code nicht mehr, sonst könnte ich da was rauskopieren. 🙄
    Zur Not nimm einen String und parse den, das geht ja ganz gut mit den Funktionen in COleDateTime.



  • danke nochmal,
    das mit der zeit ist kein problemm mehr. das kriege ich schon hin. im einfachsten fall mit einem string.

    🙂


Anmelden zum Antworten