none
Aktionsabfragen in ACCDB/SQL-Server

    Frage

  • Hallo,

    wir haben eine ACCDB (Acc2010) mit eingebundenen Tabellen Und Views (SQL-Server2008R2).

    Zum Erstellen/Ändern von Tabellen und Views auf dem SQL-Server verwenden wir eine globale Connection.
    Global gcnn As New ADODB.Connection
    gcnn.Open "ODBC;Description=SQL2008;DRIVER=SQL Server;SERVER=..."

    Bei Aktionsabfragen habe ich das Gefühl, dass sie mit gcnn.Execute wesentlich schneller ausgeführt werden als mit DoCmd.RunSQL oder CurrentDb.Execute.

    Welches ist hier die empfohlene Methode?

    Gruß Thomas

    Dienstag, 6. November 2012 07:47

Antworten

  • Hallo,

    Thomas Warnke wrote:

    danke für die Antwort. Kann ich mit ACEDAO auch Datenbankobjekte auf dem
    SQL-Server erstellen/bearbeiten?

    Klar, Stichwort PassThrough.

    Unsere Anwendung erstellt beim ersten
    Start die Datenbank auf dem SQL-Server und bindet die Views per ODBC an.
    In Updates werden später ggfs. Tabellen/Views aktualisiert. Das machen
    wir momentan noch mit ADO.

    Alles, was du per SQL (T-SQL) erledigen kannst, geht logischerweise mit
    beiden Providern. Im Funktionsumfang unterscheiden sie sich leicht, was
    aber bei der Kombination Access<->SQL Sever normalerweise keine Rolle
    spielt.
    Gruss - Peter


    Mitglied im http://www.dbdev.org
    FAQ: http://www.donkarl.com

    • Als Antwort markiert Thomas Warnke Montag, 12. November 2012 13:04
    Sonntag, 11. November 2012 23:01
    Moderator

Alle Antworten

  • Hallo,

    Thomas Warnke wrote:

    wir haben eine ACCDB (Acc2010) mit eingebundenen Tabellen Und Views
    (SQL-Server2008R2).

    Zum Erstellen/Ändern von Tabellen und Views auf dem SQL-Server verwenden
    wir eine globale Connection.

    Global gcnn As New ADODB.Connection
    gcnn.Open "ODBC;Description=SQL2008;DRIVER=SQL Server;SERVER=..."

    Bei Aktionsabfragen habe ich das Gefühl, dass sie mit gcnn.Execute
    wesentlich schneller ausgeführt werden als mit DoCmd.RunSQL oder
    CurrentDb.Execute.

    <Conn>.Execute ist eine ADO-Methode, waehrend <DB.Execute zu DAO bzw.
    ACEDAO gehoert. .RunSQL ist eine Makroaktion, die gegenueber der anderen
    beiden Aktionen sicher langsamer ist.

    Welches ist hier die empfohlene Methode?

    Generell wird seit 2003 fuer den Zugriff auf Jet/ACE wieder DAO bzw. seit
    2007 ACEDAO empfohlen, d.h. <DB>.Execute. Fuer den Zugriff auf SQL Server
    kannst du verwenden, was dir am besten liegt. Die zu Zeiten des ADO-Hype
    hochgelobten Vorteile spielen in der Praxis kaum eine Rolle, ganz abgesehen
    davon dass ADO nicht mehr weiterentwickelt wird.

    Nachdem in Access 2013 die Unterstuetzung fuer ADP, die ausschliesslich per
    ADO zugreifen konnten, komplett abgeschafft worden ist, wird von Microsoft
    fuer den Zugriff auf SQL Server ODBC/ACEDAO empfohlen. Die Empfehlung gab
    es allerdings schon laenger, mindestens seit 2010.

    Gruss - Peter


    Mitglied im http://www.dbdev.org
    FAQ: http://www.donkarl.com

    Sonntag, 11. November 2012 10:43
    Moderator
  • Hallo,

    danke für die Antwort. Kann ich mit ACEDAO auch Datenbankobjekte auf dem SQL-Server erstellen/bearbeiten? Unsere Anwendung erstellt beim ersten Start die Datenbank auf dem SQL-Server und bindet die Views per ODBC an. In Updates werden später ggfs. Tabellen/Views aktualisiert. Das machen wir momentan noch mit ADO.

    Gruß Thomas

    Sonntag, 11. November 2012 17:36
  • Hallo,

    Thomas Warnke wrote:

    danke für die Antwort. Kann ich mit ACEDAO auch Datenbankobjekte auf dem
    SQL-Server erstellen/bearbeiten?

    Klar, Stichwort PassThrough.

    Unsere Anwendung erstellt beim ersten
    Start die Datenbank auf dem SQL-Server und bindet die Views per ODBC an.
    In Updates werden später ggfs. Tabellen/Views aktualisiert. Das machen
    wir momentan noch mit ADO.

    Alles, was du per SQL (T-SQL) erledigen kannst, geht logischerweise mit
    beiden Providern. Im Funktionsumfang unterscheiden sie sich leicht, was
    aber bei der Kombination Access<->SQL Sever normalerweise keine Rolle
    spielt.
    Gruss - Peter


    Mitglied im http://www.dbdev.org
    FAQ: http://www.donkarl.com

    • Als Antwort markiert Thomas Warnke Montag, 12. November 2012 13:04
    Sonntag, 11. November 2012 23:01
    Moderator
  • Hallo,

    ich hab mir jetzt eine Funktion zum Ausführen von PT-Abfragen gebaut:

    Public Sub subRunPTR(sql As String)
        Dim qdf As QueryDef
        
        Set qdf = CurrentDb.QueryDefs("qry_PTR")
        With qdf
            .Connect = fktConnect()
            .sql = sql
            .ReturnsRecords = False
            '.Execute   'keine Fehlermeldung, nur "ODBC-Aufruf fehlgeschlagen!"
            .Close
        End With
        DoCmd.OpenQuery "qry_PTR", acViewNormal, acReadOnly

        Set qdf = Nothing
    End Sub

    Ist es nicht etwas umständlich, erst eine Query zu erstellen, um diese dann auszuführen?

    Bei Google hab ich noch etwas von einem ODBC-Direktbereich gefunden, aber das wird wohl nicht mehr unterstützt. (Set wrk = DBEngine.CreateWorkspace("temp", "", "", dbUseODBC)

    Gruß Thomas

    Montag, 12. November 2012 13:13
  • Hallo,

    Thomas Warnke wrote:

    Public Sub subRunPTR(sql As String)
        Dim qdf As QueryDef
        
        Set qdf = CurrentDb.QueryDefs("qry_PTR")
        With qdf
            .Connect = fktConnect()
            .sql = sql
            .ReturnsRecords = False

    An der Stelle solltest du noch den Timeout setzen, bzw. abschalten:

    .ODBCTimeout = 0 'kein Timeout

            '.Execute   'keine Fehlermeldung, nur "ODBC-Aufruf fehlgeschlagen!"

    Da muss stehen

    .Execute dbSQLPassThrough + dbSeeChanges

            .Close
        End With
        DoCmd.OpenQuery "qry_PTR", acViewNormal, acReadOnly

    Warum der OpenQuery?

    Rest passt.

    Ist es nicht etwas umständlich, erst eine Query zu erstellen, um diese
    dann auszuführen?

    Das ist unumgaenglich. Du kannst aber auch mit einer temporaeren Query
    arbeiten:

    Set qdf = CurrentDb.CreateQueryDef("")

    Bei Google hab ich noch etwas von einem ODBC-Direktbereich gefunden,
    aber das wird wohl nicht mehr unterstützt.

    Genau. Dafuer hat uns Microsoft sogar eine Fehlermeldung spendiert ;-)

    Gruss - Peter


    Mitglied im http://www.dbdev.org
    FAQ: http://www.donkarl.com

    Montag, 12. November 2012 14:01
    Moderator
  • Da muss stehen

    .Execute dbSQLPassThrough + dbSeeChanges

    Da kommt bei mir "Ungültiges Argument".
    Montag, 12. November 2012 14:24
  • Hallo,

    Thomas Warnke wrote:

    .Execute dbSQLPassThrough + dbSeeChanges

    Da kommt bei mir "Ungültiges Argument".

    ?

    Zeig mal die komplette Prozedur, sowie das SQL-Statement, mit der du sie
    aufrufst.

    Gruss - Peter


    Mitglied im http://www.dbdev.org
    FAQ: http://www.donkarl.com

    Montag, 12. November 2012 16:59
    Moderator
  • Hallo,

    hab jetzt nochmal einiges probiert.

    Der Fehler kommt bei Verwendung einer benamten Query, mit einer temporären Query funktioniert es. Das Erstellen und Füllen einer DB (20 Tabellen, gesamt ca. 100.000 Datensätze) ist mit einer temporären Query auch fast doppelt so schnell (mehrmals gemessen).

    Allerdings frag ich mich, was "dbSQLPassThrough" bewirkt, da ja in .Connect bereits die ODBC-Verbindung angegeben ist.

    Großer Nachteil ist aber, dass .Execute keine Fehlermeldung bringt, nur "ODBC-Aufruf fehlgeschlagen!". Darum hatte ich statt .Execute eine benamte Query gespeichert und ausgeführt (DoCmd.OpenQuery "qry_PTR"). Oder kriegt man die Fehlermeldung vom Server irgendwie durchgereicht?

    Gruß

    Dienstag, 13. November 2012 10:54
  • Hallo,

    Thomas Warnke wrote:

    Allerdings frag ich mich, was "dbSQLPassThrough" bewirkt, da ja in
    .Connect bereits die ODBC-Verbindung angegeben ist.

    Es bewirkt, dass keine SQL-Syntax-Pruefung druchgefuehrt wird.

    Großer Nachteil ist aber, dass .Execute keine Fehlermeldung bringt, nur
    "ODBC-Aufruf fehlgeschlagen!".

    Access zeigt zwar nur das letzte Element der Errors-Collection aber sie
    enthaelt alle Fehlermeldungen. Du brauchst also nur die Errors-Collection zu durchlaufen und bekommst aussagefaehige Fehlermeldungen.

    For I = 0 To Errors.Count -1
        strMsg = strMsg & Errors(I)
        strMsg = strMsg & vbCrLf
    Next I
    MsgBox strMsg

    Gruss - Peter


    Mitglied im http://www.dbdev.org
    FAQ: http://www.donkarl.com

    Dienstag, 13. November 2012 11:39
    Moderator
  • Perfekt.

    Vielen Dank!

    Dienstag, 13. November 2012 11:52