Datenbankabfrage & SQL



  • Hallo Forum

    Ich möchte in mein Programm eine Datenbankabfrage einbinden.
    Die Daten sollen aus einer Access-Datenbank mit mehreren Tabellen ausgelesen, gelöscht, bearbeitet und neue hinzugefügt werden. Ich würde gerne mit SQL-Befehlen arbeiten, die sich zur Laufzeit ändern.
    Wie geht das (ADO oder ODBC)?



  • Hallo,
    schau mal da:

    [url] http://www.markt-und-technik.de/media/buecher/VCPLUS6/data/start.htm
    [/url]
    und in die FAQ. Hat mich auch geholfen 😃

    NC



  • Das kenn ich leider schon.
    Ich möchte wissen, wie ich die Daten abrufe ohne sie gleich in Steuerelementen anzuzeigen.



  • Na da gibt es doch was viel besseres

    Bitte genau durchlesen ist nicht ganz einfach

    http://members.aon.at/murli2001/db5/db5.html

    Vossy



  • Danke Vossy,

    dieses Tutorial hat mir schon etwas mehr geholfen.
    Aber kann ich auch SQL-Anweisungen (z.B.: SELECT * FROM kundentabelle WHERE ID = 56) verwenden, und wenn ja, wie?



  • Eine überladene Stringanweisung sollte dir da helfen.
    Ob Sortierung Filterung oder Script letztendlich ist alles ein Text
    der durch schlüsselwörtern überladen wird

    Vossy



  • Das heisst ich kann in m_strFilter meine SQL-Anweisung hineinschreiben.
    🕶 Ein Problem habe ich aber noch:
    Wie kann ich die anzahl der Spalten in einer Tabelle ermitteln?
    Die brauche ich nämlich um meine CListView darauf abzustimmen.
    Und wie kann ich die Spaltennamen in die ColumnHeader der CListView schreiben? 😕

    Danke schon im Voraus



  • Recordset_Kunden *m_pSet;
    m_pSet = new Recordset_Kunden(NULL);

    int Spaltenanzahl = m_pSet->m_nFields ;//liefert die Spaltenanzahl zurück

    Hier ein Beispiel einer multilingualen Abfrage einer Tabelle
    Das erstellen Ser Sicht habe ich gleich mit eingefügt.

    Die 200 aus ...(LVS_EX_FULLROWSELECT+200|LVS... dient dazu das ein
    Automatisches Makieren des Datensatzes erfolgt und die Farbe ich ändert.
    Unter Veränderung dieser Option ist nicht nur ein Horizontales Listen möglich sondern auch ein Verdikales

    Record_Kunden1 *m_pSet;
    m_pSet = new Record_Kunden1(NULL);
    
    int Spaltenanzahl = m_pSet->m_nFields ;
    
        m_Sicht1.SetExtendedStyle(LVS_EX_FULLROWSELECT+200|LVS_EX_GRIDLINES|LVS_OWNERDRAWFIXED);
    
        m_Sicht1.ModifyStyle( LVS_LIST,LVS_REPORT);
    
        for ( int i = 0; i < Spaltenanzahl; i++)
        {
            m_Sicht1.InsertColumn( i,Inhalt[i],LVCFMT_LEFT,Breite[i] );
    
        }
    
    if ((suchen_Begriff != "" && suchen_Spalte != "") || ( m_Begriff2 != "" && m_Spalte2 != "")  )
    {
    
    if ( suchen_Begriff == "")
    {
        suchen_Begriff = " ";
    }
    
    if ( suchen_Spalte == "")
    {
        suchen_Spalte = m_Spalte2;
    }
    if ( m_Begriff2 == "")
    {
        m_Begriff2 = " ";
    }
    if ( m_Spalte2 == "")
    {
        m_Spalte2 = suchen_Spalte;
    }
    
    m_pSet->m_strFilter = "[" + suchen_Spalte + "]='" + suchen_Begriff + "'OR["+ m_Spalte2 + "]='" + m_Begriff2 + "'";
    
    }
        abc = 0;
    
        for (m_pSet->Open();m_pSet->IsEOF() == FALSE ;m_pSet->MoveNext())
    
        {
            NummerID.Format("%d",m_pSet->m_KundenID);
            PLZ.Format("%d",m_pSet->m_PLZ);
            Kundenverbindung.Format("%d",m_pSet->m_Kontoverbindung);
            Erstellungszeit.Insert(0,m_pSet->m_ErstellugsZeit.Format(_T("%d.%m.%Y")));
    
            if (PLZ == "1246576928")
            {
    
            m_Sicht1.InsertItem(abc,(LPCTSTR)"",abc);
            m_Sicht1.SetItemText(abc,0,(LPCTSTR)Erstellungszeit);
            Erstellungszeit="";
            m_Sicht1.SetItemText(abc,1,(LPCTSTR)NummerID);
            m_Sicht1.SetItemText(abc,3,(LPCTSTR)m_pSet->m_Name);
            m_Sicht1.SetItemText(abc,2,(LPCTSTR)m_pSet->m_Vorname);
            m_Sicht1.SetItemText(abc,4,(LPCTSTR)m_pSet->m_Geburtstag);
            m_Sicht1.SetItemText(abc,5,(LPCTSTR)"");
            m_Sicht1.SetItemText(abc,6,(LPCTSTR)m_pSet->m_Ort);
            m_Sicht1.SetItemText(abc,7,(LPCTSTR)m_pSet->m_Strasse);
            m_Sicht1.SetItemText(abc,8,(LPCTSTR)m_pSet->m_Bemerkungen);
            m_Sicht1.SetItemText(abc,9,(LPCTSTR)"");
    
            }
            else
            {
    
            m_Sicht1.InsertItem(abc,(LPCTSTR)"",abc);
            m_Sicht1.SetItemText(abc,0,(LPCTSTR)Erstellungszeit);
            Erstellungszeit="";
            m_Sicht1.SetItemText(abc,1,(LPCTSTR)NummerID);
            NummerID = "";
            m_Sicht1.SetItemText(abc,3,(LPCTSTR)m_pSet->m_Name);
            m_Sicht1.SetItemText(abc,2,(LPCTSTR)m_pSet->m_Vorname);
            m_Sicht1.SetItemText(abc,4,(LPCTSTR)m_pSet->m_Geburtstag);
            m_Sicht1.SetItemText(abc,5,(LPCTSTR)PLZ);
            PLZ = "";
            m_Sicht1.SetItemText(abc,6,(LPCTSTR)m_pSet->m_Ort);
            m_Sicht1.SetItemText(abc,7,(LPCTSTR)m_pSet->m_Strasse);
            m_Sicht1.SetItemText(abc,8,(LPCTSTR)m_pSet->m_Bemerkungen);
            m_Sicht1.SetItemText(abc,9,(LPCTSTR)Kundenverbindung);
            Kundenverbindung = "";
            }
    
            m_Liste.AddString((LPCTSTR)m_pSet->m_Vorname);
            abc++;
        }
    
        m_Sicht1.SetFocus();
        m_pSet->Close();
    

    Ansicht unter
    http://members.aon.at/murli2001/db5/db5.html



  • Ach bevor ich es vergesse

    die Abfrage

    if (PLZ == "1246576928")

    läßt nur die Anzeige Frei da der Zahlenwert 1246576928
    übergeben wird wenn die Spalte leer ist.
    Zumendestens bei einer SQL ServerDB

    Vossy



  • Danke für den Quelltext
    Aber wie Füllst du dein Array Inhalt[i] in dem die ColumnHeaders stehen.
    Ich möchte es in der Recordsetklasse mit den ganzen Spaltennamen füllen. Und zwar Automatisch vom Programm.



  • Ha es gibt erst einmal zwei möglichkeiten um diese zu füllen einmal

    m_Sicht1.InsertColumn(0, "WK.ID",LVCFMT_LEFT,45);
    m_Sicht1.InsertColumn(1, "K.ID",LVCFMT_LEFT,40);
    m_Sicht1.InsertColumn(2,"Besteller",LVCFMT_LEFT,100);
    m_Sicht1.InsertColumn(3,"Bezeichnung",LVCFMT_LEFT,100);
    

    das ist ohne Arrays und mit Arrays

    CString Inhalt[10]={"Erstellt am","KundenID","Vorname","Name","Geburtstag","PLZ","Ort","Straße","Bemerkung","Kontoverbindung"};
    int Breite [10] ={80,60,60,75,80,50,85,130,110,100};
    

    das ist mit Arrays

    Ein automatisches übergeben sollte möglich sein habe ich aber noch nicht benötigt da ich ja nie alle benötigte.
    Sicherlich ist der nachteil das wenn man in der DB etwas ändert es auch im programm ändern muß aber ich schau mal ob ich es hin bekomme denn es kann ja nicht so schwer sein.

    Sollte eigendlich mit

    CFieldExchange::outputColumn

    gehen. Werde dich informieren

    Vossy



  • Hallo Vossy,

    Meine Abfrage läuft jetzt schon ganz gut, ich kann auch schon SQL-Anweisungen verwenden.
    Doch irgendwie werden meine Variablen nicht mit Werten gefüllt.
    Hier der Source:

    void CMyView::OnInitialUpdate()
    {
        CListView::OnInitialUpdate();
    
        CMySet * m_pSet = new CMySet;
        m_pSet->Open(CRecordset::dynaset, "SELECT * FROM lagerliste",
            CRecordset::none);
        m_pSet->Requery();
        LVCOLUMN lvc;
    
        lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
    
        for (int i = 0; i < m_pSet->m_nFields; i++)
        {
            lvc.iSubItem = i;
            lvc.pszText = m_carrInhalt[i];
            lvc.cx = 75;
            lvc.fmt = LVCFMT_LEFT;
            GetListCtrl().InsertColumn(i, &lvc);
        }
        int j = 0;
        while (!m_pSet->IsEOF())
        {
            GetListCtrl().InsertItem   (j, _T(CString(m_pSet->m_bezeichnung)), 0);
            GetListCtrl().SetItemText(j, 1, _T(m_pSet->m_bezeichnung));
            GetListCtrl().SetItemText(j, 2, _T(m_pSet->m_kurzbezeichnung));
            GetListCtrl().SetItemText(j, 3, _T(m_pSet->m_norm));
            GetListCtrl().SetItemText(j, 4, _T(m_pSet->m_lieferant));
            GetListCtrl().SetItemText(j, 5, _T(m_pSet->m_statistik));
            GetListCtrl().SetItemText(j, 6, _T(m_pSet->m_gruppe));
            GetListCtrl().SetItemText(j, 7, _T(m_pSet->m_menge));
            GetListCtrl().SetItemText(j, 8, _T(m_pSet->m_einzelpreis));
            GetListCtrl().SetItemText(j, 9, _T(m_pSet->m_einkaufsdatum));
            m_pSet->MoveNext();
            j++;
        }
        m_pSet->Close();
    

    Es werden zwar Items in der Liste erzeugt, aber nur leere.

    An was kann es da liegen? 😕



  • Deine Schreibweise ist veraltet und du schickst sie jedesmahl duch
    ein Makro warum?

    Vossy



  • Das Makro habe ich hineingegeben um das Problem vielleicht so zu lösen.
    Und meine schreibweise ist so weil ich moch keine Erfahrung mit Datenbanken in der MFC habe. Aber warum geht das nicht?



  • Das Makro _T() formatiert von Quelle zu Ziel.
    Schaue dir mal das makro im Quellcode an.

    mache es auf die Elegante Lösung weil so auch das schreiben
    von DB zu DB möglich ist.

    hier ein paar Beispiele

    Wichtig ist abei das es immer ein CString sein muß.
    Also Zahlen Zeitformate u.s.w. müssen vorher in CString gewandelt werden

    abc = 0;
    
        for (m_pSet->Open();m_pSet->IsEOF() == FALSE ;m_pSet->MoveNext())
    
        {
            NummerID.Format("%d",m_pSet->m_KundenID);//int nach CString
    
            Erstellungszeit.Insert(0,m_pSet->m_ErstellugsZeit.Format(_T("%d.%m.%Y")));//TimeFormat nach CString
    
            m_Sicht1.InsertItem(abc,(LPCTSTR)"",abc);Initzialiesierung der kommenden Zeile
            m_Sicht1.SetItemText(abc,0,(LPCTSTR)Erstellungszeit);
            m_Sicht1.SetItemText(abc,1,(LPCTSTR)NummerID);
            m_Sicht1.SetItemText(abc,2,(LPCTSTR)m_pSet->m_Name);
            m_Sicht1.SetItemText(abc,3,(LPCTSTR)m_pSet->m_Vorname);
            m_Sicht1.SetItemText(abc,4,(LPCTSTR)m_pSet->m_Geburtstag);
    
            m_Sicht1.SetItemText(abc,5,(LPCTSTR)m_pSet->m_Strasse);
            m_Sicht1.SetItemText(abc,6,(LPCTSTR)m_pSet->m_Bemerkungen);
    

    Vossy



  • Ich hab den Code jetz so umgeändert:

    for (m_pSet->Open(CRecordset::dynaset, "SELECT * FROM lagerliste ORDER BY id", CRecordset::none);
    m_pSet->IsEOF() == FALSE;
    m_pSet->MoveNext())
    {
        m_strid.Format("%d", m_pSet->m_id);
    
        GetListCtrl().InsertItem(0, (LPCSTR)"", 0);
        GetListCtrl().SetItemText(0, 0, (LPCSTR)m_strid);
        GetListCtrl().SetItemText(0, 1, (LPCSTR)m_pSet->m_bezeichnung);
       GetListCtrl().SetItemText(0, 2, (LPCSTR)m_pSet->m_kurzbezeichnung);
        GetListCtrl().SetItemText(0, 3, (LPCSTR)m_pSet->m_norm);
        GetListCtrl().SetItemText(0, 4, (LPCSTR)m_pSet->m_lieferant);
        GetListCtrl().SetItemText(0, 5, (LPCSTR)m_pSet->m_statistik);
        GetListCtrl().SetItemText(0, 6, (LPCSTR)m_pSet->m_gruppe);
        GetListCtrl().SetItemText(0, 7, (LPCSTR)m_pSet->m_menge);
        GetListCtrl().SetItemText(0, 8, (LPCSTR)m_pSet->m_einzelpreis);
        GetListCtrl().SetItemText(0, 9, (LPCSTR)m_pSet->m_einkaufsdatum);
                                        //m_einkaufsdatum ist CString
    }
    

    Leider funzt der Sch... immer noch nicht. Bei der ID-Spalte werden aber lauter 0 anzezeigt.
    Das liegt aber am m_strid.Format("%d", m_pSet->m_id);.
    Und das sagt mir, dass die Datensätze aus der Datenbank ausgelesen werden (da ja Listen-Einträge erzeugt werden), aber nicht korrekt in die Liste aufgenommen werden. Wo könnte da der Fehler liegen?



  • Du hast da was vergessen da dir immer nur eine Zeile geschrieben wird.Du überschreibst sie also immer und löscht die nicht einmal vorher. Ich gehe davon aus das ID = int ist

    int abc = 0;
    GetListCtrl().DeleteAllItems();// löscht schon alle vorhandene DS ist gut für eine Aktualiesierung der Sicht 
    for (m_pSet->Open(CRecordset::dynaset, "SELECT * FROM lagerliste ORDER BY id", CRecordset::none);
    m_pSet->IsEOF() == FALSE;
    m_pSet->MoveNext())
    {
        m_strid.Format("%d", m_pSet->m_id);
    
        GetListCtrl().InsertItem(abc, (LPCSTR)"", abc);
        GetListCtrl().SetItemText(abc, 0, (LPCSTR)m_strid);
        GetListCtrl().SetItemText(abc, 1, (LPCSTR)m_pSet->m_bezeichnung);
       GetListCtrl().SetItemText(abc, 2, (LPCSTR)m_pSet->m_kurzbezeichnung);
        GetListCtrl().SetItemText(abc, 3, (LPCSTR)m_pSet->m_norm);
        GetListCtrl().SetItemText(abc, 4, (LPCSTR)m_pSet->m_lieferant);
        GetListCtrl().SetItemText(abc, 5, (LPCSTR)m_pSet->m_statistik);
        GetListCtrl().SetItemText(abc, 6, (LPCSTR)m_pSet->m_gruppe);
        GetListCtrl().SetItemText(abc, 7, (LPCSTR)m_pSet->m_menge);
        GetListCtrl().SetItemText(abc, 8, (LPCSTR)m_pSet->m_einzelpreis);
        GetListCtrl().SetItemText(abc, 9, (LPCSTR)m_pSet->m_einkaufsdatum);
    
    abc++;
                                    //m_einkaufsdatum ist CString
    }
    

    Und so geht es dann doch wie gesagt ID muß int sein wenn nicht sage mich was es ist

    Vossy



  • Nee das funzt auch nicht.
    Ich glaube du hast das Problem nicht richtig verstanden.

    Es werden Listeneinträge erzeügt, aber es wird nicht der text von der Datenbank ausgegeben, sondern gar keiner bzw. der mit dem die Variablen im Konstruktor der Recordsetklasse initialisiert werden.
    Die anzahl der Einträge in der Liste stimmt aber mit der in der Tabelle der Datenbank überein.
    Es muss also irgendwo in der Recordsetklasse oder beim ODBC-Treiber ein Problem geben.
    Übrigens ID ist vom Typ long. 😉



  • Da kann man eigendlich nichts falsch machen.
    Um die Recordsetklasse zu ürüfen nimm mal deine Bedingungen aus dem Openbefehl und las dir alle ausgeben.
    Einen anderen Tip habe ich jetzt im moment nicht für dich.
    Der Code sonst ist o.k.

    Vossy



  • Wenn ich alle Bedingungen aus dem Openfeld nehme, dann bekomme ich eine Dbugfehlermeldung: Debug Assertion Failure 😞


Log in to reply