Announcement

Collapse
No announcement yet.

1:1 - Kopie einer Referenztabelle erstellen

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

  • 1:1 - Kopie einer Referenztabelle erstellen

    Hallo zusammen,<BR>

    ich versuche via ADO mit folgendem Code eine Kopie einer Tabelle zu erstellen; die Methode läuft ohne Fehlermeldung durch, jedoch finde ich die Zieltabelle nicht!???<BR>

    <PRE>
    function TDMGlobal.ReplicateTable( Source, Target: string ): Boolean;
    // Erstellt eine exakte Kopie der Tabelle "Source" nach "Target"
    var
    SourceTable: TADODataSet;
    TargetTable: TADODataSet;
    begin
    SourceTable := TADODataSet.Create( nil );
    TargetTable := TADODataSet.Create( nil );
    try
    SourceTable.Connection := DBGlobal;
    SourceTable.CommandText := Source;
    SourceTable.CommandType := cmdTableDirect;
    SourceTable.Active := True;

    TargetTable.Connection := DBGlobal;
    TargetTable.CommandText := Target;
    TargetTable.CommandType := cmdTableDirect;
    TargetTable.FieldDefs.Assign( SourceTable.FieldDefs );
    TargetTable.IndexDefs.Assign( SourceTable.IndexDefs );

    TargetTable.CreateDataSet

    finally
    FreeAndNil( TargetTable );
    FreeAndNil( SourceTable )
    end
    end;
    </PRE>

    Danke für jede Antwort!

    Holger Rogge

  • #2
    Hallo,

    hinter TADODataSet verbirgt sich nur eine VCL-Wrapperkomponente für das darunterliegende native Recordset-Objekt von ADO. Daher kann TADODataSet nur das, was auch von den nativen ADO-Objekten unterstützt wird.

    Um eine Kopie einer Tabelle im Arbeitsspeicher zu erstellen, kann man folgendes machen:

    <pre>

    <b>uses</b> ActiveX, ComObj;

    <b>procedure</b> TForm1.CheckBoxCreateClick(Sender: TObject);
    <b>begin</b>
    <b>if</b> CheckBoxCreate.Checked <b>then</b>
    <b>begin</b>
    InitializeRecordset;
    ADOTable1.Recordset := FRecordset;
    ADOTable1.Open;
    StatusBar1.Panels[0].Text := Format(<font color="#9933CC">'%d Datensätze'</font>,
    [ADOTable1.RecordCount]);
    StatusBar1.Panels[1].Text := <font color="#9933CC">'Recordset ist aktiv'</font>;
    <b>end</b>
    <b>else</b>
    <b>begin</b>
    ADOTable1.Close;
    FRecordset := <b>nil</b>;
    StatusBar1.Panels[0].Text := <font color="#9933CC">''</font>;
    StatusBar1.Panels[1].Text := <font color="#9933CC">''</font>;
    <b>end</b>;
    <b>end</b>;

    <b>procedure</b> TForm1.InitializeRecordset;
    <b>begin</b>
    FRecordset := CreateComObject(CLASS_Recordset) <b>as</b> _Recordset;
    FRecordset.CursorLocation := adUseClient;
    <font color="#003399"><i>// Recordset mit eigener Datenstruktur erstellen</i></font>
    FRecordset.Fields.Append(<font color="#9933CC">'Name'</font>, adVarChar, 25, adFldUnspecified);
    FRecordset.Fields.Append(<font color="#9933CC">'Vorname'</font>, adVarChar, 25, adFldUnspecified);
    FRecordset.Fields.Append(<font color="#9933CC">'eMail'</font>, adVarChar, 25, adFldUnspecified);
    <font color="#003399"><i>// Recordset öffnen</i></font>
    FRecordset.Open(EmptyParam, EmptyParam, adOpenUnspecified,
    adLockUnspecified, 0);
    <b>end</b>;

    </pre>

    Wenn die neue Tabelle permanent in einer Datenbank angelegt werden soll, hängt die Vorgehensweise von der Datenbank ab. Im Fall einer ACCESS-Datenbank sind die <b>ADOX</b>-Objekte dafür zuständig (die Suche nach der Zeichenkette "ADOX" liefert hier im FORUM einige Beispiele). Im Fall einer SQL-Datenbank wird die Kopie über SQL angelegt

    Comment


    • #3
      Hallo Andreas<BR>

      Danke für den Hinweis, mit den Beispielen aus Ihrem Buch habe ich es so weit schon hinbekommen. Anbei der Code-Auszug:<BR>

      <PRE>
      function TDMGlobal.ReplicateTable( Source, Target: string ): Boolean;
      // Erstellt eine exakte Kopie der Tabelle "Source" nach "Target"
      var
      aCatalog : _Catalog;
      SourceTable : _Table;
      TargetTable : _Table;
      SourceColumn : _Column;
      TargetColumn : _Column;
      SourceIndex : _Index;
      TargetIndex : _Index;
      I : Integer;
      Y : Integer;
      begin
      Result := False;
      try
      aCatalog := CoCatalog.Create;
      aCatalog.Set_ActiveConnection( DBGlobal.ConnectionObject );
      SourceTable := aCatalog.Tables.Get_Item( Source );
      TargetTable := CoTable.Create;
      TargetTable.ParentCatalog := aCatalog;
      TargetTable.Name := Target;
      for I := 0 to Pred( SourceTable.Columns.Count ) do begin
      SourceColumn := SourceTable.Columns[ I ];
      TargetColumn := CoColumn.Create;
      TargetColumn.ParentCatalog := aCatalog;
      TargetColumn.Name := SourceColumn.Name;
      TargetColumn.Type_ := SourceColumn.Type_;
      TargetColumn.DefinedSize := SourceColumn.DefinedSize;
      TargetColumn.Properties[ 'Autoincrement' ].Value :=
      SourceColumn.Properties[ 'Autoincrement' ].Value;
      TargetColumn.Properties[ 'Description' ].Value :=
      SourceColumn.Properties[ 'Description' ].Value;
      TargetColumn.Properties[ 'Nullable' ].Value :=
      SourceColumn.Properties[ 'Nullable' ].Value;
      TargetColumn.Properties[ 'Fixed Length' ].Value :=
      SourceColumn.Properties[ 'Fixed Length' ].Value;
      TargetTable.Columns.Append( TargetColumn, 0, 0 );
      end;
      aCatalog.Tables.Append( TargetTable );
      // Nun noch die Indizes hinzufügen...
      for I := 0 to Pred( SourceTable.Indexes.Count ) do begin
      SourceIndex := SourceTable.Indexes[ I ];
      TargetIndex := ADOX_TLB.CoIndex.Create;
      TargetIndex.Name := SourceIndex.Name;
      TargetIndex.Clustered := SourceIndex.Clustered;
      TargetIndex.PrimaryKey := SourceIndex.PrimaryKey;
      TargetIndex.Unique := SourceIndex.Unique;
      for Y := 0 to Pred( SourceIndex.Columns.Count ) do begin
      TargetColumn := TargetTable.Columns.Item[ SourceIndex.Columns[ Y ].Name ] as Column;
      TargetIndex.Columns.Append( TargetColumn.Name,
      TargetColumn.Type_,
      TargetColumn.DefinedSize );
      end;
      TargetTable.Indexes.Append( TargetIndex, EmptyParam )
      end;
      Result := True
      except
      Result := False
      end
      end;
      </PRE>

      Das Problem an dieser Vorgehensweise ist, dass die Feldreihenfolge der Originaltabelle und der Kopie ( ist alphabetisch sortiert ) nicht identisch ist.<BR>
      Da die Tabellen auch exportiert werden ( SELECT * FROM... ) kann dies u.U. problematisch werden.<BR>

      Sollte Sie auch dafür eine Lösung wissen würde ich mich sehr freuen!<BR>

      MfG Holger Rogg

      Comment


      • #4
        Hallo,

        Ich stehe auch vor diesem Problem. Meine Frage ist, on man diese Function auch in SYBASE oder MSSQL verwenden kann???

        Ich habe die Function probiert und bekomme die Fehlermeldung <B>" Der Vorgang in diesem Zusammenhang nicht zugelassen" </B>

        Für weitere Ideen und Antwort bin ich Ihnen dankbar

        Mfg
        Khanh L

        Comment


        • #5
          Hallo,

          &gt;..auch in SYBASE oder MSSQL verwenden kann?

          die ADOX-Objekte unterstützen zur Zeit nur ACCESS-Datenbanken (*.mdb). Im Fall des MS SQL Server sind die COM-Objekte von <b>DMO</b> (Distributed Management Object) zuständig. Einfacher ist es aber, ein SQL-Script mit der CREATE TABLE-Anweisung ausführen zu lassen

          Comment


          • #6
            Guten Morgen Herr Kosch,

            znächst vielen Dank für die schnelle Antwort.
            <I meinem Problem.</I>
            Ich versuche die Daten von ASA6 und MSSQL in ASA9 zu kopieren/updaten. Wenn der Kunde in der QuellDatenbank irgendwann eine Tabelle angelegt hat, soll sie auch in der Ziel Datenbank <B>angelegt</B> und <B>upgedatet</B> werden.
            Mein Problem ist, ich weiss beim Updaten nicht wie die Tabelle aussieht. Also zu beachten sind die Tablecontraigns und Indexes und etc...
            ein SQL-Script kann icht nur basteln, wenn ich weiß wie die Voraussetzung ist??? Naja,Es wäre zu einfach , wenn man die Properties und Attributes von SourceTbl => TargetTbl kopiert.
            Das bleibt mir die Variant DMO (oder?). Für weitere Vorschläge und Ideen bedanke ich mich ganz herzlich
            Mfg Khanh L

            Comment


            • #7
              Hallo,

              &gt;Mein Problem ist, ich weiss beim Updaten nicht wie die Tabelle aussieht.

              der Vorteil von SQL-Datenbanken liegt darin, dass der SQL-Standard die Hersteller dazu <b>zwingt</b>, die Struktur der Arbeitstabellen über den SQL-Weg (Systemtabellen alias Katalog) zu veröffentlichen. Bei einer SQL-Datenbank können wir somit direkt in den Systemtabellen nachschauen, ob eine neue Tabelle hinzugekommen ist und ob sich die Struktur einer vorhandenen Tabelle geändert hat.

              Es ist dann nur eine Fleißarbeit, die in den Systemtabellen vorgefundenen Informationen so umzusetzen, dass am Ende das generierte CREATE TABLE-Statement herauskommt.

              Der Haken an der Sache liegt nur darin, dass der SQL-Standard so freizügig ist, jedem Hersteller das Gestalten der Systemtabellen selbst zu überlassen. In der Praxis führt das dazu, dass an dieser Stelle jeder Datenbank-Hersteller sein eigenes Süppchen kocht und wir für jede betroffene Datenbank das Rad neu erfinden müssen :-

              Comment


              • #8
                Vielen Dank Herr Kosch,

                Nach dem Motto:<BR>
                wenn nicht_anders_geht dann <BR>
                Todo := 'Fleiss muss sein' <BR>
                Sonst Aerger; <BR>

                na dann versuche ich ein neues Rad zu erfinden :-

                Comment

                Working...
                X