Delphi-PRAXiS
Seite 4 von 5   « Erste     234 5      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi INSERT INTO SELECT ohne Spaltenliste (https://www.delphipraxis.net/163828-insert-into-select-ohne-spaltenliste.html)

Sir Rufo 21. Okt 2011 11:14

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;

Alex.G 21. Okt 2011 11:15

AW: INSERT INTO SELECT ohne Spaltenliste
 
Zitat:

Zitat von himitsu (Beitrag 1131678)
Und
Delphi-Quellcode:
qryMasterExec.Fields[i].FieldName
?

Das funktioniert!
Eine (hoffentlich) letzte Sache noch:
Delphi-Quellcode:
  qrySlaveExec.SQL.Text := Format('INSERT INTO %s (%s) VALUES(%s)', [TableName, InsertStr, ValueStr]);
  while not qryMasterExec.Eof do begin
    qrySlaveExec.Insert;
Ist bei geschlossener Datenmenge nicht möglich. Ein qrySlaveExec.Open kann ich aber, soweit ich weiß, nur bei einem SELECT nutzen.

Bummi 21. Okt 2011 11:15

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;

joachimd 21. Okt 2011 11:34

AW: INSERT INTO SELECT ohne Spaltenliste
 
Zitat:

Zitat von Alex.G (Beitrag 1131690)
Delphi-Quellcode:
  qrySlaveExec.SQL.Text := Format('INSERT INTO %s (%s) VALUES(%s)', [TableName, InsertStr, ValueStr]);
  while not qryMasterExec.Eof do begin
    qrySlaveExec.Insert;
Ist bei geschlossener Datenmenge nicht möglich.

Delphi-Quellcode:
  qrySlaveExec.ExecSQL;

Alex.G 21. Okt 2011 11:49

AW: INSERT INTO SELECT ohne Spaltenliste
 
Zitat:

Zitat von joachimd (Beitrag 1131702)
Zitat:

Zitat von Alex.G (Beitrag 1131690)
Delphi-Quellcode:
  qrySlaveExec.SQL.Text := Format('INSERT INTO %s (%s) VALUES(%s)', [TableName, InsertStr, ValueStr]);
  while not qryMasterExec.Eof do begin
    qrySlaveExec.Insert;
Ist bei geschlossener Datenmenge nicht möglich.

Delphi-Quellcode:
  qrySlaveExec.ExecSQL;

ExecSQL bevor man die Parameter angegeben hat?
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  
---------------------------

Alex.G 21. Okt 2011 13:49

AW: INSERT INTO SELECT ohne Spaltenliste
 
Delphi-Quellcode:
    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;
Gibt mir wieder eine Exception:
Code:
---------------------------
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  
---------------------------
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))

Jumpy 21. Okt 2011 14:04

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

Alex.G 21. Okt 2011 14:11

AW: INSERT INTO SELECT ohne Spaltenliste
 
Zitat:

Zitat von Jumpy (Beitrag 1131758)
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

Es soll ja noch gar kein Datum rein. Werde es morgen oder so mal fertig machen. Allen vielen Dank für die Hilfe! :thumb:

himitsu 21. Okt 2011 14:20

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.

DeddyH 21. Okt 2011 16:02

AW: INSERT INTO SELECT ohne Spaltenliste
 
Wenn Du Parameter benutzt brauchst Du keine Quoted Strings.


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:32 Uhr.
Seite 4 von 5   « Erste     234 5      

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