Announcement

Collapse
No announcement yet.

Fehlerauffangroutine bei Fremdschlüsselverletzung

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

  • Fehlerauffangroutine bei Fremdschlüsselverletzung

    Hallo zusammen,
    bin Einsteiger und nutze MS SQL Server Management Studio 2008.
    Hänge gerade an einem Problem, dass für euch sicherlich leicht zu lösen ist.

    Ich versuche einen Fehler abzufangen, der durch eine Foreign-Key-Verletzung auftritt:

    Code:
    begin try
    	begin transaction
    	update tabelle 
    	set Spalte1=5
    	where (Spalte2)=2
    
    end try
    
    begin catch
    	print 'Fehler'
    	rollback
    end catch
    Soweit funktioniert das auch.

    Nun soll der Fehler nicht aufgefangen werden, wenn die Aktualisierung durch das Skript ausgeführt wird,
    sondern wenn der Nutzer manuell die Daten in der Tabelle ändert.

    Was passiert nach einer manuellen Eingabe? Intern wird doch wahrscheinlich auch die Aktualisierung wie oben ausgeführt, oder?
    Wo muss ich nun die Fehlerauffangroutine hinschreiben, dass diese aufgerufen wird?

    Hoffe ich konnte mich einigermaßen verständlich ausdrücken.

    Danke für die Antworten.

    Grüße rooney

  • #2
    Erstens - warum probierst du das nicht einfach aus und änderst ein Feld mit Fremdschlüssel auf einen ungültigen Wert?

    Zweitens - wenn der Fremdschlüsel richtig definiert wurde, lässt die Datenbank keinen Fehler zu (daher die Meldung über die Verletzung) und es ist deswegen (zumindest in deinem Beispiel, wo vorher keine anderen Aktionen stattfinden) auch kein Rollback nötig.

    Drittens - warum willst du überhaupt eine eigene Meldung ausgeben, die Datenbank tut das von selber?

    bye,
    Helmut

    Comment


    • #3
      Hallo Helmut,
      danke für die Antwort.

      1. Ausprobiert habe ich das natürlich schon mit einem ungültigen Wert. Das Ergebnis war die zu erwartende Fehlermeldung (Fremdschlüsselverletzung). Diese möchte ich abfangen und eine eigene Fehlermeldung ausgeben.

      3. Der Grund hierfür ist, dass SQL Server bei mir als Backend dient. Die User arbeiten mit MS Access als Frontend. Eine vom Server erzeugte Fehlermeldung wird ja zum Access weitergereicht. Die User allerdings können wahrscheinlich kaum etwas mit einer solchen Meldung anfangen. Daher woltte ich so etwas ausgeben wie "Pflegen Sie vorher die Stammdaten" o.ä.

      2. Da hast du recht, ein Rollback ist in diesem Zusammenhang nicht nötig.

      Beste Grüße
      rooney

      Comment


      • #4
        Ich löse sowas anders: wenn der Benutzer auf den Speichern-Button drückt, dann prüfe ich bei Bedarf vorher mit mehr oder weniger Datenbankabfragen, ob die Bedingungen erfüllt sind und wenn nicht, gibt es eine entsprechende Fehlermeldung und das Speichern wird nicht ausgeführt. Ich sehe den Vorteil darin, dass ich keine Server-Rückmeldungen abfangen und auswerten muss und dass ich auch Prüfungen anderer Art machen kann, die der Datenbankserver nicht macht.
        Sollte man dabei etwas übersehen, dann gibt es eine kryptische Fehlermeldung, mit der der Anwender zum Programmierer gehen soll, damit man das ergänzt oder was immer...

        bye,
        Helmut

        Comment


        • #5
          Originally posted by hwoess View Post
          Ich löse sowas anders: wenn der Benutzer auf den Speichern-Button drückt, dann prüfe ich bei Bedarf vorher mit mehr oder weniger Datenbankabfragen, ob die Bedingungen erfüllt sind ....
          Ja, und so programmiert man die halbe Bussiness - Logik eigentlich zweimal: einmal im DB - Design und einmal im Frontend.
          Das ist keine Kritik - ich mach das notgedrungen auch manchmal so.

          Im Gespann MSSQL/Access löse ich die Referenzintegrität über Trigger, die bei Verletzungen dann eine zielführende Fehlermeldung bis ins Frontend liefern können.

          [highlight=SQL]
          ALTER TRIGGER [dbo].[T_IU_XYWerte] ON [dbo].[XYWerte]
          FOR INSERT, UPDATE
          AS
          SET NOCOUNT ON

          IF (SELECT COUNT(*) FROM inserted ) !=
          (SELECT COUNT(*) FROM XY, inserted WHERE XY.XY_ID = inserted.XY_ID)
          BEGIN
          RAISERROR 50002 'Einfügen XY - Werte: Bitte geben Sie einen gültigen XY an !'
          ROLLBACK TRAN
          RETURN
          END

          [/highlight]

          Diesen Fehler zeigt Access dann auch genau so an.

          Allerdings bedeutet die Triggerlösung einen Haufen Schreibarbeit.

          Eine andere Möglichkeit wäre es, im Access das "BeiFehler" (OnError) - Event des Formulars zu nutzen. Dort kommt der Fehler immer zuerst an. Allerdings gibt es dort nur eine Nummer und man kann die Fehlerursache nur erraten.

          Ansonsten versuche ich das Formular so zu bauen, dass abhängige Felder halt auch wirklich über Comboboxen usw. auswählbar sind und nicht "direkt" durch den Nutzer bearbeitet werden.

          Alles in allem ein interessantes Problem, für dass zumindest ich noch keine Patentlösung gefunden habe.
          Ich habs gleich!
          ... sagte der Programmierer.

          Comment


          • #6
            Danke für eure Antworten.
            @tinof: So in etwa wollte ich das machen. Allerdings stellt sich bei mir noch das Problem, dass es sich ja um die Fremdschlüsselverletzung handelt. Der Server verhindert ja sofort das Update (Insert), so dass der Trigger erst gar nicht aktiviert wird.
            Ich müsste also den Fehler an einer anderen Stelle abfangen.

            nochmal zu meinem Bsp:

            Code:
            begin try
            	begin transaction
            	update tabelle 
            	set Spalte1=5
            	where (Spalte2)=2
            
            end try
            
            begin catch
            	print 'Fehler'
            	rollback
            end catch
            so würde das funktionieren. falls das Update einen Fehler verursacht, bekomme ich die Meldung "Fehler".
            Nun ist mir aber immer nicht klar, wie ich den try catch Block bei manueller Eingabe nuzen kann, also derart:

            Code:
            begin try
            Nutzer verursacht Fehler
            end try begin catch print 'Fehler' rollback end catch

            beste grüße

            Comment

            Working...
            X