MS SQL 2005er Express - Update einer Tabelle aus 2. DB
Guten morgen zusammen,
ich habe 2 Datenbanken, die beide die gleiche Tabelle "Datentab" (13 Spalten) enthalten.
Die Tabelle in DB1 enthält diverse Daten, die Tabelle in DB2 ist leer.
Nun möchte ich die Tabelle in DB2 mit Daten aus DB1 füllen.
Allerdings soll hier ein Kriterium (ArtNr=4712) berücksichtigt werden.
Die Selektion der Daten in DB1 ist kein Problem:
aber wie kriege ich das Ergebnis nun in DB2 rein?
Bei einer geringen Zeilenanzahl habe ich das ganze bisher mit Copy&Paste gemacht.
Das ist allerdings bei den heutigen Datenmenge kaum noch machbar oder dauert ewig.
Hat hier jemand einen Tip für mich?
Ja, ich habe Google schon befragt, aber komme da nicht weiter.
Nein, ich möchte keine zusätzlichen Programme oder Tools verwenden.
Tablediff.exe habe ich schon probiert, aber ist mir zu "unhandlich".
*nachtrag*
Ich habe doch noch was rausgefunden (beide DB_Server sind verbunden):
Das schmeisst mir aber einen Fehler raus:
ich habe 2 Datenbanken, die beide die gleiche Tabelle "Datentab" (13 Spalten) enthalten.
Die Tabelle in DB1 enthält diverse Daten, die Tabelle in DB2 ist leer.
Nun möchte ich die Tabelle in DB2 mit Daten aus DB1 füllen.
Allerdings soll hier ein Kriterium (ArtNr=4712) berücksichtigt werden.
Die Selektion der Daten in DB1 ist kein Problem:
SECLECT * FROM Datentab
WHERE ArtNr=4712
Bei einer geringen Zeilenanzahl habe ich das ganze bisher mit Copy&Paste gemacht.
Das ist allerdings bei den heutigen Datenmenge kaum noch machbar oder dauert ewig.
Hat hier jemand einen Tip für mich?
Ja, ich habe Google schon befragt, aber komme da nicht weiter.
Nein, ich möchte keine zusätzlichen Programme oder Tools verwenden.
Tablediff.exe habe ich schon probiert, aber ist mir zu "unhandlich".
*nachtrag*
Ich habe doch noch was rausgefunden (beide DB_Server sind verbunden):
INSERT INTO DB2.Daten.dbo.Datentab SELECT ArtNr, Beschr, Preis FROM DB1.Daten.dbo.Datentab WHERE ArtNr=4712
Meldung 7202, Ebene 11, Status 2, Zeile 1
Der Server 'DB1' wurde in sys.servers nicht gefunden. Prüfen Sie, ob der richtige Servername angegeben wurde. Führen Sie bei Bedarf die gespeicherte Prozedur sp_addlinkedserver aus, um den Server zu sys.servers hinzuzufügen.
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 176924
Url: https://administrator.de/contentid/176924
Ausgedruckt am: 22.11.2024 um 04:11 Uhr
11 Kommentare
Neuester Kommentar
Guten Tag,
also deine Datenbanken liegen auf 2 verschiedenen Servern, hast du denn auf dem Server, auf dem die Abfrage läuft auch den anderen Server als Linkserver eingerichtet?
Lauf Fehlermeldung scheinbar nicht, also erstmal Linkserver anlegen:
Du musst @135404=N'DB1', überall mit dem richtigen Hostnamen ersetzen UND
@rmtuser=N'USERNAME',@rmtpassword='PASSWORT' mit dem richtigen Usernamen und Passwort.
Wenn das der Fall ist und der Server angelegt ist, geht der Insert so:
also deine Datenbanken liegen auf 2 verschiedenen Servern, hast du denn auf dem Server, auf dem die Abfrage läuft auch den anderen Server als Linkserver eingerichtet?
Lauf Fehlermeldung scheinbar nicht, also erstmal Linkserver anlegen:
EXEC master.dbo.sp_addlinkedserver @server = N'DB1', @srvproduct=N'SQL Server'
GO
EXEC master.dbo.sp_addlinkedsrvlogin @rmtsrvname=N'DB1',@useself=N'False',@locallogin=NULL,@rmtuser=N'USERNAME',@rmtpassword='PASSWORT'
GO
EXEC master.dbo.sp_serveroption @server=N'DB1', @optname=N'collation compatible', @optvalue=N'false'
GO
EXEC master.dbo.sp_serveroption @server=N'DB1', @optname=N'data access', @optvalue=N'true'
GO
EXEC master.dbo.sp_serveroption @server=N'DB1', @optname=N'dist', @optvalue=N'false'
GO
EXEC master.dbo.sp_serveroption @server=N'DB1', @optname=N'pub', @optvalue=N'false'
GO
EXEC master.dbo.sp_serveroption @server=N'DB1', @optname=N'rpc', @optvalue=N'false'
GO
EXEC master.dbo.sp_serveroption @server=N'DB1', @optname=N'rpc out', @optvalue=N'false'
GO
EXEC master.dbo.sp_serveroption @server=N'DB1', @optname=N'sub', @optvalue=N'false'
GO
EXEC master.dbo.sp_serveroption @server=N'DB1', @optname=N'connect timeout', @optvalue=N'0'
GO
EXEC master.dbo.sp_serveroption @server=N'DB1', @optname=N'collation name', @optvalue=null
GO
EXEC master.dbo.sp_serveroption @server=N'DB1', @optname=N'lazy schema validation', @optvalue=N'false'
GO
EXEC master.dbo.sp_serveroption @server=N'DB1', @optname=N'query timeout', @optvalue=N'0'
GO
EXEC master.dbo.sp_serveroption @server=N'DB1', @optname=N'use remote collation', @optvalue=N'true'
GO
Du musst @135404=N'DB1', überall mit dem richtigen Hostnamen ersetzen UND
@rmtuser=N'USERNAME',@rmtpassword='PASSWORT' mit dem richtigen Usernamen und Passwort.
Wenn das der Fall ist und der Server angelegt ist, geht der Insert so:
-- Abfrage auf DB2 ausführen
-- Das InsertStatement zeigt auf DB2
INSERT INTO Daten.dbo.Datentab (Feld1, Feld2)
-- Der Openquery Select zeigt auf DB1
SELECT * from OPENQUERY (LINKSERVERNAME, 'select Feld1, Feld2 from Daten.dbo.Datentab WHERE ArtNr=4712 with (nolock)')
Hi, mir fallen spontan zwei Möglichkeiten ein:
MÖGLICHKEIT 1:
Die sp_addlinkedserver auf dem DB1 ausführen mit Daten von DB2, nun kennst du DB2 auf DB1 und auf DB1 kennst du DB2.
hier machst du nun folgedes auf dem Server, der die fehlenden Daten hat (DB1):
nun hast du auf DB1 eine View, in der nur Datensätze sind, die es auf DB2 nicht gibt.
Dann ersetzt du in dem Insert Schnipselchen von Oben
mit
MÖGLICHKEIT 2:
auf DB2 folgendes:
Ich kann grade nichts testen, bin unterwegs, falls irgendwelche Fehler geworfen werden, meld dich einfach nochmal mit kompletter Meldung.
Gruß
MÖGLICHKEIT 1:
Die sp_addlinkedserver auf dem DB1 ausführen mit Daten von DB2, nun kennst du DB2 auf DB1 und auf DB1 kennst du DB2.
hier machst du nun folgedes auf dem Server, der die fehlenden Daten hat (DB1):
Create View v_Differenz_DB1_zu_DB2
AS
Select Feld1, Feld2, .... from Daten.dbo.Datentab where PK not in (
SELECT * from OPENQUERY (DB2, 'select PK from Daten.dbo.Datentab with (nolock)')
Go
Dann ersetzt du in dem Insert Schnipselchen von Oben
SELECT * from OPENQUERY (LINKSERVERNAME, 'select Feld1, Feld2 from Daten.dbo.Datentab WHERE ArtNr=4712 with (nolock)')
SELECT * from OPENQUERY (LINKSERVERNAME, 'select Feld1, Feld2 from Daten.dbo.v_Differenz_DB1_zu_DB2')
MÖGLICHKEIT 2:
auf DB2 folgendes:
Create View v_Datenbestand_DB1
AS
SELECT * from OPENQUERY (DB1, 'select * from Daten.dbo.Datentab with (nolock)'
GO
INSERT INTO Daten.dbo.Datentab
SELECT ArtNr, Beschr, Preis FROM Daten.dbo.v_Datenbestand_DB1 WHERE Artnr not in (Select Artnr from Daten.dbo.Datentab (nolock))
Ich kann grade nichts testen, bin unterwegs, falls irgendwelche Fehler geworfen werden, meld dich einfach nochmal mit kompletter Meldung.
Gruß
Ja so soll es sein, DB1 ist die Quelle des Vergleichs, weil da gibt es mehr Daten.
Ich habe das mit dem "Create View" auf DB2 in einem SQL-Query ausprobiert.
Erst erhielt ich eine Fehlermeldung, aber da fehlt am Ende von Zeile 3 eine Klammer.
Erst erhielt ich eine Fehlermeldung, aber da fehlt am Ende von Zeile 3 eine Klammer.
Welch eine Nachlässigkeit von mir, war aber wie gesagt unterwegs =)
1. bei einem zweiten Aufruf erhalte ich die Meldung, das 'v_Datenbestand_DB1' schon existiert
Wie kann ich die zunächst löschen (per Skript, nicht manuell), damit sie mit jedem Aufruf neu erstellt wird?
Wie kann ich die zunächst löschen (per Skript, nicht manuell), damit sie mit jedem Aufruf neu erstellt wird?
IF EXISTS (SELECT * FROM sys.views WHERE object_id = OBJECT_ID(N'[dbo].[v_Datenbestand_DB1]'))
DROP VIEW [dbo].[v_Datenbestand_DB1]
GO
Stell dir das so vor, du führst
Select Feld1, Feld2, .... from Daten.dbo.Datentab where PK not in ( SELECT * from OPENQUERY (DB2, 'select PK from Daten.dbo.Datentab with (nolock)')
In der View passiert das gleiche, wenn du Sie aufrust, kriegst du 2 Datensätze, nach dem Insert 0.
Eine View ist praktisch sowas wie eine gewisse Query statisch anlegen und in der View ist immer das Ergebnis der Query zur Laufzeit.
Wenn das nicht verständlich ist, meld dich noch mal dazu.
2. wie kann ich den Filter auf ArtNr=4711 einbauen?
Ich habe Zeile 3 entsprechend erweitert:
In der v_Datenbestand_DB1 stehen dann auch nur die selektierten, aber es erfolgt dann Abgleich mehr mit der Zieltabelle.
Zumindest schreibt er die fehlenden Einträge nicht rein.
Ich vermute mal, das es an der schon vorhandenen ArtNr liegt, denn wenn ich als Kriterium im 2. Teil 2. Zeile statt ArtNr mal
Preis ausgewählt habe, dann funktioniert es.
Ist aber kein Problem, wenn man es weiß, nur so bekomme ich halt kein Update auf vorhandene Sätze.
Dann lösch ich halt vorhandene vorher und gut ist's.
Ich habe Zeile 3 entsprechend erweitert:
SELECT * from OPENQUERY (DB1, 'select * from Daten.dbo.Datentab with (nolock) where ArtNr=4711'
>
Zumindest schreibt er die fehlenden Einträge nicht rein.
Ich vermute mal, das es an der schon vorhandenen ArtNr liegt, denn wenn ich als Kriterium im 2. Teil 2. Zeile statt ArtNr mal
Preis ausgewählt habe, dann funktioniert es.
Ist aber kein Problem, wenn man es weiß, nur so bekomme ich halt kein Update auf vorhandene Sätze.
Dann lösch ich halt vorhandene vorher und gut ist's.
Hier kann ich dir ehrlich gesagt jetzt grade nur helfen, wenn du mir einmal den Aufbau von DB1..Tabelle und DB2..Tabelle
beschreibst und auf welchen Spalten die einzufügenden Differenzen sind. Die Abfrage dann zu finden ist kein Problem.
Zitat von @Iwan:
Das mit dem Löschen bevor ich die Daten neu einlese, ist kein Problem.
Daher ist mir das Aktualisieren der Daten jetzt nicht so wichtig.
Das mit dem Löschen bevor ich die Daten neu einlese, ist kein Problem.
Daher ist mir das Aktualisieren der Daten jetzt nicht so wichtig.
Jetzt müssen wir noch einmal begriffe abgrenzen:
Reden vir von anfügen oder aktualisieren?
Anfügen wäre in Tabelle2 gibt es Datensatz X nicht, aktualisieren wäre in Tabelle2 Gibt es
Datensatz X und im Feld muss nun der Wert Y statt Z stehen.
Beispiel für Anfügen (Datensatz von Kunde 113 fehlt noch komplett in Tabelle 2 und muss da rein):
Tabelle DB1
Artikel Kunde Preis
4711 111 5,00
4711 112 7,00
4711 113 8,00
Artikel Kunde Preis
4712 111 5,00
4713 112 7,00
Beispiel für aktualisieren (Kunde 113 der Preis muss in Tabelle 2 auch auf 1,00):
Tabelle DB1
Artikel Kunde Preis
4711 111 5,00
4711 112 7,00
4711 113 1,00
Artikel Kunde Preis
4711 111 5,00
4711 112 7,00
4711 113 8,00
Gruß
Wenn der seltene Fall, dass in DB1 was gelöscht wird
eintritt, soll der Datensatz auch in DB2 weg sein oder?
Wenn das der Fall ist, mach doch einfach folgendes:
Auf DB1 eine View mit dem Tabelleninhalt, die brauchst du nur einmal anlegen und dann nicht mehr ändern.
Auf Server 2:
Die Codepassage für Server 2 packste dir dann in einen Stores Procedure und die rufst du auf DB 2 einfach stündlich oder täglich Abends per SQLcmd auf,
dann hast du Synchronisierung ohne zutun.
Der bessere Weg wäre das Script direkt als SQL Job laufen zu lassen aber ich meine der Express Server hat keinen SQL Server Agent.
In mittleren bis großen Umgebungen (>1.000.000 Datensätze) würde man sich tatsächlich die Mühe für ein bidirektionales Differenzskript machen
aber bei "mehreren Tausend" Datensätzen, ist die Menge so schwindend gering für eine Datenbank, dass alles löschen und neu reinschreiben
vollkommen okay ist.
eintritt, soll der Datensatz auch in DB2 weg sein oder?
Wenn das der Fall ist, mach doch einfach folgendes:
Auf DB1 eine View mit dem Tabelleninhalt, die brauchst du nur einmal anlegen und dann nicht mehr ändern.
Create View v_Befuellung_DB2
AS
Select * from Daten.dbo.Datentab (nolock)
GO
Auf Server 2:
Delete from Daten.dbo.Datentab
GO
INSERT INTO Daten.dbo.Datentab
SELECT * FROM Daten.dbo.v_Befuellung_DB2
dann hast du Synchronisierung ohne zutun.
Der bessere Weg wäre das Script direkt als SQL Job laufen zu lassen aber ich meine der Express Server hat keinen SQL Server Agent.
In mittleren bis großen Umgebungen (>1.000.000 Datensätze) würde man sich tatsächlich die Mühe für ein bidirektionales Differenzskript machen
aber bei "mehreren Tausend" Datensätzen, ist die Menge so schwindend gering für eine Datenbank, dass alles löschen und neu reinschreiben
vollkommen okay ist.