Announcement

Collapse
No announcement yet.

Beziehungsprobleme bei JET 4.0 ?

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Beziehungsprobleme bei JET 4.0 ?

    Hallo,

    über das neue Schlüsselwort "CONSTRAINT" können Beziehungen definiert werden. Hier der Syntax:

    <pre>
    Syntax
    Einzelfeldeinschränkung:

    CONSTRAINT Name {PRIMARY KEY | UNIQUE | NOT NULL |
    REFERENCES FremdTabelle [(FremdFeld1, FremdFeld2)]
    [ON UPDATE CASCADE | SET NULL]
    [ON DELETE CASCADE | SET NULL]

    Mehrfeldereinschränkung:

    CONSTRAINT Name
    {PRIMARY KEY (Primär1[,Primär2[, ...]]) |
    UNIQUE (Eindeutig1[,Eindeutig2[, ...]]) |
    NOT NULL (Nichtnull1[, Nichtnull2 [, ...]]) |
    FOREIGN KEY [NO INDEX] (Ref1[, Ref2 [, ...]]) REFERENCES FremdTabelle [(FremdFeld1 [, FremdFeld2 [, ...]])]}
    [ON UPDATE CASCADE | SET NULL]
    [ON DELETE CASCADE | SET NULL]

    </pre>

    Bei Datenbankupdates sollen auch Beziehungen aktualisiert werden, aber wie kann man feststellen ob schon eine Beziehung definiert ist oder nicht ?

    Gruß Mathias

  • #2
    Hallo,

    die <i>ADO Extension for Data Definition Language and Security</i>-Objekte (ADOX) unterstützen die Schemadaten einer Jet-Datenbank (Catalog). Über Catalog.Table.Key kann die Eigenschaft <B>Type</b> ausgewertet werden, ob dort der Wert <b>adKeyForeign</b> steht. Wenn ja, ist in der Eigenschaft <b>RelatedTable</b> die übergeordnete Tabelle vermerkt. Über Columns("Spalte").RelatedColumn kommt man an die Spalte und über die Eigenschaft <b>UpdateRule</b> kann man prüfen, ob mit <b>adRICascade</b> die kaskadierende referenzielle Integrität aktiviert ist.

    In der Microsoft-Hilfedatei aus dem Platform SDK ist unter dem Titel "<i>Keys Append Method, Key Type, RelatedColumn, RelatedTable and UpdateRule Properties Example (VB)</i>" ein Visual Basic-Beispiel zu finden, das 1:1 nach Delphi übersetzt werden kann

    Comment


    • #3
      Hallo Andreas,

      danke für die Info, weist Du zufällig wie man mit Delphi auf ADOX - Funktionen zugreifen kann. Habe hier mal ein einfaches Beispiel rausgesucht. Aber wie kann das in Delphi geschrieben werden ?

      <pre>
      ' BeginOpenConnection2VB
      Sub OpenConnectionWithString()

      Dim cat As New ADOX.Catalog

      cat.ActiveConnection = "Provider=Microsoft.Jet.OLEDB.4.0;" & _
      "Data Source=c:\Program Files\Microsoft Office\" & _
      "Office\Samples\Northwind.mdb;"
      Debug.Print cat.Tables(0).Type

      End Sub
      ' EndOpenConnection2VB

      </pre>

      Was würdest Du machen wenn Du mit Access2000 arbeitest und die Datenbank beim Kunden auf den aktuellen Strukturstand bringen müsstest. Also neue Schlüssel, Felder, Tabellen, Abfragen und Beziehungen. Ein Tipp wäre sehr wichtig für mich, nur damit ich die ungefähre Lösungsrichtung weis.

      Vielen Dank
      Mathia

      Comment


      • #4
        Hallo,

        da Delphi die ADO-Bestandteile ADOX und ADOMD offiziell nicht unterstützt, muss man selbst über <i>Projekt | Typbibliothek importieren</i> die Typbibliothek <b>Microsoft ADO Ext. 2.x for DDL and Security</b> importieren - Delphi legt dann eine TLB.pas-Unit mit allen benötigten Interfaces und Konstanten an.

        Da ADOX nur eine Erweiterung von ADO ist, müssen zum Zugriff beide Typbibliotheken eingebunden werden. Ausserdem muss das Programm über das Connection-Objekt von ADO zuerst eine Verbindung zur Datenbank herstellen. Erst dann kann das erzeugte Catalog-Objekt mit dieser bereits bestehenden Verbindung verbunden werden. ADOX verwaltet in der Tables-Kollektion für jede Datenbanktabelle ein eigenständiges Table-Objekt, so das das Programm zuerst die Anzahl der Tabellen der Datenbank ausliest. Anschliessend kann jedes einzelne Table-Objekt aus der Kollektion abgefordert werden - wobei sich das Beispielprogramm nur auf das Auslesen des Tabellennamens beschränkt. Als Erweiterung könnte für jede Tabelle auch jede Tabellenspalte (Column-Objekt) über die Columns-Kollektion ausgelesen werden.
        <pre>
        uses ADOX_TLB, ADODB_TLB;

        procedure TFormMain.ButtonShowTablesClick(Sender: TObject);
        var
        aConnection : _Connection;
        aCatalog : _Catalog;
        aTable : _Table;
        swConnString: WideString;
        iRecCount : Integer;
        i : Integer;
        begin
        StatusBar1.SimpleText := 'Recordset für SQL wird geöffnet....';
        // Step 1: Connection-Objekt
        aConnection:= CoConnection.Create;
        swConnString := 'Provider=Microsoft.Jet.OLEDB.4.0;' +
        'Data Source=C:\Database\dbdemos.mdb;' +
        'Persist Security Info=False';
        aConnection.Open(swConnString, '', '', -1);
        // Step 2: Catalog-Objekt
        aCatalog := CoCatalog.Create;
        aCatalog.Set_ActiveConnection(aConnection);
        iRecCount := aCatalog.Tables.Get_Count;
        ListBoxTableName.Items.Add(Format('%d Tabellen vorhanden',[iRecCount]));
        for i := 0 to iRecCount - 1 do
        begin
        aTable := aCatalog.Tables.Item[i];
        ListBoxTableName.Items.Add(aTable.Name);
        end;
        aConnection.Close;
        end;
        </pre>
        Das Anlegen einer neuen Tabelle mit ADOX könnte so aussehen:
        <pre>
        uses ADOX_TLB;

        resourcestring
        cCONNECTSTRING = 'Provider=Microsoft.Jet.OLEDB.4.0;Data Source=';

        procedure TFormMain.Button1Click(Sender: TObject);
        var
        aCatalog : _Catalog;
        aTable : _Table;
        aColumn : _Column;
        aIndex : _Index;
        sDBPath : String;
        sDS : String;
        vColName : OleVariant;
        begin
        MemoLog.Lines.Clear;
        sDBPath := EditMDB.Text;
        if FileExists(sDBPath) then
        begin
        DeleteFile(sDBPath);
        MemoLog.Lines.Add(Format('Datenbankdatei %s gelöscht',[sDBPath]));
        end;
        aCatalog := CoCatalog.Create;
        MemoLog.Lines.Add('Catalog...');
        sDS := aCatalog.Create(Format('%s%s',[cCONNECTSTRING, sDBPath]));
        MemoLog.Lines.Add(sDS);
        aTable := CoTable.Create;
        MemoLog.Lines.Add('Table...');
        aTable.ParentCatalog := aCatalog;
        aTable.Name := 'Kunden';

        // Spalte 1
        aColumn := CoColumn.Create;
        with aColumn do
        begin
        ParentCatalog := aCatalog;
        Name := 'KdnName';
        Type_ := adVarWChar;
        DefinedSize := 20;
        Properties['Description'].Value := 'Name des Kunden';
        Properties['Nullable'].Value := False;
        end;
        aTable.Columns.Append(aColumn, 0, 0);
        MemoLog.Lines.Add('Spalte 1 hinzugefügt...');

        // Spalte 2
        aColumn := CoColumn.Create;
        with aColumn do
        begin
        ParentCatalog := aCatalog;
        Name := 'Vorname';
        Type_ := adVarWChar;
        DefinedSize := 15;
        Properties['Description'].Value := 'Vorname des Kunden';
        Properties['Nullable'].Value := False;
        end;
        aTable.Columns.Append(aColumn, 0, 0);
        MemoLog.Lines.Add('Spalte 2 hinzugefügt...');

        // Spalte 3
        aColumn := CoColumn.Create;
        with aColumn do
        begin
        ParentCatalog := aCatalog;
        Name := 'eMail';
        Type_ := adVarWChar;
        DefinedSize := 20;
        Properties['Description'].Value := 'eMail-Adresse des Kunden';
        Properties['Default'].Value := '(unbekannt)';
        Properties['Jet OLEDB:Allow Zero Length'].Value := True;
        end;
        aTable.Columns.Append(aColumn, 0, 0);
        MemoLog.Lines.Add('Spalte 3 hinzugefügt...');

        // Spalte 4
        aColumn := CoColumn.Create;
        with aColumn do
        begin
        ParentCatalog := aCatalog;
        Name := 'Telefon';
        Type_ := adVarWChar;
        DefinedSize := 15;
        Properties['Description'].Value := 'Telefonnummer des Kunden';
        Properties['Nullable'].Value := True;
        end;
        aTable.Columns.Append(aColumn, 0, 0);
        MemoLog.Lines.Add('Spalte 2 hinzugefügt...');

        // Tabelle hinzufügen
        aCatalog.Tables.Append(aTable);
        MemoLog.Lines.Add('Tabelle hinzugefügt... ');

        // Primärschlüssel hinzufügen
        aIndex := CoIndex.Create;
        aIndex.Name := 'PKMix';
        vColName := 'KdnName';
        aColumn := aTable.Columns.Item[vColName] as _Column;
        aIndex.Columns.Append(aColumn.Name, aColumn.Type_, aColumn.DefinedSize);
        vColName := 'Vorname';
        aColumn := aTable.Columns.Item[vColName] as _Column;
        aIndex.Columns.Append(aColumn.Name, aColumn.Type_, aColumn.DefinedSize);
        aIndex.PrimaryKey := True;
        aIndex.Unique := True;
        aTable.Indexes.Append(aIndex, EmptyParam);
        MemoLog.Lines.Add('Index hinzugefügt... Fertig!');
        end;
        </pre>
        Die beste Vorgehensweise, um Kundendaten umzustrukturieren, hängt immer vom Einzelfall ab. Manchmal ist es am effektivsten, eine neue Datenbank auszuliefern und die Daten in einem Konvertierungsprogramm Datensatz für Datensatz dort einzutragen (zuerst Master-, dann Detail-Datensatz)

        Comment


        • #5
          Hallo Andreas,

          geht ziehmlich Tief rein, ist natürlich ne tolle Sache mal eben einfach so eine Typenbibliothek zu importieren. Muss das mal unbedingt nachbauen. Am interessantesten finde ich das Catalog - Object. Ich werde mal versuchen dein Beispiel nachzubauen, ich hoffe es gibt keine Probleme.

          Ich glaube die Frage von Heute hat sich dann auch erledigt, Feldeigenschaft 'Leere Zeichenfolge' in den Access 2000 Datenbanken via SQL zu beeinflussen. In deinem Beispiel konnte man die Anweisung -> Properties['Nullable'].Value := True; erkennen, wahrscheinlich kann man über diese Anweisung die angesprochende Eigeschaft setzen.

          Kann man über das CATALOG - Object auch vorhandene Felder ändern, wenn ja wird die Änderung sofort durchgeführt oder muss man für eine Änderung von Feldern eine bestimmte Methode aufrufen ? Es könnte auch seine das man erst über DROP Column xxx das Feld löscht und dann wieder anlegt, oder ?

          Vielen Dank,

          Gruß Mathia

          Comment


          • #6
            Hallo Andreas,

            macht wirklich Spass über ADOX etwas tiefer in die Materie vorzudringen. Habe mich nun mal an das Column-Objekt herangetastet.

            <pre>
            procedure TxfmMain.ButtonAdoxGetFieldDataClick(Sender: TObject);
            var
            aConnection : _Connection;
            aColumn : _Column;
            aCatalog : _Catalog;
            aTable : _Table;
            swConnString: WideString;
            iRecCount : Integer;
            i,y : Integer;
            x : string;
            xl : TListBox;

            begin
            xl := ListBoxAdoxTables;
            xl.Clear;

            aConnection := CoConnection.Create;
            swConnString := xdmMain.System.ConnectionString;
            aConnection.Open(swConnString,'','',-1);

            aCatalog := CoCatalog.Create;
            aCatalog.Set_ActiveConnection(aConnection);

            aTable := aCatalog.Tables.Get_Item('AccessFields');
            for i := 0 to aTable.Columns.Count-1 do
            begin
            aColumn := aTable.Columns[i];
            x:= aColumn.Name;
            x:= x + ' | '+ IntToStr(aColumn.Type_);
            x:= x + ' | '+ IntToStr(aColumn.Attributes);
            xl.Items.Add(x);

            for y := 0 to aColumn.Properties.Count-1 do
            begin
            x:= '--------------- : ';
            x:= x + aColumn.Properties[y].Name;
            x:= x + ' Value : ' + VarToStr(aColumn.Properties[y].Value);
            xl.Items.Add(x);
            end;

            end;

            aConnection.close;
            end;
            </pre>

            Das Ergebis sieht nach Schleifendurchlauf folgerndermaßen aus, man kann dort sehr schön die einzelnen Properties und dessen Werte sehen.

            <pre>
            ADOXChar | 202 | 2
            --------------- : Autoincrement Value : 0
            --------------- : Default Value :
            --------------- : Description Value : Test access to column porperties
            --------------- : Nullable Value : -1
            --------------- : Fixed Length Value : 0
            --------------- : Seed Value : 1
            --------------- : Increment Value : 1
            --------------- : Jet OLEDB:Column Validation Text Value :
            --------------- : Jet OLEDB:Column Validation Rule Value :
            --------------- : Jet OLEDB:IISAM Not Last Column Value : 0
            --------------- : Jet OLEDB:AutoGenerate Value : 0
            --------------- : Jet OLEDB:One BLOB per Page Value : 0
            --------------- : Jet OLEDB:Compressed UNICODE Strings Value : -1
            --------------- : Jet OLEDB:Allow Zero Length Value : -1
            --------------- : Jet OLEDB:Hyperlink Value : 0
            </pre>

            Ich arbeite ab jetzt auch mehr mit der MDAC SDK 2.6, wenn man erst einmal die Typenbibiothek importiert hat wird alles ein wenig klarer. Einige Properties kann ich nun nicht genau zuordnen, habe auch in der SDK nichts gefunden. Kannst Du da etwas Licht reinbringen ?

            Gruß Mathia

            Comment

            Working...
            X