web-dev-qa-db-de.com

sp_send_dbmail, das vom Job ausgeführt wird, schlägt fehl, und das Abfrageergebnis wird als Datei angehängt

Ich habe mich mit dem folgenden Problem konfrontiert: Wenn Sie versuchen, eine E-Mail mit Ergebnissen der Abfrage als Datei zu senden, verwenden Sie sp_send_dbmail über die Ausführung einer normalen Abfrage.

Wenn Sie jedoch denselben Code in JobStep einfügen und den Job ausführen, schlägt der Job fehl. 

Fehler in der Jobgeschichte sagt 

Fehler beim Formatieren der Abfrage, wahrscheinlich ungültige Parameter [SQLSTATE 42000] (Fehler 22050). Der Schritt ist fehlgeschlagen.

Wenn ich jedoch einen Parameter auskommentiere, der sich auf das Anhängen von Dateien bezieht, funktioniert er wieder korrekt.

exec msdb.dbo.sp_send_dbmail 
    @profile_name = 'profile_name', 
    @recipients  = '[email protected]',
    @body = 'body',
    @subject = 'subj',
    --Parameters that refers to attached file
    @attach_query_result_as_file = 1, 
    @query_result_header = 0,
    @query_result_no_padding = 1,
    @query = 'select 1',
    @query_attachment_filename = 'test.csv'

Irgendwelche Vorschläge?

16
Paul Kyrejto

Ich bin zur Lösung dieses Problems gekommen. Ich weiß nicht, warum es funktionieren sollte, aber trotzdem. :) Es geht definitiv um Sicherheit.

Ich habe untersucht, dass der SQL-Agent im Namen des Domänenbenutzers ausgeführt wird, beispielsweise DOMAIN\User . Es verfügt über vollständige Administratorrechte auf dem Server (Serverrolle 'sysadmin' usw.). SQL Server selbst wird unter demselben Benutzer ausgeführt.

Der Schritt des Jobs, der den Aufruf von sp_send_dbmail enthält, wird unter demselben DOMAIN\User ausgeführt.

Außerdem habe ich festgestellt, dass beim Ausführen des Abfrageteils von sp_send_dbmail versucht wird, exec xp_logininfo 'DOMAIN\User' auszuführen, um mit Active Directory zu prüfen, ob dieser Benutzer in Ordnung ist. Und Überraschung: Etwas ist definitiv nicht in Ordnung. Diese Überprüfung endet mit:

Msg 15404, Level 16, State 19, Server SQLC002INS02\SQLC002INS02, Line 1
Could not obtain information about Windows NT group/user 'DOMAIN\User.', error code 0x2.

Das kann mit einiger Wahrscheinlichkeit bedeuten, dass irgendetwas über das Passwort dieses Benutzers abgelaufen ist oder der Benutzer gesperrt ist oder andere unangenehme Dinge für diesen Kerl.

Ich entschied, dass es zu riskant ist, den Benutzer für den Agenten zu ändern. Ich komme also zum Versenden von E-Mails im Auftrag von 'sa', das die gleiche 'sysadmin'-Serverrolle hat, jedoch die SQL-Autorisierung und diesen AD-Überprüfungsschritt weglässt. 

Es sieht aus wie ein Benutzer, der vorgibt, Admin zu sein, den echten Admin zu bitten, gefährlichen Code für ihn auszuführen :)

Der endgültige Code dieses Jobs ist also der erste und einzige Schritt, der diesem ähnelt:

execute as login = 'sa'
exec msdb.dbo.sp_send_dbmail 
    @profile_name = 'profile_name', 
    @recipients  = '[email protected]',
    @body = 'body',
    @subject = 'subj',
    --Parameters that refers to attached file
    @attach_query_result_as_file = 1, 
    @query_result_header = 0,
    @query_result_no_padding = 1,
    @query = 'select 1',
    @query_attachment_filename = 'test.csv'
revert
24
Paul Kyrejto

Ich hatte dieses Problem. Ich verwende SQL Server 2008 R2. Ich habe die E-Mail mit weiteren Informationen zum Fehler durch Hinzufügen der Option erhalten:

@append_query_error = 1,

Ich habe die E-Mail mit dieser Fehlermeldung über Berechtigungen anstelle meiner Abfrage erhalten:

   Msg 916, Level 14, State 1, Server SERVER\INST01, 
Procedure GetSalesReport, Line 62
The server principal "CONTROLLEDNETWO\sql.service" is not able 
to access the database "MYDB01" under the current security co
ntext.

Meine Abfrage hat versucht, auf einige Tabellen zuzugreifen, auf die der SQL Agent keine Berechtigungen hatte (in meinem Fall hat er nicht einmal Zugriff darauf).

Ich habe es durch SQLSMS behoben, indem ich der Datenbank "MYDB01" einen neuen Benutzer "CONTROLLEDNETWO\sql.service" hinzugefügt und Berechtigungen für "select" erteilt habe.

7
Rafa
EXEC msdb.dbo.sp_send_dbmail
    @profile_name = 'Main Profile',
    @recipients = '[email protected]',
    @subject = 'Test',
    @body = 'this is a test',
    @execute_query_database = 'myTargetDatabase_mscrm',
    @query = N'SELECT * from myTargetDatabase_mscrm.dbo.SystemUserBase',
    @attach_query_result_as_file = 1,
    @query_attachment_filename = 'Test.txt'

Zu Referenzzwecken schlug dies wiederholt fehl und wurde als Domänenadministrator aufgerufen. Es wurde jedoch als local\sqladmin ausgeführt. Nachdem ich Variablen deaktiviert und versucht hatte, Berechtigungen zu vergeben, sah ich im Skript des Jobs, dass er immer noch die Master-Datenbank verwendete. Ich fand die Einstellung, die mir ins Gesicht starrte. Es ist in der Konfiguration für den Schritt. Ich habe es in Msdb geändert und es hat funktioniert. Beachten Sie, dass ich die Auswahl aus myTable geändert habe, um sie aus myDatabase.dbo.myTable basierend auf einigen Beiträgen auszuwählen. Dies kann zur Lösung des Problems beigetragen haben oder auch nicht. Ich habe auch @execute_query_database verwendet, um sicherzustellen, dass die Abfrage an der richtigen Stelle ausgeführt wird. Auch das war vielleicht nicht nötig gewesen.

Egal, was es endlich glücklich machte, es hatte nichts damit zu tun, ob es anhaftete oder nicht.

1
Eric Hula

Das war alles hilfreich, danke. Wollte mit anderen teilen, was ich mit dem Excel-Anhang (xls) tun wollte, der die Ergebnisse in Spalten legte. Dies funktionierte für mich durch Hinzufügen von query_result_no_padding = 1 und query_result_separator = ','. (das ist ein Tab, Tab in den Häkchen)

@query_result_header= 1,
@attach_query_result_as_file = 1,
@query_result_no_padding = 1,
@query_attachment_filename = 'TestPriceFlingerReport.xls',
@query_result_separator= '  ,   ',
@profile_name = 'Test Exchange Server'
0
Dan Pullman

Ich hatte auch dieses Problem und löste es in zwei Teilen, wobei ich viele Ratschläge verwendete. 

1) Klicken Sie mit der rechten Maustaste auf "View History" (Verlauf anzeigen) des Jobs und zeigen Sie die Fehlerdetails an. In der Fehlerbenachrichtigung wurde der Name des Benutzers angegeben, unter dem der Job ausgeführt wurde. Daher habe ich diesem Benutzer schreibgeschützten Zugriff auf meine Datenbank gewährt.

2) Ich hatte vergessen, DBName.dbo . MyTableName anzugeben, und verwendete nur MyTableName. 

Die E-Mails gingen übrigens alle in meinen Junk-E-Mail-Ordner.

0
Resource

Ich glaube, dass dieses Problem auf eine in SQL 2008 implementierte Änderung zurückzuführen ist, die später nur für sp_send_dbmail .. gesperrt wurde. Dies geschieht nur, wenn Sie ein qry an send_dbmail übergeben und die Ergebnisse über die E-Mail zurückgeben. Das Problem ist, dass die Fehlermeldung irreführend und nicht geeignet ist. Eine gute Lösung ist das Erstellen eines SQL-Benutzers mit nur den minimal erforderlichen Berechtigungen zum Ausführen dieser Abfrage. Zum Beispiel db_reader oder db_writer und db_owner, falls dies unbedingt erforderlich ist. Und diesen Benutzer zum Besitzer machen. Sie können auch einen SQL-Berechtigungsnachweis erstellen und diesen SQL-Job so konfigurieren, dass er unter diesem SQL-Berechtigungsnachweis ausgeführt wird.

0
user2238156

Wenn Sie Ihre Abfrage manuell ausführen, werden Ihre Anmeldeinformationen verwendet. Wenn der SQL-Agent dieselbe Abfrage ausführt, werden die Anmeldeinformationen des SQL-Agent-Dienstkontos verwendet. Standardmäßig verwendet der SQL Server-Agent die Anmeldeinformationen des LocalSystem-Kontos. Eine Möglichkeit, das Problem zu beheben, besteht darin, den Benutzer zu ändern, unter dem der SQL Server-Agentendienst mit einem Benutzer ausgeführt wird, der Zugriff auf Ihr CSV-Verzeichnis\hat.

0
David Brabant

in meiner Situation konnte es nicht identifizieren, dass die Tabelle mit der Datenbank gehört. Sobald die database.dbo.table der Abfrage hinzugefügt wurde, funktionierte sie.

0
SQLguest