SQL Abfrageergebnis als Tabelle in E-Mail ausgeben

Bristol

Benutzer
Beiträge
7
Hi. Ich bin recht neu in SQL Abfragen schrieben. Komme soweit gut voran und die Udemy Workshops helfen ganz gut.
Allerdings komme ich an eine Grenze.
Mein Ergebnis in MS Server Management Studio möchte ich gerne für eine Workflow-Abfrage in unserem Warenwirtschaftssystem nutzen.
Es geht dabei um Lagerplätze, die extra für defekte Artikel angelegt sind. Das Controlling soll 1x wöchentlich eine Mail bekommen, wo diese aufgelistet sind und die Artikel anzeigen, die dort gelagert werden.

In MS SMS habe ich die Abfrage fertig und ich sehe mein Ergebnis. Dieses möchte ich jedoch nicht mit Save as und Excel einlesen, bearbeiten und dann dem Controlling schicken. Was muss ich um meine Abfrage bauen, damit diese:

1. Als optisch lesbare Tabelle ausgegeben wird und
2. diese auch als E-Mail gesendet wird
2.a es würde auch reichen, wenn eine Datei gespeichert wird.
 
Werbung:
Du kannst das Resultat einer Abfrage generell als neue Tabelle speichern:

Code:
create table neue_tabelle as select * from alte_tabelle;

Du kannst aber das auch als VIEW definieren, würde Platz sparen.
 
In MS SMS habe ich die Abfrage fertig und ich sehe mein Ergebnis. Dieses möchte ich jedoch nicht mit Save as und Excel einlesen, bearbeiten und dann dem Controlling schicken. Was muss ich um meine Abfrage bauen, damit diese:

1. Als optisch lesbare Tabelle ausgegeben wird und
2. diese auch als E-Mail gesendet wird
2.a es würde auch reichen, wenn eine Datei gespeichert wird.
Das ist ziemlich einfach. Ist aber eher ne Aufgabe für den DBA.
1. Database Mail muß aktiviert sein,
2. Du mußt einen Job einrichten, der aus deiner Abfrage eine Mail generiert. Der Code, den ich hier angehängt habe (eine Stored Procedure) verschickt eine HTML Mail mit den Daten aus der entsprechenden Abfrage.
SQL:
USE [msdb]

GO

ALTER procedure [dbo].[xxx_sp_check_commandlog] @rcpto nvarchar(200), @debug int = 0
AS
BEGIN
       ------------------------------------------------------------------------
       -- --- author: Marcus Deubel                                      --- --
       -- --- copyright: (c) 2019 Marcus Deubel                          --- --         
       -- --- license: BSD License                                       --- --
       -- --- description: stored procedure to check commandlog table    --- --
       -- ---            : and send emails on error messages             --- --
       ------------------------------------------------------------------------
       -- SET NOCOUNT ON added to prevent extra result sets from
       -- interfering with SELECT statements.
       set nocount on;
       declare @xml nvarchar(max) = N'';
       declare @table nvarchar(max);
       declare @header nvarchar(max);
       declare @errNo int;
       declare @database nvarchar(10);
       declare @sqlstmt nvarchar(512);
       declare @lsubject nvarchar(200);
       declare @servername nvarchar(200);
       declare @reboottime datetime;
       set @servername = @@SERVERNAME;
       set @reboottime = CONVERT(nvarchar(24), GETDATE(), 120);
       ----------------------------
       -- original T-SQL Abfrage --
       ----------------------------
       --select      ID, '',
        -- DatabaseName, '',
        -- isnull(SchemaName, 'n/a'),
        -- isnull(ObjectName, 'n/a'),
        -- isnull(ObjectType, 'n/a'),
        -- isnull(IndexName, 'n/a'),
        -- isnull(convert(nvarchar,IndexType), 'n/a'),
        -- isnull(StatisticsName, 'n/a'),
        -- isnull(convert(nvarchar,PartitionNumber), 'n/a'),
        -- isnull(ExtendedInfo, 'n/a'),
        -- isnull(Command, 'n/a'),
        -- isnull(CommandType, 'n/a'),
        -- isnull(convert(nvarchar,StartTime), 'n/a'),
        -- isnull(convert(nvarchar,EndTime), 'n/a'),
        -- isnull(convert(nvarchar,ErrorNumber), 'n/a'),
        -- isnull(ErrorMessage, 'no Error')
       --FROM [msdb].[dbo].[CommandLog] where CommandType = 'DBCC_CHECKDB' and convert(date,StartTime) = convert(date, getdate());
       set @errNo = (select errorNumber from msdb.dbo.CommandLog where CommandType = 'DBCC_CHECKDB' and convert(date,StartTime) = convert(date, getdate()) and ErrorNumber > 0);
       set @header = N'<html>' +
                     N'<style>' +
                     N'table, th, td { border: 1px solid black; }' +
                     N'</style>' +
                     N'</head>' +
                     N'<body>' +
                     N'<H3>CommandLog</H3>' +
                     N'<table border="1">' +
                     N'<tr>' +
                     N'<th>DB ID</th><th>Database Name</th>' +
                     -- N'<th>SchemaName</th><th>ObjectName</th><th>ObjectType</th><th>IndexName</th><th>IndexType</th><th>StatisticsName</th><th>PartitionNumber</th><th>ExtendedInfo</th>' +
                     N'<th>Command</th><th>CommandType</th><th>StartTime</th><th>EndTime</th><th>ErrorNumber</th><th>ErrorMessage</th>' +
                     N'</tr>';

       set @xml = cast ((select  td = ID, '',
                                 td = DatabaseName, '',
                                 --td = isnull(SchemaName, 'n/a'), '',
                                 --td = isnull(ObjectName, 'n/a'), '',
                                 --td = isnull(ObjectType, 'n/a'), '',
                                 --td = isnull(IndexName, 'n/a'), '',
                                 --td = isnull(convert(nvarchar,IndexType), 'n/a'), '',
                                 --td = isnull(StatisticsName, 'n/a'), '',
                                 --td = isnull(convert(nvarchar,PartitionNumber), 'n/a'), '',
                                  --td = isnull(ExtendedInfo, 'n/a'), '',
                                 td = isnull(Command, 'n/a'), '',
                                 td = isnull(CommandType, 'n/a'), '',
                                 td = isnull(convert(nvarchar,StartTime), 'n/a'), '',
                                 td = isnull(convert(nvarchar,EndTime), 'n/a'), '',
                                 td = isnull(convert(nvarchar,ErrorNumber), 'n/a'), '',
                                 td = isnull(ErrorMessage, 'no Error Message'), ''
                        FROM [msdb].[dbo].[CommandLog] where CommandType = 'DBCC_CHECKDB' and convert(date,StartTime) = convert(date, getdate())
                        FOR XML PATH('tr'), TYPE) AS NVARCHAR(MAX));

      set @table = @header + @xml + N'</table></body></html>'
       if @debug = 1
          begin
            set @errNo = 1;
          end;

       if @errNo > 0
          begin
            set @lsubject = @servername + N': CommandLog - DBCC CHECKDB ERROR - Please check' + N' - ' + CONVERT(nvarchar(24), GETDATE(), 120);
          end
       else
         begin
            set @lsubject = @servername + N': CommandLog - DBCC CHECKDB OK' + N' - ' + CONVERT(nvarchar(24), GETDATE(), 120);
         end

       if len(@xml) > 0 or @debug = 1
          begin
            exec msdb.dbo.sp_send_dbmail @profile_name = 'Default Public Profile',
                                         @recipients = @rcpto,
                                         @subject = @lsubject,
                                         @body = @table,
                                         @body_format = 'HTML' ;

         end                                 
END
 
Ja, VIEW geht dann so:

Code:
postgres=# \h create view
Command:     CREATE VIEW
Description: define a new view
Syntax:
CREATE [ OR REPLACE ] [ TEMP | TEMPORARY ] [ RECURSIVE ] VIEW name [ ( column_name [, ...] ) ]
    [ WITH ( view_option_name [= view_option_value] [, ... ] ) ]
    AS query
    [ WITH [ CASCADED | LOCAL ] CHECK OPTION ]

URL: https://www.postgresql.org/docs/15/sql-createview.html

sollte in M$SQL ähnlich sein, vermute ich ...
 
Das ist ziemlich einfach. Ist aber eher ne Aufgabe für den DBA.
1. Database Mail muß aktiviert sein,
2. Du mußt einen Job einrichten, der aus deiner Abfrage eine Mail generiert. Der Code, den ich hier angehängt habe (eine Stored Procedure) verschickt eine HTML Mail mit den Daten aus der entsprechenden Abfrage.
Okay. Bis ich das "ziemlich einfach" unterschreiben kann, brauch ich wohl noch einige Stunden in SQL :)

Es würde mir auch reichen, wenn ich sowas auch als Datei hätte.

So schaut meine kleine SQL aus:

SELECT [cName] AS Lagerplatz
,[cKommentar] AS Fehlerbeschreibung
,[nGesperrt] AS Sperrplatz
FROM [eazybusiness].[dbo].[tWarenLagerPlatz]
WHERE nGesperrt = 1 and cName LIKE 'Werk__'
ORDER BY cName

Auch da muss ich noch nachbessern und aus einer anderen Tabelle eine Verknüpfung herstellen, damit auch zu einem Lagerplatz der Artikel angezeigt wird, der dort liegt. Auch da muss ich mich aber einlesen und noch Videos studieren. Aber wie sagt man so schön: Man wächst mit den Aufgaben :)
 
Wer betreut denn bei euch den SQL Server? Kann derjenige das umsetzen?
Wir haben eine Warenwirtschaft auf einem Cloud Server laufen.
Die Anbindung ist über Clients/Remotes und die Angestellten können zugreifen.

Die Warenwirtschaft gibt nur nicht alle Auswertungen und Darstellungen her, die ich benötige.
Mit dem MS SQL Server Management Studio greife ich auf die DB zu.
 
Wer betreut die Warenwirtschaft bzw. die Datenbank? Wer hat diese Installiert?
Wenn das ganze richtig (siehe #3) gemacht werden soll muss das mangels Rechte eh der DBA umsetzen.

Das Management Studio ist für manuelle Bearbeitung gemacht und nicht für Regelmäßige Jobs.
 
Das habe ich alles eingerichtet. Bzw wurde die Installation damals von ecomData gemacht. Ansonsten pflege ich das soweit alles. Die Ansprüche steigen nur und deswegen reicht das Statistik-Tool nicht mehr aus. Ich werde da sonst übergehen und das Skript einmal die Woche durchlaufen lassen.

Was auch möglich ist, sind Workflows innerhalt der Warenwirtschaft, die durch Trigger ausgelöst werden. Dort habe ich schon einiges über {% capture query -%} mit SQLs verknüpft. Da ist die Sprache allerdings Dot Liquid. Damit kenne ich mich über die Jahre schon besser aus :)
 
Super. Danke. Ich muss mich damit einmal auseinandersetzen. Im WWW habe ich schon den VIEW Befehl gesehen.
Für dein Problem brauchst Du gar keinen View.
Für deine anderen Aufgaben ums wirklich richtig zu machen gibts zu Hauf Tutorials. Und falls Du nicht klar kommst, kannst mich auch per PN anschreiben.
Wer betreut die Warenwirtschaft bzw. die Datenbank? Wer hat diese Installiert?
Wenn das ganze richtig (siehe #3) gemacht werden soll muss das mangels Rechte eh der DBA umsetzen.

Das Management Studio ist für manuelle Bearbeitung gemacht und nicht für Regelmäßige Jobs.
Eben. Is ne DBA Aufgabe. Für regelmäßige Jobs gibt den SQL Server Agent.
 
Für dein Problem brauchst Du gar keinen View.
Für deine anderen Aufgaben ums wirklich richtig zu machen gibts zu Hauf Tutorials. Und falls Du nicht klar kommst, kannst mich auch per PN anschreiben.

Eben. Is ne DBA Aufgabe. Für regelmäßige Jobs gibt den SQL Server Agent.
Sehr gerne. Ich werde das aber erstmal selber in Angriff nehmen. Auf dein Angebot komme ich zurück, wenn ich hier sabbernd unter dem Tisch liege und ich den Laptop angezündet habe :cool:
 
Werbung:
Ich greife das hier nochmal auf. Es geht dabei eher um ein Verständnisproblem in meinem Kopf, glaube ich jedenfalls.

Dieses Skript ist korrekt und im Einklang mit unserer Lagerwirtschaft:

SELECT
tWarenlagerPlatz.cName AS 'Lagerplatz'
,tWarenLagerPlatz.cKommentar AS 'Fehlerbeschreibung'
FROM tWarenLagerPlatz
WHERE tWarenLagerPlatz.cName LIKE 'Werk__'
Skript klein okay.png

Das ist das 1. Bild. Mir werden alle Werk Plätze angezeigt und auch die passende Fehlerbeschreibung (Lagerplatz Kommentar).

Jetzt habe ich das Skript erweitert um mir auch den Artikelnamen und das Buchungsdatum anzeigen zu lassen.
Auch dort ist die Ausgabe da, jedoch nicht im Einklang mit der 1. Abfrage.
Mir geht es nicht um die leeren Kommentare. Die können gerne als leere Felder stehen bleiben. Ich möchte halt nur, dass mir der korrekte Artikel angezeigt wird, Ich gehe davon aus, dass das erweiterte Skript quasi alle Buchungen aufzeigt, die dort mal gewesen sind. Wir haben auf diesen Werkplätzen jeweils nur einen Artikel und auch diesen nur in Menge 1. Mir erschließt es sich nicht, dass mir zB Werk10 doppelt angezeigt wird.
Er zeigt dort auch zwei verschiedene Artikel an und keines davon ist korrekt. Ich vermute, dass ich mit den JOINs Probleme habe und diese falsch gesetzt sind.
Hier das erweiterte Skrip was zum Ergebnis Bild 2 führt.t:

SELECT
tWarenLagerPlatz.cName AS 'Lagerplatz',
tArtikelBeschreibung.cName AS 'Artikelname',
tWarenLagerPlatz.cKommentar AS 'Fehlerbeschreibung',
FORMAT(tArtikelHistory.dGebucht, 'dd.MM.yyyy') AS 'Buchungsdatum'

FROM tWarenLagerPlatz
JOIN tArtikelHistory ON tWarenLagerPlatz.kWarenLagerPlatz = tArtikelHistory.kWarenLagerPlatz
JOIN tArtikelBeschreibung ON tArtikelHistory.kArtikel = tArtikelBeschreibung.kArtikel

WHERE tWarenLagerPlatz.cName LIKE 'Werk__'
AND tArtikelBeschreibung.kSprache = 1
AND tWarenLagerPlatz.cKommentar != ''

ORDER BY tWarenLagerPlatz.cName
,tArtikelHistory.dGebucht DESC

Skript gross mit Differenzen.png
 
Zurück
Oben