H
Hugo Kornelis
Hi,
Sorry for the long message. If you don't want all the details, then just
read the next paragraph and forget about the rest. That's just an
explanation of what I'm trying and why - I welcome any ideas for
improvement, but I really hope to find an answer to this question:
Q: In an Access database (Access 2005 - but answers that apply to all
version from Access 97 are preferred) with linked tables to SQL Server
plus some QueryDef.Execute against same backend, I need to catch only
specific errors. All "standard Access" errors should show the normal
error response as if there's no error handling. All errors induced by
invoking RAISERROR in a SQL Server stored procedure or trigger should
result in the opening of a form. And errors induced by SQL Server but
not through RAISERROR (e.g. constraint violations) should preferably
show the normal response, but I can work aroound it if they also result
in opening the form instead.
Background: I'm working on an Access DB to use as front-end for a SQL
Server DB. I'm using linked tables over ODBC / SQL Native client to
connect Access to SQL Server, and VBA code (QueryDef.SQL = "EXEC MyProc"
/ QueryDef.Execute) to execute stored procedures. And now, I have a
special error handling requirement that I can't figure out how to
implement.
Basically, there are three categories of errors that are relevant:
1) Errors intercepted by Access, e.g. alphabetic info in a numeric field
or entering a value that is not in the list for a listbox.
2) Errors detected by standard constraints in SQL Server, e.g. a NULL
value in a NOT NULL column or a violation of a FOREIGN KEY constraint.
3) Errors detected by custom code, either in the stored procedure or in
a trigger. These are raised by invoking RAISERROR in the SQL Server
code.
Without error handling, the first category shows a clear message,
describing exactly what's wrong. In Dutch, since I'm using a Dutch
version of Access. Great.
The second category shows a mixed-language message. First the Dutch
equivalent of "ODBC: the call has failed", and then (in English, since
SQL Server has no Dutch version) the standard text for the constraint
violation, embedded in lots of extraneous information. For instance:
"ODBC: de oproep is mislukt.
"[Microsoft][SQL Native Client][SQL Server]Cannot insert the value NULL
into column 'xxx', table 'yyy'; column does not allow nulls. INSERT
fails.(#515)[Microsoft][SQL Native Client][SQL Server]The statement has
been terminated.(#3621)"
This is not ideal, but it is acceptable. Since the number of constraints
is limited, I could also add VBA code to check all constraints and show
custom error messages before sending modifications to SQL Server.
But it's the third category that's causing me grief. If a trigger or
stored procedure catches an error, the modification is disallowed, a row
is entered into a logging table with timestamp, userid, and reason for
the error, and RAISERROR is used to display the error message and raise
an error condition. How Access shows this depends on the source of the
problem. If data modification in a linked table causes a trigger to
throw an error, the output I see consists of Dutch for "ODBC insert
operation has failed for linked table xxx.", followed by my custom error
message embedded in a load of other stuff:
"ODBC-invoegbewerking is mislukt voor gekoppelde tabel xxx.
"[Microsoft][SQL Native Client][SQL Server]My custom error
message.(#50000)[Microsoft][SQL Native Client][SQL Server]The
transaction ended in the trigger. The batch has been aborted.(#3609"
And if the error comes from executing a stored procedure through
QDF.Execute, I get nothing but an error number and the statement that
the ODBC execution failed:
"Fout 3146 tijdens uitvoering:
"ODBC: de oproep is mislukt."
What I would like is to catch either only the third, or the second and
third category of errors. Instead of Access' normal error message, I
want to open a form that shows the most recent row in the logging table.
For errors in the third category, that will always be the custom error
message generated by the trigger or stored procedure. For errors in the
second category - well, I have already indicated that I'm able to work
around them.
I have already tried a crude experiment, using the Form_Error event:
Private Sub Form_Error(DataErr As Integer, Response As Integer)
DoCmd.Beep
DoCmp.OpenFoorm ("Custom_error_form")
Response = acDataErrContinue
End Sub
This works for errors of the third category - but it also opens the
custom error form if I enter "two" in a numeric field, showing a
completely unrelated custom error that happens to be the last error.
What I would like to know is how I can distinguish errors. If the error
is in the third category (forced by RAISERROR from SQL Server), show the
custom error form. For the first category (standard Access error), show
standard error message. And for second category (errors from SQL Server
but not issued by RAISERROR), show standard Access error if possible,
but as I said, I can work around those.
Thanks in advance!!
Sorry for the long message. If you don't want all the details, then just
read the next paragraph and forget about the rest. That's just an
explanation of what I'm trying and why - I welcome any ideas for
improvement, but I really hope to find an answer to this question:
Q: In an Access database (Access 2005 - but answers that apply to all
version from Access 97 are preferred) with linked tables to SQL Server
plus some QueryDef.Execute against same backend, I need to catch only
specific errors. All "standard Access" errors should show the normal
error response as if there's no error handling. All errors induced by
invoking RAISERROR in a SQL Server stored procedure or trigger should
result in the opening of a form. And errors induced by SQL Server but
not through RAISERROR (e.g. constraint violations) should preferably
show the normal response, but I can work aroound it if they also result
in opening the form instead.
Background: I'm working on an Access DB to use as front-end for a SQL
Server DB. I'm using linked tables over ODBC / SQL Native client to
connect Access to SQL Server, and VBA code (QueryDef.SQL = "EXEC MyProc"
/ QueryDef.Execute) to execute stored procedures. And now, I have a
special error handling requirement that I can't figure out how to
implement.
Basically, there are three categories of errors that are relevant:
1) Errors intercepted by Access, e.g. alphabetic info in a numeric field
or entering a value that is not in the list for a listbox.
2) Errors detected by standard constraints in SQL Server, e.g. a NULL
value in a NOT NULL column or a violation of a FOREIGN KEY constraint.
3) Errors detected by custom code, either in the stored procedure or in
a trigger. These are raised by invoking RAISERROR in the SQL Server
code.
Without error handling, the first category shows a clear message,
describing exactly what's wrong. In Dutch, since I'm using a Dutch
version of Access. Great.
The second category shows a mixed-language message. First the Dutch
equivalent of "ODBC: the call has failed", and then (in English, since
SQL Server has no Dutch version) the standard text for the constraint
violation, embedded in lots of extraneous information. For instance:
"ODBC: de oproep is mislukt.
"[Microsoft][SQL Native Client][SQL Server]Cannot insert the value NULL
into column 'xxx', table 'yyy'; column does not allow nulls. INSERT
fails.(#515)[Microsoft][SQL Native Client][SQL Server]The statement has
been terminated.(#3621)"
This is not ideal, but it is acceptable. Since the number of constraints
is limited, I could also add VBA code to check all constraints and show
custom error messages before sending modifications to SQL Server.
But it's the third category that's causing me grief. If a trigger or
stored procedure catches an error, the modification is disallowed, a row
is entered into a logging table with timestamp, userid, and reason for
the error, and RAISERROR is used to display the error message and raise
an error condition. How Access shows this depends on the source of the
problem. If data modification in a linked table causes a trigger to
throw an error, the output I see consists of Dutch for "ODBC insert
operation has failed for linked table xxx.", followed by my custom error
message embedded in a load of other stuff:
"ODBC-invoegbewerking is mislukt voor gekoppelde tabel xxx.
"[Microsoft][SQL Native Client][SQL Server]My custom error
message.(#50000)[Microsoft][SQL Native Client][SQL Server]The
transaction ended in the trigger. The batch has been aborted.(#3609"
And if the error comes from executing a stored procedure through
QDF.Execute, I get nothing but an error number and the statement that
the ODBC execution failed:
"Fout 3146 tijdens uitvoering:
"ODBC: de oproep is mislukt."
What I would like is to catch either only the third, or the second and
third category of errors. Instead of Access' normal error message, I
want to open a form that shows the most recent row in the logging table.
For errors in the third category, that will always be the custom error
message generated by the trigger or stored procedure. For errors in the
second category - well, I have already indicated that I'm able to work
around them.
I have already tried a crude experiment, using the Form_Error event:
Private Sub Form_Error(DataErr As Integer, Response As Integer)
DoCmd.Beep
DoCmp.OpenFoorm ("Custom_error_form")
Response = acDataErrContinue
End Sub
This works for errors of the third category - but it also opens the
custom error form if I enter "two" in a numeric field, showing a
completely unrelated custom error that happens to be the last error.
What I would like to know is how I can distinguish errors. If the error
is in the third category (forced by RAISERROR from SQL Server), show the
custom error form. For the first category (standard Access error), show
standard error message. And for second category (errors from SQL Server
but not issued by RAISERROR), show standard Access error if possible,
but as I said, I can work around those.
Thanks in advance!!