SQL - edycja rekordów w pętli

0

Witam
Własnie próbuję jakoś w pętli zedytować rekordy, czyli zrobić jeden wpis znaku do jednej kolumny w każdym rekordzie, ale mi się program zawiesza, a robię to tak:

Mam kolumnę ID, Poczta i Wysłane, do wysłane ma wstawiać znak T, ale zawiesza mi program.
Co tu jest źle?

var
 id:integer;
begin
IBquery1.first;
     while not IBQuery1.eof do
       id:=IBQuery1.Fields[0].AsInteger;
         with IBQuery1, SQL do
         begin
         Close;
         Clear;
        Add('UPDATE KLIENCI SET WYSLANE=:WYSLANE WHERE id_KLIENTA = '+IntToStr(id));
       ParamByName('WYSLANE').AsString := 'T';
      ExecSQL;
    IBTransaction1.Commit;
IBQuery1.Next;
end;
 end;
0

A zastanowiłeś się w ogóle nad tym kodem? Nie możesz zamykać zapytania w środku pętli!
BTW podaj chociaż jeden rozsądny powód, dlaczego zmieniasz te rekordy pojedyńczo

0

Szukam jakiegoś sposobu, aby odznaczyć rekordy które w danym dniu (dacie) już wysłałem do klienta, aby nie wysyłać ich jeszcze raz w tym samym dniu.

Te rekordy mają kolumny ID, Email, Treść oraz Wyslane i nie mam pomysłu, jak zaznaczyć te rekordy, że jak nowe dojdą w danym dniu to tylko te nowe będe mógł wysła.

0

zmieniaj je wtedy jak je wysyłasz

0

Olśnienie [!!!]
Kod pobiera min i max ID, a potem po zakresie edytuje kolumnę WYSLANE. :)
Kod taki sobie, ale działa sprawnie.

procedure TForm1.Button6Click(Sender: TObject);
var
 id:integer;
 minim, maxym: string;

begin
//min ID
   with ibquery1, sql do
    begin
     Close;
      Clear;
       Add('SELECT MIN (id_klienta) FROM KLIENCI');
       Open;
      minim:=IBQuery1.Fields[0].AsString;
    end;

  //max ID
   with ibquery1, sql do
    begin
     Close;
      Clear;
       Add('SELECT MAX (id_klienta) FROM KLIENCI');
       Open;
      maxym:=IBQuery1.Fields[0].AsString;
    end;

     //EDYCJA KOLUMNY WYSLANE
         with IBQuery1, SQL do
         begin
         Close;
         Clear;
        Add('UPDATE KLIENCI SET WYSLANE=:WYSLANE WHERE ID_KLIENTA  BETWEEN '+minim+ ' AND '+maxym);
       ParamByName('WYSLANE').AsString := 'T';
      ExecSQL;
    IBTransaction1.Commit;
  end;
 Button4.Click; //odświez
end;
0

Tylko jeszcze musze zrobić aby edytował tylko te rekordy które pofiltrowałem np. po dzisiejszej dacie.

0

pokaż kod, którym wybierasz i wysyłasz dane

0

Tym kodem wysyłam pocztę z rekordów biorąc emaile, tematy i treść:

procedure TForm1.Button1Click(Sender: TObject);
begin
   Button1.Enabled:=False;
   Button5.Enabled:=False;
   Button8.Enabled:=False;
   Statusbar1.Panels[0].Text:='';

     Label3.Caption:= IntToStr(IBQuery1.RecordCount);
     Form1.jvProgressbar1.Position:=0;
     Form1.jvProgressbar1.Max:=STrToInt(Label3.Caption);

     idMessage1.CharSet:='charset="windows-1250"';  //ustawiamy kodowanie
     idMessage1.ContentTransferEncoding:='8bit';  // przesyłanie 8bitowe
     idMessage1.ContentType:='text/html';  // przesyłamy tekst

     idMessage1.clear; //CZYŚCIMY
     idMessage1.from.name := 'xxx'; //NAZWA NADAWCY
     idMessage1.from.address := 'xxx'; //ADRES NADAWCY
     idMessage1.recipients.EMailAddresses:=IBQuery1.FieldByName('EMAIL').asString+' ; '; //ADRESAT MAILA

          idSMTP1.UserName := 'xxx'; //DANE DO POŁACZENIA Z SERWEREM POCZTOWYM (TUTAJ JA MAM ADRES IP)
          idSMTP1.Host := 'xxx';
          idSMTP1.Password := 'xxx';
          idSMTP1.AuthenticationType:=atNone; //wpisz gdy serwer nie wymaga uwierzytelnienia
          idSMTP1.AuthenticationType:=atLogin;  //wpisz gdy serwer wymaga uwierzytelnienia (zalecane)

     IBquery1.first;
     while not IBQuery1.eof do
        begin

          idMessage1.recipients.EMailAddresses:=IBQuery1.FieldByName('email').asString; //ADRESAT MAILA
            idmessage1.Body.Clear;
              idmessage1.Body.Add(IBQuery1.FieldByName('TRESC').asString+#13+#13+jvRichedit1.Lines.Text); //TREŚĆ MAILA
                idMessage1.subject:=IBQuery1.FieldByName('TEMAT').asString; //TEMAT MAILA
                   Edit2.Text:=IBQuery1.Fields[0].AsString;
                  Listbox1.Items.Add(IBQuery1.Fields[0].AsString);

                 Form1.jvProgressbar1.Position:=Form1.jvProgressbar1.Position+1;
                 Label3.Caption:=IntToStr(Form1.jvProgressbar1.Position)+' / '+IntToStr(Form1.jvProgressbar1.Max);

          try
            begin
             idSMTP1.connect;
              idSMTP1.Send(idmessage1);
              Application.ProcessMessages; //to dodaj
              EDIT8.Text:=IntToStr(IBQuery1.RecordCount);
             end;
            finally
          idSMTP1.disconnect;
        end;
      IBQuery1.Next;
    end;
   Button6.Click//edytuj kol WYSLANE NA "T"
end;

Button6 do edycji rekordów (kolumna WYSLANE), które wysłałem

Tym kodem edytuję tą kolumnę, ale chodzi mi aby tylko te rekordy edytował które wysłałem np. o dzisiejszej dacie pofiltrowanej:

procedure TForm1.Button6Click(Sender: TObject);
var
 minim, maxym: string;
begin
//min ID
   with ibquery1, sql do
    begin
     Close;
      Clear;
       Add('SELECT MIN (id_klienta) FROM KLIENCI');
       Open;
      minim:=IBQuery1.Fields[0].AsString;
    end;

  //max ID
   with ibquery1, sql do
    begin
     Close;
      Clear;
       Add('SELECT MAX (id_klienta) FROM KLIENCI');
       Open;
      maxym:=IBQuery1.Fields[0].AsString;
    end;

  //  Button4.Click;//cala tabela
     //EDYCJA KOLUMNY WYSLANE
         with IBQuery1, SQL do
         begin
         Close;
         Clear;
          Add('UPDATE KLIENCI SET WYSLANE=:WYSLANE WHERE ID_KLIENTA  BETWEEN '+minim+ ' AND '+maxym);
      //  Add('UPDATE KLIENCI SET WYSLANE=:WYSLANE WHERE TRESC_DATA  = '+DateToStr(Date));

        ParamByName('WYSLANE').AsString := 'N';
      ExecSQL;
    IBTransaction1.Commit;
  end;
 //Button4.Click; //odświez
end;

Rozumiem że MIN i MAX wartości on pobiera z całej tabeli, nie z rekordów które pofiltrowałem, a właśnei tak chcę zrobić, bo wtedy mi całą tabelę edytuje (kolumna WYSLANE).

Jak to wykonać? próbowałem dać do filtru jeszcze datę, ale błąd wyskakuje.


Debugger Exception Notification

Project Project1.exe raised exception class EIBInterBaseError with message 'expression evaluation not supported'. Process stopped. Use Step or Run to continue.

OK Help

0

dodaj sobie jeszcze jedno query (IBQuery2), popodpinaj i do SQL wpisz tak

UPDATE KLIENCI SET WYSLANE='T' WHERE id_KLIENTA = :idKl
  while not IBQuery1.eof do
  begin
    idMessage1.recipients.EMailAddresses:=IBQuery1.FieldByName('email').asString; 
    idmessage1.Body.Clear;
    idmessage1.Body.Add(IBQuery1.FieldByName('TRESC').asString+#13+#13+jvRichedit1.Lines.Text); //TREŚĆ MAILA
    idMessage1.subject:=IBQuery1.FieldByName('TEMAT').asString; //TEMAT MAILA
    Edit2.Text:=IBQuery1.Fields[0].AsString;
    Listbox1.Items.Add(IBQuery1.Fields[0].AsString);

    Form1.jvProgressbar1.Position:=Form1.jvProgressbar1.Position+1;
    Label3.Caption:=IntToStr(Form1.jvProgressbar1.Position)+' / '+IntToStr(Form1.jvProgressbar1.Max);

    try
      idSMTP1.connect;
      idSMTP1.Send(idmessage1);
      Application.ProcessMessages; //to dodaj
      EDIT8.Text:=IntToStr(IBQuery1.RecordCount);
    
      IBTransaction1.StartTransaction;  //albo BeginTransaction - nie pamiętam
      IBQuery2.ParamByName('idKl').AsInteger := IBQuery1.FieldByName('id_klienta').AsInteger;
      IBQuery2.ExecSQL;
      IBTransaction1.Commit;
    finally
      idSMTP1.disconnect;
    end;
    IBQuery1.Next;
  end;
0

Zrobiłem tak jak napisałeś, ale wyskakuje błąd że transakcja jest otwarta (skomentowałem tą linijkę) lub Dataset jest zamknięty hmm...

0

przypisałeś do IBQuery2 IBTransaction1? I czy gdzieś startujesz transakcję dla IBTransaction1?

0

Tak przypisałem.
Pierwsze jak odpalam program to robię selecta dla tabeli, aby pokazac rekordy i to wszystko.
Potem już tylko daję przycisk Wyślij z tym kodem powyżej. Nigdzie raczej transakcji nie otwieram przed wysyłką.

1 użytkowników online, w tym zalogowanych: 0, gości: 1