# SQL Express2012 Datenbank aus txt Datei updaten



## werner_sg (22. Oktober 2012)

Hallo ich habe mir einen SQL Server Express 2012 von MS aufgesetzt, der jetzt die Daten meiner Kasse verarbeitet.

Nun möchte ich den Warenstand gleichzeitig mit einem Mobilen Scanner aktuell halten (Einkauf oder anderes) dazu generiert mir der Scanner eine txt Datei  mit dieser würde ich gerne die Datenbank aktualisieren.

Dazu müssen die Daten auf oder abrechnend dazu gespielt werden.

Kann mir da einer helfen.

Danke Werner


----------



## rrobbyy (23. Oktober 2012)

Ich hatte eine ähnliche Anforderung und bis jetzt keine direkte Lösung gefunden, da es in MSSQL keine BULK UPDATES gibt. Ein Datenänderung per externer Datenquelle ist also m. E. nach nicht möglich.

Du könntest aber die txt in eine separate Tabelle importieren und von dort aus die Daten weiterverarbeiten, evtl. mit einer Stored Procedure. Das Vorzeichen der Warenbewegung gibt ja vor, wie sich der Stand ändert.

Andere Möglichkeiten sehe ich derzeit nicht, bzw. kenn ich nicht.


----------



## werner_sg (23. Oktober 2012)

Hallo, 
erst mal Danke für Deine Antwort.
Das MSSQL anders als MYSQL läuft durfte ich leider auch schon erfahren, traurigerweise läuft die (dumme) Kasse nur auf Access oder MSSQL ;-(.
Die Text Datei in eine neue Tabelle zu schreiben wäre kein Problem mit Unterstützung, kenne MSSQL erst seit ca. 48 Stunden und muss mich da erst mal reindenken.
Und wie die Weiterverarbeitung der Daten durch MSSQL dann aussehen muss habe ich auch noch keinen Plan, da mir auch noch die Ansätze fehlen um danach Google zu befragen.
Die txt gibt mir derzeit < Uhrzeit / Datum / EAN / Wareneingang / Warenausgang > an.
Die Zahlen sind alle ohne Vorzeichen, das ist aber leicht zu ändern.
MfG Werner


----------



## rrobbyy (23. Oktober 2012)

Wie sieht denn die Struktur der DB-Tabelle aus, in der die relaventen Daten liegen?

Ist die EAN in der txt immer gesetzt? Du bräuchtest nämlich eine eindeutige Zuordnung zur bestehenden Tabelle in der DB, und die EAN sieht für mich danach aus.

Die Daten bekommst du über ein Bulk Insert in das Programm, wobei die Tabellenstruktur mit der txt einfacherhalber übereinstimmen sollte. 

Nach dem die Daten in die Temp-Tabelle importiert wurden, kannst du mit einem Update-Befehl (inkl. inner join auf die 2. Tabelle) die Waren-Tabelle aktualisieren
Danach wird die Temp-Tabelle geleert, sodass ein neuer Import stattfinden kann.


Ich schlage vor, dass du erstmal eine temporäre anhand der txt aufbaust. Danach solltest du dich mit BULK Insert beschäftigen (was ziemlich blöd werden kann) und erst danach kommt das Update der Waren-Tabelle.

Hier ein Bsp. mit Bulk Insert in die Tabelle DIVFIBUKONTEN mit der Datei SKR04Passt.csv


```
BULK
INSERT DIVFIBUKONTEN
FROM 'c:\temp\Sachkontenstamm SKR04Passt.csv'
WITH
(
FIELDTERMINATOR = ',',
ROWTERMINATOR = '\n',
CODEPAGE = 'ACP'
)
GO
```

Fieldterminator ist das Trennzeichen (falls ein Tab als Trennzeichen vorhanden ist, ist die Option \t)
Rowterminator sollte so ok sein.
Codepage gibt es 2 weitere Optionen. (ich glaube RAW und die andere weiß ich nicht)


----------



## werner_sg (30. Oktober 2012)

Hallo rrobbyy,

habe mich endlich etwas eingearbeitet, aber noch nicht alles verstanden.

Mit folgendem Code sollte nun ein Update der Tabelle Artikelstamm in der Datenbank SMOKYKASSE erfolgen


```
BULK INSERT SMOKYKASSE.Artikelstamm
FROM 'e:\scanner.csv
GO
```

Den nächsten Teil habe ich noch nicht ganz verstanden Field und Raw sind klar aber Codepage sagt mir noch nicht viel, ich nehme aber an für die Umlaute.


```
WITH
(
FIELDTERMINATOR = ',',
ROWTERMINATOR = '\n',
CODEPAGE = 'ACP'
)
```

Da ich so wie ich das sehe im ersten Code ja noch keinerlei Zuordnung habe und wahrscheinlich die vorhandenen Daten überschreiben würde, denke ich mal wie Du sagtest alles erst einmal in eine extra Tabelle rein.


```
BULK INSERT SMOKYKASSE.Artikelupdate
FROM 'e:\scanner.csv
WITH
(
FIELDTERMINATOR = ',',
ROWTERMINATOR = '\n',
CODEPAGE = 'ACP'
)
GO
```

Hab's aber noch nicht ausprobiert ;-) wollt erst mal hören was Du dazu sagst.

Hoffe aber das ich das soweit schon mal richtig verstanden habe
mfG Werner


----------



## rrobbyy (30. Oktober 2012)

Hallo Werner,

Codepage gibt die Codepage für die in der Datendatei enthaltenen Daten an. CODEPAGE ist nur dann von Bedeutung, wenn die Datenspalten vom Typ char, varchar oder text Zeichenwerte enthalten, die größer als 127 oder kleiner als 32 sind.
hier der link
http://msdn.microsoft.com/de-de/library/ms188365.aspx

Wenn du nicht soo viele (> 1000000 Daten importierst) empfehle ich dir ACP



Eines habe ich bis jetzt unterschlagen:

Wenn du nicht irgendwelche großartigen Konvertierungen machen möchtest, muss die Tabelle in der du importierst genauso aufgebaut sein, wie deine Importdatei. Das bedeutet folgendes:

In der Datei steht im 
Feld 1 Nummer
Feld 2 Bezeichnung
Feld 3 Menge
Feld 4 Preis

Dann muss auch die SQLTabelle genauso aufgebaut sein, sprich, die erste Spalte ist Nummer, zweite Bezeichnung usw.

In SQL gibt es keine offene Schnittstelle, wo du irgendwas definieren kannst. Der Aufbau der Datenbanktabelle gibt die Schnittstelle vor.

Bei der Option FIELDOPERATOR solltest du mit bedacht vorgehen, da es ja sein kann, dass ein Text ein Komma beinhaltet. Wenn du es 100% auschließen kannst, dass ein Komma in einem Text vorkommt, ist alles OK. Wenn nicht, solltest du ein anderes Zeichen in der Datei für die Spaltentrennung verwenden.


neben all diesen Dingern gibt es aber auch eine andere Möglichkeit, ohne BULK INSERT zu arbeiten. MS hat dafür eine eigenes Tool entwickelt, welches bei der Installation von der Advanced Express Edition (und alle Editionen darüber) dabei ist.
Hast du die Advanced Edition installiert, bzw. die Express um die Advanced erweitert, steht im Startmenü ein Programm zur Verfügung (Daten importieren exportieren) hier kannst du bestimmen, wo welche Daten hinein sollen. Ein Update bestehender Daten ist weiterhin dadurch nicht möglich.


----------



## werner_sg (30. Oktober 2012)

OK soweit schon mal verstanden,

dann kann ich mir ja eventuell das umwandeln in csv ersparen.

Die Text Datei ist folgend aufgebaut 

Datum|Uhrzeit|EAN|LagerEingang|LagerAusgang|
19-10-12|18:05:55|8712566263653                   |5    |                                |
19-10-12|18:13:47|5449000017888                   |     |1                               |

Da täglich aktualisiert wird werden es nie mehr als 100 Datensätze werden

Besteht eventuell nachher beim Update die Möglichkeit den Lagerausgang negativ zu werten, sonst muss ich doch umformatieren oder das irgendwie dem Scanner beibringen ( ist dann aber andere Baustelle ;-) )


```
BULK INSERT SMOKYKASSE.Artikelupdate
FROM 'e:\scanner.txt
WITH
(
FIELDTERMINATOR = '|',
ROWTERMINATOR = '\n',
CODEPAGE = 'ACP'
)
GO
```

Die Tabelle Artikelupdate erstelle ich dann mit den Feldern - Datum - Uhrzeit - EAN - Eingang - Ausgang -

Kann ich das ganze über eine Batch Datei Automatisieren oder kann die Advanced Version dies, nutze derzeit die Express.

Das Ziel am Ende soweit wie möglich alles zu Automatisieren, da ich nicht immer da sein kann, so das der Bekannte für den ich das ganze umsetze es so einfach wie möglich hat.

Sonst muss ich nachher wieder zu viele Fehler ausbügeln ;-)

Wenns hart auf hart kommt kann ich das auch täglich über Fernwartung umsetzen.

mfG Werner


----------



## rrobbyy (30. Oktober 2012)

kommt drauf an, wie die Zieltabelle genau aussieht. Falls die Mengen in einer Spalte liegen könntest du nach dem BULK INSERT ein UPDATE machen und dort einfach sagen


```
UPDATE TABLE
SET LAGERAUSGANG = LAGERAUSGANG * -1
go
```

Damit hättest du negative Werte in der Spalte


----------



## werner_sg (31. Oktober 2012)

So in etwa hatte ich das bisher mit Excel vorbereitet ;-)
zweite Spalte mit ISTWERT und dann *-1
Aber so ist das angenehmer.

Geht auch beides in einem Code?
In etwa so


```
BULK INSERT SMOKYKASSE.Artikelupdate
FROM 'e:\scanner.txt
WITH
(
FIELDTERMINATOR = '|',
ROWTERMINATOR = '\n',
CODEPAGE = 'ACP'
)
UPDATE TABLE
SET LAGERAUSGANG = LAGERAUSGANG * -1

GO
```

und last but not least die ewige Frage nach der Lösung ohne die DB Verwaltung aufrufen zu müssen.

Kann ich den Code in eine Batch Datei legen welche sich dann mit dem Server verbindet und das Bulk Insert ausführt.

Bin schon am Google'n habe aber noch nichts gefunden.

mfG Werner


----------



## rrobbyy (31. Oktober 2012)

Selbstverständlich kannst du alles in einem Code unterbringen. Du solltest aber vor dem Update-Befehl ein GO hinzufügen, damit der Insert korrekt abgeschlossen wird, bevor das Update kommt.


Du kannst auch ohne die Verwaltungskonsole arbeiten.
Bis 2012 gibt es den Befehl OSQL. Die Paramter kannst du dir über CMD anschauen


```
OSQL -?
```

Zuerst speichere den Code in eine Datei inkl. dem USE Befehl

also



```
USE SMOKYKASSE

BULK INSERT SMOKYKASSE.Artikelupdate
FROM 'e:\scanner.txt
WITH
(
FIELDTERMINATOR = '|',
ROWTERMINATOR = '\n',
CODEPAGE = 'ACP'

)
GO


UPDATE TABLE
SET LAGERAUSGANG = LAGERAUSGANG * -1

GO
```

dann in die Kommandozeile und OSQL aufrufen (ohne <>)


```
OSQL -S<servername\instanz> -U<SQLBenutzer> -P<Password> -i<Pfad der Datei mit dem SQLScript>
```

Beachte bitte, dass osql in zukünftigen SQL-Versionen wegfallen wird. Als Ersatz gibt es dann SQLCMD.


----------



## werner_sg (31. Oktober 2012)

Wird langsam mal Zeit für ein zwischen Danke 

Habs heute Nacht auch noch gefunden OSQL wird dann ab der nächsten Version von sqlcmd abgelöst, soll mich aber nicht stören, denke wenn dann endlich alles läuft nicht daran alles neu aufzusetzen ;-)

Werde das ganze heute Mittag dann mal endlich testen, Dank der guten Erklärung habe ich den Teil nun auch richtig gut Verstanden.

Heute Abend dann mal Abschalten und Party machen auf der Godesburg  habe ich mir verdient :suspekt:, und ab morgen geht's dann mit dem Update der Artikelstamm Tabelle los.

Vieleicht kannst mir ja schon erste Hinweise bzw. Hausaufgaben zum Einarbeiten geben :-(

mfG Werner


----------



## rrobbyy (31. Oktober 2012)

Hinweise und Hausaufgaben? Reicht das hier nicht schon ? 

Wichtig ist, dass du erst mal die Daten sauber reinbekommst.

Das zweite ist natürlich, wie du die bestehenden Daten anhand der importierten änderst. Da du schriebst, dass du mit MySQL Kontakt hattest, hoffe ich, dass dir JOINs ein Begriff sind.

Das wäre dann für dich die nächsten Hausaufgaben


----------

