Abfrage und UPDATE mehrerer Tabellen und Felder

christrue

Benutzer
Beiträge
5
Hallo,

da ich Anfänger bin, überfordert mich folgende Sache.

Ich habe eine Datenbank mit vielen Tabellen. Ein Feld in einem Teil dieser Tabellen (nicht alle) möchte ich ändern.
Die zu ändernden Tabellen haben folgende Namenkonvention: dbo.SYS_(irgendwas)_DETAIL, also z.B. dbo.SYS_BOLT_DETAIL.

Das Feld, welches ich ändern möchte, hat den entsprechenden Namen: SYS_(irgendwas)_PARENTEXPRESSION, also nach dem Tabellenbeispiel oben wäre das SYS_BOLT_PARENTEXPRESSION.

Wie kann ich also eine Änderung dieser Felder durchführen, welche ja nur im hinteren Bereich eine Namensähnlichkeit aufweisen, die der zugrundeliegenden Tabelle entspricht ?

Ich arbeite mit dem MSSQL2008-Express-Server und dem dazugehörigen Management Studio.

Diese Abfrage ist momentan zuviel für mich. Ich schlage mich momentan eher nur mit SELECT-Anweisungen herum (verschachtelt, gruppiert und sortiert), das ist ja ungefährlich.
Ich hoffe, mir kann da jemand helfen.

Christian
 
Werbung:
AW: Abfrage und UPDATE mehrerer Tabellen und Felder

Hallo christrue,

WICHTIG: In der Testphase immer mit einem Backup der Daten arbeiten!

mit reinem ANSI-SQL wird das ein bischen kompliziert.

Da wir uns hier aber im T-SQL bewegen lässt sich da doch einiges machen :).

Spaltennamen in SELECT, INSERT, DELETE und UPDATE Statements dynamisch zu ändern ist nicht so einfach.

Zuerst eine Spieltabelle erzeugen:
Code:
CREATE TABLE SYS_BOLT_DETAIL (SYS_BOLT_PARENTEXPRESSION nvarchar(255))
GO

Und Spieldaten einfügen:

Code:
INSERT INTO SYS_BOLT_DETAIL(SYS_BOLT_PARENTEXPRESSION)VALUES('Testdaten')

Das Script erzeugt eine Prozedur:

Code:
create procedure upd
@TN nvarchar(255), -- Parameter der angegeben werden muss.
@UV as nvarchar(255), --Parameter der angegeben werden muss.
@WC as nvarchar(255)= '',-- Standardwert wenn nichts angegeben wird
@WV as nvarchar(255)= ''-- Standardwert wenn nichts angegeben wird
as
declare @UC nvarchar(255) -- Update_Column wird anhand des Tabellennamens erzeugt
declare @String as nvarchar(1000)
-- Das Ganze besteht nur aus den 4 Zeilen
    set @UC = RIGHT (@TN,LEN(@TN) - CHARINDEX ('_',@TN) )
    set @UC = 'SYS_' + LEFT(@UC,CHARINDEX ('_',@UC)-1) + '_PARENTEXPRESSION'
    -- Jetzt hat man den Spaltennamen zu dem Tabellennamen
    -- und kann das ganze mit einer Update-Anweisung zusammenbauen...
    if @WC = ''
     begin -- ohne Where-Klausel
      set @string = 'UPDATE [' + @TN + '] SET [' + @UC + '] = ' + '''' + @UV + ''''
     end
    else
     begin -- mit Where-Klausel
      set @string = 'UPDATE [' + @TN + '] SET [' + @UC + '] = ' + '''' + @UV + '''' + ' WHERE [' + @WC + '] = ' + '''' + @WV + ''''
     end
    -- ...und Ausführen...
    exec sp_executesql @string
 
return 0 -- wieder mal keine ordentilche Fehlerbehandlung :-)
GO

Achtung: Datenbnank-Kontext mit USE <Datenbankname> ändern
sonst steht das Script in der master-db.

Aufruf der Prozedur:

Code:
exec upd <Tabellenname>, <Update_Wert>,[<Where_Splate>],[Where_Wert]

z.B.:
Code:
exec upd 'SYS_BOLT_DETAIL', 'Testwert'

Wobei die Werte in eckigen Klammern optional sind.

Das Ergebnis mit:
Code:
SELECT SYS_BOLT_PARENTEXPRESSION FROM SYS_BOLT_DETAIL

Ergibt:

SYS_BOLT_PARENTEXPRESSION
Testwert

abfragen.

Ich mache das mit SQL2000. Bis jetzt hatte ich noch nicht die Zeit mich mit den neuen Funktionen von 2008 vertraut zu machen.
Vielleicht hat jemand für den SQL 2008 eine bessere Lösung die ohnen Prozeduren auskommt?

Beinahe vergessen: Ich denke du willst das auf alle Tabellen in der DB anwenden. Hier also die Prozedur die alle Tabellen durchläuft.

Code:
create procedure Get_Tables
as
declare @ID as int
declare @TN as nvarchar(255)
select @ID = MIN([id]) from sysobjects where type = 'U' -- hier hat man noch die Möglichkeit die Tabellen zu filtern
while @ID IS NOT NULL
 BEGIN
 
  SELECT @TN = [name] from sysobjects where id = @id -- hier hat man noch die Möglichkeit die Tabellen zu filtern
 
  PRINT @TN -- Hier kann man dann die Prozedur upd aufrufen wenn man alle Tabellen durchlaufen will
  SELECT @ID = MIN([id]) from sysobjects where type = 'U' AND [id]>@ID -- hier hat man noch die Möglichkeit die Tabellen zu filtern
 END
return 0
GO

Nochmal ein Warnung zum Schluss: Wenn die Prozeduren richtig aufgerufen werden, ändern sie ohne Rückfrage alle Tabellen und Spalten die sie finden. Wenn keine Where-Klausel angegeben wird werden alle Zeilen der Spalten geändert. Also Backup machen oder noch besser: Kopie der DB anlegen und auf der Kopie testen bis alles 100% läuft.

Gruß Charly
 
AW: Abfrage und UPDATE mehrerer Tabellen und Felder

Hallo Charly,

uff, danke. Das ist ja nun wirklich nichts für Anfänger.

Allerdings ist mir bei Deiner Bemerkung "Spaltennamen in SELECT, INSERT, DELETE und UPDATE Statements dynamisch zu ändern ist nicht so einfach" aufgefallen, das wir uns (aufgrund meiner ungenauen Beschreibung) wahrscheinlich missverstanden haben. Darum frage ich lieber nochmals nach, ehe ich Deine Funktion ausprobiere. Es ging nämlich nicht um das Ändern der Spaltennamen.

Also, ich wollte zunächst einmal alle Felder einer Spalte (welche in der Tabelle mit "SYS_" anfängt und mit "_PARENTEXPRESSION" endet) in einer Tabelle (welche mit "dbo.SYS_" anfängt und auf "_DETAIL" endet) in einem Rutsch auf z.B. NULL setzen lassen.
Da es aber eine Menge dieser Tabellen (z.B. dbo.SYS_BOLT_DETAIL, dbo.SYS_NUT_DETAIL usw.) mit jeweils dazugehöriger Spalte (z.B. SYS_BOLT_PARENTEXPRESSION, SYS_NUT_PARENTEXPRESSION usw.) gibt, brauche ich dann zusätzlich eine Funktion, die das Ganze für mehrere Tabellen und nicht nur einer durchläuft.

Entschuldige bitte, wenn ich Dir Deine Zeit mit missverständlichen Aussagen gestohlen habe. Wenn also Deine Prozedur oben genau das macht, was ich (wie ich hoffe) ausführlich beschrieben habe, dann ist es gut (ich habe nämlich noch Schwierigkeiten, auf einen Blick zu sehen, was eine Prozedur genau macht).
Ansonsten wäre es sehr nett, wenn Du mir auch dafür eine Lösung geben könntest.

Trotz zweier gelesener Bücher über SQL bin ich nicht unbedingt besser geworden. Es fehlt, glaube ich, ein Lehrer, der auf Deine Fragen eingeht, sonst wird das Ganze wohl nichts.

Christian
 
AW: Abfrage und UPDATE mehrerer Tabellen und Felder

Hallo christrue,

Entwarnung: Der Spaltenname wird nicht geändert. Das wäre eine ALTER TABLE-Anweisung.
Das 'dynamisch' bedeutet hier soviel wie: Der Spaltenname für das UPDATE muss zur Laufzeit erzeugt werden.

Kurze Anmerkung zu Prozeduren: Wenn du die Scripts ausführst werden erstmal nur die Prozeduren erzeugt. Die Prozeduren sind jetzt fest in der Datenbank gespeichert (wie eine Tabelle oder eine Sicht).

Erst durch aufrufen der Prozeduren z.B. durch ein Programm werden die Befehle ausgeführt.

Es sind 2 Prozeduren. Die machen (fast) genau das was du willst.

1.) Die Prozedur get_Tables gibt alle Benutzertabellen einer Datenbank zurück (jedenfalls alles was ein 'U' im Typ hat).

2.) Die Prozedur upd (sorry für die kurzen Namen in meinen Scripts) Erzeugt ein Update-Statement und führt es aus.

zu 1.) zwischen den Befehlen BEGIN und END lassen sich belibig viele Komandos für jede gefundene Tabelle ausführen.

In deinem Fall würde hier also die Prozedur upd stehen. Das PRINT gibt lediglich den Wert aus den die Variablen @TN aktuell hat.

Die Variable @TN enthält also immer den nächsten Tabellennamen.

Damit du nicht alle Tabellen deiner Datenabbank durchläufts sondern nur die die du haben willst. brauchen wir noch eine WHERE-Klausel

äh, denk denk. Wir sollten das besser mit einer IF-Anweisung filtern

so z.B.

Code:
-- Das steht zwischen dem BEGIN und dem END der WHILE-Schleife
  SELECT @TN = [name] from sysobjects where id = @id
 
  IF @TN LIKE '%SYS_%_DETAIL'
   BEGIN
    PRINT @TN
   END
  SELECT @ID = MIN([id]) from sysobjects where type = 'U' AND [id]>@ID

Das gibt dann nur die Tabellen aus die du brauchst.

zu 2.) Die Prozedur erzeugt anhand des Tabellennamen die zu aktualisierende Spalte und das dazugehörige UPDATE-Statement.

Je nachdem was für Parameter du der Prozedur übergibst erzeugt Sie ein UPDATE mit oder ohne WHERE. ACHTUNG: Es werden so gut wie keine Fehleingaben abgefangen. Also in der Get_Table alles richtig an upd übergeben.

Wenn du alle Felder einer Spalte auf NULL setzen willst ändern wir die Prozedur ein bischen ab. Setze einfach noch den folgenden Codeschnipsel vor die Zeile mit dem ELSE

Code:
    else if @UV = 'NULL'
     begin
       set @string = 'UPDATE [' + @TN + '] SET [' + @UC + '] = NULL'
     end

Wenn du jetzt dem Parameter @UV den String-Wert 'NULL' übergibst werden alle Zeilen auf NULL gesetzt.

Der vollständigkeit halber noch die Zeile die in die Prozedur Get_Tables eingefügt werden muss:

Code:
EXEC upd @TN, 'NULL'

Kurz testen ... OK kann man lassen.

So das war nur eine Zeile. Die andern 10.000 kannst du auf NULL setzten.:D

Nur zur Sicherheit: Bitte nicht auf Produktivsystemen testen.

Gruß Charly
 
AW: Abfrage und UPDATE mehrerer Tabellen und Felder

Kleine Korektur:

Nur falls es noch andere Benutzer auser dbo mit den gleichen Tabellen gibt:

aus:
Code:
IF @TN LIKE '%SYS_%_DETAIL'
wird dann:

Code:
IF @TN LIKE 'dbo.SYS_%_DETAIL'
Gruß Charly
 
AW: Abfrage und UPDATE mehrerer Tabellen und Felder

Hallo Charly,

mann, das ist ja ein tolles Forum. Solche ausführlichen Beschreibungen und Programmcodes sieht man selten.

Ich danke Dir wirklich vielmals und werde das mal (an einer Testdatenbank) ausprobieren. Mit dieser Anleitung ja kein Problem.

Und auch wenn man das eigentlich in Foren nicht machen sollte, aber hier noch eine Frage:
weißt Du, wo es Kurse in SQL gibt, welche man nicht mit dem Gefühl verlässt, seine Zeit oder das Geld verschwendet zu haben ?
Du hast das ja sicherlich auch irgendwo erlernt (oder war das autodidaktisch erworbenes Wissen) ?!

Zwei Bücher zu dem Thema und ein E-Book beantworten sicherlich die Standardfragen, aber eben nicht die im meinem Umfeld befindlichen Datenbankkonstrukte.

Also, danke nochmals und grüße aus (dem regnerischen) Berlin,

Christian
 
AW: Abfrage und UPDATE mehrerer Tabellen und Felder

Hallo,

da hat sich doch tatsächlich schon ein Fehler eingeschlichen.

Die Prozedur Get_Tables gibt die Tabellennamen ohne dbo. aus.

Also den letzten Kommentar von mir einfach ignorieren und falls gewünscht in der Prozedur upd die Update-Anweisung abändern.

aus

Code:
[FONT=Verdana][COLOR=black][COLOR=black][FONT=Verdana]set @string = 'UPDATE [' + @TN + '] SET [' + @UC + '] = NULL'[/FONT][/COLOR]
[/COLOR][/FONT]
wird

Code:
[FONT=Verdana][COLOR=black][COLOR=black][FONT=Verdana]set @string = 'UPDATE [dbo.' + @TN + '] SET [' + @UC + '] = NULL'[/FONT][/COLOR]
[/COLOR][/FONT]


genauso mit den anderen Update-Zeilen verfahren.


Ich mache mal ein neues Thema unter Angebote auf. Da kann sich dann jeder im Forum ungestraft über Kurse und Bücher unterhalten. Ich selber habe nur über viel Praxis, Bücher, Kollegen und Foren gelernt und keine Kurse besucht. Ich halte einen guten Kurs aber für die schnellere Art etwas zu lernen.

Gruß Charly
 
AW: Abfrage und UPDATE mehrerer Tabellen und Felder

Hallo Charly,

wow, mit Fehlerkorrektur für die eigenen Codes im Nachhinein....hehe, zum Glück hatte ich gestern noch keine Zeit für´s Ausprobieren, sonst wäre ich schon steckengeblieben.

Ich danke Dir dafür und auch für den Kommentar unter Angebote. Das Buch von Wolfgang D. Misgeld kenne ich noch nicht. Leider scheint es aber nicht mehr aufgelegt worden zu sein.

Grüße,

Christian
 
AW: Abfrage und UPDATE mehrerer Tabellen und Felder

Hallo,

Naja, so toll war das gestern dann doch nicht. Nach 2 Stunden Schlaf sollte mann nicht versuchen seine Fehler zu korigieren.:eek:

also nochmal:

Code:
set @string = 'UPDATE [dbo].[' + @TN + '] SET [' + @UC + '] = NULL'
Gruß Charly

PS: Hoffe das wars jetzt:D
 
Werbung:
Zurück
Oben