Query bei einer Datenbank



  • Kann ich eine CSV genau so abfragen wie eine Datenbank? Wie geht das einbinden einer CSV? Hat mir jemand eine kurze Anleitung?

    THX



  • Kann ich eine CSV genau so abfragen wie eine Datenbank?

    Nein, eine CSV ist eine normale Textdatei.Die Daten werden durch ein Trennzeichen (Seperator) getrennt.
    Kannst ja mal mit Excel ein Arbeitsblatt als CSV Datei abspeichern, und dir diese mit dem Notepad anschauen.
    Um sowas auszulesen kannst du eine TStringList verwenden.
    Nur "Abfragen" zwischen verschiedenen "Tabellen" (Dateien) musst du dann selber programmieren.Ist je nachdem was du brauchst ziemlich aufwendig.



  • Beispiel:

    TStringList *list=new TStringList();
    list->LoadFromFile(filename);
    list->Delimiter =';';
    list->DelimitedText = list->Text;
    Label1->Caption = list->Strings[0];
    delete list;
    


  • Super Danke.. werde gleich mal schauen was sich daraus machen läßt! 👍



  • du kannst auch mit den ADO-Komponenten direkt auf Excel-Dateien zugreifen, dabei ist jedes Excel-Tabellenblatt eine Tabelle, in der 1. Zeile des Tabellenblattes steht der Tabellenkopf, und der Tabellename ist der Name des Tabellenblattes. Beschränkungen gibt es hier bezüglich der Reihen (max. 65536) und Spalten (max 255).

    Bsp:

    ADOConnection1->ConnectionString = "Provider=MSDASQL;Persist Security \
     Info=False;Data Source=Excel-Dateien;Initial Catalog=C:\\Test.xls";
    ADOConnection1->LoginPrompt = false;
    ADOConnection1->Open();
    
    ADODataSet1->Connection = ADOConnection1;
    ADODataSet1->CommandText = "[Tabelle1$]";
    ADODataSet1->CommandType = cmdTable;
    ADODataSet1->Open();
    ...
    

    Im Beispiel heisst das Tabellenblatt Tabelle1. Die eckigen Klammern und das $-Zeichen sind beim Zugriff wichtig.



  • Hallo Linnea, wie geht es dann weiter?

    ich habe mir nun eine Tabelle so wie du geschrieben hast angelegt..
    Habe die Connection wie oben genannt erstellt.. aber wie frag ich da jetzt was ab und kann es dann ausgeben? Danke



  • Die Abfrage kannst du über SQL machen, z.B.:

    ADODataSet1->CommandText = "select Wert from [Tabelle1$]";
    ADODataSet1->CommandType = cmdText;
    ADODataSet1->Open();
    

    Die Behandlung von Select-Ergebnissen hast du ja schon aus der FAQ

    und hier noch ein paar Hinweise die ich mal irgendwo im Internet gefunden hab:

    Excel:

    1.Generelles:
    -Am einfachsten connected man mit Hilfe des „Excel-Dateien“-Treibers, eine eigene DSN zu erstellen macht wenig Sinn, da es sich dabei sowieso um einen ganz normalen Excel-Treiber handelt. Außerdem erspart man sich dadurch die lästigen „Extended Properties“, die so nicht gesetzt werden müssen. „READONLY“ muss so auch nicht explizit auf FALSE gesetzt werden. Der eigentliche ConnectionString bleibt kurz und übersichtlich und leistet dabei dasselbe wie eine eigene DSN.

    -Tabellennamen werden grundsätzlich in eckige Klammern gepackt. Dabei muss der Tabellenname immer mit einem „“-Zeichen abgeschlossen werden. Das gilt für alle SQL-Befehle, nicht nur für „Select“ ! Beispiel : [MyTable]. Die MSDN behauptet, man könne auch ohne eckige Klammern auf „Ranges“ zugreifen. Das mag für VB gelten, bei Delphi hatte ich bis jetzt noch keinen Erfolg. Bleibe aber weiter dran...;)

    -Excel-Tabellen können grundsätzlich nur einmal geöffnet werden. Das sollte beim Debuggen berücksichtigt werden. Eine Connection, die auf TRUE steht, kann stören. Meines wissens nach ist es auch nicht möglich, besagte Tabelle ein zweites mal im Exclusiv-Modus zu öffnen.

    2. Einen Connect ausführen
    -Ein typischer ConnectionString sieht in etwa so aus:

    -ConnectionString := ’Provider=MSDASQL;Data Source=Excel-Dateien;Initial Catalog=C:\myTable.XLS;’

    -Mehr ist nicht nötig, man glaubt es kaum...

    3. CREATE DATABASE
    -Ein CREATE DATABASE ist nicht so ohne weiteres anwendbar. Man muss einen kleinen Trick anwenden. Man connected auf eine Datei, die bis jetzt noch nicht existiert. Dann führt man einen CREATE TABLE aus. Der Treiber erzeugt dann automatisch die .XLS-Datei. Die DataBase (sprich das XLS-File) heißt dann so, wie zuvor angegeben.

    4. CREATE TABLE
    -Hier gilt es zu berücksichtigen, dass außer dem Tabellennamen auch die Feldnamen in eckigen Klammern stehen müssen! Excel kennt eine Vielzahl von Formaten, darunter VARCHAR, DOUBLE, CURRENCY oder DATETIME. Einen Typ "int" gibt es nicht! Zahlen werden generell als "Double" angegeben. Ein typischer CREATE TABLE könnte so aussehen:

    -CREATE TABLE [myTable$] ([Name] varchar(50), [Vorname] varchar(50), [PLZ] Double, [GeburtsDatum] DateTime)

    -Die Feldnamen erscheinen im Worksheet dann in der ersten Zeile. Die msdn behauptet, man könne mit "FirstRowHasNames" die erste Zeile zu einem weiteren Datensatz machen, ich hatte bisher keinen Erfolg damit.

    5. Zugriff & Manipulation
    -Zugegriffen und manipuliert wird auf ganz normale Art und Weise. Bei einem "Insert" können jetzt auch die eckigen Klammern weggelassen werden. Beispiel:

    -INSERT INTO (Name, Vorname, PLZ, GeburtsDatum) values (’Müller’, ’Martin’, 74523, 22.02.02)

    -ansonsten funktioniert alles im SQL-typischen Stil.

    6. Abschließendes
    -als sehr kooperativ erweist sich Excel mit Datums- und Currency-Werten. Wenn man die Felder bereits richtig definiert, kann man auch mit Sicherheit davon ausgehen, dass alle Zellen richtig formatiert und angezeigt werden. Hier leistet der Treiber ausgezeichnete Arbeit.
    -Leider ist es IMHO nicht möglich, den Feldtyp VarChar(x) richtig zu beeinflussen. Excel macht sich nichts aus der Größe x, es legt sich anscheinend soviel Speicherplatz an chars zurecht, wie es (Excel) meint, zu benötigen. Wenn man die Daten dann im Excel anschaut, ist das kein Problem; wird allerdings versucht, die Daten mit einem Grid anzuzeigen, gibt das Probleme, weil die Felder überdurchschnittlich groß geraten sind.
    -stets beachten sollte man auch, dass Excel nicht in der Lage ist, mehr als 65535 Datensätze zu speichern. Das ist aber ein Problem der Excel-Philosophie.

    7. Wichtiges
    -Ein SELECT * FROM kann nicht ausgeführt werden. Woher sollte Excel auch wissen, wann das Ende der Feldnamen erreicht ist? Und wenn, was würde es dann mit leeren Einträgen machen, die im Excel ja durchaus zulässig sind?



  • Na super!! Dank dir schon einmal.. Hast mir richtig geholfen.

    Auf dem Zielrechner muss dann Excel installiert sein und keine weiteren Treiber oder?

    from [Tabelle1$]

    .. das hatte mir gerade gefehlt da hatte ich die xls hingeschrieben.



  • Frage:

    Als ich die sache mit BDE gemacht habe konnte ich in der SQL mit Variablen arbeiten mit ParamByName ...

    ADOQuery1->ParamByName("VARIABLE")->Value = Edit1->Text;
    

    Das scheint hier in der SQL nicht zu funktionieren... Gibts da noch eine andere möglichkeit die sql mit variablen zu bestücken?



  • das geht auch hier, allerdings mit leicht verändertem Syntax:

    ADOCommand1->Parameters->ParamByName("VARIABLE")->Value = Edit1->Text;
    


  • Da bringt er mir immer die Fehlermeldung Parameter X nicht gefunden...

    Auszug:

    String x;
    ADOConnection1->ConnectionString = "Provider=MSDASQL;Persist Security \Info=False;Data Source=Excel-Dateien;Initial Catalog=test.xls";
    
    ADOConnection1->LoginPrompt = false;
    ADOConnection1->Open();
    
    ADODataSet1->Connection = ADOConnection1;
    ADODataSet1->CommandText = "[Tab20$]";
    ADODataSet1->CommandType = cmdTable;
    ADODataSet1->Open();
    
    ADOQuery1->Close();
    ADOQuery1->SQL->Clear();
    ADOQuery1->SQL->Add("select id from [Tab20$] where smms like :x");    
    
    ADOCommand1->Parameters->ParamByName("x")->Value = Edit1->Text;
    
    ADOQuery1->Open();
    ADOQuery1->First();
    
    Memo1->Lines->Add(ADOQuery1->Fields->Fields[0]->AsString);
    


  • kann auch nicht gehen, da du den Parameter dem ADOCommand und nicht dem Query zuordnest. Ausserdem brauchst du das Query nicht mehr:

    String x;
    ADOConnection1->ConnectionString = "Provider=MSDASQL;Persist Security
    \Info=False;Data Source=Excel-Dateien;Initial Catalog=test.xls";
    
    ADOConnection1->LoginPrompt = false;
    ADOConnection1->Open();
    
    ADODataSet1->Connection = ADOConnection1;
    ADODataSet1->CommandText = "select id from [Tab20$] where smms like :x";
    ADODataSet1->CommandType = cmdText;
    ADODataSet1->Parameters->ParamByName("x")->Value = Edit1->Text;
    ADODataSet1->Open();
    ADODataSet1->First();
    
    Memo1->Lines->Add(ADODataSet1->Fields->Fields[0]->AsString);
    


  • Na jetzt wird es tag!!! 👍 👍



  • Hi all,

    ich wollte mich an dieser Stelle noch einmal Bedanken für Eure super Hilfe!!!

    Jetzt läuft das grobe alles wunderbar.

    THX!!!



  • hi zusammen,

    ich komme einfach nicht weiter, warscheinlich übersehe ich nur ne kleinigkeit.

    zur erläuterung:
    ich möchte eine excel datei in eine sql datenbank importieren. hierbei soll geprüft werden ob der datensatz in der datenbank schon vorhanden ist oder nicht. ist dieser vorhanden, dann soll dieser in den edit modus gesetzt werden und überschrieben werden. ist der datensatz noch nicht vorhanden, dann soll die datenbank auf append gesetzt werden und der datensatz angefügt werden.
    hierzu gehe ich hin und überprüfe auf das feld "titel".
    nur irgendwie will das ganze nicht wirklich funktionieren. in der ausführung gibt er immer an das dieser datensatz noch nicht vorhanden ist.
    zur verdeutlichung hier nun der quelltext ( in abgespeckter variante )

    void __fastcall Tfrm_import::cmd_importClick(TObject *Sender)
    {
    	Connection_excel->ConnectionString = "Provider=MSDASQL;Persist Security \Info=False;Data Source=Excel-Dateien;Initial Catalog = '" + excel + "'";
    	Connection_excel->LoginPrompt = false;
    	Connection_excel->Open();
    
    	ADODataSet1->Connection = Connection_excel;
    	ADODataSet1->CommandText = "[Tabelle1$]";
    
    	ADODataSet1->CommandText = "SELECT Titel, Kategorie, Format, Anzahl, Bemerkung FROM [Tabelle1$]";
    	ADODataSet1->CommandType = cmdText;
    	ADODataSet1->Open();
    	ADODataSet1->First();
    
    	queryimport->First();
    	ProgressBar1->MaxValue = ADODataSet1->RecordCount;
    	ProgressBar1->Progress = 0;
    
    	for(int i = 0; i < ADODataSet1->RecordCount; i++)
    	{
    		if(queryimport->FieldByName("titel")->AsString == ADODataSet1->FieldByName("Titel")->AsString)
    		{
    			queryimport->Edit();
                    // dient jetzt nur zum testen, normalerweise die sql anweisungen
    			Application->MessageBoxA("0","",MB_OK);
    		}
    		if(queryimport->FieldByName("titel")->AsString != ADODataSet1->FieldByName("Titel")->AsString)
    		{
    			queryimport->Append();
                    // dient jetzt nur zum testen, normalerweise die sql anweisungen
    			Application->MessageBoxA("1","",MB_OK);
    		}
    		ProgressBar1->Progress = ProgressBar1->Progress +1;
    		ADODataSet1->Next();
    	}
    	ProgressBar1->Progress = 0;
    }
    

    warum wird nicht erkannt das ein titel in der datenbank vorhanden ist?

    anmerkung:
    die felder in der datenbank sind vom typ nvarchar (mssql)

    ich hoffe das mir einer helfen kann

    danke schon mal im voraus für eure mühen

    gruß
    Avalon



  • wie ist queryimport definiert?



  • hi Linnea,

    Linnea schrieb:

    wie ist queryimport definiert?

    SELECT * FROM tbl_filme
    

    hab das prob nun auf folgende art gelöst:

    void __fastcall Tfrm_import::cmd_importClick(TObject *Sender)
    {
    	Connection_excel->ConnectionString = "Provider=MSDASQL;Persist Security \Info=False;Data Source=Excel-Dateien;Initial Catalog = '" + excel + "'";
    	Connection_excel->LoginPrompt = false;
    	Connection_excel->Open();
    
    	ADODataSet1->Connection = Connection_excel;
    	ADODataSet1->CommandText = "[Tabelle1$]";
    
    	ADODataSet1->CommandText = "SELECT Titel, Kategorie, Format, Anzahl, Bemerkung FROM [Tabelle1$]";
    	ADODataSet1->CommandType = cmdText;
    	ADODataSet1->Open();
    	ADODataSet1->First();
    
    	queryimport->First();
    	ProgressBar1->MaxValue = ADODataSet1->RecordCount;
    	ProgressBar1->Progress = 0;
    
    	for(int i = 0; i <= ADODataSet1->RecordCount; i++)
    	{
    		AnsiString titel = ADODataSet1->FieldByName("Titel")->AsString;
    		queryimport->Close();
    		queryimport->SQL->Clear();
    		queryimport->SQL->Add("SELECT * FROM tbl_filme");
    		queryimport->SQL->Add("WHERE titel = '" + titel + "'");
    		queryimport->Open();
    
    		if(queryimport->RecordCount == 0)
    		{
    			queryimport->Append();
    			queryimport->FieldByName("titel")->AsString = ADODataSet1->FieldByName("Titel")->AsString;
    			queryimport->FieldByName("kategorie")->AsString = ADODataSet1->FieldByName("Kategorie")->AsString;
    			queryimport->FieldByName("format")->AsString = ADODataSet1->FieldByName("Format")->AsString;
    			queryimport->FieldByName("anzahl")->AsString = ADODataSet1->FieldByName("Anzahl")->AsString;
    			queryimport->FieldByName("bemerkung")->AsString = ADODataSet1->FieldByName("Bemerkung")->AsString;
    			queryimport->FieldByName("bild")->AsString = ".\\images\\nopic.jpg";
    			queryimport->Post();
    		}
    		if(queryimport->RecordCount == 1)
    		{
    			queryimport->Edit();
    			queryimport->FieldByName("titel")->AsString = ADODataSet1->FieldByName("Titel")->AsString;
    			queryimport->FieldByName("kategorie")->AsString = ADODataSet1->FieldByName("Kategorie")->AsString;
    			queryimport->FieldByName("format")->AsString = ADODataSet1->FieldByName("Format")->AsString;
    			queryimport->FieldByName("anzahl")->AsString = ADODataSet1->FieldByName("Anzahl")->AsString;
    			queryimport->FieldByName("bemerkung")->AsString = ADODataSet1->FieldByName("Bemerkung")->AsString;
    			queryimport->FieldByName("bild")->AsString = ".\\images\\nopic.jpg";
    			queryimport->Post();
    		}
    		ProgressBar1->Progress = ProgressBar1->Progress +1;
    		ADODataSet1->Next();
    
    	}
    	ProgressBar1->Progress = 0;
    	queryimport->Close();
    	ADODataSet1->Close();
    	Label2->Visible = true;
    	cmd_import->Enabled = false;
    }
    

    jetzt erkennt er endlich ob ein datensatz vorhanden ist oder nicht. wie im vorherigen post kann das ja auch nicht funktionieren da ich jede zeile der excel mit der ersten zeile der sql vergleiche.
    evtl lässt sich mein code hier noch etwas effectiver, bzw schlanker gestalten ?

    gruß
    Avalon


Anmelden zum Antworten