Perl ADO denkt, dass in Stored Procedure gedruckten Ausgabe ist ein Fehler!
-
03-07-2019 - |
Frage
Zu allererst (falls das ist wichtig) Ich verwende Active Perl (v5.8.7 gebaut für mswin32-x86-Multi-Thread).
Ich habe gerade von einem dreistündigen Debug-Sitzung heraus, versuchen, die Quelle eines Fehlers zu finden. Ich fand es gab einfach keine Fehler, aber aus irgendeinem Grunde ADO Connection-Objekt wurde immer die Errors.Count
mit jeder gedruckten Nachricht erhöhten in meiner gespeicherten Prozedur ausgegeben.
Betrachten Sie folgende Transact SQL-Code:
CREATE PROCEDURE dbo.My_Sample() AS
BEGIN TRAN my_tran
-- Does something useful
if @@error <> 0 BEGIN
ROLLBACK TRAN my_tran
RAISERROR( 'SP My_Sample failed', 16, 1)
END ELSE BEGIN
COMMIT TRAN my_tran
PRINT 'SP My_Sample succeeded'
END
Nun stellen Sie einen Perl-Unter mehr oder weniger wie:
sub execute_SQL {
# $conn is an already opened ADO connection object
# pointing to my SQL Server
# $sql is the T-SQL statement to be executed
my($conn, $sql) = @_;
$conn->Execute($sql);
my $error_collection = $conn->Errors();
my $ecount = $error_collection->Count;
if ($ecount == 0 ) { return 0; }
print "\n" . $ecount . " errors found\n";
print "Executed SQL Code:\n$sql\n\n";
print "Errors while executing:\n";
foreach my $error (in $error_collection){
print "Error: [" . $error->{Number} . "] " . $error->{Description} . "\n";
}
return 1;
}
Irgendwo anders, im Haupt Perl-Code, ich rufe die obigen Unter wie:
execute_SQL( $conn, 'EXEC dbo.My_Sample' );
Am Ende habe ich es, dass alle PRINT-Anweisung wird ein neuer Pseudofehler auf die ADO-Errors-Auflistung angehängt werden. Die schnelle Lösung ich implementiert war, dass PRINT in der SP in ein SELECT, zu ändern, um dies zu umgehen.
Die Fragen Ich mag würde stellen sind:
- Ist dieses Verhalten normal?
- Gibt es eine Möglichkeit / Bypass zu vermeiden, ist es?
Lösung
Dies ist zu erwarten, wie es ist, was ADO tut und die Win32 :: ADO ist eine ziemlich dünne Schicht darüber.
ref: Wissensbasis beachten Sie, dass die RAISERROR und PRINT-Anweisungen durch die ADO-Sammlung Error zurückgegeben werden
Andere Tipps
OK, nachdem ein Los der Prüfung und Lesen, ich kam es zu finden, erklärte in den Bols' Artikel "Mit PRINT" (Hervorhebung von mir):
Die PRINT-Anweisung wird verwendet, um Nachrichten zu Anwendungen zurückzukehren. PRINT nimmt entweder ein Zeichen oder Unicode-String-Ausdruck als Parameter und gibt die Zeichenfolge als eine Nachricht an die Anwendung. Die Nachricht wird als Informationsfehler auf Anwendungen mit dem SQLClient Namespace oder der ActiveX Data Objects (ADO), OLE DB und Open Database Connectivity (ODBC) Application Programming Interfaces (APIs) zurückgegeben. SQLSTATE wird auf 01000, die native Fehler auf 0 gesetzt wird, und die Fehlermeldung Zeichenfolge wird an die angegebene Zeichenkette in der PRINT-Anweisung gesetzt. Die Zeichenfolge wird an den Message-Handler Callback-Funktion in DB zurück -Bibliothek Anwendungen.
Mit diesem Wissen ich diesen VB6 angepasst von diesem DevX Artikel bis ich folgt aus:
sub execute_SQL {
# $conn is an already opened ADO connection object
# pointing to my SQL Server
# $sql is the T-SQL statement to be executed
# Returns 0 if no error found, 1 otherwise
my($conn, $sql) = @_;
$conn->Execute($sql);
my $error_collection = $conn->Errors();
my $ecount = $error_collection->Count;
if ($ecount == 0 ) { return 0; }
my ($is_message, $real_error_found);
foreach my $error (in $error_collection){
$is_message = ($error->{SQLState} eq "01000" && $error->{NativeError}==0);
$real_error_found=1 unless $is_message;
if( $is_message) {
print "Message # " . $error->{Number}
. "\n Text: " . $error->{Description} ."\n";
} else {
print "Error # " . $error->{Number}
. "\n Description: " . $error->{Description}
. "\nSource: " . $error->{Source} . "\n";
}
}
print $message_to_print;
return $real_error_found;
}
So, jetzt meine Perl Unter wirkliche Fehler richtig aussortiert (emittiert von SQL Server über eine RaisError) und eine gemeinsame Nachricht über „PRINT“ ausgegeben wird.
Dank Richard Harrison für seine Antwort, die mich führt auf Erfolg den Weg.