Nummernbereich Von Bis einfügen
spacer
Autor Nachricht
Bronstein
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starhalf offtopic star
Beiträge: 564

WIN XP
Delphi 6
BeitragVerfasst: Fr 05.08.11 07:30 
Hallo,
gibt es eine Möglichkeit das folgende zu vereinfachen:

Ich habe z.B. einen Nummernbereich von 1-1000000 und möchte diesen jetzt einfügen

ausblenden Delphi-Quelltext markieren
1:
2:
3:
4:
5:
for i:=1 to 1000000 do
begin
AdoCommand.CommandText := 'Insert INTO DATEN (NUMMER, TEXT) VALUES ('+IntToStr(i)+ ', ' + QuotedStr(tmpText) +')'
AdoCommand.Execute;
end;


Geht das auch ohne diese Schleife?

_________________
Es gibt keine dummen Fragen nur dumme Antworten!!!
 
Antworten mit Zitat Beitrag melden
Private Nachricht sendenPosting in privater Nachricht zitieren
Werbung ausblenden? Dann registriere Dich kostenlos. Weitere Gründe für eine Registrierung.


Werbung ausblenden? Dann registriere Dich kostenlos. Weitere Gründe für eine Registrierung.
Xion
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starhalf offtopic star
EE-Maler
Beiträge: 1754
Erhaltene Danke: 62

Windows XP
Delphi (2005 Bug Edition), Java (Eclipse), Haskell (ghci), C++ (Visual Studio 2010, Qt Creator)
BeitragVerfasst: Fr 05.08.11 07:45 
glaube nicht dass das ohne Schleife geht. (du kannst dir natürlich eine Funktion außenrum bauen)

Aber um die Geschwindigkeit zu steigern:
msdn.microsoft.com/e...1%28v=sql.80%29.aspx

ausblenden Delphi-Quelltext markieren
1:
2:
3:
4:
5:
6:
7:
ADOConnection.BeginTrans;
for i:=1 to 1000000 do
begin
AdoCommand.CommandText := AdoCommand.CommandText + 'Insert INTO DATEN (NUMMER, TEXT) VALUES ('+IntToStr(i)+ ', ' + QuotedStr(tmpText) +');'
end;
//AdoCommand.Execute; //vielleicht noch nötig, mal ausprobieren
ADOConnection.CommitTrans;


Vielleicht gehts auch ohne dem Begin/Commit Trans, wenn du einfach alles in einen String reinschreibst. Probiers mal aus und sag, obs hilft :)

Es kann auch sein, dass du jedes Statement für sich "Executen" musst.

_________________
a broken heart is like a broken window - it'll never heal
Jen, [this computer] is infected. If this was a human being, I'd shoot it in the face. (IT Crowd)
 
Antworten mit Zitat Beitrag melden
Private Nachricht sendenPosting in privater Nachricht zitieren
ZeitGeist87
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starhalf offtopic starofftopic star
Beiträge: 1564
Erhaltene Danke: 14

Win95-WinXP Pro
Delphi 7 Prof., C++, WSH, Turbo Pascal, PHP
BeitragVerfasst: Fr 05.08.11 09:40 
ausblenden Delphi-Quelltext markieren
1:
2:
3:
4:
5:
6:
7:
AdoCommand.CommandText := 'Insert INTO DATEN (NUMMER, TEXT) VALUES ';
for i:=1 to 1000000 do
begin
AdoCommand.CommandText:= AdoCommand.CommandText + '('+IntToStr(i)+ ', ' + QuotedStr(tmpText) +'), ';
end;
//Vorher hinten das letzte Komma abschneiden ;-)
AdoCommand.Execute;

_________________
Wer Provokationen, Ironie, Sarkasmus oder Zynismus herauslesen kann soll sie ignorieren um den Inhalt meiner Beiträge ungetrübt erfassen zu können.
 
Antworten mit Zitat Beitrag melden
Private Nachricht sendenPosting in privater Nachricht zitieren
baka0815
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 452
Erhaltene Danke: 10

Win XP, Debian GNU/Linux
Delphi 2007 Enterprise, Java, C#
BeitragVerfasst: Do 02.02.12 14:17 
Ich habe ein ähnlich gelagertes Problem und zwar geht es um das Importieren von Daten in eine Datenbank.
Die Daten müssen hierbei allerdings umgewandelt, geprüft und verarbeitet werden, weswegen der Weg über BULK INSERT nicht möglich ist. Außerdem soll das ganze unter Oracle und MS-SQL funktionieren.

Der Import ist so aufgebaut, dass ich pro Datenbanktabelle eine eigene Datei habe, die zeilenweise ausgelesen wird. Im Prinzip sind es CSV-Dateien mit einem Tabulator als Trenner.

Das ganze Programm läuft (leider und aus verschiedenen historischen Gründen) über die BDE.

Ich habe ein TQuery-Objekt, in welchem ich das SQL mit Parametern setze, das ganze dann mit Prepare vorbereite und dann in der Schleife nur noch die Parameter setze und das INSERT per ExecSQL an die DB sende.
Mit Zeitmessungen habe ich festgestellt, dass bei einem Import der 277 Sekunden dauert, 200 Sekunden alleine für das ExecSQL drauf gehen (also ~70%). Nachdem ich jetzt Transaktionen pro Tabelle eingebaut habe, dauert derselbe Vorgang nur noch 133 Sekunden, allerdings sind noch immer etwa 70% davon ExecSQL.


Exemplarischer Code:
ausblenden Delphi-Quelltext markieren
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
  Ok = FindFirst();
while (Ok = 0) do
begin
// SQL mit Parametern anhand der Struktur in der ersten Zeile der Datei zusammenbauen
ReadLn(Ueberschriften, Datei);

Query.SQL.Clear;
Query.SQL.Add('insert into Tabelle (A, B, C) values (:A, :B, :C)');

while not Eof(Datei) do
begin
// Einzelne Werte aus der Datei lesen
Wert := LeseWert(Datei);

if (Spalte = ftInteger) then
Query.ParamByName(SpaltenName).AsInteger := StrToInt(Wert)
else if (Spalte = ftString) then
Query.ParamByName(SpaltenName).AsInteger := Wert;

Query.ExecSQL;
end;

Ok := FindNext();
end;


Kann man das ganze noch weiter beschleunigen?
 
Antworten mit Zitat Beitrag melden
Private Nachricht sendenPosting in privater Nachricht zitieren
olliterski
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 99
Erhaltene Danke: 2

Win7 64-Bit
D7 Ent.
BeitragVerfasst: Do 02.02.12 15:58 
...lässt sich sicher beschleunigen...

_________________
Viele Grüße
Oliver


Zuletzt bearbeitet von olliterski am Mo 13.02.12 00:24, insgesamt 1-mal bearbeitet
 
Antworten mit Zitat Beitrag melden
Private Nachricht sendenPosting in privater Nachricht zitieren
baka0815
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 452
Erhaltene Danke: 10

Win XP, Debian GNU/Linux
Delphi 2007 Enterprise, Java, C#
BeitragVerfasst: Do 02.02.12 19:10 
Nachteil daran ist, dass du keine Parameter nutzen kannst und daher jeden SQL-Text immer schön selbst escapen musst - oder du öffnest SQL Injections Tür und Tor.
Für mich ist das auch nichts, da durchaus auch Binärdaten importiert werden müssen - in den Textdateien sind diese dann Base64 kodiert.

Das Sperren der Eingabedateien ist für mich kein Problem, da diese genau für diesen Import-Vorgang zur Verfügung stehen und die Gefahr dass andere genau auf dieselben Daten zum Import zugreifen ist ziemlich genau bei 0. Dateisperren sind also gar kein Problem.
 
Antworten mit Zitat Beitrag melden
Private Nachricht sendenPosting in privater Nachricht zitieren
olliterski
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 99
Erhaltene Danke: 2

Win7 64-Bit
D7 Ent.
BeitragVerfasst: Do 02.02.12 20:09 
Yepp, wäre halt ein anderer Ansatz, eine andere Idee.
Ob man sie für seinen speziellen Fall verwenden kann ist eine ander Frage!

_________________
Viele Grüße
Oliver


Zuletzt bearbeitet von olliterski am Mo 13.02.12 00:53, insgesamt 1-mal bearbeitet
 
Antworten mit Zitat Beitrag melden
Private Nachricht sendenPosting in privater Nachricht zitieren
baka0815
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 452
Erhaltene Danke: 10

Win XP, Debian GNU/Linux
Delphi 2007 Enterprise, Java, C#
BeitragVerfasst: Fr 03.02.12 12:43 
Du nutzt keine Parameter, sondern baust dir das SQL immer neu mit den Werten zusammen.

Ich meine Parameter in Verbindung mit einem PreparedStatement:
ausblenden Delphi-Quelltext markieren
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
  Query.SQL.Add('insert into Tabelle (SpalteA, SpalteB)');
Query.SQL.Add('values (:WertA, :WertB)');

Query.Prepare;

for I := 0 to 100000 do
begin
Query.ParamByName('WertA').AsInteger := I;
Query.ParamByName('WertB').AsString := IntToStr(I);

Query.ExecSQL;
end;


Das ist das, was ich zur Datenbanktheorie gelernt habe. Wenn man ein und dasselbe SQL mehrfach hintereinander ausführt das Query mit Parametern aufbauen, Vorbereiten und dann nur noch Parameter setzen und ausführen.

Und was die SQL-Injections betrifft ist das natürlich nicht Sache des DBA, sondern des Softwareentwicklers. Ich importiere schließlich Textdaten, wenn da jetzt jemand - warum auch immer - den Eintrag "'; DROP DATABASE XYZ;" einfügen würde, würde er in deinem Fall die Datenbank droppen. Was von dem Programm sicherlich nicht gewollt ist.
Zwar läuft mein Tool nicht in Produktivumgebungen sondern bei uns im Support um Kundendaten einzuspielen, trotzdem soll dies natürlich so "sicher wie möglich" sein, ohne dass jemand Schindluder treiben kann.
 
Antworten mit Zitat Beitrag melden
Private Nachricht sendenPosting in privater Nachricht zitieren
ZeitGeist87
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starhalf offtopic starofftopic star
Beiträge: 1564
Erhaltene Danke: 14

Win95-WinXP Pro
Delphi 7 Prof., C++, WSH, Turbo Pascal, PHP
BeitragVerfasst: Fr 03.02.12 14:23 
Oder du nutzt, falls das DBMS es unterstützt Transatkionen.

Pseudo :-)

ausblenden Delphi-Quelltext markieren
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
try
query.sql.text:= 'BEGIN TRANSACTION';
query.ExecSQL;

//SChleife
query.sql.text:= '<InsertStatement>';
query.ExecSQL;
//Schleife-Ende

query.sql.text:= 'COMMIT WORK';
query.ExecSQL;
except
query.sql.text:= 'ROLLBACK WORK';
query.ExecSQL;
end;

_________________
Wer Provokationen, Ironie, Sarkasmus oder Zynismus herauslesen kann soll sie ignorieren um den Inhalt meiner Beiträge ungetrübt erfassen zu können.
 
Antworten mit Zitat Beitrag melden
Private Nachricht sendenPosting in privater Nachricht zitieren
Martok
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Moderator
Beiträge: 2837
Erhaltene Danke: 182

Win 2000, Win XP
Delphi 7, Turbo Delphi Exp.
BeitragVerfasst: Fr 10.02.12 16:37 
Hinweis:
Diskussion über SQL-Injections abgetrennt nach hier hier.

Ein paar Zeilen gehörten noch hier rein:
user profile iconolliterski hat folgendes geschrieben Zum zitierten Posting springen:
Moin,

Parameter...ja ich stand auf der Leitung! ;)
Hatte auch das Prepare überlesen!

{...}

Viele Grüße

Oliver

_________________
"The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."
Ich code EdgeMonkey -~==~- #ee-lounge in Freenode
 
Antworten mit Zitat Beitrag melden
Private Nachricht sendenPosting in privater Nachricht zitieren
baka0815
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 452
Erhaltene Danke: 10

Win XP, Debian GNU/Linux
Delphi 2007 Enterprise, Java, C#
BeitragVerfasst: Fr 10.02.12 18:15 
Die Syntax rollback work bzw commit work ist mir neu, welches DBMS ist das? Ich kenne es nur ohne das work.

Habe bei mir auch Transaktionen eingebaut und war erstaunt, dass es immerhin knapp 30% schneller geht. Ich hatte vermutet, dass der Overhead um die Transaktionen dann zu synchronisieren größer sei, aber so kann man sich täuschen.
 
Antworten mit Zitat Beitrag melden
Private Nachricht sendenPosting in privater Nachricht zitieren
Martok
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Moderator
Beiträge: 2837
Erhaltene Danke: 182

Win 2000, Win XP
Delphi 7, Turbo Delphi Exp.
BeitragVerfasst: Fr 10.02.12 22:31 
Bei Oracle wird sich der Automatic Database Diagnostic Monitor (ADDM) beschweren, wenn man solche Massen-Abfragen nicht mit Parametern macht. Dann dauert nämlich das Parsen des SQL-Text länger als die Verarbeitung und der merkt das. Gibt dann schöne Meldungen in der Admin-Konsole, man solle doch mal gucken was man da verzapft hat.

Man will also eigentlich immer Parameter, auch wenn die in Delphi etwas seltsam realisiert sind. In Pythons DBI ist das schöner, da kann man gar nicht versehentlich was anderes verwenden, weil das so einfach ist ;)

Man kann auch noch (je nach DB-Binding) Parameter-Arrays übergeben, so dass man dann sagt "Hier hast du ein Statement und 2x1000000 Variablen, mach mal". Ob man das aber mit ADO hinbekommt ist die andere Frage.

Aber 1 Mio Werte, das darf schon mal ein bisschen dauern. Wenn du mal 10 Minuten auf 97MB Access-DB durchnudeln gewartet hast, weißt du was langsam ist ;)

_________________
"The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."
Ich code EdgeMonkey -~==~- #ee-lounge in Freenode
 
Antworten mit Zitat Beitrag melden
Private Nachricht sendenPosting in privater Nachricht zitieren
olliterski
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 99
Erhaltene Danke: 2

Win7 64-Bit
D7 Ent.
BeitragVerfasst: So 12.02.12 00:49 
@Martok:
Hast du doch schon in deinem vorletzten Beitrag geschrieben was hier drin stand!
;)

_________________
Viele Grüße
Oliver
 
Antworten mit Zitat Beitrag melden
Private Nachricht sendenPosting in privater Nachricht zitieren
baka0815
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 452
Erhaltene Danke: 10

Win XP, Debian GNU/Linux
Delphi 2007 Enterprise, Java, C#
BeitragVerfasst: Mo 13.02.12 13:59 
Ich finde Parameter in Delphi relativ simpel und gut gelöst - ich mag benannte Parameter.

Bei Java hingegen ist's ein Graus. Jeder Parameter ein Fragezeichen und dann zählen - ätzend. Vor allem wenn man dann in der Mitte einen weiteren Parameter einfügt...
 
Antworten mit Zitat Beitrag melden
Private Nachricht sendenPosting in privater Nachricht zitieren
Martok
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Moderator
Beiträge: 2837
Erhaltene Danke: 182

Win 2000, Win XP
Delphi 7, Turbo Delphi Exp.
BeitragVerfasst: Mo 13.02.12 15:45 
user profile iconbaka0815 hat folgendes geschrieben Zum zitierten Posting springen:
Ich finde Parameter in Delphi relativ simpel und gut gelöst - ich mag benannte Parameter.

Recht hast du. Ich meinte eher das vorherige Binden: in Python kann ich einfach beim Ausführen einen "Hash" mit Name-Wert-Paaren übergeben. Delphi fehlen eben echte assoziative Arrays, jenseits von der COM-Lösung immer Name und Wert abwechselnd in ein Array zu stecken.

Hatte mal für php-mysqli einen Wrapper geschrieben, der benannte Parameter live in "?" übersetzt. Kenne dein Leid also ;-)

_________________
"The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."
Ich code EdgeMonkey -~==~- #ee-lounge in Freenode
 
Antworten mit Zitat Beitrag melden
Private Nachricht sendenPosting in privater Nachricht zitieren
baka0815
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 452
Erhaltene Danke: 10

Win XP, Debian GNU/Linux
Delphi 2007 Enterprise, Java, C#
BeitragVerfasst: Di 14.02.12 12:09 
Das kann man sich aber doch recht einfach bauen, über ein array of const.
Da ist nur der Nachteil, dass man Double und TDateTime nicht mehr auseinanderhalten kann und daher nicht weiß ob .AsCurrency oder .AsDateTime... Also vielleicht doch keine Lösung. :D
 
Antworten mit Zitat Beitrag melden
Private Nachricht sendenPosting in privater Nachricht zitieren
home home