none
SQL2008R2, ACC2010 – SQL-View einbinden und Daten bearbeiten RRS feed

  • Frage

  • Hallo,

    ich habe auf einem MS-SQL-Server eine größere Datenbank mit einigen Tabellen angelegt. Diese Einzeltabellen ergeben zusammen eine sehr große Auswertung diese ich über eine Sicht auf dem SQL-Server zusammengelegt habe. Damit die User die Daten ändern können, wird immer die komplette Sicht benötigt und hierfür habe ich eine Verknüpfung zu Access2010 gemacht.

    Nun habe ich aber das Problem, dass die User die komplette Sicht bekommen, aber keine Daten ändern können. Aus diesem Grund habe ich die Tabellenverknüpfungen in Access nochmals erstellt und über eine Access-Abfrage dargestellt. Über diesen Weg können nun Daten geändert werden, nur der Aufbau der Abfrage dauert extrem lang.

    Was muss ich machten, damit ich eine MS-SQL-Sicht in Access darstellen kann und die User die Daten ändern können?

    Ich muss dazu gesehen, dass ich auf der MS-SQL-Ebene ein sehr blutiger Anfänger bin.

    Danke

    Sonntag, 10. März 2013 10:29

Antworten

  • Es kann sein, daß die View per se nicht aktualisierbar ist. Und wenn
    sind wie schon von Stefan geschrieben nur die Daten von 1 beteiligten
    Tabelle änderbar.
     
    Wenn du die Sicht trotzdem änderbar gestalten möchtest, mußt du INSTEAD
    OF Trigger verwenden.
     
    Lutz
     
    • Als Antwort markiert sbrand Montag, 11. März 2013 17:16
    Montag, 11. März 2013 14:51

Alle Antworten

  • Hi,

    je nach Abfrage ist es nicht möglich, über diese die Daten der der Abfrage zugrundeliegenden Tabellen zu ändern.

    Poste doch mal die Abfragedefinition (also das SQL Statement der Abfrage), dann kann man evtl. mehr dazu sagen.


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community

    Montag, 11. März 2013 10:01
    Moderator
  • Hallo,

    gerne:

    SELECT     a.inventorynumber AS Seriennummer, a.contact AS PersNr, dbo.Personalstamm.Nachname, dbo.Personalstamm.Vorname, a.name AS Produktname,
                          a.comments AS Kommentar, dbo.Personalstamm.KST AS Kostenstelle, dbo.Kostenstellenplan.Bezeichnung AS KSTBezeichnung,
                          dbo.assettypes.name AS Gruppe
    FROM         dbo.assettypes INNER JOIN
                          dbo.assets AS a ON dbo.assettypes.guid = a.guid_assettype LEFT OUTER JOIN
                          dbo.Kostenstellenplan INNER JOIN
                          dbo.Personalstamm ON dbo.Kostenstellenplan.KSTNR = dbo.Personalstamm.KST ON a.contact = dbo.Personalstamm.PNR

    Gruss

    Montag, 11. März 2013 12:29
  • Hi,

    bei der Abfrage glaube ich nicht, dass eine Aktualisierung der dahinterliegenden Daten über die View möglich ist. Siehe dazu auch:

      http://msdn.microsoft.com/de-de/library/ms187956.aspx
      (Abschnitt: Aktualisierbare Sichten)

    und

      http://msdn.microsoft.com/de-de/library/ms180800.aspx

    Falls es dennoch vom Grundsatz her gehen sollte/müsste, dürfen pro Update Statement nur die Spalten einer einzigen Tabelle geändert werden. Das könnte beim Generieren des Update Statements durch Access schon das Problem sein. Evtl. werden dort alle Spalten, auch die nicht geänderten, im UPDATE Statement angegeben.


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community


    Montag, 11. März 2013 13:34
    Moderator
  • Es kann sein, daß die View per se nicht aktualisierbar ist. Und wenn
    sind wie schon von Stefan geschrieben nur die Daten von 1 beteiligten
    Tabelle änderbar.
     
    Wenn du die Sicht trotzdem änderbar gestalten möchtest, mußt du INSTEAD
    OF Trigger verwenden.
     
    Lutz
     
    • Als Antwort markiert sbrand Montag, 11. März 2013 17:16
    Montag, 11. März 2013 14:51
  • Hallo,

    zunächst Danke für diesen Tipp.

    Aber ich glaube, dieser Weg ist für mich noch zu hoch :).

    Ich werde vorerst noch auf der Access-Basis bleiben und in weiter Zukunft auf den Tipp mit dem Trigger zurückkreifen.

    Trotzem Danke

    Montag, 11. März 2013 17:18
  • Am 11.03.2013 18:18, schrieb sbrand:
    > Hallo,
    >
    > zunächst Danke für diesen Tipp.
    >
    > Aber ich glaube, dieser Weg ist für mich noch zu hoch :).
    >
    > Ich werde vorerst noch auf der Access-Basis bleiben und in weiter
    > Zukunft auf den Tipp mit dem Trigger zurückkreifen.
     So schwierig ist das gar nicht, du musst eben nur beachten, daß diese
    Trigger nicht nur einen Datensatz verarbeiten sondern evtl auch mehrere
    - je nachdem was eingefügt/bearbeitet wird.
     
    Wenn du brauchst schick ich dir mal ein Beispiel für Insert und Update
    auf eine Abfrage mit 2 Tabellen zu.
     
    Dienstag, 12. März 2013 07:38
  • Hallo,

    wenn es keine Umstände macht.

    Ich bin aber "blutiger Anfänger" :).

    Danke

    Dienstag, 12. März 2013 09:55
  • Umstände macht es keine - dauert nur einen Moment ;)
    Und ich kenne es selber - für Anfänger sind Beispiele immer sehr hilfreich!
     
    Hier ist eins:
     
    Beim Insert nutze ich für beide Tabellen als PK den Wert aus
    a_stamm_anl.ID, ein Update der beiden Werte lasse ich über die Abfrage
    nicht zu.
    Der zusammengesetzte Wert kann zwar theoretisch beschrieben werden -
    eine Änderung wird aber ignoriert, da diese aus "inserted" nicht an die
    Original-Tabellen weitergereicht wird.
    Über "deleted" kommst du auch an die alten Werte und könntest
    theoretisch Bedingungen überprüfen und Werte wieder zurücksetzen.
     
    Die Lösung wie sie jetzt ist unterstützt auch das Einfügen und Ändern
    mehrerer Datensätze auf einen Rutsch wie von den Triggern eigentlich
    vorgesehen, d.h. inserted enthält X Datensätze.
    Zum Beispiel aus einem INSERT INTO dbo.a_stamm_anl (..) SELECT ... FROM ...
     
    -------------------------------------------------
     
    Abfrage über zwei Tabellen einer 1:1 Beziehung
     
    CREATE VIEW dbo.a_stamm_anl
    AS
    SELECT
     dbo.DB_ANLAGEN.ID, dbo.DB_ANLAGEN.ANL_NR, dbo.DB_ANLAGEN.BEZ,
    dbo.DB_ANLAGEN.TYP, dbo.DB_STAMM_ANL.ANL_ID,
     dbo.DB_STAMM_ANL.B2, dbo.DB_STAMM_ANL.B4, dbo.DB_STAMM_ANL.B5,
    dbo.DB_STAMM_ANL.B6, dbo.DB_STAMM_ANL.B8,
     dbo.DB_STAMM_ANL.B9, (dbo.DB_ANLAGEN.ANL_NR + N' - ' +
    dbo.DB_ANLAGEN.BEZ) AS ANL_GESAMT
    FROM dbo.DB_ANLAGEN INNER JOIN dbo.DB_STAMM_ANL ON dbo.DB_ANLAGEN.ID =
    dbo.DB_STAMM_ANL.ANL_ID
     Insert-Trigger
     
    CREATE TRIGGER dbo.TR_IOI_dbo_a_stamm_anl ON dbo.a_stamm_anl INSTEAD OF
    INSERT
    AS
    BEGIN
        IF (@@ROWCOUNT=0) RETURN;
        -- SET NOCOUNT ON added to prevent extra result sets from interfering
    with SELECT statements.
        SET NOCOUNT ON;
         BEGIN TRY
            INSERT INTO dbo.DB_ANLAGEN
                        ([ID]
                        ,[ANL_NR]
                        ,[BEZ]
                        ,[TYP])
                 SELECT [ID]
                        ,[ANL_NR]
                        ,[BEZ]
                        ,ISNULL(inserted.TYP], 0) AS [TYP]
                  FROM inserted
             INSERT INTO dbo.DB_STAMM_ANL
                        ([ANL_ID]
                        ,[B2]
                        ,[B4]
                        ,[B5]
                        ,[B6]
                        ,[B8]
                        ,[B9])
                 SELECT inserted.ID AS [ANL_ID]
                        ,[B2]
                        ,[B4]
                        ,[B5]
                        ,[B6]
                        ,[B8]
                        ,[B9]
                   FROM inserted
        END TRY
        BEGIN CATCH
            -- Use RAISERROR inside the CATCH block to return error
            -- information about the original error that caused
            -- execution to jump to the CATCH block.
            DECLARE @ErrorMessage NVARCHAR(4000);
            DECLARE @ErrorSeverity INT;
            DECLARE @ErrorState INT;
            SELECT
                @ErrorMessage = CAST(ERROR_NUMBER() AS NVARCHAR(10)) + N':
    ' + ERROR_MESSAGE() + N' (Proc: ' + ERROR_PROCEDURE() + N', Line: ' +
    CAST(ERROR_LINE() AS NVARCHAR(10)) + N')',
                @ErrorSeverity = ERROR_SEVERITY(),
                @ErrorState = ERROR_STATE();
            RAISERROR (@ErrorMessage, -- Message text.
                       @ErrorSeverity, -- Severity.
                       @ErrorState -- State.
                       );
            IF (@@TRANCOUNT > 0) ROLLBACK TRAN;
        END CATCH
    END
     Update-Trigger
     
    CREATE TRIGGER dbo.TR_IOU_dbo_a_stamm_anl ON dbo.a_stamm_anl INSTEAD OF
    UPDATE
    AS
    BEGIN
        IF (@@ROWCOUNT=0) RETURN;
        -- SET NOCOUNT ON added to prevent extra result sets from interfering
    with SELECT statements.
        SET NOCOUNT ON;
         IF (UPDATE(ID))
        BEGIN
            RAISERROR (N'ID kann nicht geändert werden', -- Message text.
                       16, -- Severity.
                       1 -- State.
                       );
            IF (@@TRANCOUNT > 0) ROLLBACK TRAN;
            RETURN;
        END
        IF (UPDATE(ANL_ID))
        BEGIN
            RAISERROR (N'ANL_ID kann nicht geändert werden', -- Message text.
                       16, -- Severity.
                       2 -- State.
                       );
            IF (@@TRANCOUNT > 0) ROLLBACK TRAN;
            RETURN;
        END
         BEGIN TRY
        -- Update dbo.DB_ANLAGEN ohne ID
            UPDATE dbo.DB_ANLAGEN
               SET [ANL_NR] = i.ANL_NR
                  ,[BEZ] = i.BEZ
                  ,[TYP] = i.TYP
          FROM inserted i INNER JOIN dbo.DB_ANLAGEN a ON i.ID = a.ID
         -- Update dbo.DB_STAMM_ANL ohne ANL_ID
            UPDATE dbo.DB_STAMM_ANL
               SET [B2] = i.B2
                  ,[B4] = i.B4
                  ,[B5] = i.B5
                  ,[B6] = i.B6
                  ,[B8] = i.B8
                  ,[B9] = i.B9
               FROM inserted i INNER JOIN dbo.DB_STAMM_ANL s ON i.ANL_ID =
    s.ANL_ID
        
        END TRY
        BEGIN CATCH
            -- Use RAISERROR inside the CATCH block to return error
            -- information about the original error that caused
            -- execution to jump to the CATCH block.
            DECLARE @ErrorMessage NVARCHAR(4000);
            DECLARE @ErrorSeverity INT;
            DECLARE @ErrorState INT;
            SELECT
                @ErrorMessage = CAST(ERROR_NUMBER() AS NVARCHAR(10)) + N':
    ' + ERROR_MESSAGE() + N' (Proc: ' + ERROR_PROCEDURE() + N', Line: ' +
    CAST(ERROR_LINE() AS NVARCHAR(10)) + N')',
                @ErrorSeverity = ERROR_SEVERITY(),
                @ErrorState = ERROR_STATE();
            RAISERROR (@ErrorMessage, -- Message text.
                       @ErrorSeverity, -- Severity.
                       @ErrorState -- State.
                       );
            IF (@@TRANCOUNT > 0) ROLLBACK TRAN;
        END CATCH
    END
     
    Mittwoch, 13. März 2013 09:04