[C++Builder] Hilfe zu ADO-Abfragen
-
Ich hab noch eine kleine Frage!
Wenn ich nun eine Ergebnismenge bekomme die mehrere Einträge hat, wie kann man am besten diese Werte an andere Methoden übergeben.
Ich kann ja z.B. einen Pointer auf das TADOQuery Objekt übergeben wobei ich das nicht so toll finde.
Gibt es eine Komponente oder Struktur, in die man ganz leicht alle Werte er Ergebnismenge kopieren kann und die dann als return - Wert übergibt?
Ich habe mir auch schon überlegt, alle Werte in einem AnsiString zu speichern und diesen dann zu übergeben, doch dann muss ich den an der anderen Stelle wieder auseinander filtern.
Schön wäre eine Liste, mit der man leicht auf alle Werte drauf zugreifen kann!
Eine Idee??
-
Stellt sich mir die Frage, wozu Du die Ergebnismenge in einer Liste haben willst?!? Was willst Du mir dieser Liste machen?
Im Prinzip ist die Query die Liste.
-
Das schöne an einem DataSet ist, daß der Container so variabel ist. Du mußt nicht allzu viel über die Datenmenge wissen, die dort "aufbewahrt" wird.
Klar kannst Du den ganzen Kram an einen StringArray übergeben, doch da mußt Du mindestens die Struktur des RecordSets kennen, nachbilden und bei jeder Änderung des DataSets mit ändern. Vieeel Arbeit für welchen Nutzen?
Warum sollte ein DataSet nicht mehrere Datensätze enthalten (ja ich mische hier C++ und SQL Terminologie wild durcheinander). Angezeigt wird in einen DBEdit immer der aktuelle DS oder alle DS der Abfragemenge in einem DBGrid (einer Tabelle mit Bezug auf eine DataSource mit Bezug auf ein DataSet z.B. BDGrid->DataSource->DataSet->FieldByName("DaskommtMirBekanntVor"))
Navigieren kannst Du durch das DataSet mit (also den aktuellen DS wählen/ändern):
RecNo = Aktueller DS
First = Erster
Last = Letzter
Next = Nächster
Prior = Vorheriger
etc. uvm. (siehe BCB-Hilfe Methoden TDataSet) :p
-
Morgen,
ich habe mein Programm so aufgebaut, das es keine visuellen Anzeigen geben wird. Das programm wirr im HIntergrund laufen und Aufgaben erledigen.
Ich habe eine Klasse die z.B. folgende Methode hat:
->ueberpruefe_Akzeptanz();
Mit dieser Methode möchte ich einen Wert aus der Datenbank holen und überprüfen welche Information der Wert mir leifert.
In der Methode ueberpruefe_Akzeptanz() wird ein SQL Befehl an die folgende Methode gegeben.
->sql_statement_ausfuehren(AnsiString sql_befehl)
und hier möchte ich dann die Sache durchführen die wir hier in diesem Thread so toll besprochen haben!
Wenn es ein SQL-Befehl ist, der nur Sachen in die DB schreibt, dann ist das ja kein Problem, da keine Ergebnismenge doch gerade bei diesem Beispiel (->ueberpruefe_Akzeptanz() ) will ich ja eine Ergebnismenge zurückgekommen. Das heißt die Methode sql_statement_ausfuehren muss mir die Ergebnismenge an die Methode ->ueberpruefe_Akzeptanz() geben damit ich mit dieser was machen kann.Meine Frage ist jetzt eh da ich schon das ganz getestet habe, warum er mir nicht alle Werte des SQL-Befehls liefert.
Wenn ich z.B. den Befehl:
select * from Mitarbeiter;
ausführe (DB-Explorer), dann bekomme ich wirklich alle Werte angezeigt. Wenn ich das aber jetzt mit der ADOQuery-Koponente mache, dann bekomm ich leider nicht alle Werte geliefert, sondern nur eine willkürlichen Teil.
Ist das normal??
Wie kann ich denn alle Werte bekommen??
Danke für die Antworten
-
Ohne Where-Bedingung hat er alle Werte der Tabelle zu liefern, so oder so.
Bist Du sicher, daß Du immer auf die gleiche Datenbank zugreift. Das ist mein beliebtester Fehler um bei gleichem Select unterschiedliche Ergebnismengen zu erhalten.
Alternativ dazu steht immer im Raum, daß der Select doch nicht identisch ist.
(z.B. ein vergessener Parameter)
-
Es ist die gleicher Datenbank!
Er leifert ja einen Teil von den Ergebnissen die er bringen soll.Wenn ich im DB-Explorer folgenden SQL-Befehl eingebe:
select * from Mitarbeiter;
dann bekomme ich 5*4 = 20 Ergebnisse (ist nur eine Test-DB *g*)
Dieses Ergebnis erwarte ich auch jetzt mit der ADOQuery-Koponente.
Wenn ich den gleichen SQL-Befehl
AnsiString sql; sql = "select * from Mitarbeiter"; sql_statement_ausfuehren(sql);
jetzt mit der ADOQuery ausführe, dann liefert mir adoquery->RecoredCount = 5 und
das Ergebnis ist die erste Zeile der Ergebnismenge. Es sollten aber noch 4 weitere Zeilen folgenEine Ahnung an was das liegen kann?
Hier jetzt mal die definierte sql_statement_ausfuehren Methode:
Test::sql_statement_ausfuehren(AnsiString sql_befehl) { TADOQuery *adoq = new TADOQuery(Application); TADOConnection *adoc = new TADOConnection(Application); AnsiString DB_PROVIDER = "MSDASQL.1"; AnsiString DB_PASSWORD = "root"; AnsiString DB_USER_ID = "root"; AnsiString DB_DATA_SOURCE = "Time_Server"; adoc->ConnectionString = "Provider="+DB_PROVIDER+";Password="+DB_PASSWORD+";" "User ID="+DB_USER_ID+";Data Source="+DB_DATA_SOURCE+";" "Persist Security Info=True;"; adoc->Open(); adoq->Connection = adoc; AnsiString sql; AnsiString ergebnis; int count; if (adoq->Active) { adoq->Close(); } adoq->SQL->Clear(); adoq->SQL->Add(sql_befehl); adoq->Open(); count = adoq->RecordCount; AnsiString Ergebnis = ""; Ergebnis += IntToStr(count) + ";"; for(int i=0; i < count ; i++) { Ergebnis += adoq->Fields->Fields[i]->AsString; Ergebnis += ";"; } }
-
Deine for-Schleife kommt mir dubios vor.
Folgendes Beispiel liest die einzelnen Datensätze aus der Tabelle. In der Variable Ergebnis werden die einzelnen Felder zusammengekettet.while (!adoq->Eof) { Ergebnis = adoq->FieldByName("Feldname1")->AsString; Ergebnis = Ergebnis + "," + adoq->FieldByName("FeldnameX")->AsString; adoq->Next(); }
-
dann bekomme ich 5*4 = 20 Ergebnisse (ist nur eine Test-DB *g*)
kann es sein dass die 4 in deinem Beispiel die Anzahl der Spalten ist?
das Query liefert dir Datensätze und jeder Datensatz besteht aus einer tabellenabhängigen Anzahl von Spalten
ich glaube du weißt immer noch nicht wie Query funktioniert
-
Das scheint schon eine gute Lösung zu sein, doch was mich bis jetzt noch ein bisschen daran stört ist die Methode
adoq->FieldByName("....")->AsString;
denn woher soll ich denn z.B. bei einem SQL-Befehl wie "select * from Mitarbeiter" wissen, welche Spalten er da alle findet? Ich muss die ihm ja dann immer als String in die Methode übergeben, oder?
Ich sehe das so, das die Methode ->FieldByName("...") immer den Ausdruck braucht, den ich nach dem select Statement benutze, also z.B.
select vorname from ---> FieldByName("Vorname");
oder
select Persnr from ----> FieldByName("Persnr");
wie mach ich das dann aber in einer Schleife und vor allem mit dem SQL Befehl:
select * from... ??????
Das habe ich noch nicht richtig verstanden!
-
Du hast vollkommen recht das ich mich noch nicht mit dieser Koponente auskenne!
Ich war der Meinung die Query-Komponente führt SQL-Befehle aus und speichert alle Ergebnisse in sich.So wie ich dich gerade verstanden habe speichert sie immer nur eine Zeile ab, oder?
Die 4 ist die Spaltenanzahl, richtig! Ich habe 4 Spalten und zu denen gibt es 5 Zeilen mit Werten.
Kann ich jetzt trotzdem mit einem SQL-Befehl an alle Werte ran kommen?
Denn ich benötige ja alle!
-
Die for-Schleife aus deinem Beispielcode erfüllt doch den gewünschten Zweck. EDIT: Also deine for schleife in meine while Schleife. Nur RecordCount musst du durch FieldCount ersetzen.
Ich bevorzuge halt den Zugriff über den Namen der Spalte. Die Spaltennamen kann man auch bei 'select * from' nutzen. Select * würde ich aber auch vermeiden und alle Felder auflisten, denn nur was man explizit hinschreibt, ist auch eindeutig.
-
Nachdem, was ich gelesen habe, ist das Ergebnis des Selects immer das gleiche
jeweils 5 Datensätze je x(4) Spalten.Ein select * ist für adhoc-Abfragen OK. Für eine Hinterlegung in Code ist eigentlich immer Blödsinn. Was passiert, wenn Du in einem halben Jahr der Tabelle noch weitere Spalten hinzufügst? Willst Du diese Spalten dann sofort in der Abfrage haben. Hier sehe ich einen konzeptionellen Fehler.
Diesen hat bei uns auch mal ein Praktikant begangen, Schreib- und Denkarbeit gespart und nach kurzer Zeit funktionierte sein Programm nicht mehr.
Zweitens solltest Du Dich dringend mit der Hilfe befassen & Du solltest Dich mit den Grundlagen von (relationalen) Datenbanken befassen.
Wenn Du einen Ergebnisstring willst, kannst Du das auch einfacher haben!
Bsp.
select Spalte1 + ';'+Spalte2+'___'+convert(varchar(120),Spalte3)+'irgendEineStringKonstante' as Ergebnis from Tabelle
Das geht schneller als es in C++ nachzustellen. Für derartige Datenoperationen ist SQL ja schließlich entworfen und optimiert.
-
Also in Sachen Datenbanken bin ich leider noch ein Anfänger. Einige Sachen habe ich von den Vorlesungen mitbgenommen, doch die müssen sich in der pratischen Arbeit erst noch festigen und setzen.
Den SQL-Befehl: "select * from Mitarbeiter" war nur als kleinen test gedacht, damit ich mal sehen, wie die Query_koponente die Ergebnisse verwaltet und wie ich auf sie zugreifen kann.
In den meisten Fällen werde ich in meinem programm nach einem Ergebnis abfragen und nicht eine große Menge!
Doch trotzdem kommt es an manchen Stellen vor und ich möchte halt damit umgehen können um auf alle Daten zugreifen zu können.Die BCB-hilfe ist an manchen Stellen recht gut und verständlich und hilft auch sehr weiter doch manchmal (gerade in diesem Fall) werden Begriffe benutzt die bei mir einen anderen Sinn haben.
Also ich versuche mal mit den Erkenntnissen dieses Threads zurecht zukommen. Doch wenn noch Fragen sind hoffe ich ich kann mich wieder an euch wenden
!?