2. Tabelle beim Import automatisch erstellen

CharlyOli

Aktiver Benutzer
Beiträge
31
Hallo Zusammen,



seit langer Zeit bräuchte ich mal wieder Hilfe von euch.

Ich bekomme in regelmäßigen Abständen eine Exceltabelle mit aktuellen Artikeln. Diese Tabelle entspricht allen lieferbaren Artikelvarianten.

Ist es möglich auf Basis dieser Tabelle die Daten in 2 SQL Datenbanktabellen zu importieren?

1. Artikelvarianten

Der noch einfachste Part ist der Import in die Tabelle "Artikelvarianten" weil sie im großen und ganze den Aufbau der Excel Datei wiederspiegelt.

Keyfeld: = [Material]

Diesen Import bekomme ich über eine gespeicherte Prozedur mit Hilfe von Powerautomate Desktop hin.



2. Artikel

Der schwierige Teil ist aber die Daten zusätzlich als Artikeldatensatz in die Tabelle "Artikel" zu importieren.

Keyfeld: = [Artikelnummer]



Ich bin leider noch nicht so firm in SQL, arbeite mich aber gerade in das Thema ein.

Kann mir hier jemand helfen?



Da ich die Daten regelmäßig einlesen möchte, muss in dem SQL Statement auch die Prüfung enthalten sein, ob sich Felder von bereits in der Datenbank befindlichen Datensätzen geändert haben.


Würde mich über Hilfe wirklich sehr freuen.

Eine Exceldatei mit Erklärungen lade ich hoch.


Viele Grüße

Oliver
 

Anhänge

  • Artikelübergabe.zip
    13,2 KB · Aufrufe: 2
Werbung:
Guten Morgen :)

das klingt ja erstmal nicht so wild. Ich glaube aber es hilft allen wenn du die Struktur der beiden Tabellen darstellst. ;)

Sehen die Excel-dateien vom Aufbau immer so aus wie in deinem Beispiel?
 
Hallo Chuky666,

stimmt da hast du natürlich Recht.

Ich habe den Prozess einmal aufskizziert und einen Auszug aus einer Original Excel Daten anhängt, die ich regelmäßig bekomme.
Der Prozess auf dem PDF funktioniert manuell sehr gut.

Mir geht es jetzt um den im ersten Post genannten 2. Step. Die Excel Tabelle stellte jeweils die Artikelvarianten dar, und ich würde gern (am besten während des Imports) eine 2. Tabelle "Artikel" füllen, die aber "nur" den Artikeldatensatz beinhaltet.
Im konkreten gesagt, die Artikelnummern gruppiert.
 

Anhänge

  • Datenimport.pdf
    146,5 KB · Aufrufe: 5
  • Beispiel Excel.zip
    8,6 KB · Aufrufe: 0
Hier der Code. Wie gesagt, ich bin nicht so fit... aber lerne gerne dazu.



--Synchronisierung der Tabelle [WDF_PORDUKTE_VARIANTEN] (target table)
--mit der temporären Importabelle [IMPORT_PRODUKTE_VARIANTEN_GEALAN] (source table)

MERGE WDF_PRODUKTE_VARIANTEN AS TARGET
USING IMPORT_PRODUKTE_VARIANTEN_GEALAN AS SOURCE
ON (TARGET.Produkte_id = SOURCE.Produkte_id)
--When records are matched, update the records if there is any change
WHEN MATCHED AND TARGET.Artikelnummer <> SOURCE.Artikelnummer
OR TARGET.Hersteller_Artikelnummer <> SOURCE.Hersteller_Artikelnummer
OR TARGET.Bezeichnung1 <> SOURCE.Bezeichnung1
OR TARGET.FarbeA_id <> SOURCE.FarbeA_id
OR TARGET.FarbeI_id <> SOURCE.FarbeI_id
OR TARGET.Grundkörper_id <> SOURCE.Grundkörper_id
OR TARGET.Dichtungsart_id <> SOURCE.Dichtungsart_id
OR TARGET.Dichtungsfarbe_id <> SOURCE.Dichtungsfarbe_id
OR TARGET.IKD_id <> SOURCE.IKD_id
OR TARGET.STV_id <> SOURCE.STV_id
OR TARGET.Std_id <> SOURCE.Std_id
OR TARGET.Zusatzausstattung <> SOURCE.Zusatzausstattung


THEN UPDATE SET
TARGET.Artikelnummer = SOURCE.Artikelnummer,
TARGET.Hersteller_Artikelnummer = SOURCE.Hersteller_Artikelnummer,
TARGET.Bezeichnung1 = SOURCE.Bezeichnung1,
TARGET.FarbeA_id = SOURCE.FarbeA_id,
TARGET.FarbeI_id = SOURCE.FarbeI_id,
TARGET.Grundkörper_id = SOURCE.Grundkörper_id,
TARGET.Dichtungsart_id = SOURCE.Dichtungsart_id,
TARGET.Dichtungsfarbe_id = SOURCE.Dichtungsfarbe_id,
TARGET.IKD_id = SOURCE.IKD_id,
TARGET.STV_id = SOURCE.STV_id,
TARGET.Std_id = SOURCE.Std_id,
TARGET.Zusatzausstattung = SOURCE.Zusatzausstattung


--When no records are matched, insert the incoming records from source table to target table
WHEN NOT MATCHED BY TARGET
THEN INSERT (Produkte_id, Artikelnummer, Hersteller_Artikelnummer, Bezeichnung1, FarbeA_id, FarbeI_id, Grundkörper_id, Dichtungsart_id, Dichtungsfarbe_id, IKD_id, STV_id, Std_id, Zusatzausstattung)
VALUES (SOURCE.Produkte_id, SOURCE.Artikelnummer, SOURCE.Hersteller_Artikelnummer, SOURCE.Bezeichnung1, SOURCE.FarbeA_id, SOURCE.FarbeI_id, SOURCE.Grundkörper_id, SOURCE.Dichtungsart_id, SOURCE.Dichtungsfarbe_id, SOURCE.IKD_id, SOURCE.STV_id, SOURCE.Std_id, SOURCE.Zusatzausstattung)
--When there is a row that exists in target and same record does not exist in source then delete this record target
WHEN NOT MATCHED BY SOURCE
THEN DELETE
--$action specifies a column of type nvarchar(10) in the OUTPUT clause that returns
--one of three values for each row: 'INSERT', 'UPDATE', or 'DELETE' according to the action that was performed on that row
OUTPUT $action,
DELETED.Produkte_id AS TargetProdukte_id,
DELETED.Hersteller_Artikelnummer AS TargetHersteller_Artikelnummer,
DELETED.FarbeA_id AS TargetFarbeA_id,
DELETED.FarbeI_id AS TargetFarbeI_id,
DELETED.Grundkörper_id AS TargetGrundkörper_id,
DELETED.Dichtungsart_id AS TargetDichtungsart_id,
DELETED.Dichtungsfarbe_id AS TargetDichtungsfarbe_id,
DELETED.IKD_id AS TargetIKD_id,
DELETED.STV_id AS TargetSTV_id,
DELETED.Std_id AS TargetStd_id,
DELETED.Zusatzausstattung AS TargetZusatzausstattung,
INSERTED.Produkte_id AS SourceProdukte_id,
INSERTED.Hersteller_Artikelnummer AS SourceHersteller_Artikelnummer,
INSERTED.FarbeA_id AS SourceFarbeA_id,
INSERTED.FarbeI_id AS SourceFarbeI_id,
INSERTED.Grundkörper_id AS SourceGrundkörper_id,
INSERTED.Dichtungsart_id AS SourceDichtungsart_id,
INSERTED.Dichtungsfarbe_id AS SourceDichtungsfarbe_id,
INSERTED.IKD_id AS SourceIKD_id,
INSERTED.STV_id AS SourceSTV_id,
INSERTED.Std_id AS SourceStd_id,
INSERTED.Zusatzausstattung AS SourceZusatzausstattung;
SELECT @@ROWCOUNT;
GO

delete FROM [WindowDataPortal].[dbo].[IMPORT_PRODUKTE_VARIANTEN_GEALAN]
GO
 
so, hier mit Code Tags. Diese Statement ist mein Merge Statement.


Code:
--Synchronisierung der Tabelle [WDF_PORDUKTE_VARIANTEN] (target table)
--mit der temporären Importabelle [IMPORT_PRODUKTE_VARIANTEN_GEALAN] (source table)

MERGE WDF_PRODUKTE_VARIANTEN AS TARGET
USING IMPORT_PRODUKTE_VARIANTEN_GEALAN AS SOURCE
ON (TARGET.Produkte_id = SOURCE.Produkte_id)
--When records are matched, update the records if there is any change
WHEN MATCHED AND TARGET.Artikelnummer <> SOURCE.Artikelnummer
OR TARGET.Hersteller_Artikelnummer <> SOURCE.Hersteller_Artikelnummer
OR TARGET.Bezeichnung1 <> SOURCE.Bezeichnung1
OR TARGET.FarbeA_id <> SOURCE.FarbeA_id
OR TARGET.FarbeI_id <> SOURCE.FarbeI_id
OR TARGET.Grundkörper_id <> SOURCE.Grundkörper_id
OR TARGET.Dichtungsart_id <> SOURCE.Dichtungsart_id
OR TARGET.Dichtungsfarbe_id <> SOURCE.Dichtungsfarbe_id
OR TARGET.IKD_id <> SOURCE.IKD_id
OR TARGET.STV_id <> SOURCE.STV_id
OR TARGET.Std_id <> SOURCE.Std_id
OR TARGET.Zusatzausstattung <> SOURCE.Zusatzausstattung


THEN UPDATE SET
TARGET.Artikelnummer = SOURCE.Artikelnummer,
TARGET.Hersteller_Artikelnummer = SOURCE.Hersteller_Artikelnummer,
TARGET.Bezeichnung1 = SOURCE.Bezeichnung1,
TARGET.FarbeA_id = SOURCE.FarbeA_id,
TARGET.FarbeI_id = SOURCE.FarbeI_id,
TARGET.Grundkörper_id = SOURCE.Grundkörper_id,
TARGET.Dichtungsart_id = SOURCE.Dichtungsart_id,
TARGET.Dichtungsfarbe_id = SOURCE.Dichtungsfarbe_id,
TARGET.IKD_id = SOURCE.IKD_id,
TARGET.STV_id = SOURCE.STV_id,
TARGET.Std_id = SOURCE.Std_id,
TARGET.Zusatzausstattung = SOURCE.Zusatzausstattung


--When no records are matched, insert the incoming records from source table to target table
WHEN NOT MATCHED BY TARGET
THEN INSERT (Produkte_id, Artikelnummer, Hersteller_Artikelnummer, Bezeichnung1, FarbeA_id, FarbeI_id, Grundkörper_id, Dichtungsart_id, Dichtungsfarbe_id, IKD_id, STV_id, Std_id, Zusatzausstattung)
VALUES (SOURCE.Produkte_id, SOURCE.Artikelnummer, SOURCE.Hersteller_Artikelnummer, SOURCE.Bezeichnung1, SOURCE.FarbeA_id, SOURCE.FarbeI_id, SOURCE.Grundkörper_id, SOURCE.Dichtungsart_id, SOURCE.Dichtungsfarbe_id, SOURCE.IKD_id, SOURCE.STV_id, SOURCE.Std_id, SOURCE.Zusatzausstattung)
--When there is a row that exists in target and same record does not exist in source then delete this record target
WHEN NOT MATCHED BY SOURCE
THEN DELETE
--$action specifies a column of type nvarchar(10) in the OUTPUT clause that returns
--one of three values for each row: 'INSERT', 'UPDATE', or 'DELETE' according to the action that was performed on that row
OUTPUT $action,
DELETED.Produkte_id AS TargetProdukte_id,
DELETED.Hersteller_Artikelnummer AS TargetHersteller_Artikelnummer,
DELETED.FarbeA_id AS TargetFarbeA_id,
DELETED.FarbeI_id AS TargetFarbeI_id,
DELETED.Grundkörper_id AS TargetGrundkörper_id,
DELETED.Dichtungsart_id AS TargetDichtungsart_id,
DELETED.Dichtungsfarbe_id AS TargetDichtungsfarbe_id,
DELETED.IKD_id AS TargetIKD_id,
DELETED.STV_id AS TargetSTV_id,
DELETED.Std_id AS TargetStd_id,
DELETED.Zusatzausstattung AS TargetZusatzausstattung,
INSERTED.Produkte_id AS SourceProdukte_id,
INSERTED.Hersteller_Artikelnummer AS SourceHersteller_Artikelnummer,
INSERTED.FarbeA_id AS SourceFarbeA_id,
INSERTED.FarbeI_id AS SourceFarbeI_id,
INSERTED.Grundkörper_id AS SourceGrundkörper_id,
INSERTED.Dichtungsart_id AS SourceDichtungsart_id,
INSERTED.Dichtungsfarbe_id AS SourceDichtungsfarbe_id,
INSERTED.IKD_id AS SourceIKD_id,
INSERTED.STV_id AS SourceSTV_id,
INSERTED.Std_id AS SourceStd_id,
INSERTED.Zusatzausstattung AS SourceZusatzausstattung;
SELECT @@ROWCOUNT;
GO

delete FROM [WindowDataPortal].[dbo].[IMPORT_PRODUKTE_VARIANTEN_GEALAN]
GO
 
Der dargestellte Teil sieht doch ganz gut aus. Ich kann es aber mangels MSSQL Kenntnis / Verfügbarkeit nicht wirklich beurteilen.
Jetzt noch ein 2. Insert und Du bist fertig.

Ich will ganz allgemein aber was anderes nachfragen: ob es sein muss, bei solchen Operationen Excel als Medium zu verwenden. Am wenigsten problematisch wäre das, wenn die Exceldatei selbst von niemand (kein Mensch) editiert wird und auch von keinem Menschen transportiert wird (zum Zielsystem). Da es nicht nur um Updates, sondern sogar um Löschungen geht, finde ich die Verwendung so einer "sensiblen" Dateiform recht kritisch.
Ähnliches Thema, andere Stelle. Du willst beim Import 2 Tabellen "gleichzeitig" erstellen. Ich stelle mir vor, Du meintst einen Arbeitsvorgang (für den User)? Wie wäre es mit:
- einem Import der Originaldaten 1:1
- (dem dauerhaften Speichern der Importdaten, weil man es kann, optional)
- (der Plausibilisierung und Fehlererkennung innerhalb der Importdaten)
- Tatsächliche Weiterverarbeitung / Weiterverteilung der Daten (ETL/TEL) in 1, 2 .. n weiteren Prozessschritten
 
Die Excel ist leider gesetzt, da ich diese in regelmäßigen Abständen und immer im gleichen Format vom Lieferanten bekomme.

Wie muss der 2. Insert aussehen, damit ich die "komprimierte" 2. Tabelle "Artikel" bekomme?
Im SQL wäre das ein GROUP BY auf die Artikelnummer.

Habe es hintenrum schon mit einer View probiert, aber eine Tabelle wäre mir lieber und die eben im Merge Statement mit integriert.

Bedeutet:
Statement updated/löscht/fügt erst die Artikelvariantendaten in die Tabelle und aus diesen Daten wird dann die "komprimierte" Artikeltabelle erstellt.
 

Anhänge

  • View.jpg
    View.jpg
    89,1 KB · Aufrufe: 2
Ok, Du solltest Dir bewusst sein, dass es fehleranfällig ist, wie gesagt, besonders, wenn diese Exceldatei auch noch von Menschen angefasst wird.
Dein 2. Problem verstehe ich nicht. Du hast schon so viele Dateien hier angehängt, alles recht umständlich für Helfer. Wie soll Deine Zieltabelle im Fall 2 aussehen? Ohne das kann man kein Insert Statement bestimmen. Es ist üblich für so etwas einfach die nötigen DDL Statements der betroffenen Objekte und Daten, also Insert Statements (DML) in Textform zu posten, kein Hexenwerk. Ggf. in der Variante Soll und Ist.

Im Prinzip:
Code:
insert into Tabelle2 (<Feldliste>) 
Select <passendeFelderZuFeldliste> from Quelltabele(OderExcel)
[where Filterbedingung]
[group by <nichtAggregierteFelder>]
Wenn Du ein Group By brauchst, was anhand Deiner Beschreibung sein kann, bitte die Spielregeln zur Gruppierung beachten.
Das Select Statement für sich genommen muss fehlerfrei laufen und die Menge liefern, die eingefügt werden soll. Davor dann die Insert Sektion einsetzen.
 
Ich würde mich auch mehr mit SSIS beschäftigen, da man eig. alles per SSIS erschlagen kann ;) Excel einlesen, inserten usw usw usw... Dazu kommt das man vllt. mit dem Lieferanten sprechen sollte ob er in der Datei nicht auch einen Tab nutzen kann wo die Artikeldaten drin stehen(Fall 2). Erster Export vom Lieferanten enthält alle Artikel, jeder weitere nur Änderungen.
 
Werbung:
Hallo Zusammen,

ich danke euch für eure Hilfe. Werde all eure Ratschläge berücksichtigen.
In einem ersten Schritt mache ich es über folgenden Code, der gut funktioniert:

Code:
MERGE INTO Artikel_test AS TGT
USING
(
  SELECT Artikelnummer
  FROM WDF_PRODUKTE_VARIANTEN
 GROUP BY Artikelnummer
) AS SRC
  ON  SRC.Artikelnummer = TGT.Artikelnummer
WHEN NOT MATCHED THEN
  INSERT (Artikelnummer)
  VALUES (SRC.Artikelnummer);

Der Code schreibt mir mit Group by im MERGE Statement die Artikelnummern weg.

Ich spreche aber auch noch mit dem Lieferanten (wie von Chuky666 vorgeschlagen)

VG
CharlyOli
 
Zurück
Oben