quando
Goto Top

SQL Befehl gesucht, der Daten aus Tabelle weitergibt

Hi zusammen,
bevor ich zum Problem komme, hier etwas Hintergrundwissen:

Ich bin Supporttechniker für EDV-Kassensysteme, unsere Software verwendet SQL-Datenbanken zur Speicherung aller Daten. Damit die Datenbanken schlank bleiben, erstellen wir nach einigen Jahren bei den Kunden Backups und kopieren nur die letzten 7 Jahre in eine leere DB.

Damit wir das nicht immer manuell machen müssen, hat unsere Programmierabteilung uns ein Tool dafür geschrieben, leider war in der ersten Version noch ein Fehler enthalten, nun haben wir bei manchen Datenbanken ein paar defekte Constraints, die ich gern rausnehmen würde.

Momentan ist die Programmierabteilung ausgelastet und für mich nicht erreichbar, darum schreibe ich hier rein.
Ich habe bereits eine Batch geschrieben, die mir alle Befehle ausführt und eine Auflistung der defekten Constraints in eine temporäre Tabelle speichert (siehe Bild).

Ich brauche nur Hilfe dabei, wie ich einen einfachen delete-Befehl erstellen kann, der diese Tabelle durcharbeitet.
In diesem Beispiel gibt es in der Tabelle Zahlungsmittel defekte Daten, die ich löschen kann.
Der Befehl für die erste Zeile wäre "delete from [dbo].[Zahlungsmittel] where [AbrGrp] = '1'", also delete from Spalte1 where Spalte 3.

Leider hab ich nirgends eine Möglichkeit gefunden, die Daten auszulesen und in einen Befehl zu verpacken, sodass er alles durchläuft (Sufu und Google konnten mir nicht weiterhelfen).

Ich bin wie geschrieben kein Programmierer, nur Techniker, der sich etwas mit Batch-Dateien und gängigen SQL Befehlen auskennt.
Hätte jemand eine Idee dazu?

Lg Quando
defekte constraints

Content-ID: 4100299926

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

Ausgedruckt am: 08.11.2024 um 11:11 Uhr

Miciti
Miciti 29.09.2022 um 15:00:12 Uhr
Goto Top
Vielleicht verstehe ich dich falsch, aber eine einfache DO WHILE Schleife die Zeile für Zeile durchgeht müsste dein Problem lösen?
https://sqlhints.com/tag/do-while-loop-in-sql-server/
ukulele-7
ukulele-7 29.09.2022 um 15:28:55 Uhr
Goto Top
Ich habe grade eine Antwort geschrieben aber wieder gelöscht weil erlich gesagt verstehe ich kein Wort.

Du hast "defekte" Constraints, was heißt das? Gibt es in der Datenbank überhaupt echte Constraints oder sind die nicht gesetzt weil die Anwendung darauf achtet (achten soll) das die Daten konsistent sind?

Ich vermute deine Daten sind also aktuell inkonsistent? In wie vielen Tabellen, einer? Warum genau sollen Datensätze gelöscht werden, die sind dann doch weg und nicht repariert oder hast du schon neue Datensätze in einer zweiten Tabelle die an deren Stelle treten sollen? Ich würde sagen dann wären UPDATE, MERGE oder DELETE und INSERT gefragt aber warum sollte man die Datensätze einzeln abarbeiten?
Crusher79
Crusher79 29.09.2022 um 15:43:47 Uhr
Goto Top
Hallo, ich steig auch nich ganz durch.

Vielen Daten reinziehen geht auch anders. Man muss nicht schleifen selber durchlaufen. Reicht wenn der Where-Part soweit passt. In Prinzip wie ein SELECT zu sehen. Alles was man sieht,kann man auch mit DELETE löschen.

Der Tabellen Schnipsel sagt auch nicht viel aus. Wenn es um [AbrGrp] = "1" geht - wäre es schon fast fertig. Vorausgesetzt die Spalte heißt dort auch so. Bzw. es gehört so zusammen... Da geht es schon los. Sonst wären wir bei JOINS oder verschachtelten SELECTs.

Darfst/ solllst du überhaupt? Würd eher den Entwicklern in den Hintern treten. Also du nicht - aber dein Chef.

[AbrGrp] = '1' hochzählen macht auch keinen Sinn. Sonst kommen ggf. falsche Zeilen unter die Räder. Ist es doch fortlaufend, würde man einfach so <7536 udn alles von 1-7535 wäre gelöscht.

ABER alleine die fehlerhaften Constraints etc. sind unschön. Da wäre es ratsamer wenn es die Entwickler selb machen....

Was ist eig. mit der Fiskalisierung? Wenn da nachher was nicht stimmt, hast du größere Probleme.

mfg Crusher
Quando
Quando 29.09.2022 um 15:58:16 Uhr
Goto Top
Danke für eure Antworten, sorry dass ich mich da etwas umständlich ausgedrückt habe.

Das Tool der Programmierung hat alle Abhängigkeiten deaktiviert, damit die Daten ohne Probleme in eine neue DB kopiert werden konnten. Anschließend wurden die Abhängigkeiten wieder gesetzt, manche Trigger waren aber noch disabled. Die konnte ich mit dem Befehl

SELECT
[so].[name] AS [trigger_name],
OBJECTPROPERTY([so].[id], 'ExecIsTriggerDisabled') AS [disabled]
FROM sysobjects AS [so]
INNER JOIN sysobjects AS so2 ON so.parent_obj = so2.Id
WHERE [so].[type] = 'TR'

anschauen.

Hiermit aktiviere ich die Trigger und überprüfe die constraints:

EXEC sp_MSforeachtable @command1="ALTER TABLE ? CHECK CONSTRAINT ALL"
EXEC sp_MSForEachTable 'ENABLE TRIGGER ALL ON ?'

Dann erstelle ich eine temporäre Tabelle und kopiere die Daten rein:

CREATE TABLE Constraintstatus (
[Spalte1] varchar(200),
[Spalte2] varchar(200),
[Spalte3] varchar(200)
)
INSERT INTO Constraintstatus
EXEC ('DBCC CHECKCONSTRAINTS WITH ALL_CONSTRAINTS')

Es betrifft meistens dieselben 3 Tabellen, bei dieser DB hier z.B. nur eine Tabelle, manchmal sind auch nur 2-3 Artikel betroffen, darum können diese Einträge ohne Bedenken gelöscht werden. Anschließend lasse ich die Datenbank nochmal updaten, damit fehlende Einträge wieder angelegt werden.

Eine Schleife zur Abarbeitung der Befehle zu bauen ist kein großes Problem, nur habe ich keinen Plan, wie ich den Inhalt der 1. Spalte in einen delete-Befehl einsetze mit where der 3. Spalte, ohne dass ich den Inhalt im Voraus kenne, dort scheitert es bei mir leider.
Quando
Quando 29.09.2022 um 16:02:51 Uhr
Goto Top
@Crusher Danke für die Info, die Tabellenschnipsel sind genau so zu verwenden, 1:1 umsetzbar.
Ich darf und soll es machen, da die Einträge bei zukünftigen Updates sonst Probleme machen könnten, dem Entwickler hab ich schon in den Hintern getreten ^^.

Wegen der Fiskalisierung gibt es keine Bedenken, da keine Tabellen mit Journalen oder ähnlichen Dingen betroffen sind, darauf hab ich extra geachtet.
Quando
Quando 29.09.2022 um 16:12:49 Uhr
Goto Top
Hier wäre ein Beispiel einer Datenbank, wo es ein paar Artikel dazu erwischt hat.
defekte constraints 2
ukulele-7
ukulele-7 29.09.2022 aktualisiert um 16:34:51 Uhr
Goto Top
Zitat von @Quando:

EXEC sp_MSforeachtable @command1="ALTER TABLE ? CHECK CONSTRAINT ALL"
EXEC sp_MSForEachTable 'ENABLE TRIGGER ALL ON ?'
Ich musste es selbst erstmal lesen um es zu glauben, ich hätte erwartet das es hier schon knallt:
WITH CHECK | WITH NOCHECK Specifies whether the data in the table is or is not validated against a newly added or re-enabled FOREIGN KEY or CHECK constraint. If not specified, WITH CHECK is assumed for new constraints, and WITH NOCHECK is assumed for re-enabled constraints.
Zu deinem Vorgehen:
Spalte3 deiner Auswertung versucht den Datensatz zu beschreiben, der den Constraint mit dem Namen in Spalte2 verletzt. Was genau der Constraint eigentlich für Bedingungen aufstellt geht daraus nicht hervor. Diese ArtikelIndex Splate sieht komisch aus, welche Funktion hat die, ist die Teil des Primary Key?

Um all diese Datensätze zu löschen müsstest du mit dynamischem SQL arbeiten. Besser als eine Schleife wäre ein Cursor der dann die Werte deiner Auswertungstabelle als DELETE String zusammen setzt und per EXEC(String) aus der Tabelle entfernt, tatsächlich Datensatz für Datensatz. Aber: Auch hier können neue Contraints verletzt werden, wenn z.B. ein zu löschender Datensatz von einem anderen Datensatz referenziert wird. Da alle Constraints aktiv sind muss es hier wieder knallen.

Außerdem stören mich nach wie vor zwei Dinge:
1) Keiner befasst sich mit der Ursache der kaputten Daten. Wenn die Constraints nur für eine Migration deaktiviert wurden, warum sind die Daten dann nicht mehr konsistent? Wohl wegen der fehlenden Trigger, aber lässt sich das reproduzieren / nachvollziehen?
2) Ja Löschen "behebt" eventuell die Inkonsistenz. Aber die Datensätze fehlen dann doch trotzdem!? Ich würde die tatsächlich "reparieren" wollen.
Quando
Quando 29.09.2022 um 16:45:03 Uhr
Goto Top
Danke für deine Antwort ukulele.

Die ArtikelIndex-Spalte ist kein Primärschlüssel, sie ist immer 1, bei allen Artikeln.

Die Artikel im letzten Bild kann die Kundschaft über die Software gar nicht mehr sehen, da sie keine Abhängigkeiten mehr haben, die sind eh schon "kaputt". Hier hab ich den krassesten Fall genommen, den ich bei den Kunden gefunden habe, 26 Zeilen sind betroffen, davon die meisten von ein paar wenigen Artikeln.

Die paar Artikel kann die Kundschaft wieder selbst anlegen, bzw. haben sie eh schon, da das Tool etwa 3 Monate lang schon benutzt wurde, aber nur bei wenigen Kundschaften.

Einträge wie z.B. die Tabelle Zahlungsmittel werden beim erneuten Updaten der Datenbank wiederhergestellt.

Anschließend überprüfe ich die Constraints erneut, bisher waren hinterher nie mehr Probleme enthalten.
ukulele-7
Lösung ukulele-7 29.09.2022 aktualisiert um 16:56:03 Uhr
Goto Top
DECLARE 
    @query VARCHAR(1000),
    @saplte1 VARCHAR(200),
    @saplte3 VARCHAR(200)

DECLARE cursor1 CURSOR
FOR SELECT 
        spalte1, 
        saplte3
    FROM 
        Constraintstatus;

OPEN cursor1;

FETCH NEXT FROM cursor1 INTO 
    @spalte1, 
    @saplte3;

WHILE @@FETCH_STATUS = 0
    BEGIN
        SET @query = 'DELETE FROM ' + @spalte1 + ' WHERE ' + @Spalte3;  
EXEC(@query);
FETCH NEXT FROM cursor1 INTO 
    @spalte1, 
    @saplte3
    END;

CLOSE cursor1;

DEALLOCATE cursor1;
Quando
Quando 29.09.2022 um 17:03:37 Uhr
Goto Top
Ukulele, du bist der Hammer, so funktioniert es einwandfrei :D :D

Ich möchte allen für die Mühe danken, die Lösung ist gefunden, ihr seid eine klasse Community :D

Glg Quando