Announcement

Collapse
No announcement yet.

Mal wieder Export von MSSQL in Formate der Jet Engine

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

  • Mal wieder Export von MSSQL in Formate der Jet Engine

    Hallo,<BR>
    <BR>
    Ich m&ouml;chte mit reinem ADO unter Delphi4 Prof. einen Export von MSSQL7.0 nach dBASE, Paradox und Access machen. Dazu habe ich selbstverst&auml;ndlich alle (auch die mitlerweile gel&ouml;schten) Beitr&auml;ge gelesen, und auch umgesetzt ;-)<BR>
    An dieser Stelle vielen Dank an Herrn Kosch.<BR>
    <BR>
    Aber leider klappt nicht alles so reibungslos, wie in den Beitr&auml;gen beschrieben. Ich verwende MDAC2.7 auf deutschem NT mit SP6a.<BR>
    <BR>
    Der Export nach dBASE klappt einwandfrei, aber nach Paradox und Access bekomme ich immer die Fehlermeldung: "Please use updateable query"<BR>
    <BR>
    <PRE>
    //ConnectString JetEngine zusammenbasteln:
    JetConnString:='Provider=Microsoft.Jet.OLEDB.4.0;D ata Source=C:\Temp;'+
    'Extended Properties=dBASE 5.0;Persist Security Info=False';
    //ConnectString MSSQL Server zusammenbasteln:
    SQLConnString:='Provider=SQLOLEDB.1;Password='+FPa ssword+';Persist Security Info=False;User ID='+
    FUserID+';Initial Catalog='+InitCat+';Data Source='+FDataSource;
    //Select-String MSSQL-Server zusammensetzen:
    SQLSelectString:='SELECT Vorname, Nachname FROM Tabelle1_MSSQL';
    //SQL-String um die dBASE-Tabellen auf der Festplatte tatsächlich anzulegen:
    GenTableString:='CREATE TABLE Tabelle1_dBASE'+
    ' (Vorname CHAR(100), Nachname CHAR(100));';
    // Schritt 1: Daten von MSSQL-Server holen:
    aConMSSQL:=coConnection.Create;
    aConMSSQL.CursorLocation:=adUseClient;
    aConMSSQL.Open(SQLConnString,'','',adConnectUnspec ified);
    try // SQL-Server Recordset erzeugen
    aRSMSSQL:=coRecordset.Create;
    aRSMSSQL.Set_ActiveConnection(aConMSSQL);
    aRSMSSQL.CursorLocation:=adUseClient;
    try
    //MSSQL-Recordset füllen:
    aRSMSSQL.Open(SQLSelectString,EmptyParam,adOpenSta tic,adLockReadOnly, adCmdText);
    //Jet-Engine Connection erzeugen:
    aConJet:=coConnection.Create;
    aConJet.CursorLocation:=adUseClient;
    aConJet.Open(JetConnString,'','',adConnectUnspecif ied);
    //Tabellen zuerst anlegen (sonst schlägt aRSJet.Open fehl):
    aConJet.Execute(GenTableString,iRowsaffected,adCmd Unknown);
    try
    //Jet-Engine Recordset erzeugen:
    aRSJet:=coRecordset.Create;
    aRSJet.Set_ActiveConnection(aConJet);
    aRSJet.CursorLocation:=adUseClient;
    aRSJet.Open('Tabelle1_dBASE.dbf', EmptyParam, adOpenStatic, adLockOptimistic, adCmdTableDirect);
    aRSMSSQL.MoveFirst;
    // 2. Schritt: Daten in die Tabelle schreiben:
    while not aRSMSSQL.EOF do
    begin
    aRSJet.AddNew(EmptyParam, EmptyParam);
    aRSJet.Fields[0].Value:=aRSMSSQL.Fields[0].Value;
    aRSJet.Fields[1].Value:=aRSMSSQL.Fields[1].Value;
    aRSJet.Update(EmptyParam, EmptyParam);
    aRSMSSQL.MoveNext;
    end;
    //Jet-Engine-Recordset zerstören:
    aRSJet.Close;
    aRSJet:=nil;
    finally
    aConJet.Close;
    aConJet:=nil;
    end;
    finally
    aRSMSSQL.Close;
    aRSMSSQL:=nil;
    end;
    finally
    aConMSSQL.Close;
    aConMSSQL:=nil;
    end;
    </PRE>
    Das ganze funktioniert wie gesagt einwandfrei f&uuml;r dBASE. Aber wenn ich das gleiche für Paradox machen will ("Extended Properties=Paradox 5.x" und Datenbank-Endung nat&uuml;rlich ".db"), geht es schief.<BR>
    Der erste Update in der neuen Tabelle funktioniert noch, der zweite Update mit Fehlermeldung "Please use updateable query" leider nicht mehr.<BR>
    Die neue Paradox-Tabelle enthält danach selbstverst&auml;ndlich auch nur einen Datensatz.<BR>
    Ich habe schon mit den diversen Konstanten für Lock-, Open-, Connect- und Command-Type gespielt, aber noch keine Kombination gefunden, die passt.<BR>
    <BR>
    Kann mir irgend jemand sagen, wo der Fehler liegt?<BR>
    <BR>
    Mit freundlichen Gr&uuml;ssen,<BR>
    <BR>
    Peter Cr&auml;mer

  • #2
    Hallo,

    &gt;Kann mir irgend jemand sagen, wo der Fehler liegt?

    ja - die Ursache für dieses Problem liegt nicht an ADO, sondern an der Struktur der Zieldatenbank. Die als Ziel genutzte Paradox-Tabelle verwendet <b>keinen</b> Primärschlüssel, somit ist für die Microsoft JET Engine der Inhalt nur dann eindeutig, wenn die Tabelle nur aus einem einzigen Datensatz besteht. Für das Einfügen wird die Sequenz<br>
    a) neuen <b>leeren</b> Datensatz anlegen <br>
    b) Field-Werte dieses Datensatzes ändern <br>
    c) geänderten Inhalt über Update einarbeiten <br>
    aufgerufen, somit benötigt die JET-Engine für den Schritt c) ein logisch eindeutiges Kriterium, um den betroffenen Datensatz eindeutig zu finden (da <b>adUseClient</b> verwendet wurde, puffert die <i>OLE DB Client Cursor Engine</i> alle Änderungen erst im Arbeitsspeicher, um diese dann beim Update zurück zur Datenbank zu schicken (SQL)).

    Sobald die Paradox-Tabellen einen Primärschlüssel erhält, können problemlos mehrere Datensätze hinzugefügt werden.

    Wenn die JET-Engine mit einem Server-seitigen Cursor für die Paradox-Tabelle betrieben wird, liefert sie sofort das Veto zurück:
    <pre>
    uses ADODB_TLB;

    const
    cCS = 'Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Temp\;' +
    'Extended Properties=Paradox 5.x;Persist Security Info=False';
    cSQL= 'CREATE TABLE PdxTest (' +
    'RecID INTEGER,' +
    'Vorname VARCHAR(20),' +
    'Nachname VARCHAR(20))';

    procedure TForm1.Button1Click(Sender: TObject);
    var
    aCon : _Connection;
    aRS : _Recordset;
    vRows : OleVariant;
    i : Integer;
    begin
    aCon := CoConnection.Create as _Connection;
    aCon.CursorLocation := adUseServer;
    aCon.Open(cCS, '', '', adConnectUnspecified);
    try
    aCon.Execute(cSQL, vRows, adExecuteNoRecords);
    aRS := CoRecordset.Create as _Recordset;
    aRS.CursorLocation := adUseServer;
    aRS.Open('PdxTest', aCon, adOpenStatic,
    adLockOptimistic, adCmdTableDirect);
    for i := 0 to 50 do
    begin
    aRS.AddNew(EmptyParam, EmptyParam);
    aRS.Fields[0].Value := i + 100;
    aRS.Fields[1].Value := 'Vorname' + IntToStr(i);
    aRS.Fields[2].Value := 'Nachname' + IntToStr(i);
    aRS.Update(EmptyParam, EmptyParam);
    end;
    aRS.Close;
    finally
    aCon.Close;
    aCon := nil;
    end;
    end;
    </pre>
    Fehlermeldung beim Öffnen des Recordset: <i>"Operation wird für eine Paradox-Tabelle ohne Primärschlüssel nicht unterstützt."</i>

    &gt;Aber leider klappt nicht alles so reibungslos, wie in den Beiträgen beschrieben.

    Ich bin eben zu "Datenbank-lastig" und versehe jede Tabelle generell mit einem Primärschlüssel, so dass ich diese Probleme erst dann "sehe", wenn Sie als Fragen hier im FORUM auftauchen :-)

    Comment


    • #3
      Vielen Dank Herr Kosch!<BR>
      <BR>
      Da h&auml;tte ich eigentlich auch selber drauf kommen m&uuml;ssen! Aber die Fehlermeldung "Use updateable Query" hat mich wohl etwas zu sehr verwirrt ;-)<BR>
      <BR>
      Pete

      Comment

      Working...
      X