![]() |
Datenbank: MSSQL • Version: 2005 • Zugriff über: ADO
INSERT INTO SELECT ohne Spaltenliste
Moin!
Ich will alle Daten einer Datenbank (aus jeder Tabelle) in eine Zweite identisch aufgebaute Datenbank übertragen. Da dies in Delphi mit einer For-Schleife abläuft, kann ich keine feste Spaltenliste eintragen. Habe auch schon gegooglet und diese Variante gefunden:
Code:
Leider bekomme ich eine Exception, da keine Spaltenliste angegeben ist. Gibt es eine Möglichkeit die Spaltenliste auszulassen bzw. variabel anzugeben?
INSERT INTO TestDB2.dbo.Kunden SELECT * FROM TestDB1.dbo.Kunden
Gruß Alex |
AW: INSERT INTO SELECT ohne Spaltenliste
|
AW: INSERT INTO SELECT ohne Spaltenliste
Du müsstest erst z.B. mit einem
Code:
dir die Liste der Ergebnisspalten liefern und dann das SQL-Statement entsprechend erweitern.
Select * from TestDB1.dbo.Kunden where 1=2
|
AW: INSERT INTO SELECT ohne Spaltenliste
Code:
gegf.
Select *
Into NewTable From OldTable
Code:
Select *
Into AndereDB.dbo.NewTable From OldTable |
AW: INSERT INTO SELECT ohne Spaltenliste
Danke für die Antworten!
Was aber, wenn die Datenbanken auf verschiedenen Servern laufen? |
AW: INSERT INTO SELECT ohne Spaltenliste
Zitat:
Ist je nach DMBS unterschiedlich aufwändig und Fehleranfällig. |
AW: INSERT INTO SELECT ohne Spaltenliste
Zitat:
Wie müsste ich da vorgehen? |
AW: INSERT INTO SELECT ohne Spaltenliste
Guckst du in der
![]() |
AW: INSERT INTO SELECT ohne Spaltenliste
Zitat:
|
AW: INSERT INTO SELECT ohne Spaltenliste
Zitat:
|
AW: INSERT INTO SELECT ohne Spaltenliste
@joachimd
Du hast recht, ich hatte nicht gesehen dass er die Tabellen schon angelegt hatte .... |
AW: INSERT INTO SELECT ohne Spaltenliste
Als erstes mache ich ein SELECT * ... über eine ADOConnection zum ersten Server. Danach über eine zweite Connection ein INSERT INTO ...
Leider funktioniert das ganze nicht richtig. Mit diesem Quelltext...
Delphi-Quellcode:
...bekomme ich leider nur Insert's wie:
for i := 0 to qryMaster.Recordset.RecordCount-1 do
begin columnList := ''; valList := ''; qryMasterExec.SQL.Text := 'SELECT * FROM ' + qryMaster.Recordset.Fields.Item['TABLE_NAME'].Value; qryMasterExec.Open; qryMasterExec.Requery; qryMasterExec.Recordset.MoveFirst; for n := 0 to qryMasterExec.Recordcount-1 do begin for t := 0 to qryMasterExec.RecordCount-1 do begin columns[t] := qryMaster.Recordset.Fields.Item['COLUMN_NAME'].Value; values[t] := qryMasterExec.Recordset.Fields.Item[columns[t]].Value; end; qryMasterExec.Recordset.MoveNext; end; for e := 0 to High(values)-1 do begin columnlist := columnlist + columns[e] + ' '; valList := valList + values[e] + ' '; mSQL.Lines.Add('INSERT INTO ' + qryMaster.Recordset.Fields.Item['TABLE_NAME'].Value + ' ('+columnList+') VALUES' + ' ('+valList+')' ); end; qryMaster.Recordset.MoveNext; end;
Code:
(Alle Daten sind ausgedacht!)
INSERT INTO Rechnung (ID ) VALUES (4 )
INSERT INTO Rechnung (ID ID ) VALUES (4 4 ) INSERT INTO Rechnung (ID ID ID ) VALUES (4 4 4 ) INSERT INTO Rechnung (KID ) VALUES (2 ) INSERT INTO Rechnung (KID KID ) VALUES (2 2 ) INSERT INTO Rechnung (KID KID KID ) VALUES (2 2 2 ) INSERT INTO Rechnung (PID ) VALUES (1 ) INSERT INTO Rechnung (PID PID ) VALUES (1 1 ) INSERT INTO Rechnung (PID PID PID ) VALUES (1 1 1 ) INSERT INTO Kunde (ID ) VALUES (3 ) INSERT INTO Kunde (ID ID ) VALUES (3 3 ) INSERT INTO Kunde (ID ID ID ) VALUES (3 3 3 ) INSERT INTO Kunde (Name ) VALUES (Plaum ) INSERT INTO Kunde (Name Name ) VALUES (Plaum Plaum ) INSERT INTO Kunde (Name Name Name ) VALUES (Plaum Plaum Plaum ) INSERT INTO Kunde (Vorname ) VALUES (Jürgen ) INSERT INTO Kunde (Vorname Vorname ) VALUES (Jürgen Jürgen ) INSERT INTO Kunde (Vorname Vorname Vorname ) VALUES (Jürgen Jürgen Jürgen ) INSERT INTO Kunde (Ort ) VALUES (Siegen ) INSERT INTO Kunde (Ort Ort ) VALUES (Siegen Siegen ) INSERT INTO Kunde (Ort Ort Ort ) VALUES (Siegen Siegen Siegen ) INSERT INTO Produkt (ID ) VALUES (2 ) INSERT INTO Produkt (ID ID ) VALUES (2 2 ) INSERT INTO Produkt (ID ID Ort ) VALUES (2 2 Siegen ) INSERT INTO Produkt (Name ) VALUES (Lenovo R500 ) INSERT INTO Produkt (Name Name ) VALUES (Lenovo R500 Lenovo R500 ) INSERT INTO Produkt (Name Name Ort ) VALUES (Lenovo R500 Lenovo R500 Siegen ) INSERT INTO Produkt (Kommentar ) VALUES (Lenovo Thinkpad Laptop ) INSERT INTO Produkt (Kommentar Kommentar ) VALUES (Lenovo Thinkpad Laptop Lenovo Thinkpad Laptop ) INSERT INTO Produkt (Kommentar Kommentar Ort ) VALUES (Lenovo Thinkpad Laptop Lenovo Thinkpad Laptop Siegen ) Was mache ich falsch? |
AW: INSERT INTO SELECT ohne Spaltenliste
Nimm den Debugger und steppe mal durch die Anwendung.
Richte dein Augenmerk besonders auf die Laufvariablen aus den For-Schleifen ;) |
AW: INSERT INTO SELECT ohne Spaltenliste
Nur so ein Gedanke: könnte man nicht das SQL über GetFieldnames zusammensetzen? Aus der hohlen Hand:
Delphi-Quellcode:
Anschließend könnte man dann in einer Schleife den Parametern die aktuellen Werte zuweisen.
InitialSQL := 'INSERT INTO %s(%s) VALUES(%s)';
ADOConnection.GetFieldNames(<Tabellenname>, <Feldliste>); FieldnameStr := <Feldliste>.CommaText; for i := 0 to <Feldliste>.Count - 1 do <Feldliste>[i] := ':' + <Feldliste>[i]; ParamnameStr := <Feldliste>.CommaText; InsertQuery.SQL.Text := Format(InitialSQL, [<Tabellenname>, FieldnameStr, ParamnameStr]); |
AW: INSERT INTO SELECT ohne Spaltenliste
Zitat:
Code:
EDIT: Exception kommt bei conMaster.GetFieldNames(tableName, fieldList);
---------------------------
Benachrichtigung über Debugger-Exception --------------------------- Im Projekt pDatenbankabgleich.exe ist eine Exception der Klasse EAccessViolation aufgetreten. Meldung: 'Zugriffsverletzung bei Adresse 0046A3CE in Modul 'pDatenbankabgleich.exe'. Schreiben von Adresse 0048AAA8'. Prozess wurde angehalten. Mit Einzelne Anweisung oder Start fortsetzen. --------------------------- OK Hilfe --------------------------- |
AW: INSERT INTO SELECT ohne Spaltenliste
Warum richtest Du keinen Verbindungsserver ein, geht auch über Script und fährst
Insert into Ziel Select * from verbindungsserver.ddo.quelle |
AW: INSERT INTO SELECT ohne Spaltenliste
Die Feldliste hast Du aber erzeugt, und die Connection ist aktiv?
|
AW: INSERT INTO SELECT ohne Spaltenliste
Zitat:
Zitat:
Code:
---------------------------
Benachrichtigung über Debugger-Exception --------------------------- Im Projekt pDatenbankabgleich.exe ist eine Exception der Klasse EAbstractError aufgetreten. Meldung: 'Abstrakter Fehler'. Prozess wurde angehalten. Mit Einzelne Anweisung oder Start fortsetzen. --------------------------- OK Hilfe --------------------------- |
AW: INSERT INTO SELECT ohne Spaltenliste
Von welchem Typ ist denn Fieldlist? Falls TStrings, dann mach mal TStringlist daraus.
|
AW: INSERT INTO SELECT ohne Spaltenliste
Und wie sieht es mit sowas aus?
Delphi-Quellcode:
Und ich glub das Quoten der Values wurden oftmals vergessen.
Source.SQL.Text := 'SELECT * FROM ' + TableName;
Source.ExecSQL; InsertStr := ''; ValueStr := ''; for i := 0 to Source.ParamCount - 1 do begin InsertStr := InsertStr + IfThen(InsertStr <> '', ', ', '') + Source.Fields[i].FieldName; ValueStr := ValueStr + IfThen(ValueStr <> '', ', :', ':') + Source.Fields[i].FieldName; end; Dest.SQL.Text := Format('INSERT INTO %s (%s) VALUES(%s)', [TableName, InsertStr, ValueStr]); while not Source.Eof do begin Dest.Insert; for i := 0 to Source.ParamCount - 1 do Dest.Params.ParamByName(Source.Fields[i].FieldName).Value := Source.Fields.FieldByName(Source.Fields[i].FieldName).Value; Dest.Post; end; (entfällt bei dem Preparedzeugs aber) |
AW: INSERT INTO SELECT ohne Spaltenliste
First nach ExecSQL? Geht sowas in ADO?
|
AW: INSERT INTO SELECT ohne Spaltenliste
Delphi-Quellcode:
Diese Zeile verstehe ich nicht. Müsste da nicht ein Recordcount hin? Wenn ich ein Breakpoint setze, sehe ich bei Parameters.Count den Wert 0.
for i := 0 to qryMasterExec.Parameters.Count - 1 do begin
|
AW: INSERT INTO SELECT ohne Spaltenliste
@DeddyH: Frag mich doch nicht. :lol: (ich fang auch grad erst mit diesem ganzen Zeugs an)
(hab mir erst letzte Woche mein erstes kleines brennendes Vögelchen zugelegt) RecordCount = Anzahl der Zeilen/Datensätze Parameters.Count = Anzahl der Splten/Parameter |
AW: INSERT INTO SELECT ohne Spaltenliste
Du hast doch ein Abfrageergebnis, was soll es da für Parameter geben? Nimm statt Parameters einmal Fields.
|
AW: INSERT INTO SELECT ohne Spaltenliste
Du willst keinen Verbindugsserver aufbauen und hast die Zieltabellen schon?
Die Insert-SQL's aufzubauen mit Berücksichtigung aller Besonderheiten bzgl. Feldtypen, Codierung etc. wird Dich einige Zeit kosten, warum nicht die billige Variante ExDataset = Select * from Quelle Ads= Select * from Ziel
Delphi-Quellcode:
While (not ExDataset.EOF) do begin Ads.Append; for i:=0 to Ads.Fieldcount-1 do begin Ads.Fields[i].Assign(ExDataset.FieldByName(Ads.Fields[i].FieldName)); end; ads.Post; ExDataset.Next; end; |
AW: INSERT INTO SELECT ohne Spaltenliste
Zitat:
|
AW: INSERT INTO SELECT ohne Spaltenliste
Zitat:
Hatte das schonmal wer hier erwähnt`? |
AW: INSERT INTO SELECT ohne Spaltenliste
Zitat:
Ich habe es nun mit:
Delphi-Quellcode:
und
InsertStr := InsertStr + IfThen(InsertStr <> '', ', ', '') + qryMasterExec.Parameters[i].Name;
Delphi-Quellcode:
probiert. Wenn ich ein Breakpoint setze, sehe ich, dass InsertStr leider nach Ablauf der Schleife immer leer bleibt.
InsertStr := InsertStr + IfThen(InsertStr <> '', ', ', '') + qryMasterExec.Fields[i].Name;
|
AW: INSERT INTO SELECT ohne Spaltenliste
Was ist denn mit der Vorgehensweise nach #14 bis #19?
|
AW: INSERT INTO SELECT ohne Spaltenliste
Und
Delphi-Quellcode:
?
qryMasterExec.Fields[i].FieldName
|
AW: INSERT INTO SELECT ohne Spaltenliste
Ich bin hierfür (mal eben herunter getippt)
Delphi-Quellcode:
procedure CopyADOData( SrcCon, TarCon : TADOConnection; const TableName : string );
var SrcData : TADOTable; TarData : TADOQuery; SqlStrFld : string; SqlStrPar : string; fld : TField; begin SrcData := TADOTable.Create( nil ); TarData := TADOQuery.Create( nil ); try SrcData.Connection := SrcCon; SrcData.TableName := TableName; SrcData.FieldDefList.Update; TarData.Connection := TarCon; SqlStrFld := ''; SqlStrPar := ''; for fld in SrcData.Fields do begin if not( SqlStrFld = '' ) then SqlStrFld := SqlStrFld + ', '; SqlStrFld := SqlStrFld + fld.FieldName; if not( SqlStrPar = '' ) then SqlStrPar := SqlStrPar + ', '; SqlStrPar := SqlStrPar + ':' + fld.FieldName; end; TarData.SQL.Text := 'INSERT INTO ' + TableName + ' ( ' + SqlStrFld + ' ) VALUES ( ' + SqlStrPar + ' )'; TarData.Prepared := True; try SrcData.Open; try while not SrcData.Eof do begin for fld in SrcData.FieldList do begin TarData.Parameters.ParamByName(fld.FieldName).Value := fld.Value; end; TarData.ExecSQL; SrcData.Next; end; finally SrcData.Close; end; finally TarData.Prepared := False; end; finally TarData.Free; SrcData.Free; end; end; |
AW: INSERT INTO SELECT ohne Spaltenliste
Zitat:
Eine (hoffentlich) letzte Sache noch:
Delphi-Quellcode:
Ist bei geschlossener Datenmenge nicht möglich. Ein qrySlaveExec.Open kann ich aber, soweit ich weiß, nur bei einem SELECT nutzen.
qrySlaveExec.SQL.Text := Format('INSERT INTO %s (%s) VALUES(%s)', [TableName, InsertStr, ValueStr]);
while not qryMasterExec.Eof do begin qrySlaveExec.Insert; |
AW: INSERT INTO SELECT ohne Spaltenliste
zum fertigbasteln:
Delphi-Quellcode:
Function GetTableValueScript(Ads:TAdodataset;const tableName:String;HasIdentity:Boolean):String; var FieldNames:TStringList; Values:TStringList; i:Integer; FieldNamesStr:String; Function Prepare(f:TField):String; begin if f.IsNull then Result := 'NULL' else Case f.DataType of ftSmallint, ftInteger, ftWord,ftAutoInc,ftLargeint, ftFloat, ftCurrency, ftBCD ,ftFMTBcd,ftLongWord, ftShortint, ftByte, ftExtended ,ftSingle: Result := Stringreplace(f.AsString, ',','.',[]) ; ftString,ftWideString,ftGuid : Result := QuotedStr(f.AsString); ftDate, ftDateTime, ftTime : Result := QuotedStr(FormatdateTime('yyyymmdd hh:nn:ss.zzz',f.AsDateTime)); ftBoolean: Result := IntToStr(Integer(f.AsBoolean)); // to be continued End; end; Function GetValues:String; begin Result := StringReplace(Values.Text,#13#10,', ',[rfReplaceAll]); Result := Copy(Result,1,Length(Result) - 2); end; begin FieldNames:=TStringList.Create; Values:=TStringList.Create; try Ads.CommandText := 'Select top 100 * from ' + tablename; Ads.Open; for I := 0 to Ads.FieldCount -1 do FieldNames.Add('[' + Ads.Fields[i].FieldName + ']'); FieldNamesStr := StringReplace(FieldNames.Text,#13#10,', ',[rfReplaceAll]); FieldNamesStr := Copy(FieldNamesStr,1,Length(FieldNamesStr) - 2); while not Ads.Eof do begin Values.Clear; for I := 0 to Ads.FieldCount -1 do Values.Add(Prepare(Ads.Fields[i])); Ads.Next; Result := Result + 'Insert Into ' + tablename + '(' + FieldNamesStr + ') VALUES (' + GetValues + ')' + #13#10#13#10; end; finally FieldNames.Free; Values.Free; end; if HasIdentity then Result := 'Set Identity_Insert ' + tableName + ' ON' + #13#10 + Result + 'Set Identity_Insert ' + tableName + ' OFF' + #13#10 end; procedure TForm1.Button1Click(Sender: TObject); begin Memo1.Text := GetTableValueScript(ADS,'[Adressen]',true); end; |
AW: INSERT INTO SELECT ohne Spaltenliste
Zitat:
Delphi-Quellcode:
qrySlaveExec.ExecSQL;
|
AW: INSERT INTO SELECT ohne Spaltenliste
Zitat:
EDIT: Ergibt wieder eine Exception
Code:
---------------------------
Benachrichtigung über Debugger-Exception --------------------------- Im Projekt pDatenbankabgleich.exe ist eine Exception der Klasse EOleException aufgetreten. Meldung: 'Der Wert NULL kann in die 'ID'-Spalte, 'TestDB2.dbo.Produkt'-Tabelle nicht eingefügt werden. Die Spalte lässt NULL-Werte nicht zu. Fehler bei INSERT'. Prozess wurde angehalten. Mit Einzelne Anweisung oder Start fortsetzen. --------------------------- OK Hilfe --------------------------- |
AW: INSERT INTO SELECT ohne Spaltenliste
Delphi-Quellcode:
Gibt mir wieder eine Exception:
while not qryMasterExec.Eof do begin
for i := 0 to qryMasterExec.Fields.Count - 1 do valList.Add(qryMasterExec.Fields[i].Value); valueStr := valList.CommaText; qrySlaveExec.SQL.Text := Format('INSERT INTO %s (%s) VALUES(%s)', [TableName, InsertStr, ValueStr]); qrySlaveExec.ExecSQL; qryMasterExec.Next; end;
Code:
Wieso sollte Acer Monitor nicht zulässig sein? Es steht an der richtigen Stelle und ist ein 20-Zeichen langer String. (In der Datenbank: nChar(20))
---------------------------
Benachrichtigung über Debugger-Exception --------------------------- Im Projekt pDatenbankabgleich.exe ist eine Exception der Klasse EOleException aufgetreten. Meldung: 'Der Name "Acer Monitor " ist in diesem Kontext nicht zulässig. Gültige Ausdrücke sind Konstanten, konstante Ausdrücke und (in bestimmten Kontexten) Variablen. Spaltennamen sind nicht zulässig'. Prozess wurde angehalten. Mit Einzelne Anweisung oder Start fortsetzen. --------------------------- OK Hilfe --------------------------- |
AW: INSERT INTO SELECT ohne Spaltenliste
Es ist ein String, wird aber innerhalb des Strings nicht in Anführungsstrichen stehen. D.h. du musst String-Felder in deinem Value-String in Gänsefüßchen setzen, also wäre der Sting gleich:
'1,1,Acer Monitor,10.10.2011' müsste er eigentlich sein: '1,1,'Acer Monitor','10.10.2011'' und noch eigentlicher, müssten die Anführungsstrich maskiert werden, also: '1,1,''Acer Monitor'',''10.10.2011''' und das Datumfeld müsste ggf. nochmal anders behandelt werden. In Oracle säh das z.B. evtl. so aus: '1,1,''Acer Monitor'',To_Date(''10.10.2011'',''dd.mm.yyyy'')' Besser wäre es glaub ich generell mit Parametern zu arbeiten, dann haste das Problem nicht, denn in der Form wie du das machst, müssteste je nach Feldtyp in der Mastertabelle die Elemente des Value-Strings anpassen. Edit: Siehe z.B. mal wie Bummi das in #33 gemacht hat! Der Passus hier:
Delphi-Quellcode:
if f.IsNull then Result := 'NULL'
else Case f.DataType of ftSmallint, ftInteger, ftWord,ftAutoInc,ftLargeint, ftFloat, ftCurrency, ftBCD ,ftFMTBcd,ftLongWord, ftShortint, ftByte, ftExtended ,ftSingle: Result := Stringreplace(f.AsString, ',','.',[]) ; ftString,ftWideString,ftGuid : Result := QuotedStr(f.AsString); ftDate, ftDateTime, ftTime : Result := QuotedStr(FormatdateTime('yyyymmdd hh:nn:ss.zzz',f.AsDateTime)); ftBoolean: Result := IntToStr(Integer(f.AsBoolean)); // to be continued End |
AW: INSERT INTO SELECT ohne Spaltenliste
Zitat:
|
AW: INSERT INTO SELECT ohne Spaltenliste
Und dafür war die parametrisierte Variante vorgesehn ... dort muß man sich um nichts kümmern,
aber irgendwo sollte es auch eine QuoteString-Funktion geben, welche die ' für dich setzt. |
AW: INSERT INTO SELECT ohne Spaltenliste
Wenn Du Parameter benutzt brauchst Du keine Quoted Strings.
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 13:30 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz