teslajr
Goto Top

XML insert-update in einer MS SQL DB

Hallo Leute

Mein Code zum importieren einer xml in die MS SQL 2008 DB funktioniert, jedoch möchte ich dass die Daten bei bestehenden auch ein update machen und diese überschreiben.

wie müsste ein update aussehen?
(ich habe vieles ausprobiert, aber komme nicht weiter)

use testDB
declare @xmldata xml

set quoted_identifier on

set @xmldata=(select CONVERT(xml, bulkcolumn) as bulkcolumn
from openrowset(bulk 'd:\export.xml', single_blob)as x)

insert into dbo.testTableA
select Tab.Col.query('.').value('(/Mitarbeiter/Mitarbeiter-Nr.) [1]', 'varchar (50)') as mid,
Tab.Col.query('.').value('(/Mitarbeiter/Nachname) [1]', 'varchar (50)') as nachname,
Tab.Col.query('.').value('(/Mitarbeiter/Vorname) [1]', 'varchar (50)') as vorname,
Tab.Col.query('.').value('(/Mitarbeiter/Manager) [1]', 'varchar (50)') as manager,
Tab.Col.query('.').value('(/Mitarbeiter/SamAccountName) [1]', 'varchar (50)') as SamAccountName
from @xmldata.nodes('/Personal/Mitarbeiter') Tab (Col)
left join dbo.testTableA as z
on Tab.Col.query('.').value('(/Mitarbeiter/Mitarbeiter-Nr.) [1]', 'varchar (50)') = z.mid
and Tab.Col.query('.').value('(/Mitarbeiter/Nachname) [1]', 'varchar (50)') = z.name
and Tab.Col.query('.').value('(/Mitarbeiter/Vorname) [1]', 'varchar (50)') = z.vorname
and Tab.Col.query('.').value('(/Mitarbeiter/Manager) [1]', 'varchar (50)') = z.manager
and Tab.Col.query('.').value('(/Mitarbeiter/SamAccountName) [1]', 'varchar (50)') = z.SamAccountName
where z.mid is null

Danke & Gruss

Content-ID: 286922

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

Ausgedruckt am: 25.11.2024 um 10:11 Uhr

MadMax
Lösung MadMax 28.10.2015, aktualisiert am 30.10.2015 um 08:19:08 Uhr
Goto Top
Hallo teslajr,

damit sollte das gehen:
merge	testTableA t
using	(
	select Tab.Col.query('.').value('(/Mitarbeiter/Mitarbeiter-Nr.) [1]', 'varchar (50)') as mid,  
	Tab.Col.query('.').value('(/Mitarbeiter/Nachname) [1]', 'varchar (50)') as nachname,  
	Tab.Col.query('.').value('(/Mitarbeiter/Vorname) [1]', 'varchar (50)') as vorname,  
	Tab.Col.query('.').value('(/Mitarbeiter/Manager) [1]', 'varchar (50)') as manager,  
	Tab.Col.query('.').value('(/Mitarbeiter/SamAccountName) [1]', 'varchar (50)') as SamAccountName  
	from xmldata.nodes('/Personal/Mitarbeiter') Tab (Col)  
	) x on x.mid = t.mid
when matched then update
	set	nachname = x.nachname,
		vorname = x.vorname,
		manager = x.manager,
		SamAccountName = x.SamAccountName
when not matched by target then insert
	(mid, nachname, vorname, manager, SamAccountName)
	values (x.mid, x.nachname, x.vorname, x.manager, x.SamAccountName);

Achja, nochwas: bevor ich dieses sperrige XML mehrmals verwende, würde ich das lieber in eine temporäre Tabelle schieben und dann mit der weitermachen.

Gruß, Mad Max
teslajr
teslajr 30.10.2015 um 08:20:10 Uhr
Goto Top
Vielen Dank Max, dein Code löst mein Update Problem

Danke & Gruss
teslajr
teslajr 30.10.2015 um 15:21:35 Uhr
Goto Top
Etwas hätte ich noch...ich bekomme eine logische Fehlermeldung:
Der Wert NULL kann in die 'TaetigkeitID'-Spalte, 'testDB.dbo.testTableA'-Tabelle nicht eingefügt werden. Die Spalte lässt NULL-Werte nicht zu. Fehler bei UPDATE.

wenn ich nur nachname und vorname update, wie kann ich es umgehen, dass felder welche einen wert verlangen nicht meckern?
(ohne die tabelle zu ändern, dass das feld auch ohne einen wert erstellt wird)

Danke & Gruss
MadMax
MadMax 30.10.2015 um 19:05:10 Uhr
Goto Top
Hallo teslajr,

das bekommst Du mit isnull (x.nachname, '') z.B. für den Nachnamen.

Gruß, Mad Max
teslajr
teslajr 02.11.2015 um 16:36:44 Uhr
Goto Top
Hallo Max

bin wieder am kämpfen, wo frage/setze ich dieses ISNULL?
habe schon alles versucht, ohne Erfolg.

Frage ich das beim einlesen der XML ab oder am schluss beim insert?

use testDB
declare @xmldata xml

set quoted_identifier on

set @xmldata=(select CONVERT(xml, bulkcolumn) as bulkcolumn
from openrowset(bulk '\\Server\export$\export.xml', single_blob)as x)  

merge	Person t
using	(
	select Tab.Col.query('.').value('(/Mitarbeiter/Personalnummer) [1]', 'varchar (50)') as PersonalNummer,  
	Tab.Col.query('.').value('(/Mitarbeiter/Nachname) [1]', 'varchar (50)') as nachname,  
	Tab.Col.query('.').value('(/Mitarbeiter/Vorname) [1]', 'varchar (50)') as vorname,  
	Tab.Col.query('.').value('(/Mitarbeiter/Initialen) [1]', 'varchar (50)') as kurzzeichen  
	from @xmldata.nodes('/Personal/Mitarbeiter') Tab (Col)  
	) x on x.PersonalNummer = t.PersonalNummer
when matched then update
	set	name = x.nachname,
		vorname = x.vorname,
		kurzzeichen = x.kurzzeichen
when not matched by target then insert
	(PersonalNummer, name, vorname, kurzzeichen)
	values ( x.PersonalNummer, x.nachname, x.vorname, x.kurzzeichen);

Danke & Gruss
MadMax
MadMax 02.11.2015 um 20:52:14 Uhr
Goto Top
Moin teslajr,

in Deinem Fall geht es an beiden Stellen. isnull prüft, ob der erste Wert NULL ist und gibt in dem Fall den zweiten Wert zurück. Ist auch alles in der Hilfe beschrieben, da sollte man als erstes mal reinschauen bei Problemen.

Für Deinen Befehl habe ich es mal beim insert/update für den Nachnamen angegeben:
use testDB
declare @xmldata xml

set quoted_identifier on

set @xmldata=(select CONVERT(xml, bulkcolumn) as bulkcolumn
from openrowset(bulk '\\Server\export$\export.xml', single_blob)as x)  

merge	Person t
using	(
	select Tab.Col.query('.').value('(/Mitarbeiter/Personalnummer) [1]', 'varchar (50)') as PersonalNummer,  
	Tab.Col.query('.').value('(/Mitarbeiter/Nachname) [1]', 'varchar (50)') as nachname,  
	Tab.Col.query('.').value('(/Mitarbeiter/Vorname) [1]', 'varchar (50)') as vorname,  
	Tab.Col.query('.').value('(/Mitarbeiter/Initialen) [1]', 'varchar (50)') as kurzzeichen  
	from @xmldata.nodes('/Personal/Mitarbeiter') Tab (Col)  
	) x on x.PersonalNummer = t.PersonalNummer
when matched then update
	set	name = isnull (x.nachname, ''),  
		vorname = x.vorname,
		kurzzeichen = x.kurzzeichen
when not matched by target then insert
	(PersonalNummer, name, vorname, kurzzeichen)
	values ( x.PersonalNummer, isnull (x.nachname, ''), x.vorname, x.kurzzeichen);  
teslajr
teslajr 03.11.2015 aktualisiert um 09:21:26 Uhr
Goto Top
Guten Morgen Max

Vielen Dank für deine Hilfe, die Funktion isnull() habe ich schon verstanden, aber im Zusammenhang mit dem XML Import nicht.
Denn ich bekomme den Error dass die TaetigkeitID leer ist: Der Wert NULL kann in die 'TaetigkeitID'-Spalte, 'testDB.dbo.testTableA'-Tabelle nicht eingefügt werden. Die Spalte lässt NULL-Werte nicht zu.

In der XML gibt es diese Spalte nicht, nur in der Tabelle, deswegen weiss ich nicht wo ich isnull(TaetigkeitID,'') machen soll?

when matched then update
	set	name = x.nachname,
		vorname = x.vorname,
		taetigkeitID = isnull(x.taetigkeitID, ''),  
		kurzzeichen = x.kurzzeichen		
when not matched by target then insert
	(taetigkeitID, PersonalNummer, name, vorname, kurzzeichen)
	values (isnull(x.taetigkeitID,''), x.PersonalNummer,  x.nachname, x.vorname, x.kurzzeichen);  



Danke & Gruss
MadMax
MadMax 03.11.2015 um 12:19:50 Uhr
Goto Top
Hallo teslajr,

ok, jetzt versteh ich Dein Problem.

Du kannst da auch Variable oder Konstante setzen und mußt Dich nicht nur auf die Daten, die bei "using" stehen, beziehen. Da im Import scheinbar keine TaetigkeitID enthalten ist, brauchst Du das isnull dann auch nicht.

Ob Du beim Update die TaetigkeitID zurücksetzen mußt, weiß ich nicht, ansonsten kannst Du sie auch weglassen.

Beim Insert kannst Du statt Deines "isnull(x.taetigkeitID,'')" dann einfach eine 0 oder 1 oder sonstwas setzen. Oder eine Variable, in der irgendein ermittelter Standardwert dafür steht.

Also z.B.:
when matched then update
	set	name = x.nachname,
		vorname = x.vorname,
		kurzzeichen = x.kurzzeichen		
when not matched by target then insert
	(taetigkeitID, PersonalNummer, name, vorname, kurzzeichen)
	values (0, x.PersonalNummer,  x.nachname, x.vorname, x.kurzzeichen);

oder
when matched then update
	set	name = x.nachname,
		vorname = x.vorname,
		taetigkeitID = @taetigkeitID,
		kurzzeichen = x.kurzzeichen		
when not matched by target then insert
	(taetigkeitID, PersonalNummer, name, vorname, kurzzeichen)
	values (@taetigkeitID, x.PersonalNummer,  x.nachname, x.vorname, x.kurzzeichen);

Gruß, Mad Max