Mehrfachanmeldung bei Datenbank



  • Hallo!

    ich habe immernoch das Glück mit dem Borland C++ Builder 6 lustige Zugriffe und Abgleiche mit DBs zu machen.

    Mein Derzeitiges Problem:
    Wir haben eine Oracle DB die je nach eingegebenem Benutzernamen ein anderes Schemata zur Verfügung stellt. Diese erscheinen einem (subjektiv!) quasie als 2 verschiedene Datenbanken (so hab ich das zumindest verstanden).

    Nun ich darf für den Abgleich einiger Tables dieser beiden ich sage mal "Pseude Datenbanken" sorgen.

    Wie melde ich mich mit einem 2. Benutzer an? Beim Aktivieren der Verbindung zu nem Table der ersten "DB" kommt ja der Login. Versuche ich aber jetzt eine Verbindung zu einem Table des anderen Schemas aufbauen, sucht er natürlich da wo ich gerade mit Benutzer 1 eingeloggt bin. *moep* Exception. Was nun?

    EDIT: Ich betone nochmal dass User 1 auch eingeloggt bleiben muss, da es recht unschön wäre 5 Tables mit je nen paar Tausend Datensätzen irgendwie in ein Arrays zu stecken (wenn das überhaupt ginge...) und ein ständiges "hier einloggen, ausloggen, da ein loggen ... sollte auch nicht die Lösung sein oder? 😕



  • Vielleicht über ein zweites Datenbankobjekt (TDatabase, oder was du benutzt). Der Login erfolgt doch auch über das Datenbankobjekt.



  • Oder mit einem User, der Rechte auf die Tabellen sowohl des ersten als auch des zweiten Users hat (DB-ADMIN). Falls das geht, ist es deutlich einfacher Updates,INSERTs etc. zu realisieren als überr zwei Login's.



  • Also ich habe hier (in meinem Fremdcode) kein Datenbankobjekt gefunden. Lediglich ein DataModule, in dem sich nen haufen TTables, TDataSources und TQuerys befinden. Beim TTable (BDE) gibt man ja den Datenbanknamen an und die DataSource macht dann doch irgendwie den letzten Schritt zum Connect oder? Naja keine Ahnung auf jeden Fall ist das mit dem Database Objekt ne gute Idee, werde mal kurz durchdenken wie ich das hier alles umstricke... wie gesagt is ja nicht meinen Händen entsprungen das Prog hier.

    Das mit dem DB-Admin is mir leider momentan noch verwährt... ich bin ja nur Praktikant und obwohl ich mit einer Entwicklungsdatenbank arbeite is man da sehr vorsichtig mit, weil sie aus irgendeinem Grund "gepflegt" wird...



  • *moep* "doppelter Datenbankname"

    das mit 2 DataBase Objekten klappt leider nicht... 😞 gibts noch andere Möglichkeiten?



  • Wenn Du TDatabase-Objekte verwendest, gehe ich davon aus, dass Du über die BDE auf die Oracle-DB connectest. Du brauchst dann natürlich einen weiteren Alias, damit Du die Möglichkeit hast, dich erneut an der DB anzumelden.



  • Wegen dem doppeltem Datenbanknamem: Du musst die Eigenschaft AliasName benutzen, nicht DatabaseName, ist verwirrend, da bei TTable anderst.

    Mit TTable habe ich noch nicht viel gemacht, aber statt das Projekt jetzt auf TDatabase umzustellen, wäre es vielleicht einfacher mit zusätzlichen TTable-Objekten zu arbeiten. Musst du ausprobieren 😉



  • "isch fasses nisch, der geeeeht!"

    ja es läuft so weit ^^ Die beiden DB's sind laut meiner Abfrage abrufbereit (Active) 😃

    Ich hab mal beide eure Vorschläge verbunden.

    1. nen 2. Alias erstellt
    2. nur bei den Tables den Alias bzw. Databasename geändert (also ohne TDatabase gemacht)

    Jetzt gehts ans Eingemachte 😉 sich nen paar Tables schnappen, gucken was drin is und ggf. die 2. DB um fehlende Datensätze (aus Nr.1) erweitern.

    Hört sich einfach an oder? ^^ naja bei 65k Datensätzen in einem Table muss ich da schon was schickes nicht zu langsames konstruieren *g*

    Schönen Tag noch 🙂

    LG

    Oklino



  • Wenn Du mit zwei verschiedenen Aliasen arbeitest, kannst Du mit der BDE einen Cross-Select auf beide Datenbanken gleichtzeitig machen.

    SELECT 
    *
    FROM "Alias1:Tabelle"
    WHERE (NOT merkmal IN (SELECT FROM "Alias2:Tabelle")))
    

    Du darfst dann in der Query allerdings nichts bei DatabaseName angeben.



  • das einzige was ich jetzt mitten im Büro von mir gegeben habe, war: "*lach* cooool" - wie peinlich 😉

    Danke ich musste mir zwar im ersten Moment einen Knoten ins Hirn machen um die Verneinung zu verstehen aber hey, das is wie ich schon sagte "cool".

    EDIT: Vielen Dank erstmal 🙂 ich werd mal nen bisschen damit experimentieren!



  • [Schnipp] Antwort entfernt, da durch Bearbeitung des vorherigen Posts überflüssig. [Schnapp]



  • ich weiß... mir macht das doch auch keinen Spaß 😛 ^^

    irgendwie meckert er wegen dem SQL Query - wahrscheinlich habe ich nur was falsch geschrieben oder "merkmal" falsch interpretiert.

    DataModule1->Query2->SQL->Clear();
    DataModule1->Query2->SQL->Add("SELECT * FROM Haltestellen");
    DataModule1->Query2->Prepare();
    DataModule1->Query2->Open();
    
    AnsiString strSQLp2 = "' IN (SELECT * FROM teledb2.zHaltestellen))";
    
            while(!DataModule1->Query2->Eof)
            {
            AnsiString strSQLmid = DataModule1->Query2->FieldByName("Name")->AsString;
                    AnsiString SQLQry = "SELECT * FROM teledb.Haltestellen WHERE (NOT Name='" +strSQLmid+strSQLp2;
    

    teledb ist Schema 1 und teledb2 somit Schema 2. die Tables heißen fast gleich. in S2 ist ein z vorangestellt. also kann da der Fehler schonmal nicht sein *Schweißvonstirnwisch*



  • Vorab: So etwas solltest Du nicht an der echten Datenbank ausprobieren, wenn Du dir nicht absolut (150% !!!!) sicher bist, was passiert! Sonst mach dir vorsichtshalber eine Kopie der Tabellen und teste erst mal.

    Also 'merkmal' ist ein eindeutiges Indentifikationsmerkmal in den Tabellen. Also ein Feld, das in beiden Tabellen vorkommt und über das jeder Datensatz eindeutig indentifiziert werden kann. Im Regelfall kann der Primärindex verwendet werden (solange es kein Auto-Inc-Feld ist).

    SELECT
    * 
    FROM "teledb1:Haltestellen" db1hs
    WHERE NOT (db1hs.Name IN (
      SELECT
      Name
      FROM "teledb2:Haltestellen"))
    

    liefert dir eine Datenmenge, die alle Datensätze beinhaltet deren 'Name' sich in teledb1:Haltstellen befindet, aber nicht in teledb2:Haltestellen.



  • hmmmkay das mit dem Merkmal hatte ich gestern abend auch nochmal korrigiert... aber irgenwie schluckt die BDEngine das immernoch nicht. Erst kam ungültiges Schlüsselwort oder so ähnlich und moserte an einem nicht existierenden "?" rum. Zumindest gab die Fehlermeldung NUR das her.

    Ok irgendwann kam ich I*** mal auf die Idee die hochkommatar die ich für die " eingesetzt habe (sry war ich von PHP gewohnt...), wieder gegen " auszutauschen... in einem weiteren Denkvorgang kam ich dann auch mal auf die Idee diese zu Maskieren...

    SELECT * FROM \"teledb1:Haltestellen\" db1hs WHERE NOT (db1hs.Name IN (SELECT Name FROM \"teledb2:zHaltestellen\"))
    

    wobei man das äußere Klammernpaar auch weglassen kann oder?

    Wie auch immer - jetzt meint die BDE (wahscheinlich) dass sich hinter db1hs(.Name) ein Dateiname verbirgt. - Was der Aussage meines SQL Validators eig. widerspricht... aber die BDEngine gibt weder eine realistische Zeilenangabe (1) noch teilt sie einem mit welchen Dateinamen sie nicht findet damit man wenigstens sehen kann was falsch interpretiert wird (jaja compiliert 😛 )

    Hast du noch ne Idee woran das liegen kann? ich bin alle Schritte nach und nach durchgegangen aber es kommt erst beim prepare bzw. open des Statements zur Fehlermeldung.



  • ok, Du darfst mich schlagen... Ich habs gerade in einem alten Projekt noch mal nachgesehen. Da fehlt ein Doppelpunkt vor dem Aliasnamen... es muß heißen: ":Aliasname:Tabellenname"

    Sorry (aber ich bin schon sooo alt, da wird man vergesslich... 😉 )



  • was soll ich denn sagen mein Nachname ist Alt 😛

    EDIT: naja ich bin ziemlich froh, dass du die Ruhe und Geduld hast mir Dinge zu erklären die bei dir wahrscheinlich zu den Basics zählen 😉

    naja und nebenbei sollte ich das hier eigentlich im schlaf können aber dank unserer kompetenten Lehrkräfte haben wir während der Ausbildung nur Konsolenanwenungen geschrieben die ziemlich primitiven Kram gemacht haben... (Lohnabrechnungen die man nur während der Laufzeit sehen konnte - nix Datenbank, nix Csv 😉 ... *augenverdreh* )

    EDIT:
    ok Fehler is weg... ein andere da ^^ ich mach gleich den hier:
    http://www.urbachletter.com/0511/CubeWarsWinner_300x375.jpg

    und wieder die gute alte EDIT(H):

    void __fastcall TSDIAppForm::ZeRPClick(TObject *Sender)
    {
    //### User ein Gefühl von Sicherheit geben
    SDIAppForm->Memo->Lines->Add("Verbindung mit teledb wird hergestellt...");
    
    //### Verbindung checken und aufbauen. Dann User mit beruhigenden OKs ablenken
            if(!DataModule1->Haltestellen->Active){DataModule1->Haltestellen->Active = true;}
            SDIAppForm->Memo->Lines->Add("Haltestellen... OK");
            if(!DataModule1->Verkehrsmittel->Active){DataModule1->Verkehrsmittel->Active = true;}
            SDIAppForm->Memo->Lines->Add("Verkehrsmittel... OK");
            if(!DataModule1->Linien->Active){DataModule1->Linien->Active = true;}
            SDIAppForm->Memo->Lines->Add("Linien... OK");
            if(!DataModule1->Linienwege->Active){DataModule1->Linienwege->Active = true;}
            SDIAppForm->Memo->Lines->Add("Linienwege... OK");
            if(!DataModule1->Orte->Active){DataModule1->Orte->Active = true;}
            SDIAppForm->Memo->Lines->Add("Orte... OK");
    SDIAppForm->Memo->Lines->Clear();
    SDIAppForm->Memo->Lines->Add("Verbindung zu teledb steht!");
    
    //### Verbindung zu teledb2 Tables aufbauen und übliche Usernachrichten ausgeben.
    SDIAppForm->Memo->Lines->Add("Verbindung mit ZeRP wird hergestellt...");
            if(!DataModule1->zHaltestellen->Active){DataModule1->zHaltestellen->Active = true;}
            SDIAppForm->Memo->Lines->Add("Haltestellen... OK");
            if(!DataModule1->zLinientypen->Active){DataModule1->zLinientypen->Active = true;}
            SDIAppForm->Memo->Lines->Add("Linientypen... OK");
            if(!DataModule1->zLinien->Active){DataModule1->zLinien->Active = true;}
            SDIAppForm->Memo->Lines->Add("Linien... OK");
            if(!DataModule1->zLinienwege->Active){DataModule1->zLinienwege->Active = true;}
            SDIAppForm->Memo->Lines->Add("Linienwege... OK");
            if(!DataModule1->zOrte->Active){DataModule1->zOrte->Active = true;}
            SDIAppForm->Memo->Lines->Add("Orte... OK");
    SDIAppForm->Memo->Lines->Clear();
    SDIAppForm->Memo->Lines->Add("Verbindung zu teledb2 steht!");
    
    //### Beide Schemata erreichbar?
    if(DataModule1->Haltestellen->Active == true && DataModule1->zHaltestellen->Active == true)
    SDIAppForm->Memo->Lines->Add("eine Meldung...");
    
    //### so lange wir nicht alle Datensätze von Haltestellen durch haben...
            //while(!DataModule1->Query2->Eof)
            //{
            //AnsiString strSQLmid = DataModule1->Query2->FieldByName("Name")->AsString;
    
                    AnsiString SQLQry = "SELECT * FROM \":teledb:Haltestellen\" db1hs WHERE NOT (db1hs.Name IN (SELECT Name FROM \":teledb2:zHaltestellen\"))";
                    DataModule1->Query3->SQL->Clear();
                    DataModule1->Query3->SQL->Add(SQLQry);
            //      DataModule2->Query3->Prepare();
                    DataModule1->Query3->Open();
            //}
    


  • //### so lange wir nicht alle Datensätze von Haltestellen durch haben...
            //while(!DataModule1->Query2->Eof)
            //{
            //AnsiString strSQLmid = DataModule1->Query2->FieldByName("Name")->AsString;
    
                    AnsiString SQLQry = "SELECT * FROM \":teledb:Haltestellen\" db1hs WHERE NOT (db1hs.Name IN (SELECT Name FROM \":teledb2:zHaltestellen\"))";
                    DataModule1->Query3->SQL->Clear();
                    DataModule1->Query3->SQL->Add(SQLQry);
            //      DataModule2->Query3->Prepare();
                    DataModule1->Query3->Open();
            //}
    

    Ich verstehe nicht was Du damit erreichen willst. Und welche Fehlermeldung wird wann ausgegeben? Ich hab mir auch abgewöhnt \" zu verwenden. Ich finde es viel lesbarer QuotedStr() zu verwenden (ist aber wohl Geschmackssache).

    Noch eine andere Frage: ist der durchzuführende Abgleich bidirektional?



  • achso die Schleife die da auskommentiert ist, kann eigentlich ganz raus, das is noch nen Überbleibsel 😉

    nein der Abgleich ist quasie unidirektional (wenn ich die Frage richtig verstehe). es wird nur von teledb -> teledb2 geschoben.

    Wie der Name des Tables ja unschwer erraten lässt geht es um haltestellen. In teledb2 müssen alle Hst stehen die es gibt und jemals gab(d.h. dort wird nie etwas gelöscht, sie wird immer größer). In teledb stehen nur aktuelle drin, weil sie regelmäßig aktualisiert wird (einmal alles löschen und neue Daten rein).
    Ich (Depp) soll nun dafür sorgen dass teledb2 auf Knopfdurck bzw. klicken auf einen schon vorhandenen Menüpunkt, mit eventuell fehlenden Haltestellen gefüttert wird.

    Nun dachte ich nach deinem Ratschlag, mache ich dieses Cross-Select, und schreibe die Ergebnismenge (wie im Detail lassen wir mal außen vor) in teledb2.

    des weiteren dienen die Abfragen nach dem "Active" der TTables nur der Überprüfung für mich. Am Ende kommt das alles raus.



  • Oklino schrieb:

    ...
    //### User ein Gefühl von Sicherheit geben
    ...
    //### Verbindung checken und aufbauen. Dann User mit beruhigenden OKs ablenken
    ...
    

    Ich habe nichts zum Thema beizutragen, aber die Kommentare finde ich wunderbar 😉



  • Fincki schrieb:

    Oklino schrieb:

    ...
    //### User ein Gefühl von Sicherheit geben
    ...
    //### Verbindung checken und aufbauen. Dann User mit beruhigenden OKs ablenken
    ...
    

    Ich habe nichts zum Thema beizutragen, aber die Kommentare finde ich wunderbar 😉

    irgendwie muss man ja zwischendurch mal was unterhaltsames haben... zur Not lache ich dann über meine Kommentare (die ich vor der Übergabe natürlich entferne/editiere) 😃


Anmelden zum Antworten