Beziehungen von Access Tabellen abfragen



  • Aloha,

    ich habe eine Access DB per CDatabase und CRecordset an meine Applikation angebunden.

    Nun würde ich gerne bevor ich einen Datensatz aus einer Tabelle lösche, abfragen, ob dieser in irgendeiner Beziehung zu einer anderen Tabelle steht.

    Access läßt natürlich kein Löschen zu, wenn ich einen Datensatz löschen möchte, der in einer Beziehung steht, aber ich würde gerne vor dem Löschen wissen, ob der Datensatz löschbar ist, sprich die potentiellen Beziehungen abfragen.

    wie könnte ich dies realisieren ?

    Grüße

    BOA



  • Eine Möglichkeit:
    wenn die Tabellen z.B. über das Feld ID miteinander verknüpft sind:
    - ID aus dem Datensatz von Tabelle 1 auslesen
    - mit der ausgelesenen ID von Tabelle 1 auf Tabelle 2 filtern
    - gucken, ob Datensätze mit der gleichen ID in Tabelle 2 vorhanden sind
    Das geht ganz gut, wenn nicht ständig gelöscht werden soll. Bei vielen Zugriffen ist es evtl. nicht sehr performant.

    Noch eine Möglichkeit (nicht ausprobiert, nur so eine Idee):
    vielleicht kann man ja mit try/catch gucken ob das Löschen erfolgreich war. Wenn nicht, dann hast du das zwar nicht vorher gewusst, kannst aber die evtl. auftauchende Access-Fehlermeldung im catch-Block umgehen oder sonstwie drauf reagieren.



  • isabeau schrieb:

    Eine Möglichkeit:
    wenn die Tabellen z.B. über das Feld ID miteinander verknüpft sind:
    - ID aus dem Datensatz von Tabelle 1 auslesen
    - mit der ausgelesenen ID von Tabelle 1 auf Tabelle 2 filtern
    - gucken, ob Datensätze mit der gleichen ID in Tabelle 2 vorhanden sind
    Das geht ganz gut, wenn nicht ständig gelöscht werden soll. Bei vielen Zugriffen ist es evtl. nicht sehr performant.

    Noch eine Möglichkeit (nicht ausprobiert, nur so eine Idee):
    vielleicht kann man ja mit try/catch gucken ob das Löschen erfolgreich war. Wenn nicht, dann hast du das zwar nicht vorher gewusst, kannst aber die evtl. auftauchende Access-Fehlermeldung im catch-Block umgehen oder sonstwie drauf reagieren.

    Aloha isabeau,

    Deine erste Möglichkeit ist die die mir im Kopf rumgeschwirrt ist, ich kann sie aber nicht in Quellcode umsetzen, weil mir die Befehle fehlen.

    Ich kann per CDatabase zwar ein

    ExecuteSQL()
    

    ausführen, bekommen aber keinen Rückgabewert, der mich über ein Ergebnis informiert.
    Und das ist mein Problem.
    Du schreibst, daß das sehr gut geht, hast Du ein wenig Quellcode ?

    Die zweite Möglichkeit war auch schon in meinem Kopf, aber ich muß es vorher wissen, weil ich in einer Liste ausgeben möchte, ob ein Datensatz löschbar ist, oder nicht.

    Beste Grüße und Danke

    BOA



  • Mal zu der ersten Lösung (nicht getestet, nur ausm Kopp!):
    Mmmmhhh, du schreibst ja, dass du mit CDatabase und CRecordset arbeitest... Du müsstest also mindestens zwei von CRecordset abgeleitete Klassen auf deine beiden Tabellen mit den Beziehungen haben.
    Ausserdem schreibst du, dass du in einer Liste stehen haben möchtest, welche Datensätze man löschen kann und welche nicht.
    Dann geht das in etwa so:

    CTabelle1 Tabelle1;	// CTabelle1 ist die von CRecordset abgeleitete Klasse auf Tabelle 1
    Tabelle1.Open();
    
    CTabelle2 Tabelle2;	// CTabelle2 ist die von CRecordset abgeleitete Klasse auf Tabelle 2
    Tabelle2.Open();
    
    while(!Tabelle1.IsEOF())	// komplette Tabelle 1 auslesen
    {
    	Tabelle2.m_strFilter = "ID='" + Tabelle1.m_ID + "'";	// Filter auf das Feld ID von Tabelle 2
    								// mit dem Inhalt des Feldes ID aus Tabelle 1
    
    	Tabelle2.Requery();	// Tabelle 2 aktualisieren
    
    	if(Tabelle2.IsEOF())
    	{
    		// keine Datensätze vorhanden -> kann in Tabelle 1 gelöscht werden
    	}
    	else
    	{
    		// Datensätze vorhanden -> nicht in Tabelle 1 löschen
    	}
    
    	Tabelle1.MoveNext();
    }
    
    Tabelle2.Close();
    Tabelle1.Close();
    

    Da kommt dann aber ziemlich oft Requery() vor. Bei vielen Datensätzen in Tabelle 1 könnte das relativ lange dauern...

    Vielleicht gibt es ja noch etwas besseres, z.B. so in der Art:

    CTabelle2 Tabelle2;	// CTabelle2 ist die von CRecordset abgeleitete Klasse auf Tabelle 2
    Tabelle2.m_strSort = "ID";	// nach Feld ID sortiert
    Tabelle2.Open();
    
    CString strAltID;	// merkt sich die alte ID
    CString strIDs;		// merkt sich alle vorkommenden verschiedenen IDs
    
    while(!Tabelle2.IsEOF())	// komplette Tabelle 2 auslesen
    {
    	strAltID = Tabelle2.m_ID;	// merken
    
    	strIDs += "'" + Tabelle2.m_ID + "'"; // mit Trennzeichen ' merken
    
    	while(!Tabelle2.IsEOF()) && strAltID == Tabelle2.m_ID)
    		Tabelle2.MoveNext();	// haben wir schon, brauchen wir nicht doppelt
    }
    
    Tabelle2.Close();
    
    // ...und jetzt Tabelle 1 auslesen:
    
    CTabelle1 Tabelle1;	// CTabelle1 ist die von CRecordset abgeleitete Klasse auf Tabelle 1
    Tabelle1.Open();
    
    CString strID;	// Kontrollstring
    
    while(!Tabelle1.IsEOF())	// komplette Tabelle 1 auslesen
    {
    	strID = "'" + Tabelle1.m_ID + "'";	// den hier suchen wir im String mit den ganzen IDs
    
    	if(strIDs.Find(strID) != -1)
    	{
    		// diese ID ist auch in Tabelle2 vorhanden -> nicht löschen
    	}
    	else
    	{
    		// diese ID ist nicht in Tabelle2 vorhanden -> löschen
    	}
    
    	Tabelle1.MoveNext();
    }
    
    Tabelle1.Close();
    

    Das ist aber auch nur so eine Idee. Ist vielleicht besser, sich die IDs nicht in einem CString, sondern in einem Array oder sonstwie zu merken. Vielleicht gibt es aber auch noch was ganz anderes...



  • Aloha isabeau,

    nur ein Satz.

    Fühl Dich virtuell geküßt

    Genau so habe ich mir das vorgestellt. Perfekt !!!!!!!!!!!!!!!!!!!!!!!!!!!!

    Nicht nur 1000 und einen, sondern 2000 und einen Dank in Deine Richtung.

    Grüße

    BOA



  • BOA schrieb:

    Fühl Dich virtuell geküßt

    Das ist leider ein Mann, obwohl der Name sich weiblich anhört. 😃



  • haha schrieb:

    BOA schrieb:

    Fühl Dich virtuell geküßt

    Das ist leider ein Mann, obwohl der Name sich weiblich anhört. 😃

    Aloha,

    deswegen auch nur virtuell.

    Aber im Notfall, auf einer einsamen Insel...... 😉

    Nee, hat mir prima geholfen, egal ob Männchen oder Weibchen.

    Grüße

    BOA


Anmelden zum Antworten