albossum
Goto Top

SQLCMD - Ausgabe in Datei nur bei Ergebnis größer 0

Hallo,

ich bin neu hier und habe schon einiges sinnvolles hier gefunden. Danke!
Allerdings habe ich zu einem Problem nichts finden können, vielleicht hatte das schon jemand:

Ich habe eine Batch-Datei geschrieben, die eine SQL-Datenbankabfrage (SQL Server Express 2005) vornimmt und in eine Datei ausgibt. Das funktioniert auch soweit.

1. wie kann ich die Ausgabe von "(X Zeilen betroffen)" verhindern?

2. wie kann ich verhindern, dass die Ausgabedatei auch dann erzeugt wird, wenn die Abfrage Null Zeilen als Ergebnis liefert?

Hintergrund ist der, dass die Batchdatei per Taskplanung im 30s - Takt gestartet werden soll. Das wären dann ja 2880 Dateien, von denen vielleicht nur 5 einen brauchbaren Inhalt haben.

Hat da jemand vielleicht nen Tipp?

Vielen Dank und liebe Grüße!

albossum

Content-Key: 130473

Url: https://administrator.de/contentid/130473

Printed on: April 19, 2024 at 23:04 o'clock

Member: TsukiSan
TsukiSan Nov 29, 2009 at 05:25:43 (UTC)
Goto Top
Hallo albossum,

Auslesen einzlner Zeilen aus einem TXT File mittels Batch kannst du dir dein Batchfile anpassen und mittels "delim" oder "token" die Sachen rausfiltern, die du nicht benötigst.

Gruss
Tsuki
Mitglied: 60730
60730 Nov 29, 2009 at 08:49:32 (UTC)
Goto Top
Moin,

@tsuki:
Ein Schleifchen finde ich da aber arg übertrieben - genauso wie den Ansatz alle 30 sekunden ein SQL Statement loszujagen - in der Hoffnung ein neuer Datensatztreffer ist dabei.

@ albossum:

Du mußt nicht nur Ross sondern auch Reiter nenen - deine Batch - am liebsten in Blöcken.

Mittels:
find /v "Zeilen betroffen" "meine sql ausgabe.xyz" > "meine SQL Ausgabe.xyz"

Könntest du - wenn wir deinen Weg weitergehen - "Problem 1" umschiffen.

2) Tja - dazu müßte man die Abfrage kennen..

Gruß
Member: TsukiSan
TsukiSan Nov 29, 2009 at 08:56:17 (UTC)
Goto Top
Hallo Timo,

Du mußt nicht nur Ross sondern auch Reiter nennen - deine Batch - am liebsten in <code > - </ code> Blöcken.

das habe ich mir heute morgen auch gedacht, nur wollte ich nicht den ersten Advent zu arg angehen und von daher meine "profane" und allgemeine Antwort face-wink

Warten wir mal auf die Antwort vom TO

Einen schönen 1.Advent

Tsuki
Member: albossum
albossum Nov 29, 2009 at 12:05:49 (UTC)
Goto Top
Also erstmal vielen Dank für die schnellen Antworten!

@tsuki Deinen Link werde ich mir mal zu Gemüte führen...

@Timo
find /v "Zeilen betroffen" "meine sql ausgabe.xyz" > "meine SQL Ausgabe.xyz"  
klingt sehr interessant... Zum Verständnis: Es wird die durch die Abfrage erzeugte Datei durchsucht und alle Zeilen die NICHT den Suchstring enthalten werden in einer neuen Datei gespeichert? Dann bräuchte ich die erste Datei nur noch zu löschen, oder?

Ich dachte es gibt vielleicht was Allgemeines (Einen Schalter oder so) mit dem man das einstellen kann.

Mit dem Schalter "-h -1" kann ich ja auch die Ausgabe des headers unterbinden. Bei Problem 2 ist es ja auch nur entscheidend, ob ein Treffer erziehlt wird, oder nicht. Da kommt es ja auf die konkrete Abfrage eigentlich nicht an, oder?

Das 30s Intervall ist vielleicht etwas eng, aber viel größer sollte es auch nicht sein. Es geht darum in einer Software einen Flag zu setzen um dann automatisiert mit einer anderen Software Daten zu verarbeiten und einen Druck zu starten. Zwischen "Flag setzen" und dem Druck sollten nun eben keine Ewigkeiten vergehen...

Aber fürs Verständnis:

Der SQLCMD Aufruf aus der Batch (die Variablen werden oben in der Batch gesetzt), Die Batch und die Abfrage funktionieren auch zuverlässig.
SQLCMD -U %benutzername% -P %passwort% -S %server% -d %datenbank% -i %arbeits_sql% -o %datei% -W -s "|" -h -1  

und die Abfrage
SELECT 


	Referenz,
	Kundennummer,
	Name,
	Strasse,
	PLZ,
	Ort,
        Land,
	Email

FROM

	Addresses

WHERE

	Flag = -1

GO

Eine Idee wäre vor der SQL-Abfrage mit Dateiausgabe eine quasi "Prüfabfrage" zu starten, die prüft, ob es Ergebnisse gibt (natürlich ohne Ausgabe in eine Datei). Dann müßte man aber das Abfrageergebnis für eine IF-Anweisung zur Verfügung haben.

Oder man lässt das Prüfergebnis doch in eine Datei schreiben, die man dann auswertet, indem man filtert wie viel Zeilen die Abfrage liefert... (steht ja in der Datei drin)

Ist das sinnvoll und machbar?

Ich muss sagen, dass ich mich in die SQLCMD - Problematik erst kürzlich eingelesen habe und hier sicher kein Profi bin. Ebenso habe ich mit Batchdatein bisher nur in rudimentärer Weise gearbeitet. Mit Dateien auslesen unfdanalysieren habe ich mich bisher noch nicht beschäftigt. Komme eher aus dem WEB -Bereich mit PHP, HTML, JavaScript usw.

Bin daher für jeden Vorschlag offen!

Besten Dank und einen schönen 1. Advent.

Gruß

Albossum
Member: albossum
albossum Nov 29, 2009 at 12:36:57 (UTC)
Goto Top
Was mir grad einfällt...

auf die gleiche Weise, wie @Timo vorgeschlagen hat Problem 1 zu lösen könnte man doch auch Problem 2 angehen...

Man könnte prüfen ob die durch die SQL-Abfrage erzeugte Datei den String "0 Zeilen betroffen" enthält und wenn das so ist, dann wird die Datei gelöscht.

Ist sicher nicht die eleganteste Methode, aber sollte gehen, oder?

Und um zu verhindern, dass sich die 2. Software die Datei schon greift, bevor die Prüfung abgeschlossen ist könnte man die Datei ja erstmal in ein TEMP-Verzeichnis schreiben lassen und wenn mehr als 0 Zeilen gefunden wurden wird sie in das Arbeitsverzeichnis der 2. Software verschoben, sonst gelöscht.

Was haltet Ihr davon?

Besser würde mir aber natürlich gefallen, wenn die Datei gar nicht erst erzeugt werden würde, wenn es keine Ergebnisse gibt...

Gruß

albossum
Member: MadMax
MadMax Nov 30, 2009 at 01:05:36 (UTC)
Goto Top
Hallo albossum,

zu 1.: Ein "set nocount on" am Anfang Deines Skriptes verhindert die Ausgabe der Anzahl der betroffenen Zeilen.

zu 2.: Die Ausgabe ganz unterbinden dürfte nicht funktionieren (wenn doch, dann vielleicht über den SQLCMD-Befehl ":out"), aber das SQL-Skript kann Dir zurückgeben, ob Daten gefunden wurden und dementsprechend kannst Du die Datei dann löschen. Das würde dann so aussehen:

Batch:
SQLCMD -U %benutzername% -P %passwort% -S %server% -d %datenbank% -i %arbeits_sql% -o %datei% -W -s "|" -h -1 -b  
if errorlevel 1 del %datei%

Skript:
set nocount on

SELECT 


	Referenz,
	Kundennummer,
	Name,
	Strasse,
	PLZ,
	Ort,
        Land,
	Email

FROM

	Addresses

WHERE

	Flag = -1

if @@rowcount = 0 raiserror (0, 11, 0)

Der Parameter "-b" sorgt dafür, daß SQLCMD mit errorlevel 1 beendet wird, wenn ein Fehler > 10 auftritt. Mit der Zeile "if @@rowcount = 0 raiserror (0, 11, 0)" sorgen wir dafür, daß eben das passiert, wenn keine Daten zurückgegeben werden. Nach dem SQLCMD wird dann auf den errorlevel geprüft und ggf. eine leere Datei gelöscht.

Gruß, Mad Max
Member: albossum
albossum Nov 30, 2009 at 01:27:45 (UTC)
Goto Top
Hallo Mad Max,

Deine Lösung klingt sehr gut, probier ich gleich aus...

Danke!!! (an alle)

Gruß

albossum
Member: albossum
albossum Dec 01, 2009 at 14:48:18 (UTC)
Goto Top
Hallo,

Ich habe Mad MAx´ Lösung ausprobiert und noch etwas angepasst. Es wird eine Prüfabfrage durchgeführt. Nur wenn diese Ergebnisse liefert wird die eigentliche Abfrage ausgeführt, die eine Ausgabe in eine Datei erzeugt. Somit muss auch nix mehr gelöscht werden. face-wink

Batch:
REM Start der Prüf-Datenbankabfrage

SQLCMD -U %benutzername% -P %passwort% -S %server% -d %datenbank% -i %pruef_sql% -W -s "|" -h -1 -b  

REM Start der Arbeits-Datenbankabfrage

if NOT errorlevel 1 SQLCMD -U %benutzername% -P %passwort% -S %server% -d %datenbank% -i %arbeits_sql% -o %datei% -W -s "|" -h -1 -b  

pruef_sql
SELECT 
	Referenz
FROM
	Addresses
WHERE
	Flag = -1

if @@rowcount = 0 raiserror (13001, 11, 1)

arbeits_sql
set nocount on

SELECT 
	Referenz,
	Kundennummer,
	Name,
	Strasse,
	PLZ,
	Ort,
        Land,
	Email
FROM
	Addresses
WHERE
	Flag = -1

if @@rowcount = 0 raiserror (13001, 11, 1)

"if @@rowcount = 0 raiserror (0, 11, 0)" musste ich anpassen, da es eine Fehlermeldung gab, die meinte, die Message-ID sollte ab 13000 sein. (Keine Ahnung warum)

Also vielen Dank nochmal an alle Helfer!

Gruß

albossum
Member: blacky-hh
blacky-hh Apr 29, 2014 at 10:44:10 (UTC)
Goto Top
Hey, habe die gleiche Idee gehabt, mir eine Batch geschrieben welche die SQL Abfrage startet.
Nun ist meine Frage, ob man diese Batchdatei die ja den Benutzername und Passwort enthält noch irgendwie schützen kann.

Zwar liegt diese Datei auf einem Server wo keiner Zugriff, außer dem Admin, aber wo ein Wille ist, ist auch ein Weg.

Habt ihr eine Idee oder mach ich mir da zu viele Sorgen?