"Christmas - the time to fix the computers of your loved ones" « Lord Wyrm

[REQ] SQL: USE @variable funktioniert nicht

3mind 03.01.2008 - 12:26 1815 12
Posts

3mind

mimimi
Avatar
Registered: Sep 2004
Location: 1030
Posts: 1588
hallo leute,

ich möchte ein script erstellen (vorzugsweise t-sql / sql) mit welchem die datensätze und tabellen zweier datenbanken abgeglichen werden können. am liebsten hätte ich das folgendermaßen: eingabe der namen von master-datenbank und der neuen datenbank und das script durchläuft jede tabelle der masterDB und schaut ob diese existiert in der neuen DB (wenn nicht --> copy der kompletten tabelle inklusive daten, wenn ja --> fehlende datensätze kopieren, keine datensätze löschen). wenn tabellen nur in der neuen jedoch nicht in der masterDB existieren sollen diese nicht gelöscht werden.

ich hab jetzt schonmal begonnen mir das zu überlegen, bin mir aber nichtmal sicher ob es möglich ist eine procedure zu schreiben die unterschiedliche datenbanken verwendet?

das codefragment zeigt meinen ersten ansatz:

Code:
/* synchronizeDB.sql                                                 mk | 03.01.08
   --                                                                           --
   Synchronisiert eine Datenbank mit einer Master-Datenbank. Dabei werden fehlende
   Datensätze und Tabellen hinzugefügt, jedoch keine bestehenden Daten oder
   Tabellen gelöscht!
                                                            last update : 03.01.08
   ===============================================================================
*/

CREATE PROCEDURE Synchronize(@masterDB VARCHAR(200), @newDB VARCHAR(200))
AS
  DECLARE @command varchar(500)
  DECLARE @tblName varchar(200)

  DECLARE cur CURSOR FOR
  -- Wenn es sich um Tabellen handelt, dann xtype='u', bei Views xtype='v'
  SELECT [name] 
  FROM sysobjects 
  WHERE xtype = 'u' AND [name] LIKE 't%'

  
  OPEN cur
  
    FETCH NEXT FROM cur INTO @tblName
    WHILE @@fetch_status = 0 BEGIN
	  
	  /*
	  IF (EXISTS (SELECT * FROM @newDB.@tblName))
      ELSE
        SELECT *
        INTO @newDB.@tblName
        FROM @masterDB.@tblName		

      SET @command = 'drop View ' + @tblName

      EXECUTE(@command)
	  */
	  
    FETCH NEXT FROM cur INTO @tblName
    END -- WHILE

  CLOSE cur
  DEALLOCATE cur

-- PROCEDURE 

jegliche vorschläge und tipps sind mehr als willkommen!

tia
Bearbeitet von 3mind am 22.04.2008, 10:14

3mind

mimimi
Avatar
Registered: Sep 2004
Location: 1030
Posts: 1588
hm, keiner auch nur irgend einen ansatz? :(

Triple-X

Addicted
Avatar
Registered: Feb 2001
Location: Pregarten (OÖ)
Posts: 485
Zwischen Datenbanken kannst du mit USE wechseln
also: USE [DB Name]

Am besten wechselst du nach dem Öffnen des Cursors auf die neue Datenbank.

Was dir vielleicht auch noch hilft: "SELECT * FROM sys.tables" liefert eine Auflistung der vorhandenen Tabellen in einer Datenbank.

3mind

mimimi
Avatar
Registered: Sep 2004
Location: 1030
Posts: 1588
danke Triple-X ... das mit USE hab ich mittlerweile schon umgesetzt, und auch erste fortschritte erzielt. leider stellt mich besonders der ansatz der dynamischen sql-programmierung immer wieder vor schwierigkeiten, die besonders zeitaufwändig sind (meist ist es eh nur eine syntax-gschicht).

soweit funktionierts jetzt schonmal:

Code:
/* synchronizeDB.sql                                                 mk | 03.01.08
   --                                                                           --
   Synchronisiert eine Datenbank mit einer Master-Datenbank. Dabei werden fehlende
   Datensätze und Tabellen hinzugefügt, jedoch keine bestehenden Daten oder
   Tabellen gelöscht!
                                                            last update : 04.01.08
   ===============================================================================
*/

DECLARE @masterDB NVARCHAR(200)
DECLARE @syncDB NVARCHAR(200)
DECLARE @sql1 NVARCHAR(4000)
DECLARE @sql2 NVARCHAR(4000)
DECLARE @tblName NVARCHAR(200)

SET @masterDB = 'masterDB'
SET @syncDB = 'syncDB'


USE masterDB;
DECLARE cur CURSOR FOR
-- Wenn es sich um User-Tabellen handelt, dann xtype='u'
SELECT [name] 
FROM sysobjects 
WHERE xtype = 'U'

USE syncDB;
OPEN cur
  
  FETCH NEXT FROM cur INTO @tblName
  WHILE @@fetch_status = 0 
  BEGIN
    IF NOT EXISTS (SELECT * FROM sysobjects WHERE type = 'U' AND NAME LIKE @tblName)
      -- copy the table and all of its contents
      BEGIN  
        SET @sql1 = (N'SELECT * INTO ' + @tblName + ' FROM ' + @masterDB+ '..' + @tblName);
        EXEC(@sql1);
      END
    ELSE
      -- copy only missing values, don't overwrite anything
      BEGIN
        PRINT 'bla';
      END      
	  
    FETCH NEXT FROM cur INTO @tblName
  END -- WHILE

CLOSE cur
DEALLOCATE cur


schön wärs ja wenn man auch für das USE statement eine variable verwenden kann, funktioniert aber leider nicht :(

ica

hmm
Avatar
Registered: Jul 2002
Location: Graz
Posts: 9818
ich kenn deine anforderungen zwar nicht, aber schön schaut diese lösung nicht aus. wieso nicht eine slave datenbank einrichten? wird der sql server wohl unterstützen.

vorallem die konsistenz kann dir da schnell verloren gehen bei relationen.

3mind

mimimi
Avatar
Registered: Sep 2004
Location: 1030
Posts: 1588
also, zum einen: ms sql server 2000 wird eingesetzt, keine ahnung ob da was mit slave datenbank zu machen ist (hab ich auch noch nichts zu gelesen bisher).

zum anderen, der voraussichtliche einsatz:
man fährt mit masterDB + script zum kunden und gleicht dessen datenbank ab. daher ist die konsistenz kein relevanter argumentations-grund (weil eh nie beide auf einer maschine verwendet werden sollen).

3mind

mimimi
Avatar
Registered: Sep 2004
Location: 1030
Posts: 1588
zwar konnten nicht alle meine fragen beantwortet werden, aber setz es dennoch mal auf solved.

3mind

mimimi
Avatar
Registered: Sep 2004
Location: 1030
Posts: 1588
ich hab den thread mal wieder aufgemacht.

es wär mir nach wie vor ein großes anliegen eine möglichkeit zu finden wie man einen DB-wechsel im script (USE ...) mit einer variablen welche den namen der DB enthält durchführen kann. (also bspw. USE @otherDB )

vielleicht hat ja doch wer die zeit und das wissen mir zu helfen, wäre spitze!


\\edit: threadtitel geändert
Bearbeitet von 3mind am 22.04.2008, 10:14

DKCH

...
Registered: Aug 2002
Location: #
Posts: 3279
du kannst use zwar in einem exec-aufruf verwenden, es gilt aber nur für genau diesen aufruf.

Code:
SET @sql1 = (N'USE '+@db_name+' SELECT * INTO ' + @tblName + ' FROM ' + @masterDB+ '..' + @tblName);
EXEC(@sql1);

würd funktionieren...

prayerslayer

Oar. Mh.
Avatar
Registered: Sep 2004
Location: vorm Sucher
Posts: 4073
wennst dort premiummember bist/wen kennst ders is, hier stellt wer die gleiche frage.

hier steht eine lösung for free, hth.

USE darfst nämlich net verwenden in procedures/functions/triggers, wie du eh schon gemerkt hast :D

//damnit, DKCH!!

prayerslayer

Oar. Mh.
Avatar
Registered: Sep 2004
Location: vorm Sucher
Posts: 4073
whoho, kann es sein, dass in einer stored procedure
Code:
DROP TABLE @table;
auch nicht geht?

DKCH

...
Registered: Aug 2002
Location: #
Posts: 3279
jo, ich glaub für ddl-statements brauchst immer exec()

prayerslayer

Oar. Mh.
Avatar
Registered: Sep 2004
Location: vorm Sucher
Posts: 4073
tatsächlich... drop procedure schluckt er aber. ts... thx!
Kontakt | Unser Forum | Über overclockers.at | Impressum | Datenschutz