Insert in mehrere Schritten teilen

norwegen60

Benutzer
Beiträge
12
Hallo zusammen,

ich habe eine Tabelle, in der viele Messwerte in einem Memo abgespeichert wurde. Diese Memodaten möchte ich per folgendem SQL in eine "saubere" Tabelle aufsplitten, in der jeder Messwert in einem eigenen Feld liegt
Code:
 insert into zzRunProtocol (RelDataSet, [Type], ValueGes, TimePoint, Value)
select RelDataSet, [Type], SUBSTRING(Memo1, Number+1, 30) as [Value],
SUBSTRING(Memo1, Number+1, CHARINDEX(',', SUBSTRING(Memo1, Number+1, 30))-1),
SUBSTRING(Memo1, Number+CHARINDEX(',', SUBSTRING(Memo1, Number+1, 30))+1, CHARINDEX(';', SUBSTRING(Memo1, Number+1, 30)) - CHARINDEX(',', SUBSTRING(Memo, Number+1, 30))-2)
from MemoStore
 join zzNumbers on (number <= LEN(Memo1)) and (SUBSTRING(Memo1, Number, 1) = ';') and (len(SUBSTRING(Memo1, Number+1, 30))>3)
Problem ist, das die Tabelle mehrere tausend Sätze enthalten kann und in dem Memo noch mal mehrere tausend Einzelwerte liegen können. Das würde bedeuten, dass mit dem Insert auf einmal mehrere Mio. Datensätze eingefügt würden.

Mit folgendem Ansatz könnte ich das jetzt in kleinere Schritte aufsplitten.
Code:
BEGIN TRANSACTION	                
-- Messwerte aus der bestehenden Tabelle MemoStore auslesen, in Einzelwerte extrahieren und in zzRunProtocol speichern 
insert into zzRunProtocol (RelDataSet, [Type], ValueGes, TimePoint, Value)
select RelDataSet, [Type], SUBSTRING(Memo1, Number+1, 30) as [Value], 
SUBSTRING(Memo1, Number+1, CHARINDEX(',', SUBSTRING(Memo1, Number+1, 30))-1),
SUBSTRING(Memo1, Number+CHARINDEX(',', SUBSTRING(Memo1, Number+1, 30))+1, CHARINDEX(';', SUBSTRING(Memo1, Number+1, 30)) - CHARINDEX(',', SUBSTRING(Memo, Number+1, 30))-2)
from MemoStore
join zzNumbers on (number <= LEN(Memo1)) and (SUBSTRING(Memo1, Number, 1) = ';') and (len(SUBSTRING(Memo1, Number+1, 30))>3)              
where RelDataSet between 1 and 300
COMMIT

BEGIN TRANSACTION	                
-- Messwerte aus der bestehenden Tabelle MemoStore auslesen, in Einzelwerte extrahieren und in zzRunProtocol speichern 
insert into zzRunProtocol (RelDataSet, [Type], ValueGes, TimePoint, Value)
select RelDataSet, [Type], SUBSTRING(Memo1, Number+1, 30) as [Value], 
SUBSTRING(Memo1, Number+1, CHARINDEX(',', SUBSTRING(Memo1, Number+1, 30))-1),
SUBSTRING(Memo1, Number+CHARINDEX(',', SUBSTRING(Memo1, Number+1, 30))+1, CHARINDEX(';', SUBSTRING(Memo1, Number+1, 30)) - CHARINDEX(',', SUBSTRING(Memo, Number+1, 30))-2)
from MemoStore
join zzNumbers on (number <= LEN(Memo1)) and (SUBSTRING(Memo1, Number, 1) = ';') and (len(SUBSTRING(Memo1, Number+1, 30))>3)              
where RelDataSet between 301 and 600
COMMIT
...
Wie aber kann ich das so automatisieren, dass ich nicht bis zur höchsten RelDataSet Einzelschritte programmieren muss. Am liebsten wäre mir, dass ich zuerst über (RelDataSet max /Schrittweite) die Anzahl der SQL-Schritte festlege und die dann über eine Schleife automatisch durchlaufe.

Oder hat jemand noch einen besseren Ansatz?

Vielen Dank
Gerd
 
Werbung:
Also eine Schleife macht ja im Gegensatz zu einem einzigen Insert nicht unbedingt mehr Sinn, du kannst die Schleife nicht pausieren oder unterbrechen. In beiden Fällen würde die Aufgabe in einem Stück erledigt werden, die Schleife könnte höchstens zwischendurch Meldungen über den Fortschritt zurück geben.

Ich würde dem Quelldatensatz ein weiteres Atribut "verarbeitet" zuordnen. Dann würde ich ein Statement schreiben, das die ersten 10, 100 oder egal wie viele Datensätze nimmt und durchläuft (das kann ein einziger Select oder eine Schleife sein) und dann "verarbeitet" auf 1 setzt. Wenn das Script bereits verarbeitete Datensätze ignoriert kannst du es immer wieder ausführen bis alles fertig ist.
 
Daran habe ich auch schon gedacht. Problem ist, dass ich die Quelldaten wenn möglich nicht anfassen soll. Aber selbst wenn, wie mache ich es dann, dass die Daten erst gekennzeichnet werden, wenn sie auch wirklich verarbeitet sind und wie bau ich die Schleife auf, dass sie sich so lange wiederholt, bis alles abgearbeitet ist. Zumal wenn du sagst, dass die Daten auch in einer Schleife in einem Stück abgearbeitet würden.

Das versteh ich aber auch nicht ganz. Mit meinen "manuellen" Schritten hat der Übertrag funktioniert, während es beim Abarbeiten in einem Stück zu einem Timeout oder Speicherüberlauf kam. Blöderweise muss ich ein Tool verwenden, dass mir keine Rückmeldung gibt, weshalb die "in einem Stück-Lösung" abbricht. Ich habe nur nach einigem Rumprobieren herausbekommen, dass die Filterlösung geht, die am Stück-Lösung nicht.
 
Mich hat der Kommentar
Also eine Schleife macht ja im Gegensatz zu einem einzigen Insert nicht unbedingt mehr Sinn, du kannst die Schleife nicht pausieren oder unterbrechen. In beiden Fällen würde die Aufgabe in einem Stück erledigt werden,...
etwas verunsichert. Denn ich war auch der Meinung, dass eine Transaktion erst vollständig abgearbeitet wird bevor die nächste startet.

Ich habe es jetzt so gelöst
Code:
declare @iStep int
declare @iLoop int
set @iStep = 100
set @iLoop = 0

while @iLoop * @iStep < (select MAX(RelDataSet) from MemoStore)
BEGIN
  BEGIN TRANSACTION
      insert into zzRunProtocol (RelDataSet, Type, ValueGes, TimePoint, Value)
      select RelDataSet, Type, SUBSTRING(Memo1, Number+1, 30) as [Value],
        SUBSTRING(Memo1, Number+1, CHARINDEX(',', SUBSTRING(Memo1, Number+1, 30))-1),
        SUBSTRING(Memo1, Number+CHARINDEX(',', SUBSTRING(Memo1, Number+1, 30))+1, CHARINDEX(';', SUBSTRING(Memo1, Number+1, 30)) - CHARINDEX(',', SUBSTRING(Memo, Number+1, 30))-2)
      from MemoStore
      join zzNumbers on (number <= LEN(Memo1)) and (SUBSTRING(Memo1, Number, 1) = ';') and (len(SUBSTRING(Memo1, Number+1, 30))>3)
      where RelDataSet between ((@iLoop * @iStep) + 1) and ((@iLoop + 1) * @iStep)
  COMMIT
  set @iLoop = @iLoop + 1
END
d.h. über iStep kann ich festlegen, wie viele Datensätze in einer Transaktion abgearbeitet werden und über iLoop durchlaufe ich die Schleife so oft, bis auch der Datensatz mit der höchsten ID (in dem Fall RelDataSet) abgearbeitet ist
 
Werbung:
Daran habe ich auch schon gedacht. Problem ist, dass ich die Quelldaten wenn möglich nicht anfassen soll.
Die Information könnte auch in einer eigenen Tabelle stehen die mit IDs der Datensätze gefüllt wird, die verarbeitet wurden.
wie mache ich es dann, dass die Daten erst gekennzeichnet werden, wenn sie auch wirklich verarbeitet sind
Alles was in einer Transaktion geschieht, wird kann mit einem ROLLBACK rückabgewickelt werden. Mir scheint das hast du in meiner Abwesenheit schon gelesen :)
 
Zurück
Oben