Fehler abfangen

30/06/2008 - 09:24 von Stefan Simon | Report spam
Hallo,

ich habe ein Statement, das funktioniert beim ersten Aufruf. Beim 2. tritt
ein Fehler auf 'ungültiger Spaltenname 'MagVar''. Mir ist 1. nicht klar,
warum delete überhaupt ausgeführt wird, da die vorherige Bedingung nicht
zutrifft, und 2. wie der Fehler aus Try...Catch rauskommt. Was mache ich
falsch?

BEGIN TRY
IF EXISTS( SELECT sc.[name] FROM syscolumns sc
JOIN sysobjects so ON (sc.id=so.id)
WHERE so.[name]='B100_Log'AND sc.[name]='MagVar')
BEGIN
DELETE FROM dbo.B101_Values WHERE ID IN (SELECT MagVar FROM dbo.B100_Log)
ALTER TABLE B100_Log DROP COLUMN MagVar
END
END TRY
BEGIN CATCH
PRINT 'Fehler'
END CATCH

folgendes hingegen funktioniert:

BEGIN TRY
SELECT 1/0
END TRY
BEGIN CATCH
PRINT 'Fehler'
END CATCH

Warum?

tia
Stefan
 

Lesen sie die antworten

#1 Elmar Boye
30/06/2008 - 10:03 | Warnen spam
Hallo Stefan,

Stefan Simon schrieb:
ich habe ein Statement, das funktioniert beim ersten Aufruf.



Genauer hast Du einen Batch (Stapel) aus mehreren Statements.
Und ein Batch wird in der Gesamtheit übersetzt.

Beim 2. tritt
ein Fehler auf 'ungültiger Spaltenname 'MagVar''. Mir ist 1. nicht klar,
warum delete überhaupt ausgeführt wird, da die vorherige Bedingung nicht
zutrifft,



Das DELETE wird nicht ausgeführt, sondern es wird versucht,
es in einen Ausführungsplan umzusetzen. Die Übersetzung wird
immer für den gesamten Stapel vorgenommen und nicht je Anweisung.
Und schlàgt fehl, da die Spalte nicht mehr existiert,
zur Prüfung kommt es gar nicht erst.

und 2. wie der Fehler aus Try...Catch rauskommt.



Kompilierungsfehler können nicht durch Try...Catch abgefangen werden,
da der Code gar nicht erst zur Ausführung gelangt.
Und eine indirekte Folge der verzögerten Namensauflösung:
<URL:http://www.sommarskog.se/error-hand...ortion>


BEGIN TRY
IF EXISTS( SELECT sc.[name] FROM syscolumns sc
JOIN sysobjects so ON (sc.id=so.id)
WHERE so.[name]='B100_Log'AND sc.[name]='MagVar')
BEGIN



Packe die Befehle in ein

EXEC ( N'

DELETE FROM dbo.B101_Values WHERE ID IN (SELECT MagVar FROM dbo.B100_Log)
ALTER TABLE B100_Log DROP COLUMN MagVar


')

Damit hast Du einen eigenen Sitzungskontext, der nur ausgeführt wird,
wenn die Spalte noch vorhanden ist.

Da Du in einer .NET NG fragst, gàbe es die Alternative, den Batch aufzusplitten.
Das heißt erst die EXISTS Abfrage als ExecuteScalar ausführen.
Und das DELETE/ALTER TABLE als ExecuteNonQuery, nur wenn die Spalte existiert
Das TRY CATCH kann entfallen und im Client durch eine Ausnahmebehandlung
ersetzt werden.

Gruß Elmar

Ähnliche fragen