none
Anbindung SQL-Server an ACCDB

    Frage

  • Hallo,

    wir haben ein ADP-Projekt, dass auf SQL-Server 2000/2005 zugreift. Da ADPs unter Acc2007/2010 nur noch eingeschränkt unterstützt werden, wollen wir die Anwendung auf ACCDB umstellen (wie von Microsoft für den Zugriff auf SQL-Server  empfohlen). Wie ist hier die beste Vorgehensweise für die Anbindung von Formularen?

    Eine Abfrage über die eingebundenen Tabellen funktioniert zwar, ist aber bei komplexen Kriterien langsam. Eine Pass-Through Abfrage ist schnell, aber nicht aktualisierbar.

    Bin für jeden Tip dankbar!

    Gruß Thomas

    Donnerstag, 30. September 2010 07:56

Antworten

  • hallo Thomas,

    Wenn ich die View im adp öffne, kann ich löschen.
    Mache ich etwas falsch, oder geht das generell nicht?

    Es geht nicht. Das kannst du ganz leicht prüfen, in dem du einen Datensatz im SSMS zu löschen versuchst.

    Das es im ADP geht ist eher ein Feature vom ADP.

    Hier ist mußt du eigentlich einen Trigger verwenden (ganz am Ende):

    USE [test] ;
    GO
    
    SET ANSI_NULLS ON ;
    GO
    
    SET QUOTED_IDENTIFIER ON ;
    GO
    
    IF EXISTS ( SELECT  *
                FROM    sys.triggers
                WHERE   object_id = OBJECT_ID(N'[dbo].[tr_AB_Del]') )
        DROP TRIGGER [dbo].[tr_AB_Del] ;
    GO
    
    IF EXISTS ( SELECT  *
                FROM    sys.views
                WHERE   object_id = OBJECT_ID(N'[dbo].[AB]') )
        DROP VIEW [dbo].[AB] ;
    GO
    
    IF EXISTS ( SELECT  *
                FROM    sys.objects
                WHERE   object_id = OBJECT_ID(N'[dbo].[A]')
                        AND type IN ( N'U' ) )
        DROP TABLE [dbo].[A] ;
    GO
    
    IF EXISTS ( SELECT  *
                FROM    sys.objects
                WHERE   object_id = OBJECT_ID(N'[dbo].[B]')
                        AND type IN ( N'U' ) )
        DROP TABLE [dbo].[B] ;
    GO
    
    CREATE TABLE [dbo].[A]
        (
          [aID] [int] NOT NULL,
          [aText] [varchar](255) NULL,
          [aTS] [timestamp] NOT NULL,
          [abID] [int] NULL,
          PRIMARY KEY CLUSTERED ( [aID] ASC )
            WITH ( PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
                   IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
                   ALLOW_PAGE_LOCKS = ON ) ON [PRIMARY]
        )
    ON  [PRIMARY] ;
    GO
    
    CREATE TABLE [dbo].[B]
        (
          [bID] [int] NOT NULL,
          [bText] [varchar](255) NULL,
          [bTS] [timestamp] NOT NULL,
          PRIMARY KEY CLUSTERED ( [bID] ASC )
            WITH ( PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
                   IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
                   ALLOW_PAGE_LOCKS = ON ) ON [PRIMARY]
        )
    ON  [PRIMARY] ;
    GO
    
    CREATE VIEW [dbo].[AB]
    AS  SELECT  A.*,
                B.*
        FROM    A
                LEFT OUTER JOIN B ON A.abID = B.bID ;
    GO
    
    CREATE TRIGGER [dbo].[tr_AB_Del] ON [dbo].[AB]
        INSTEAD OF DELETE
    AS
        SET NOCOUNT ON ;
        DELETE  FROM dbo.A
        WHERE   aID IN ( SELECT aID
                         FROM   DELETED ) ;
    GO

    Microsoft MVP Office Access
    https://mvp.support.microsoft.com/profile/Stefan.Hoffmann
    • Als Antwort markiert Thomas Warnke Montag, 4. Oktober 2010 13:32
    Montag, 4. Oktober 2010 11:49
    Moderator

Alle Antworten

  • hallo Thomas,

    Eine Abfrage über die eingebundenen Tabellen funktioniert zwar, ist aber bei komplexen Kriterien langsam.

    Du bist auf dem richtigen Weg.

    Komplexe, langlaufende Abfragen bekommen eigene Sichten. Dadurch übernimmt der SQL Server die Filterung. Access/Jet repektive ODBC fragen den SQL Server dann in etwa "SELECT * FROM view WHERE complexCriteria;".


    Microsoft MVP Office Access
    https://mvp.support.microsoft.com/profile/Stefan.Hoffmann
    Donnerstag, 30. September 2010 08:54
    Moderator
  • Hallo,

    Thomas Warnke wrote:

    wir haben ein ADP-Projekt, dass auf SQL-Server 2000/2005 zugreift. Da
    ADPs unter Acc2007/2010 nur noch eingeschränkt unterstützt werden,
    wollen wir die Anwendung auf ACCDB umstellen (wie von Microsoft für den
    Zugriff auf SQL-Server  empfohlen).

    Das ist richtig, aber ADP funktioniert auch weiterhin. Es ist mit 2007/2010
    moeglich, neue ADPs anzulegen und wenn das BE ein SQL 2008 ist, kann man
    sogar wieder Serverobjekte bearbeiten.

    Wie ist hier die beste Vorgehensweise für die Anbindung von Formularen?

    Eine Abfrage über die eingebundenen Tabellen funktioniert zwar, ist aber
    bei komplexen Kriterien langsam. Eine Pass-Through Abfrage ist schnell,
    aber nicht aktualisierbar.

    Genau das. Wenn du eine aktualisierbare RecordSource brauchst, verwende
    eingebundene Tabellen, fuer komplexe Read-only-Abfragen PT. Du kannst aber
    auch wie gewohnt ueber ADO zugreifen.

    Situationen, in denen Konstrukte ueber eingebundene Tabellen zu langsam
    waeren, sind eher die Ausnahme und muessten individuell behandelt werden,
    z.B. ueber Korrekturen im Datenmodell oder eben, wie bisher ueber ADO.

    Gruss - Peter


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

    Donnerstag, 30. September 2010 09:04
    Moderator
  • Hallo Stefan
    Das ist soweit richtig. Für die, die's noch nie gemacht haben: Die Views (Sichten) werden in Access dann als Tabellen eingebunden und sehen dann aus wie Tabellen. Views sind per se allerdings nicht immer aktualisierbar, das hängt davon ab, wie die Tabellen verknüpft sind. Wenn diese allerdings in einem ADP aktualsierbar waren, sollten diese auch als eingebundene "Tabellen" in Acces aktualisierbar sein.
    Ein wichtiger Hinweis für das Einbinden der Tabellen in Access ist, dass alle Tabellen mit einer TimeStamp Spalte versehen werden sollten. Das macht die Updates wesentlich schneller und entlastet das Netzwerk.
    Gruss
    Henry
    "Stefan Hoffmann" <=?utf-8?B?U3RlZmFuIEhvZmZtYW5u?=> wrote in message news:970588b5-2efd-4e7b-9ec1-c7f9083c5ab2...

    hallo Thomas,

    Eine Abfrage über die eingebundenen Tabellen funktioniert zwar, ist aber bei komplexen Kriterien langsam.

    Du bist auf dem richtigen Weg.

    Komplexe, langlaufende Abfragen bekommen eigene Sichten. Dadurch übernimmt der SQL Server die Filterung. Access/Jet repektive ODBC fragen den SQL Server dann in etwa "SELECT * FROM view WHERE complexCriteria;".


    Microsoft MVP Office Access
    https://mvp.support.microsoft.com/profile/Stefan.Hoffmann

    [MVP Office Access]
    Donnerstag, 30. September 2010 09:08
  • Danke für die Antworten.

    Eine Abfrage auf eine eingebundene View habe ich auch schon probiert. Allerdings kann ich in der View keine Datensätze löschen (Bearbeiten und Anfügen funktioniert). Wenn ich die View im ADP öffne kann ich löschen.

     

    Gruß Thomas

    Donnerstag, 30. September 2010 09:32
  • Am 30.09.2010 schrieb Thomas Warnke:

    Eine Abfrage auf eine eingebundene View habe ich auch schon probiert. Allerdings kann ich in der View keine Datensätze löschen (Bearbeiten und Anfügen funktioniert). Wenn ich die View im ADP öffne kann ich löschen.

    In der FAQ von Bernd Jungbluth finden sich Tipps dazu:
    http://www.berndjungbluth.de/sqlfaq/faqb2.htm

    Servus
    Winfried


    Connect2WSUS: http://www.grurili.de/tools/Connect2WSUS.exe
    GPO's: http://www.gruppenrichtlinien.de
    Community Forums NNTP Bridge: http://communitybridge.codeplex.com/

    Donnerstag, 30. September 2010 09:54
  • In der FAQ von Bernd Jungbluth finden sich Tipps dazu:
    http://www.berndjungbluth.de/sqlfaq/faqb2.htm

    Hallo Winfried,

    ohne Primarykey kann ich nicht ändern. Mit Primarykey kann ich ändern und erfassen, aber nicht löschen.

     

    Gruß Thomas

    Donnerstag, 30. September 2010 11:13
  • Hallo!

    Thomas Warnke schrieb:

    wir haben ein ADP-Projekt, dass auf SQL-Server 2000/2005 zugreift. Da ADPs unter Acc2007/2010 nur noch eingeschränkt unterstützt werden, wollen wir die Anwendung auf ACCDB umstellen (wie von Microsoft für den Zugriff auf SQL-Server  empfohlen). Wie ist hier die beste Vorgehensweise für die Anbindung von Formularen?

    Ich nutze gerne ADODB-Recordsets als Datenquelle für das Formular.
    Dann entspricht das Formular (bezüglich Formular-Eigenschaften)
    ungefähr einem ADP-Formular (Unique-Table-Eigenschaft ist verfügbar).
    Eindeutiger Nachteil gegenüber verknüpften Tabellen (den man auch als
    Vorteil betrachten kann ;-)): Die Datenquelle muss per Code
    eingestellt werden.
    Vorteil: man kann auch gespeicherte Prozeduren als Datenquelle
    einsetzen und muss dabei nicht den Umweg über PT-Abfragen gehen.

    Bei der Bindung ist allerdings zu beachten, dass ein Client-seitiger
    Cursor zum Einsatz kommen muss, sonst streikt Access bei der Zuweisung
    des Recordset.
    Das RS kann übrigens auch verbindungslos genutzt werden.

    mfg
    Josef

    Donnerstag, 30. September 2010 11:35
  • hallo Thomas,

    ohne Primarykey kann ich nicht ändern. Mit Primarykey kann ich ändern und erfassen, aber nicht löschen.

    Das ist einer der schönen Sachen: Access/Jet/ACE müssen nur an einen Primärschlüssel glauben. D.h. du muß für eingebundene Sichten lediglich einen mittels

     

     CurrentDb.Execute _
      "CREATE INDEX pk_AName " & _
      "ON linkedView (primaryKeyFieldList) " & _
      "WITH PRIMARY;"
    
    
    anlegen.
    Microsoft MVP Office Access
    https://mvp.support.microsoft.com/profile/Stefan.Hoffmann
    Donnerstag, 30. September 2010 11:53
    Moderator
  • Hallo Stefan,

    das habe ich gemacht. Aber ich kann mit DS markieren und ENTF nicht löschen.

    Gruß

    Donnerstag, 30. September 2010 13:16
  • hallo Thomas,

    Die Primärschlüsselfelder haben exakte Datentypen?

    Hast du den Hinweis mit der ROW_VERSION()-Spalte schon umgesetzt?


    Microsoft MVP Office Access
    https://mvp.support.microsoft.com/profile/Stefan.Hoffmann
    Donnerstag, 30. September 2010 13:44
    Moderator
  • Hallo Stefan,

    ich hab jetzt alles probiert, aber beim Löschen kömmt immer der Fehler "Die Sicht oder Funktion ist nicht aktualisierbar, da die Änderung sich auf mehrere Basistabellen auswirkt".

    Meine Testobjekte:

    Tabelle A
    ----------
    aID INT, PK
    aText VARCHAR
    aTS TIMESTAMP
    abID INT

    Tabelle B
    ----------
    bID INT, PK
    bText VARCHAR
    bTS TIMESTAMP

    View
    ------
    SELECT     A.*, B.*
    FROM         A LEFT OUTER JOIN B ON A.abID = B.bID

    Beim Einbinden wähle ich im PopUp-Formular "Eindeutigen Datensatzbezeichner auswählen" aID aus. Hab es auch per Code gemacht aber das sollte das Gleiche sein (oder?).

    In aText kann ich Daten ändern und eingeben. Beim Löschen eines DS kommt der obige Fehler.

    Wenn ich die View im adp öffne, kann ich löschen.

    Mache ich etwas falsch, oder geht das generell nicht?

     

    Danke & Gruß

    Thomas

    Montag, 4. Oktober 2010 10:29
  • hallo Thomas,

    Wenn ich die View im adp öffne, kann ich löschen.
    Mache ich etwas falsch, oder geht das generell nicht?

    Es geht nicht. Das kannst du ganz leicht prüfen, in dem du einen Datensatz im SSMS zu löschen versuchst.

    Das es im ADP geht ist eher ein Feature vom ADP.

    Hier ist mußt du eigentlich einen Trigger verwenden (ganz am Ende):

    USE [test] ;
    GO
    
    SET ANSI_NULLS ON ;
    GO
    
    SET QUOTED_IDENTIFIER ON ;
    GO
    
    IF EXISTS ( SELECT  *
                FROM    sys.triggers
                WHERE   object_id = OBJECT_ID(N'[dbo].[tr_AB_Del]') )
        DROP TRIGGER [dbo].[tr_AB_Del] ;
    GO
    
    IF EXISTS ( SELECT  *
                FROM    sys.views
                WHERE   object_id = OBJECT_ID(N'[dbo].[AB]') )
        DROP VIEW [dbo].[AB] ;
    GO
    
    IF EXISTS ( SELECT  *
                FROM    sys.objects
                WHERE   object_id = OBJECT_ID(N'[dbo].[A]')
                        AND type IN ( N'U' ) )
        DROP TABLE [dbo].[A] ;
    GO
    
    IF EXISTS ( SELECT  *
                FROM    sys.objects
                WHERE   object_id = OBJECT_ID(N'[dbo].[B]')
                        AND type IN ( N'U' ) )
        DROP TABLE [dbo].[B] ;
    GO
    
    CREATE TABLE [dbo].[A]
        (
          [aID] [int] NOT NULL,
          [aText] [varchar](255) NULL,
          [aTS] [timestamp] NOT NULL,
          [abID] [int] NULL,
          PRIMARY KEY CLUSTERED ( [aID] ASC )
            WITH ( PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
                   IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
                   ALLOW_PAGE_LOCKS = ON ) ON [PRIMARY]
        )
    ON  [PRIMARY] ;
    GO
    
    CREATE TABLE [dbo].[B]
        (
          [bID] [int] NOT NULL,
          [bText] [varchar](255) NULL,
          [bTS] [timestamp] NOT NULL,
          PRIMARY KEY CLUSTERED ( [bID] ASC )
            WITH ( PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
                   IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
                   ALLOW_PAGE_LOCKS = ON ) ON [PRIMARY]
        )
    ON  [PRIMARY] ;
    GO
    
    CREATE VIEW [dbo].[AB]
    AS  SELECT  A.*,
                B.*
        FROM    A
                LEFT OUTER JOIN B ON A.abID = B.bID ;
    GO
    
    CREATE TRIGGER [dbo].[tr_AB_Del] ON [dbo].[AB]
        INSTEAD OF DELETE
    AS
        SET NOCOUNT ON ;
        DELETE  FROM dbo.A
        WHERE   aID IN ( SELECT aID
                         FROM   DELETED ) ;
    GO

    Microsoft MVP Office Access
    https://mvp.support.microsoft.com/profile/Stefan.Hoffmann
    • Als Antwort markiert Thomas Warnke Montag, 4. Oktober 2010 13:32
    Montag, 4. Oktober 2010 11:49
    Moderator
  • Hallo Stefan,

    es funktioniert *schwer begeistert*.

    Ich werde für jedes Formular eine VIEW erstellen, welche dann ohne JOINs gefiltert werden kann.

    Der Ansatz von Josef, ADODB-Recordsets als Datenquelle für das Formular zu verwenden, gefällt mir auch. Da immer alle Daten geladen werden, funktioniert es aber nur bei kleinen Datenmengen hinreichend schnell.

     

    Gruß

    Thomas

    Montag, 4. Oktober 2010 13:37