Announcement

Collapse
No announcement yet.

Wie erzeugt man mit ADO eine neue ACCESS Datenbank-Datei?

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

  • Wie erzeugt man mit ADO eine neue ACCESS Datenbank-Datei?

    Wenn die Datenbank-Datei „MyFile.MDB“ nicht wie in „MyFile.UDB“ definiert zu finden ist, soll sie automatisch erzeugt werden.

    Ich habe das Delphi Demoprogramm „AdoTest.exe“ lauffähig, auch mit einer „eigenen“ Datenbank. Ich kann neue Tabellen und neue Spalten erzeugen:<br>
    MasterQuery.SQL.Text := 'CREATE TABLE NewTable';<br>
    MasterQuery.ExecSQL;<br>
    MasterQuery.SQL.Text := 'ALTER TABLE NewTable ADD NewColumn smallint';<br>
    MasterQuery.ExecSQL;<br>
    Aber wie erzeuge ich die MDB-Datei?<br>
    MasterQuery.SQL.Text := 'CREATE DATABSE MyFile.UDB';<br>
    ergibt Fehlermeldungen.

    Mit freundlichen Grüßen <br>
    Rainer

  • #2
    Hallo,

    für diese Aufgabe muss auf <b>ADOX</b> (ADO Extension for Data Definition Language and Security) zurückgegriffen werden. Unter Delphi wird dazu zuerst die Typbibliothek <b>Microsoft ADO Ext. 2.1 for DDL and Security</b> importiert, so das die Unit ADOX_TLB.pas eingebunden werden kann. ADOX verwendet ein eigenes Objekt-Modell - das folgende Beispiel demonstriert das Anlegen einer neuen MDB, der Pfadname wird dabei in der TEdit-Instanz <i>EditMDB</i> definiert:
    <pre>
    uses ADOX_TLB;

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

    procedure TFormMain.ButtonCreateClick(Sender: TObject);
    var
    aCatalog : _Catalog;
    aTable : _Table;
    aColumn : _Column;
    sDBPath : String;
    sDS : String;
    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';
    aCatalog.Tables.Append(aTable);
    aColumn := CoColumn.Create;
    MemoLog.Lines.Add('Column...');
    with aColumn do
    begin
    Name := 'KdnName';
    Type_ := adVarWChar;
    ParentCatalog := aCatalog;
    Attributes := adColNullable;
    aColumn.DefinedSize := 30;
    Properties['Jet OLEDB:Allow Zero Length'].Value := True;
    Properties['Description'].Value := 'Name des Kunden'
    end;
    aTable.Columns.Append(aColumn.Name, adVarWChar, 0);
    MemoLog.Lines.Add('Spalte 1 hinzugefügt...');
    // Alternative 2: Spalte direkt deklarieren
    aTable.Columns.Append('eMail', adVarWChar, 20);
    MemoLog.Lines.Add('Spalte 2 hinzugefügt...');
    aTable.Columns.Refresh;
    MemoLog.Lines.Add('.... Fertig!');
    end;
    </pre&gt

    Comment


    • #3
      Besten Dank!! Auch dieser Tipp funktionierte auf Anhieb. „AdoTest.exe“ kann auch mit dieser neu erzeugten Datei arbeiten (Create Table und Alter Table ...). Aber Microsoft Access 97 SR-1 meckert: Unrecognized database format 'd:\Folder\MyFile.mdb'.
      Obwohl bisher die Datenbanken sowohl von „AdoTest.exe“ als auch Microsoft Access 97 zu öffnen waren. Ich bin auf die nächste Lektion gespannt, was zu tun ist, damit auch Access zufrieden ist.
      Nochmals vielen Dank für die schnelle und gute Hilfe.
      Raine

      Comment


      • #4
        Hallo,

        der Grund für diese Fehlermeldung liegt darin, das die JET ENGINE 4.0 als Vorgabewert eine ACCESS2000-Datenbank anlegt. Wenn man eine "alte" ACCESS97-MDB haben will, muss der Standardwert nur geändert werden. Anstelle von
        <pre>
        'Provider=Microsoft.Jet.OLEDB.4.0;....'
        </pre>
        muss nur der Provider für die "alte" DAO-Engine angefordert werden:
        <pre>
        'Provider=Microsoft.Jet.OLEDB.3.51;....'
        </pre&gt

        Comment


        • #5
          Es fehlt mir leider noch einiges Wissen! Die Änderung auf:<br>
          cCONNECTSTRING = 'Provider=Microsoft.Jet.OLEDB.3.51;....' <br>
          generiert zur Laufzeit die Fehlermeldung ´Class not registered‘. Leider weiß ich weder wo ich die Klasse her bekomme und wie sie heißt, noch wie sie registriert wird. Für „OLEDB 4.0“ habe ich nichts dergleichen bewußt getan. Kann ich das gewünschte Ziel noch erreichen oder ist es zu weit gesteckt? Ich hoffe auf den nächsten Tip.<br>
          Im Voraus besten Dank – Raine

          Comment


          • #6
            Hallo,

            in diesem Fall ist DAO 3.51 nicht auf dem Rechner installiert. Die Version 4.0 wird zusammen mit MDAC installiert - wenn diese fehlen würde, wäre ADO nicht einsatzfähig.

            In diesem Fall würde ich auf die zweite Alternative ausweichen und die JET ENGINE 4.0 beauftragen, die MDB im 3.5er-Format von ACCESS97 anzulegen. Im Connection-String wird <b>Jet OLEDB:Engine Type=4</b> definiert:
            <pre>
            'Provider=Microsoft.Jet.OLEDB.4.0;Data Source=xyz.mdb;Jet OLEDB:Engine Type=4;'
            </pre&gt

            Comment


            • #7

              Comment


              • #8
                Hallo,<br>
                ich habe das gleiche Problem und würde gerne auch eine MDB erzeugen.
                Ich habe aber leider die ADOX_TLB.pas werde auf der Delphi 5.0 Enterprice noch auf meiner Festplatte gefunden. Hat hier noch jemand eine Idee, wo man die findet.
                <br>
                Wolfgan

                Comment


                • #9
                  Noch mal ich,<br>
                  problem selber gelöst. Bei mir läuft es jetzt auch. Ein schönes Wochenende noch.<br>
                  Wolfgan

                  Comment


                  • #10
                    Ich möchte mit <b>aTable.Colums.Append(...)</b> ein Datenfeld „Bemerkung“ erzeugen, das nicht zwingend ausgefüllt wird. Wie setzt man die Required-Eigenschaft auf FALSE?

                    Im Voraus vielen Dank
                    Raine

                    Comment


                    • #11
                      Hallo,

                      in meinem Beispiel ist dafür die Zeile <b>Attributes := adColNullable; </b> zuständig:

                      <pre>
                      aColumn := CoColumn.Create;
                      with aColumn do
                      begin
                      Name := 'KdnName';
                      Type_ := adVarWChar;
                      ParentCatalog := aCatalog;
                      Attributes := adColNullable;
                      aColumn.DefinedSize := 30;
                      Properties['Jet OLEDB:Allow Zero Length'].Value := True;
                      Properties['Description'].Value := 'Name des Kunden'
                      end;
                      aTable.Columns.Append(aColumn.Name, adVarWChar, 0);
                      </pre&gt

                      Comment


                      • #12
                        Vorab nochmals vielen Dank für die Mühe. Aber je tiefer man einsteigt, um so mehr Wissen fehlt einem.<br>
                        Jetzt die Frage: Kann man den Feldtyp, bei String die Feldlänge und die Attribute auslesen, um z.B. Strings vorher auf das erlaubte Maß zu begrenzen. Ich nehme an, daß es geht. Also ist die Frage natürlich „wie geht das?“ .<br>

                        Mit freundlichen Grüßen<br>
                        Rainer

                        Comment


                        • #13
                          Hallo,

                          selbstverständlich geht das, wobei die Art und Weise vom verwendeten OLE DB-Provider abhängt. Bei einer SQL-Datenbank kann man direkt auf die Systemtabellen zugreifen - hier reicht ein einfacher SELECT-Aufruf aus.

                          Bei einer ACCESS-Datenbank steht <b>ADOX</b> (ADO Extension for Data Definition Language and Security) zur Verfügung. Die ADOX-Objekte unterstützen die Schemadaten der Datenbank (Catalog) sowie die Zugriffsberechtigungen (User und Groups). Für jedes Datenbankobjekt gibt es ein entsprechendes ADOX-Objekt. Das folgende Beispiel liest alle Tabellen aus:
                          <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>
                          Jedes Table-Objekt hat Kollektionen für <b>Columns</b>, <B>Indexes</b> und <b>Keys</b>, um auch auf die Struktur-Infos einer bestimmten Tabelle zugreifen zu können

                          Comment


                          • #14
                            Wahrscheinlich muß eine weitere Typenbibliothek importiert werden. <b>Aber wie ermittelt man den vollständigen „Lang-Namen“</b>, der im entsprechenden Import-Fenster angezeigt wird? <br>
                            Mit meiner Frage, wie man das „DefinedSize“ einer Spalte ermittelt, habe ich es mir wohl zu einfach gemacht. Trotzdem <b>vielen Dank</b> für das Beispiel. <b>Wo </b>kann man die verfügbaren Statements denn bloß <b>nachlesen?</b> Wenn ich es kompilieren kann, werde ich folgenden Weg ausprobieren:<br>
                            for i := 0 to iRecCount - 1 do <br>
                            begin <br>
                            aTable := aCatalog.Tables.Item[i]; <br>
                            ListBoxTableName.Items.Add(aTable.Name); <br>
                            IRecCount2 := aCatalog.Tables.Item[i].Columns.Get_Count; <br>
                            for i2 := 0 to iRecCount2 - 1 do <br>
                            begin <br>
                            aColumn := aCatalog.Tables.Item[i].Columns.Item[i2]; <br>
                            ListBox2.Items.Add(IntToStr(aColumn.DefinedSize)); <br>
                            end; <br>
                            end;<br>
                            (Sorry, ich bekomme das Einrücken nicht hin). Wird das funktionieren?<br>

                            MfG<br>
                            Raine

                            Comment


                            • #15
                              Hallo,

                              ADO ist eine Microsoft-Technologie und wird daher sehr ausführlich im <b>Platform SDK</b> - Untermenge <b>MDAC 2.5 SDK</b> dokumentiert. Dieses Hilfesystem erhält man entweder über das MSDN-Abo als CDROM, oder als Platform SDK-Download von der Microsoft Webseite oder in der Online-Version unter den MSDN-Webseiten

                              Comment

                              Working...
                              X