Hallo Daniel,
Daniel Barisch <Daniel Barisch> schrieb ...
Post by Gleich mal vorneweg.... Ich möchte hier niemandem auf den Schlips
treten oder so.
ich trage keine Schlipse, also kann mir nie auf denselben treten ;-).
Post by Ich will hier sicher nicht alles als "Theorie" abtun! Zum einen, weil
die DB nicht auf meinem Mist gewachsen ist, zum anderen (im
speziellen Fall der Text-PK's) aber auch,
Wenns die Anwendungen hergeben, würde ich würde zwar wegen
"Sued" <-> "Süd" für eine separate Bezeichnungsspalte plädieren,
denn das ist schon etwas krude (und eigentlich teuer mehr dazu unten)...
Und evtl. gäbe es über Sichten etc. die Möglichkeit das vor alten
"dummen" Anwendungen zu verstecken.
Und ein hier irgendwo gebrachtes Argument bezüglich der paar Joins
ziehen bei heutigen Datenbanken eher wenig.
Und wenn man eine Anwendung migriert, sollte man das meiner Meinung
nach, auch bei den Frontends versuchen. Und neue Erkenntnisse
bei der Gelegenheit einfliessen lassen.
Aber sparen wir uns das für eine andere Diskussion für später auf.
Post by weil ich GUID-Schlüssel einfach nicht für sinnvoll/erforderlich halte,
wenn durch das DBMS die ref. Integrität sichergestellt werden kann
(an dieser Stelle mal abstrahiert von der tatsächlichen Umsetzung).
Wiederholt: Man benötigt (hier) keine Guids.
Die im übrigen häufig von Entwicklern am meisten "geliebt" werden,
die mit ADO.NET etc. Probleme haben. (Und da gilt: siehe unten).
Da müsste mir jemand schon mehr als mit "wirtschaftliche Lösung"
als Begründung daher kommen, wie z. B. Replikation, *echt verteilte*
Anwendung usw.
Post by Post by Elmar BoyePost by Um das am schnellsten zu realisieren würde mir als erstes folgendes
einfallen...
UPDATE Adressgruppen SET Name = Replace(Name, 'Sued', 'Süd)'
Und das heisst dann: Wo ist da ein Problem...
UPDATE dbo.Adressgruppen SET Name = Replace(Name, 'Sued', 'Süd')
-- wir gehen stillschweigend von genügend Platz aus
UPDATE dbo.Banken SET Name = Replace(Name, 'KSK-', 'Volkcenter ')
SELECT * FROM dbo.Adressen
GO
Dann habe ich Adressen, wo immer noch die alte Gruppe/Bank drin
steht,
Hast Du Dir die Ausgabe überhaupt mal angeguckt???
Post by weil unsere (AFTER-) UPDATE-Trigger im jetzigen Stand nur den
PK-Wert des letzten Datensatzes aus der inserted und deleted Tabelle
auslesen und mit diesen die Aktualisierungsweitergabe durchführen.
Wenn Du Deine Trigger wegwirfst und durch die FOREIGN KEY Einschränkungen
wie im Beispiel ersetzt (übrigens so wie in Access/Jet), sind die
Adressen gleich mit korrigiert.
Umd das gefahrlos für Deine vollständigen Daten auszuprobieren
verwende eine Kopie in tempdb wie auch das Beispiel.
Post by Wird jeweils nur ein Datensatz geändert, dann steht in diesen temp.
Tabellen ja auch jeweils nur ein Datensatz drin. Werden mehrere
Datensätze geänderten dann erwische ich mehr oder weniger zufällig
zwei PK-Werte, die (wie ich gelernt habe), streng genommen nicht mal
zusammenpassen müssen (alt -> neu).
Post by Elmar BoyeMit Triggern gehts genauso...
Den Satz hätte ich nicht "..." sollen, da er aus dem Zusammenhang
gerissen ist (er wurde vor dem Erstellen des UPDATE Beispiel geschrieben).
Post by Ich sehe bisher keine Möglichkeit, einen eindeutigen Zusammenhang
zwischen den einzelnen Datensätzen in Detail-Daten-, inserted- und
deleted-Tabelle herzustellen, so dass ich Datensätze mit dem alten Wert
(aus deletetd) in der Detail-Datentabelle selektieren und mit dem
neuen Wert (aus inserted) aktualisieren könnte.
Denn gibts nicht. Somit wäre das obige UPDATE mit jeder Form
von Trigger nicht umsetzbar. Der Trigger müsste wie schon gezeigt
Änderungen mehrerer Zeilen verweigern.
Das könnte nur eine Prozedur leisten, die jedoch ebenso mit
beliebigem Clientcode (ADO/ADO.NET geschrieben sein könnte).
Exemplarisch für
-- UPDATE dbo.Adressgruppen SET Name = Replace(Name, 'Sued', 'Süd')
DECLARE @name varchar(30)
DECLARE AdressgruppenCursor CURSOR
LOCAL STATIC -- STATIC bzw. INSENSITIVE muss sein!
FOR SELECT Name FROM dbo.Adressgruppen
WHERE name LIKE '%Sued%'
OPEN AdressgruppenCursor
FETCH NEXT FROM AdressgruppenCursor INTO @name
WHILE @@FETCH_STATUS = 0
BEGIN
UPDATE dbo.Adressgruppen
SET Name = Replace(Name, 'Sued', 'Süd')
WHERE name = @name
FETCH NEXT FROM AdressgruppenCursor INTO @name
END
CLOSE AdressgruppenCursor
DEALLOCATE AdressgruppenCursor
GO
Ja ich weiss: Viel Holz für fast nichts...
Und nochmals NEIN: Im Trigger geht das nicht.
Und die Kopierlösung wäre zwar insofern besser in SQL geschrieben
als sie aus INSERT ... SELECT und späterem DELETE bestände...
aber würde dann über Anweisungen für alle beteiligten Tabellen
(also Adressen + Adressgruppen, Adressen + Banken)
Was in realen Datenbank schon einige Dutzend bis Hunderte
Anweisungen werden können - naja mit der Cursor nehme man
alles mal Zwanzig...
(Kein Beispiel - ich muss jetzt was essen)
Und auch das geht nicht mit einem Trigger.
Allerdings könnte der FOREIGN KEY ohne UPDATE CASCADE eine
leichtsinnige Änderung des Primärschlüssel verhindern.
Post by Post by Elmar BoyeJa und ich weiss, dass es bei zirkulären Beziehungen so nicht
mehr geht, nur das gibt das Dein Beispiel nicht her.
Zirkuläre Bezüge kommen bei uns nicht vor.
Und so würde ich zu den FOREIGN KEY CONSTRAINTS mit UPDATE/DELETE
CASCADE greifen. Denn nur damit geht das UPDATE da oben - also
über mehrere Zeilen.
Und im Trigger - wenn überhaupt noch notwendig - nur für Aufgaben,
die kein Constraint (siehe auch den CHECK im Beispiel) übernehmen kann.
Post by Post by Elmar BoyeNa und? Ich denke, Du bist ein Entwickler, das sind endlich
mal Herausforderungen ;-)
Herausforderungen die ich aus technischer Sicht sehr gern annehmen
würde, aber aus wirtschaftlicher (Zeit/Kosten) und praktischer
(Fremdsystem!) Sicht nicht angehen kann.
Nimms mir nicht übel: Diese Sätze höre ich (leider) meistens
immer dann, wenn die Leute von den technischen Möglichkeiten
zu wenig Kenntnis haben. Und das dazu führt, dass eine Lösung
zuviel Zeit kostet und so als "unwirtschaftlich" eingestuft wird.
Nur ist das ein Verdrehen von Ursache und Wirkung.
Wobei: Gespart wird wenig bis gar nichts, denn am Ende schreibt (fällt)
man das Holz (mit obigem Cursor) an anderer Stelle, was viel Zeit
(Geld) kostet.
Wobei: Wenn man das oben angesprochene Aufteilen in eine Anzeigespalte
und Primärschlüssel betrachtet, was ein Entwickler genau deswegen
vornehmen sollte - siehts erst richtig traurig aus.
(Und NEIN: das muss immer noch keine Identity, Guid Spalte beim
Primärschlüssel sein, notfalls kann man auch mit "Sued-A" (PK)
= "Südbayern rechts von Passau" (Anzeige) leben).
Post by Post by Elmar BoyeDamit das mit (damaligen) nicht immer passiert empfehle ich
etwas mehr Lektüre...
Da bin ich ja gerade dabei, aber es geht nun mal nicht alles auf
einmal. Und ihr helft mir nunmal immer so nett, das verwöhnt...
Kontinuierliche Weiterbildung hilft am ehesten...
(Ich mache das auch schon bald 20 Jahre und hatte anfangs von
relationalen Datenbanken auch herzlich wenig Ahnung, habe auch
kein Informatik Diplom...)
Gruss
Elmar