Jak załadować TStringList do bazy PostgreSQL?

0

Witam Wszystkich.

Mam pytanie? Czy ktoś może podpowiedzieć jak dane ze TStringList załadować do przykładowej tabeli w postgresql. Dla przykładu podam:

                                                                                                  nr kol   1234  
   sl := TStringList.Create; // w tej liście znajdują się np dwie linijki liczb linia nr 1 2564
                                                                                                 linia nr 2 7198

Chcę, aby każda kolumna mogła być przypisania konkretnej do konkretnego polu w tabeli. Dla przykładu podam:

Niech tabela nazywa się Dane a pola w niej to D_1; D_W1; D_2; D_W2; D_3; D_W3; D_4; D_W4
Chciałby, aby do pól:

 D_W1; D_W2; D_W3; D_W4
  2         5         6         4
  7         1         9         8

Jak widać chcę mieć możliwość sterowania wpisaniem w pętli do pól tabeli konkretnej kolumny z TStringListy. Oczywiście podałem dla przykładu dwa wiersze, domyślacie się że tych wierszy może być 100 000 lub 50 000. Ilość wierszy nie jest istotne. Istotne jest ilość kolumn w TStringList i możliwość przypisania konkretnej kolumny np nr 1 do pola DW_1.
Oczywiście może być tak:

kolumna nr 1 do pola D_W3 itd jeśli się da.

Jeśli nie to po kolei:

kol nr 1 do D_W1;
kol nr 2 do D_W2 ;
kol nr 3 do D_W3 
kol nr 4 do D_W4;

Mam nadzieję że dobrze wytłumaczyłem o co mi chodzi. Z góry dziękuję za pomoc w tej sprawie. Znaki w TSTRINGLIST nie są odzielone niczym tj. spacją czy średnikiem lub innym znakiem. Lista jest zapisana tak : 0256 tak wygląda 1 linia. pod nią kolejna linia 5698 itd.

Dłuższy

0

Procedura dodające dane, za pomoca FireDAC:

procedure TFoo.AppendData(const AST: TStringList; const AFields: string);

  function ParseFields(const AFields: string; const APrefix : string = '') : string;
  var
    lStrArray : TArray<string>;
    I         : Integer;
  begin
    lStrArray := AFields.Split([',', ';'], ExcludeEmpty);

    if not APrefix.IsEmpty then
      for I := Low(lStrArray) to High(lStrArray) do
        lStrArray[i] := APrefix + lStrArray[i];

    Result := Result.Join(', ', lStrArray);
  end;

var
  i       : Integer;
  lCommand: IFDPhysCommand;
  lToken  : string;
  lFields : TArray<string>;
  J       : Integer;
begin
  if Assigned(AST) and (AST.Count > 0) then
  begin
    // conMain, to jest FireDAC Connection
    conMain.ConnectionIntf.CreateCommand(lCommand);
    lCommand.Options.FormatOptions.DefaultParamDataType := ftInteger;
    lCommand.CommandText := Format('insert into Dane(%s) values(%s)', [ParseFields(AFields), ParseFields(AFields, ':')]);
    // Użyj Array DML, będzie bardzo szybko
    lCommand.Params.ArraySize := AST.Count;

    lFields := AFields.Split([',', ';'], ExcludeEmpty);

    i := 0;
    for lToken in AST do
    begin
      for J := Low(lFields) to High(lFields) do
        lCommand.Params[J].Values[i] := lToken.Chars[j];
      Inc(i);
    end;

    lCommand.Execute(lCommand.Params.ArraySize);
  end;
end;

Użycie:

procedure TFooo.Test;
var
  lST: TStringList;
begin
  lST := TStringList.Create;
  try
    lST.Add('1234');
    lST.Add('4562');
    lST.Add('7895');

    AppendData(lST, 'D_W1;D_W2;D_W3;D_W4');
  finally
    lST.Free;
  end;
end;
0

Dzięki za tak szybką reakcję. Przystosowałem kod do moje bazy danych trochę wywala w tym miejscu

  i := 0;
    for lToken in AST do
    begin
      for J := Low(lFields) to High(lFields) do
        lCommand.Params[J].Values[i] := lToken.Chars[j];
      Inc(i);
    end;

Pierwsze przejście pętli jest Ok. zakres Pól liczy od O to jest ok. Przy drugim przejściu gdy J=1 też jest ok, ale przy ostatnim przejściu gdy J=2 wywala błąd:

"Argument out of range" - sygnalizuje przekroczenie tablicy. Na moje potrzeby skróciłem TstringList do dwóch kolumn.

    lST.Add('12');
    lST.Add('45');
    lST.Add('78');

tak więc powinien do tabeli D_W1 przypisać wiersze 1,4,7 , a do tabeli D_W2 przypisać wiersze 2,5,8 oczywiście licząc po kolumnach.

Jeszcze jedno moja lista jest wygenerowana i znajdują się w niej 100000 wierszy w dwóch trzech kolumnach. Mam taki kod do wstawiania listy do Stringgrida a chciałby aby wstawiać do tabeli oczywiście twój patent

AppendData(lST, 'D_W1;D_W2;D_W3;D_W4');

jest Ok po wstawiam kolumny z TStringListy do kolumn które chce i o to chodzi. Ale jakbyś mógł ten kod zamienić na tablę a nie Stringgrida to byłoby ok. Po prostu nie ważne jaka jest TStringLista to zawsze po kolumnach można wstawić do Tabeli.

  // Zliczenie maksymalnelnej liczby kolumn
  iCols := 0;
   for i := 0 to sl.Count-1 do begin
     if Length(sl[i])+1>iCols then
       iCols := Length(sl[i])+1;
  end;

    // numeracja nagłówków kolumn
    for j := 1 to iCols-1 do
     begin
      AdvStringGrid1.Cells[j,0] := IntToStr(j);
     end;


    // Wypełnienie siatki
      AdvStringGrid1.RowCount := sl.Count+1;
      AdvStringGrid1.ColCount := iCols;
      AdvStringGrid1.DefaultColWidth := 18;
      AdvStringGrid1.ColWidths[0] := 64;

 // wstawianeie danych ze zmiennej Sl do Stringgrida
    for i := 0 to sl.Count-1 do
     begin
      ARow := i+1;
      ss := sl[i];
       for j := 1 to Length(ss) do
        begin
        ACol := j;
         AdvStringGrid1.Cells[ACol,ARow] := ss[j];
          AdvStringGrid1.Cells[0,ARow] := Format('%d',[i+1]);
        end;
     end;
   end;

// ten kod chodzi. Twoja propozycja jest lepsza z uwagi na to, że wpisuję pola do których mam być kierowana konkretna kolumna ze zmiennej sl. 

W związku z błędem jaki mi wywala. Może coś robię nie tak, a więc proszę o pomoc. Dla twojej uwagi też korzystam z komponentów FireDac.

Wcześniej nie pokazywałem tego kodu bo chciałem zobaczyć czy ktoś ma inny pomysł na rozwiązanie tego problemu. Uważam że Twoja metoda jest zdecydowanie lepsza niż moja. Poza tym w mojej nie mogę kierować zapisem do konkretnej kolumny i ponadto wpisuje do Stringgrida, a nie do Bazy danych.

Tak więc czekam na podpowiedź no i usunięcie błędu lub wskazanie mojego błędu. Dla jasności procedurę wywołująca przypisałem do Buttona.

procedure TForm1.Button215Click(Sender: TObject);
var
  lST: TStringList;
begin
  lST := TStringList.Create;
  try
    lST.Add('12');
    lST.Add('45');
    lST.Add('78');

    AppendDatabase(lST, 'inwestycje_srednia; eksploatacje_srednia');
  finally
    lST.Free;
  end;
end;

Podziękowania dla user2324 jeśli by Ci nie przeszkadzało prowadzenie korespondencji e-mail to proszę napisz
[email protected]

pozdrawiam
Dluższy

dodanie znaczników <code class="delphi"> i `` - furious programming

0

A ja poproszę, bo przeszkadza tutaj brak tagowania. Abyś powstawiał fragmenty kodu w odpowiednie znaczniki delphi.

0

@dluzszy hmm...
Po pierwsze - niestety nie masz pojęcia jak ten kod działa. Gdybyś miał, to ten błąd wyłapał byś od razu. Wiesz jak się używa debuggera? To go użyj.
Po drugie - to był przykład, a nie gotowe rozwiązanie. Chcesz gotowca? Ok - ile płacisz?
Po trzecie - no ja Cię przerpaszam, ale wyjątki i sprawdzenia możesz chyba zrobic sobie sam, prawda? Specjalnie ich nie robiłem, bo nie znam wymagań. A Twój opis problemu... szkoda komentować.
I po czwarte - w innym poście nie odpowiedziałeś na cholerę chcesz ładować dane do StringGrida, zamiast do DBGrida. Nie tylko nie odpowiedziałeś, ale też pyskowałeś. Nieładnie.

Ale niech będzie;

//MMWIN:CLASSCOPY
unit _MM_Copy_Buffer_;

interface

type
  TFoo = class
  strict private
    type
      EFooException = class(Exception);
    const
      cErr_ParamsCount = 'Niezgodna liczba parametrów dla tokenu [%s].' + sLineBreak +
                         'Ilość wartości w tokenie [%d].' + sLineBreak +
                         'Oczekiwana ilość parametrów w bazie danych [%d].';
      cErr_EmptyFields = 'Nie zdefinowano pól do których mają zostać przypisane dane.';
  strict private
    FConnection: TFDConnection;
  strict protected
    function ParseFields(const AFields: string; const APrefix : string = '') : string;
  public
    constructor Create(AConnection : TFDConnection);
    procedure AppendData(const AST: TStringList; const AFields: string);
  end;

implementation

procedure TFoo.AppendData(const AST: TStringList; const AFields: string);
var
  i       : Integer;
  lCommand: IFDPhysCommand;
  lToken  : string;
  J       : Integer;
begin
  if Assigned(AST) and (AST.Count > 0) then
  begin
    // conMain, to jest FireDAC Connection
    FConnection.ConnectionIntf.CreateCommand(lCommand);
    lCommand.Options.FormatOptions.DefaultParamDataType := ftInteger;
    lCommand.CommandText := Format('insert into Dane(%s) values(%s)', [ParseFields(AFields), ParseFields(AFields, ':')]);
    // Użyj Array DML, będzie bardzo szybko
    lCommand.Params.ArraySize := AST.Count;

    i := 0;
    for lToken in AST do
    begin
      if lToken.Length <> lCommand.Params.Count then
        raise EFooException.CreateFmt(cErr_ParamsCount, [lToken, lToken.Length, lCommand.Params.Count]);

      for J := 0 to lCommand.Params.Count - 1 do
        lCommand.Params[J].Values[i] := lToken.Chars[j];
      Inc(i);
    end;

    lCommand.Execute(lCommand.Params.ArraySize);
  end;
end;

constructor TFoo.Create(AConnection: TFDConnection);
begin
  inherited Create;
  FConnection := AConnection;
end;

function TFoo.ParseFields(const AFields, APrefix: string): string;
var
  lStrArray : TArray<string>;
begin
  if AFields.IsEmpty then
    raise EFooException.Create(cErr_EmptyFields);

  lStrArray    := AFields.Split([',', ';'], ExcludeEmpty);
  lStrArray[0] := APrefix + lStrArray[0];

  Result := Result.Join(', ' + APrefix, lStrArray)
end;

end.

Używasz analogicznie jak poprzednio, z tym że musisz powołać do życia obiekt klasy TFoo - ale to oczywista oczywistość...
Co do ładowania takiej ilośc danych do StringGrida (100K wierszy?); to nie jest dobry pomysł, a jeżeli est tego więcej to powinieneś użyć czegoś co wspiera tryb wirtualny.
A więc będzie to TDrawGrid, TListView lub VirtualTreeView. Z kodu widzę, że używasz StringGrida do TMSa - nie wiem czy on wspiera tryb wirutalny. Jeżeli tak, powinieneś go użyć.

0

Witaj user2324

Na początek wielkie dzięki. Teraz może nie powinienem, ale skoro zaczepiłeś mnie o innego posta. Jak widzisz wszystkie moje posty mają charakter zapytań. Nikogo nie obrażam i nie robię wycieczek personalnych do nikogo, chyba że mnie ktoś zaczepi to też staram się grzecznie odpowiadać. Skoro uważasz że cytat:

" Próbujesz być w [CIACH!] grzeczny aby inni zobaczyli jaki to z ciebie "kurturarny (pisownia zamierzona) dżentelmen" a zamiast tego wychodzi słoma z butów. Takich jak ty, którzy wszystko wiedzą najlepiej a trzech linijek kodu do kupy nie potrafią skleić było tutaj już od groma." Koniec cytatu.
Nie mam zamiaru odpowiadać na zaczepki. Jeżeli ktoś prosi o pomoc bo nie jest tak dobry jak niektóre osoby w sieci. To chyba o to chodzi. Nikt nie prosi o napisanie całego programu tylko o rozwiązanie jakiegoś problemu. Między innymi po to powstał internet.

Teraz odnośnie debuggera oczywiście, że to robiłem ponieważ, skąd bym widział w którym miejscu wywala się kod i przecież wstawiłem linijkę. I na koniec. Myślę że skromność jest największą cechą człowiek. Pomoc drugiem jest czymś co budzi wielki szacunek. Tobie i wszystkim, którzy pomagają innym wielkie dzięki. Do pozostałych spraw nie chcę się odnosić.

pozdrawiam

Dluższy

0
dluzszy napisał(a):

Witaj user2324
Na początek wielkie dzięki. Teraz może nie powinienem, ale skoro zaczepiłeś mnie o innego posta. Jak widzisz wszystkie moje posty mają charakter zapytań. Nikogo nie obrażam i nie robię wycieczek personalnych do nikogo, chyba że mnie ktoś zaczepi to też staram się grzecznie odpowiadać.

To Twoja opinia - inni mieli inną na ten sam temat.

Skoro uważasz że cytat:
" Próbujesz być w [CIACH!] grzeczny aby inni zobaczyli jaki to z ciebie "kurturarny (pisownia zamierzona) dżentelmen" a zamiast tego wychodzi słoma z butów. Takich jak ty, którzy wszystko wiedzą najlepiej a trzech linijek kodu do kupy nie potrafią skleić było tutaj już od groma." Koniec cytatu.

Oczywiście, tak było. Tylko, jakim cudem zapomniałeś wcześniejszych wpisów swoich i innych, które są istotne i doprowadziły do takiego wpisu?
Szczerze - zasłużyłeś sobie na takie traktowanie i nie jesteś bez winy.
Zresztą, co mnie to....

Nie mam zamiaru odpowiadać na zaczepki. Jeżeli ktoś prosi o pomoc bo nie jest tak dobry jak niektóre osoby w sieci. To chyba o to chodzi. Nikt nie prosi o napisanie całego programu tylko o rozwiązanie jakiegoś problemu. Między innymi po to powstał internet.

Wiesz co, odrobinę pokory by Ci się przydało bo masz strasznie irytujące bicia.
Skoro wiesz, że nie wiesz i prosisz o pomoc, to dostosuj się do tych, którzy chcą i wiedza jak Ci pomóc. Nawet, jeśli Ci się to nie podoba.
A jak Ci się nie podoba, to nie zawracaj nikomu doopy i też będzie dobrze.

Teraz odnośnie debuggera oczywiście, że to robiłem ponieważ, skąd bym widział w którym miejscu wywala się kod i przecież wstawiłem linijkę.

I nie poprawiłeś "błędu", który błędem nie był.
Nie odpowiedziałeś na pytanie - wiesz dokładnie jak ten kod działa?

I na koniec. Myślę że skromność jest największą cechą człowiek. Pomoc drugiem jest czymś co budzi wielki szacunek. Tobie i wszystkim, którzy pomagają innym wielkie dzięki. Do pozostałych spraw nie chcę się odnosić.

Skoro wyznajesz taką szczytną zasadę to, dlaczego jej nie hołdujesz? Wybacz, ale skromny to Ty na pewno nie jesteś - sądząc po tym co i w jaki sposób piszesz. Ale to moja opinia ;-)

I na koniec - zaspokoisz moją ciekawość i powiesz mi dlaczego uparłeś sią na ładowanie danych do StringGrida?
Jeżeli opiszesz wszystko ślicznie, czyli bez skrótów myślowych, od których roi się w Twoich opisach! Zauważ, że my nie wiemy, co dokładnie masz zrobić, a najgorsze co możesz powiedzieć - to "nie chcę o tym mówić, bo to nieistotne dla istoty problemu".
Tak więc opisz dokładnie co robisz i dlaczego tak jak sześciolatkowi, a ja Ci pokażę jak ładować te dane do StingGrida tak jak chcesz. Pod warunkiem, że dalej będziesz chciał i opiszesz to w sposób zrozumiały.

0

@user2324 - przypominam o zachowaniu kultury i pozostaniu przy rozwiązywaniu problemu, a nie dyskusji na tematy niezwiązane z poruszanym problemem; Jeżeli nie podoba Ci się cokolwiek w wypowiedziach pytacza czy kogokolwiek innego, to albo zgłoś to moderacji, albo po prostu skończ się udzielać w tym wątku; Twoja kultura też pozostawia wiele do życzenia, więc dopóki sam nie będziesz umieszczać kulturalnych wypowiedzi, to zakończ upominanie innych;

Po drugie nie omijaj cenzury - po to ona jest, aby zwroty takie jak d*** były maskowane; Jeżeli nie potrafisz zachować choćby pozorów bycia kulturalnym i inteligentnym - skończ się wypowiadać; Odciągasz uwagę od poruszanego problemu i prowokujesz do offtopu, więc następne tego typu posty będą kasowane;

Próbujesz być w [CIACH!] grzeczny aby inni zobaczyli jaki to z ciebie "kurturarny (pisownia zamierzona) dżentelmen" a zamiast tego wychodzi słoma z butów. Takich jak ty, którzy wszystko wiedzą najlepiej a trzech linijek kodu do kupy nie potrafią skleić było tutaj już od groma.

Nie wiem czyj to cytat, ale łby polecą, jeśli ktokolwiek będzie się w ten sposób wypowiadał; Jeśli komuś coś u kogoś nie pasuje, to proszę się upominać w PM'kach, a nie w publicznej części serwisu; Forum jest po to, aby rozwiązywać problemy dotyczące programowania;

Poza tym w wypowiedziach @dluzszy'ego nie widzę wypowiedzi niekulturalnych, wręcz przeciwnie;


Podsumowując - koniec offtopu; Albo dyskusja będzie dotyczyć pierwotnego problemu, albo wątek zostanie zamknięty i nic nie wnoszące do tematu posty zostaną skasowane.

0

Chyba nastąpiła blokada tego wątku. Nie mogę udzielić odpowiedzi.
Dluzszy.

0

User2324. Wielkie dzięki za podpowiedz. Nie chcę odnosić się do uwag. Wcześniej napisałem, ale mój post został przyblokowany. Tak więc kończę wycieczki personalne, których mam nadzieję nie używałem jak to stwierdził "Furious Programming".

Do rzeczy:

  1. Po co mi Stringgrid. Odpowiadając krótko, ponieważ nie tylko mogę edytować dane, ale jeszcze ładnie prezentować. Jak zauważyłeś korzystam z komponentów TMS i dzięki nim mogę szybko i ładnie prezentować dane. Bo nie tylko chodzi o pokazanie danych, tak jak jest to w DBgrid, w każdym razie o to mi też chodzi. Ale mój problem został rozwiązany przez "Johnny_Bit" i tyle w tym temacie. W jednym z postów podał procedurę, jak to zrobić i pięknie chodzi.

  2. Mój problem polega na tym, abym zmienną TStringList w której znajduje się np. 5 kolumn i 10 000 wierszy tj. razem 50 000 znaków mógł wczytać do pola w Tabeli bazy danych, w tym wypadku do PostgresSql za pomocą FireDac. I dzięki Tobie próbuję to zrealizować na tyle ile potrafię. Podałeś parę "patentów", jak się do tego zabrać i dzięki za to. Tak jak powiedziałeś opisałem mój problem.

Linia

 AppendDatabase(lST, 'D_W1;D_W2;D_W3;D_W4'); 

jest jednym z tych patentów. Staram się Twoje drugie rozwiązanie zaimplementować, pewnie mi zejdzie o ile w ogóle to zrobię. Ponieważ tamten kod wbrew temu co pisałeś zrozumiałem - myślę o idei. Pisząc, że coś wywala nie miałem nic złego na myśli, ponieważ byłem przekonany, że pójdzie. Oczywiście, że nie mam takiej wiedzy jak Ty, gdybym ją miał, to nie prosiłbym o podpowiedź, jak do tego problemu się zabrać. Twoja druga wersja jest inna. Próbuję ją zaimplementować i rozgryźć na ile potrafię.

0

Ok. Furious Programming; Dzięki i zostawmy to. user2324 mimo wszystko jest ok ponieważ pomaga. Myślę że każdy może mieć chwilę słabości. Jego wypowiedzi w stosunku do innego użytkownika Forum są w porządku. Mam nadzieję że moja odpowiedź będzie wystarczając dla niego i odezwie się. Po drugie nie wiem ile te osoby mają lat i może młodzieńczy wiek powoduje że chcą podzielić się swoimi wrażeniami. Dziękuję za wsparcie i myślę, że co do user2324 nie można mieć większych uwag.

0
dluzszy napisał(a):

User2324. Wielkie dzięki za podpowiedz. Nie chcę odnosić się do uwag. Wcześniej napisałem, ale mój post został przyblokowany. Tak więc kończę wycieczki personalne, których mam nadzieję nie używałem jak to stwierdził "Furious Programming".

Spoko, nim się nie przjmujemy - nic ciekawego nie powiedział, pomylił cytaty i zadał sobie trudu aby dojść kto co brzydkiego na kogo pisał.

Do rzeczy:

  1. Po co mi Stringgrid. Odpowiadając krótko, ponieważ nie tylko mogę edytować dane, ale jeszcze ładnie prezentować. Jak zauważyłeś korzystam z komponentów TMS i dzięki nim mogę szybko i ładnie prezentować dane. Bo nie tylko chodzi o pokazanie danych, tak jak jest to w DBgrid, w każdym razie o to mi też chodzi. Ale mój problem został rozwiązany przez "Johnny_Bit" i tyle w tym temacie. W jednym z postów podał procedurę, jak to zrobić i pięknie chodzi.

Dwie rzeczy bym tam (tam czyli w ładowaniu danych do string grida) zmienił i by było dobrze. Do bardzo dobrze, to trzeba jednak więcej przysiąść.
Jeśli ma być bardzo dobrze to powinien być tryb wirtualny, rozumiesz dokładnie o czym mowa? Bo 10K wierszy to nie problem, ale już np. 100K czy milion to już będzie zadyszka...
Poza tym - dlaczego dane są w TStringList?
Ładujesz te dane z pliku do TStringList? Jesli tak, to dlaczego nie od razu z pliku? Będzie szybciej i zajmie znacznie mniej pamięci.

Co do DBGrida - nie zgadzam się z tym co napisałeś, ale i też nie znam wszystkich Twoich wymagań co do prezentacji i oczekiwanego zachowania kontrolki.

  1. Mój problem polega na tym, abym zmienną TStringList w której znajduje się np. 5 kolumn i 10 000 wierszy tj. razem 50 000 znaków mógł wczytać do pola w Tabeli bazy danych, w tym wypadku do PostgresSql za pomocą FireDac.

Eeee... ale tam było wiele pól, a nie jedno - ja to tak zrozumiałem.

I dzięki Tobie próbuję to zrealizować na tyle ile potrafię. Podałeś parę "patentów", jak się do tego zabrać i dzięki za to. Tak jak powiedziałeś opisałem mój problem.
Linia

 AppendDatabase(lST, 'D_W1;D_W2;D_W3;D_W4'); 

No dobra, ale masz już wszystko; ladowanie do bazy danych i do StringGrida.
Co jeszcze?

Bo ja mam wrażenie, że chcesz ładować dane do dynamicznie tworzonego StringGrida (dynamika w kontekście ilości pól i ich nazw - podobnie ja zrobiłem to z FireDAC i bazą danych), a potem ze StringGrida do bazy danych.
Dobrze mi się wydaje?

jest jednym z tych patentów. Staram się Twoje drugie rozwiązanie zaimplementować, pewnie mi zejdzie o ile w ogóle to zrobię. Ponieważ tamten kod wbrew temu co pisałeś zrozumiałem - myślę o idei. Pisząc, że coś wywala nie miałem nic złego na myśli, ponieważ byłem przekonany, że pójdzie. Oczywiście, że nie mam takiej wiedzy jak Ty, gdybym ją miał, to nie prosiłbym o podpowiedź, jak do tego problemu się zabrać. Twoja druga wersja jest inna. Próbuję ją zaimplementować i rozgryźć na ile potrafię.

Eee.... to trzeba było tak od razu, że newbie jesteś. A skoro tak, to wierz mi - nie rozumiesz tego kodu do końca. On jest lekko podchwytliwy ;-)
np. nie ma zwolnienia zmiennej lCommand - dlaczego?

0

Zacznę od końca.

Dlaczego nie zwalniasz zmiennej lCommand. Wydaje mi się że dlatego aby:

  1. Jest zmienną która ma przypisać dane do pola tablicy ( bazy danych ) za pomocą funkcji CommandText, świadczy o tym ta linia
 lCommand.CommandText := Format('insert into Dane1(%s) values(%s)', [ParseFields(AFields), ParseFields(AFields, ':')]); 
  1. Po pętli for przypisuje dane za pomocą parametru do tablicy, świadczy o tym ta linia
   lCommand.Execute(lCommand.Params.ArraySize); 

Myślę że tak jest. Pewnie może się mylę. Ale jak wiesz biegły to ja nie jestem aż tak.

Stringgrid - Odnośnie Stringgrida już napisałem że procedurę pobrania z bazy danych za pomocą FDQuery już mam. Stringgrida ma służyć do prezentacji danych. Co do prezentacji każdy ma jakiegoś fioła. U mnie jest nim Stringgrid.
**
TStringgrid** - cały mój problem polega na tym, że nie wiem jak zapisać dane do poszczególnych kolumn w tabeli ( postgresql). Dla jasności. W zmiennej STL przechowuje dane znakowe z jakieś procedury np.

 procedure Wstaw; 
  STL   := TStringList.Create; 
                       Wstaw(STL);


Chcę tak jak wcześniej pisałem dane z

 procedure Wstaw; 

przypisane do zmiennej **STL ** wstawić do tabeli o nazwie Dane1 to co podałeś w linii

   lCommand.CommandText := Format('insert into Dane1(%s) values(%s)', [ParseFields(AFields), ParseFields(AFields, ':')]);

po wszystkich pętlach wywołanie pod Buttonem zrobiłem tak:

procedure TForm1.Button215Click(Sender: TObject);
var
  lST: TStringList;

begin
  lST := TStringList.Create;
  try
    lST.Add('7678');
    lST.Add('8546');
    lST.Add('7923');

  AppendDane(lST, 'D_W1;D_W2;D_W3;D_W4');
  finally
    lST.Free;

  end;
end; 

Jak słusznie zauważyłeś Twoja pierwsza procedura nie powinna być przeze mnie wpisana lecz powinienem trochę ja przerobić. Tak naprawdę to do wywołania potrzebna jest mi zmienna moja " STL" z procedury Wstaw. Wywołanie mogłoby wyglądać tak:

procedure TForm1.Button215Click(Sender: TObject);

begin
  try
  AppendDane(STL, 'D_W1;D_W2;D_W3;D_W4');
  finally
    STL.Free;

  end;
end; 

Dlaczego tak, ponieważ zmienna **STL ** jest już wcześniej zadeklarowana i do niej są przypisane dane a ja je tylko chcę umieścić w konkretnym polu tabeli (bazy danych postgresql).

**Dlaczego nie do pliku ** - Na moje potrzeby właśnie tym plikiem jest konkretna tabela i pole w bazie danych (Postgresql).

**Ostatnia wiadomość Twoja z kodem **- czytając zalecenia doświadczonych programistów, którzy radzą aby każda klasa była w osobnym unit-cie cały twój kod wkleiłem do osobnego unitu. Bardzo podoba mi się to rozwiązanie ponieważ jest czytelne. Ale za nic nie wiem jak wywołać w innym Unicie tą klasę, aby nie być gołosłowny pokazuję, jak to zrobiłem:

 

unit ULadowanie_Postgresql;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.Imaging.jpeg, Vcl.ExtCtrls,
  Vcl.StdCtrls,  AdvPanel, Vcl.Grids, AdvObj, BaseGrid,
  AdvGrid, DBAdvGrid, AdvCGrid, Vcl.Menus, AdvMenus, AdvPageControl,
  Vcl.ComCtrls, Vcl.ImgList, System.Actions, Vcl.ActnList, listlink, AdvGroupBox,
  AdvProgr, AdvProgressBar, AeroButtons, FireDAC.Stan.Intf, FireDAC.Stan.Option,
  FireDAC.Stan.Param, FireDAC.Stan.Error, FireDAC.DatS, FireDAC.Phys.Intf,
  FireDAC.DApt.Intf, FireDAC.Stan.Async, FireDAC.DApt, FireDAC.UI.Intf,
  FireDAC.Stan.Def, FireDAC.Stan.Pool, FireDAC.Phys, Data.DB,
  FireDAC.Comp.Client, FireDAC.Comp.DataSet, FireDAC.Phys.PG,
  FireDAC.VCLUI.Wait, FireDAC.Comp.UI,ShellAPI, Datasnap.DBClient;

type
  TFoo = class
  strict private
    type
      EFooException = class(Exception);
    const
      cErr_ParamsCount = 'Niezgodna liczba parametrów dla tokenu [%s].' + sLineBreak +
                         'Ilość wartości w tokenie [%d].' + sLineBreak +
                         'Oczekiwana ilość parametrów w bazie danych [%d].';
      cErr_EmptyFields = 'Nie zdefinowano pól do których mają zostać przypisane dane.';
  strict private
    FConnection: TFDConnection;
  strict protected
    function ParseFields(const AFields: string; const APrefix : string = '') : string;
  public
  procedure AppendDane1(const AST: TStringList; const AFields: string);
  constructor Create(AConnection : TFDConnection);
  end;

implementation

uses U_Dobor_Kanalizacji_Menu_Glowne;



constructor TFoo.Create(AConnection: TFDConnection);
begin
  inherited Create;
  FConnection := AConnection;
end;


function TFoo.ParseFields(const AFields, APrefix: string): string;
var
  lStrArray : TArray<string>;
begin
  if AFields.IsEmpty then
    raise EFooException.Create(cErr_EmptyFields);

  lStrArray    := AFields.Split([',', ';'], ExcludeEmpty);
  lStrArray[0] := APrefix + lStrArray[0];

  Result := Result.Join(', ' + APrefix, lStrArray)
end;


procedure TFoo.AppendDane1(const AST: TStringList; const AFields: string);
var
  i       : Integer;
  lCommand: IFDPhysCommand;
  lToken  : string;
  J       : Integer;
begin
  if Assigned(AST) and (AST.Count > 0) then
  begin

    FConnection.ConnectionIntf.CreateCommand(lCommand);
    lCommand.Options.FormatOptions.DefaultParamDataType := ftInteger;
    lCommand.CommandText := Format('insert into Dane1(%s) values(%s)', [ParseFields(AFields), ParseFields(AFields, ':')]);

    lCommand.Params.ArraySize := AST.Count;

    i := 0;
    for lToken in AST do
    begin
      if lToken.Length <> lCommand.Params.Count then
        raise EFooException.CreateFmt(cErr_ParamsCount, [lToken, lToken.Length, lCommand.Params.Count]);

      for J := 0 to lCommand.Params.Count - 1 do
        lCommand.Params[J].Values[i] := lToken.Chars[j];
      Inc(i);
    end;

    lCommand.Execute(lCommand.Params.ArraySize);
  end;
 end;
end.

Gdzie:

  1. AppendDane1 - to procedura, która ma przypisać dane ze zmiennej STL ** (StringList) do Tabeli o nazwie Dane1 ** ( Bazy danych - postgresql).
  2. Dane1 - to nazwa tabeli w mojej bazie danych
  3. A to wszystko po to, aby dane ze zmiennej **STL ** wstawić do pól
 AppendDane(STL, 'D_W1;D_W2;D_W3;D_W4'); 

Jak wywołać w innym unicie Twoją Klasę, tak aby dane, ze zmiennej **STL ** wstawić do tabeli **Dane1 ** ( bazy danych).

w opisie znalazłem:

nazwa_unitu.nazwa_procedury;

w moim przypadku

ULadowanie_Postgresql.AppendDane1; ale nie działa mimo że mam powiązane ze sobą unity ( alt + F11).

Na tym mój problem polega. Gdybyś teraz podpowiedział, jak mam napisać procedurę zapisująca dane ze zmiennej **STL ** to byłby wdzięczny. Myślę o rozwiązaniu 1 Klasa 1 Unit. Ponieważ jest porządek i zawsze z każdego miejsca programu można się odwołać. Jeszcze jedna uwaga. W zmiennej **STL ** może być 3 kolumny i 10000 wierszy a innym razem 5 kolumn i 1000 wierszy . chodzi o to aby wywołanie było uniwersalne tak jak to mam gdy przypisuję zmienną bezpośrednio do Stringrida. Tam sprawdzam ilość kolumn pętlą for i wiersz po wierszu zapisuję do Stringgrida. Niestety nie wiem jak zapisywać do wybranych kolumn w Stringgridzie, ale teraz mi to nie jest potrzebne. Potrzebuję zapisu zmiennej **STL ** do tabeli bazy danych i do wybranej kolumny.

Mam nadzieję że wyjaśniłem mojej problemy dokładnie.

pozdrawiam
Dłuższy

0

Mały błąd

 
 AppendDane(STL, 'D_W1;D_W2;D_W3;D_W4'); 

powinno być

 
 AppendDane1(STL, 'D_W1;D_W2;D_W3;D_W4'); 

Tabela ma nazwę Dane1.

pozdrawiam

Dłuższy

0

Wywołanie w innym Unicie

Pisząc o wywołaniu Twojej klasy

  TFoo = class 

w innym unicie miałem na myśli wywołanie procedury

  procedure AppendDane1(const AST: TStringList; const AFields: string); 

i jak wcześniej pisałeś powołanie do życia klasy TFoo = class

. 
Jak to zrobić nie wiem, choć kombinuję. 

Dłuższy
0

Pytanie?

  1. Dlaczego w Twojej klasie o nazwie TFoo konstruktor został przypisany w ten sposób
 constructor Create(AConnection : TFDConnection);

Rozumiem że klasa musi połączyć się przez komponent FDConnection1 z bazą danych. Dla mnie to oczywiste. Ale gdy chcę wywołać klasę w taki sposób

 procedure TForm1.Button215Click(Sender: TObject);
var SS : TFoo;
begin

 SS:= TFoo.Create(); // system zgłasza za mała ilość parametrów a w zasobach jest do dyspozycji parametr Self oraz FDConnection1
  try
  SS.AppendData1(sl,'D_W1;D_W2;D_W3;D_W4' );

  finally
    SS.Free;
  end;
end;

To kod się kompiluje gdy wstawię do

  TFooCreate(FDConnection1)

, ale procedura

   SS.AppendData1(sl,'D_W1;D_W2;D_W3;D_W4' ); 

nie jest uruchomiona.

Przypominam że zmienna sl jest typu TStringList i w niej znajdują się dane które chce przypisać polom tabeli o nazwie Dane1

Jak byś mógł powiedzieć gdzie leży błąd byłbym wdzięczny.

Dłuższy

P.S. A może ktoś inny może podpowiedzieć

0

Ostatnia Uwaga

zrezygnowałem ze swojej zmiennej i wstawiłem Twoje wywołanie tj.

 

procedure TForm1.Button215Click(Sender: TObject);
var SS_1 : TFoo;
    lST: TStringList;
begin
    lST := TStringList.Create;
    SS_1:= TFoo.Create(FDConnection1);

   try
    lST.Add('1234');
    lST.Add('4562');
    lST.Add('7895');

    SS_1.AppendDane(lST,'D_W1;D_W2;D_W3;D_W4' );

  finally
    SS_1.Free;
    lST.Free;
  end;
end;

Pokazuje błąd FireDac - że relacja Dane1 nie istnieje. w debugger wywala błąd na tej linii:

 lCommand.CommandText := Format('insert into Dane1(%s) values(%s)', [ParseFields(AFields), ParseFields(AFields, ':')]); 

mam problem z parametrem konstruktora

  SS_1:= TFoo.Create(FDConnection1); 

to wszystko co mogę wstawić, aby program się kompilował. Konstruktor prosi o parametr, bo inaczej wywala błąd. Nie wiem jaki mu inny parametr wstawić bo po naciśnięciu ctr + spacja lista parametrów jest ograniczona i tylko wstawienie FDConnection1 kompiluje kod. Nie wiem co wpisać. Bez parametru konstruktora program się nie kompiluje. Nie wiem co robić. Cała klasa jest w porządku, ponieważ przechodzi i wstawia dane z listy TStringgrid te wstawione ręcznie. To tyle prośba o wskazanie co robię nie tak.

0
dluzszy napisał(a):

Ostatnia Uwaga

zrezygnowałem ze swojej zmiennej i wstawiłem Twoje wywołanie tj.

 

procedure TForm1.Button215Click(Sender: TObject);
var SS_1 : TFoo;
    lST: TStringList;
begin
    lST := TStringList.Create;
    SS_1:= TFoo.Create(FDConnection1);

   try
    lST.Add('1234');
    lST.Add('4562');
    lST.Add('7895');

    SS_1.AppendDane(lST,'D_W1;D_W2;D_W3;D_W4' );

  finally
    SS_1.Free;
    lST.Free;
  end;
end;

Pokazuje błąd FireDac - że relacja Dane1 nie istnieje. w debugger wywala błąd na tej linii:

 lCommand.CommandText := Format('insert into Dane1(%s) values(%s)', [ParseFields(AFields), ParseFields(AFields, ':')]); 

A tabela Dane1 w ogóle istnieje w bazie danych, do której się łączysz i masz do niej uprawnienia?
Bo innego wytłumaczenia nie ma...

mam problem z parametrem konstruktora

  SS_1:= TFoo.Create(FDConnection1); 

to wszystko co mogę wstawić, aby program się kompilował. Konstruktor prosi o parametr, bo inaczej wywala błąd. Nie wiem jaki mu inny parametr wstawić bo po naciśnięciu ctr + spacja lista parametrów jest ograniczona i tylko wstawienie FDConnection1 kompiluje kod. Nie wiem co wpisać. Bez parametru konstruktora program się nie kompiluje. Nie wiem co robić. Cała klasa jest w porządku, ponieważ przechodzi i wstawia dane z listy TStringgrid te wstawione ręcznie. To tyle prośba o wskazanie co robię nie tak.

W konstruktorze masz podać Twoje TFDConnection, które masz gdzieś tam ustawione i łączysz się nim do konkretnej bazy danych.
To chyba oczywiste, czy nie?

0

Odpowiadam

  1. Baza danych na podstawie FDConnection1 jest połączona ponieważ, gdyby tak nie było to w DBgridzie nie wyświetlały się dane z tabeli Dane1.
  2. Szukam w dokumentacji Firedac i SQL i piszą, że mimo tego trzeba uruchomić linię. typu
 FDQuery.open lub FDtable.Open.

Uruchamiam i nic z tego.
3. Jeśli ktoś mam całą procedurę wstawienia rekordu to proszę podajcie ponieważ ta moja nie działa. Otwieram bazę, odświeżam, robię append, robię edit, commit i na kocu post. Zaznaczam że z bazą jestem prawidłowo połączony ponieważ gdy robię na bazie Select w FDquery to system zwraca całą tabelę wyświetlając wszystkie rekordy.

czekam na jakieś propozycję.
Dłuższy

0
dluzszy napisał(a):

Odpowiadam

  1. Baza danych na podstawie FDConnection1 jest połączona ponieważ, gdyby tak nie było to w DBgridzie nie wyświetlały się dane z tabeli Dane1.
  2. Szukam w dokumentacji Firedac i SQL i piszą, że mimo tego trzeba uruchomić linię. typu
 FDQuery.open lub FDtable.Open.

Uruchamiam i nic z tego.

Zaraz, chwila - skoro pojawiają cię się dane w DBGrid, to przecież jakoś musiałeś otworzyć (czyli wywołać metodę open lub oznaczyć Active = True, np. w Object Inspectorze w IDE - co jest zdecydowanie niefajnym rozwiązaniem.) TFDQuery lub TFDTable.
A więc uruchamiasz i co nic z tego?
Mam wrażenie, że nie ogarniasz w ogóle jak to nalezy poustawaić i jakie są zalezności pomiędzy TDataSet (tak, tak - zarówno TFDQuery jak i TFDTable dziedziczą z TDataSet, a więc są TDataSet), TDataSource i np. TDBGrid i dlatego piszesz "nic z tego".

  1. Jeśli ktoś mam całą procedurę wstawienia rekordu to proszę podajcie ponieważ ta moja nie działa.

Co znaczy, nie działa? Dlaczego nie dział - jakiś komunikat błędu? Jeśli ten co wcześniej - to dostałeś odpowiedź.
Tam nie ma żadnej magii - to **MUSI ** działać, no chyba że coś zamotałeś totalnie...

Otwieram bazę, odświeżam, robię append, robię edit, commit i na kocu post.

Jeśli w tej kolejności, to ma prawo nie działać...

Zaznaczam że z bazą jestem prawidłowo połączony ponieważ gdy robię na bazie Select w FDquery to system zwraca całą tabelę wyświetlając wszystkie rekordy.

Propozycje? Mam jedną - skoro opisujesz tak jak opisujesz (tragedia!), to nic sensownego nie da się zrobić.
Niech przemówi kod - umieść gotowy projekt z czym tam masz problem (pobieranie danych, ładowanie do StringGrida, dodawanie danych czy cokolwiek innego), a wtedy pokażę co i jak.

0

Dzięki za szybką reakcję gotowy kod jest na początku tego wątku, ale jeśli mogę podesłać cały projekt to OK. Przesyłam cały projekt w załączniku. Posiadam wersję Delphi XE5 wraz z FireDac. Baza danych Postgresql 9.3 Jeśli nie będzie ci przeszkadzać korespondencja na e-maila to proszę o to mój adres:

[email protected]
  1. Idea jest prosta chodzi o to, aby z klasy TStringList, a dokładniej ze *zmiennej *będzie można wstawiać do dowolnej kolumny dane w tym przykładzie są wartości
    '12' i wstawiamy do kolumny bazy danych D_1= 1 , D_4=2 i tak, aż skończą się dane zawarte w zmiennej "LST". Jak się domyślasz tych danych będzie około 50000 rekordów. W tym przykładzie dla uproszczenia użyłem 3 wierszy i dwóch kolumn, aby nie zaciemniać sprawy. Tabela czasem będzie posiadał 8 kolumn do których należy wstawić dane. Dane chcę wstawiać dowolnie.

Zmienna LST = ( 24567893) // każdy wiersz w tym wypadku ma osiem miejsc o wartościach wskazanych. Funkcja parser oddziela każdy znak. Po tym chcę, aby każdy znak był wstawiany do dowolnej kolumny np.: mamy kolumny D_1,D_2,D_3,D_4,D_5,D_6,D_7,D_8; ( w załączonym przykładzie są tylko cztery) i teraz chcę dowolnie kształtować wstawianie danych (żaglować) i tak:

D_1= 2, D_4= 3, D_3= 5, D_6=9, D_7=4,D_8=7; D_2 = 6; D_5= 8; Celowo wstawiam nie poklei.

uporządkowany zbór według zmiennej LST, a więc LST = ( 24567893);

D_1= 2,D_7=4, D_3= 5,D_2 = 6;D_8=7;D_5= 8, D_6=9, D_4= 3;

Jak widać chciałby mieć dostęp do każdej pozycji w zmiennej LST, która jest typu TStringList i mieć możliwość wstawiać do wybranej kolumny w bazie danych.
Mam nadzieję, że teraz jest wszystko wiadomo.

W tym projekcie wstawiłem kilka przycisków z czego przycisk o nazwie "Wstaw rekordy do kolumny D_1 i D_4 TStringListy" jest tym przyciskiem ktróy jest dla mnie najważniejszy, aby go oprogramować. Pozostałe jeśli możesz oprogramować, to będę wdzięczny i wtedy rzeczywiście przekonam się co robię źle.

pozdrawiam dłuższy

0
dluzszy napisał(a):

Dzięki za szybką reakcję gotowy kod jest na początku tego wątku, ale jeśli mogę podesłać cały projekt to OK. Przesyłam cały projekt w załączniku.

OK, super - to teraz jeszcze pozbądź się kontrolek z TMS to będę mógł to skompilować.
Ale najpierw daj DDL'a dla tabeli eksploatacje; chodzi o kod SQL który utworzy taką tabelę, wiesz;

create table eksploatacje(pole int, pole2 int)

Muszę mieć jakąś bazę do testowania...

0

Przesyłam kod SQL:

-- Table: eksploatacje

-- DROP TABLE eksploatacje;

CREATE TABLE eksploatacje
(
  id_eksploatacje serial NOT NULL,
  id_zestawienie_wag integer,
  "D_1" "char",
  "D_2" "char",
  "D_3" character(1),
  "D_4" integer,
  "Status" character(1),
  CONSTRAINT pk_eksploatacje PRIMARY KEY (id_eksploatacje)
)
WITH (
  OIDS=FALSE
);
ALTER TABLE eksploatacje
  OWNER TO postgres;
GRANT ALL ON TABLE eksploatacje TO postgres;

-- Index: eksploatacje_pk

-- DROP INDEX eksploatacje_pk;

CREATE UNIQUE INDEX eksploatacje_pk
  ON eksploatacje
  USING btree
  (id_eksploatacje);

Co do danych: Wstaw sobie ręcznie jakieś wartości w dwóch wierszach i już będą dane. W tej sprawie nie chodzi o stare dane, tylko o nowe, które będą wstawiane. Co będzie wstawiane zakres liczb od 0 do 9 stąd pole typu "char" lub "character" i dla przykładu "integer". Jak coś to pisz.
A mam pytanie? Czy możesz zwrócić uwagę na fakt, że Dbgrid nie pokazuje wszystkich kolumn lecz tylko trzy. Nie mam formatu na szerokość kolumny a nie chce mi się definiować szerokości każdej kolumny. W ustawieniach domyślnych tego nigdzie nie ma, a ja nie chcę ustawiać ręcznie. To tyle dołączam poprawiony kod.

Dłuższy

0
dluzszy napisał(a):

Przesyłam kod SQL:
Co do danych: Wstaw sobie ręcznie jakieś wartości w dwóch wierszach i już będą dane. W tej sprawie nie chodzi o stare dane, tylko o nowe, które będą wstawiane. Co będzie wstawiane zakres liczb od 0 do 9 stąd pole typu "char" lub "character" i dla przykładu "integer". Jak coś to pisz.
A mam pytanie? Czy możesz zwrócić uwagę na fakt, że Dbgrid nie pokazuje wszystkich kolumn lecz tylko trzy. Nie mam formatu na szerokość kolumny a nie chce mi się definiować szerokości każdej kolumny. W ustawieniach domyślnych tego nigdzie nie ma, a ja nie chcę ustawiać ręcznie. To tyle dołączam poprawiony kod.
Dłuższy

OK, to ja się tym zajmę w wolnej chwili - pewnie jutro...
Co do DBGrida, on nie pokazuje trzech kolumn tylko trzy widać, bo reszta jest zbyt szeroka aby się na ekranie zmieściła - prawda?
Możesz to zrobić za pomocą DataSet.Field.DisplayWidth - resztę w manualu.
Zawsze możesz ustawić szerokość kolumn w pętelce po otwarciu danych, czyi w zdarzeniu AfterOpen.

0

I jeszcze jedno, bo dopiero teraz spojrzałem...
Na cholerę tworzysz klucz główny (Primary Key) i indeks unikalny (Unique Index) na tym samym polu w tabeli eksploatacje?
Wygląda na to, że "programujesz" w trybie shotgun, ale tak daleko nie zajedziesz... Czas ciut się podszkolić!

0

Oj, namieszałeś w tym projekcie...
W załączniku kompletny projekt z bazą danych i serwerem Firebird Embd.

0

Cóż mam odpowiedzieć - pewnie masz rację trochę namieszałem. Przerabiam teraz ten kod na Postgrsql mam nadzieję, że mi się uda. Oczywiście zamieszczę gotowy kod dla wszystkich zgodnie z tytułem wątku. Dla Ciebie serdeczne podziękowania bo teraz wiem jak mam się do tego zabrać. Jakby co mam nadzieję, że podpowiesz co ewentualnie robię źle. Chodzi mi o współpracę z Postgresql.

Jeszcze raz wielkie dzięki.

Dłuższy

0

Współpraca z PostgreSQL zaczyna się i kończy, w tym projekcie, na odpowiedniej konfiguracji połączanie do bazy danych (TFDConnection).
To wszystko.
A więc naprawdę nie wiem, jaki możesz mieć problem.
Co do zamieszczania tego gdziekolwiek - proszę nie!
Nie w Twoim wykonaniu, bo Jeszce musisz wagon soli zjeść żeby móc cokolwiek pokazać na zewnątrz ;-)
Ale pracuj, pracuj, I'm your friend ;-)

0

**Szanowni Koledzy, a może Koleżanki. **

W dniu w którym Polska reprezentacja wygrała inauguracyjny mecz z Serbami 3:0 zapamiętam długo. Z góry przepraszam za taką informację, ale dzięki wam rozwiązałem swoją bolączkę. Moje podziękowania jeszcze raz kieruję do:

1.** user2324 ** - serdeczne dzięki;
2. wloochacz - serdeczne dzięki;

Mimo, że panowie lub panie moją wiedzę ocenialiście różnie - ja tego nigdy nie robię, bez waszej pomocy, nie udało by mi się rozwiązać mojego problemu. Przypominam wszystkim tytuł mojego wątku:

**Jak załadować TStringList do bazy PostgreSQL? ** Czas najwyższy podzielić się sposobem w jakim to zostało osiągnięte. Wszystkie uwagi kolegów/koleżanek ( sorki, że tak piszę po pseudonimach wnoszę, że to Panowie, ale że nie jestem pewien to pozwalam sobie na trochę żartu) brałem do serca i dziś mogę powiedzieć - Dzięki.

Teraz do rzeczy:

  1. Dzięki user2324 dostaliśmy klasę parsująca ( separująca znaki w zmiennej TStringList)
  2. Dzięki wloochacz dostaliśmy sposób łączenia się z bazą danych i wczytywaniem TStringList z pliku. To nic, że z FireBirdem, choć pytanie było skierowane o Postgresql.
  3. Sygnalizowałem w ostatnim poście, że mam problem połączenia się z bazą Postgrsql. Oto dlaczego nie mogłem tego zrobić:

a) **Linia błędna: **

lCommand.CommandText := Format('insert into test(%s) values(%s)', [ParseFields(AFields), ParseFields(AFields, ':')]);  

b) **Linia poprawna: **

 lCommand.CommandText := Format('insert into "Test"(%s) values(%s)', [ParseFields(AFields), ParseFields(AFields, ':')]);

c) Wyjaśnienie:

nazwa tabeli w bazie danych w tym wypadku **test ** była wpisana [małymi literami i bez cudzysłowowa] w bazie miałem zdefiniowaną z dużej litery tj. Test

kolejny błąd:

d) **Linia błędna: **
SS_Klasa.AppendData(LST, 'D_1;D_2;D_3;D_4');

e) **Linia poprawna: **
SS_Klasa.AppendData(LST, '"D_1";"D_2";"D_3";"D_4"');

Jak widać pola bazy muszą być ujęte w cudzysłów i oto cała tajemnica Postgresql-a.

**Kolejny błąd: **

f) dotyczy pola id_test we wcześniejszych postach było to pole id_eksploatacje. Pamiętajcie, aby typ tego pola był typu serial lub musicie stworzyć autoinkrementację bezpośrednio w kodzie inaczej nie pójdzie.

W katalogu bin dorzuciłem Clienta Postgrsql - tak na wszelki wypadek.

W załączniku macie gotowy program, który wykorzystuje technologię FireDac do zapisu i odczytu bazy danych Postgresql ze zmiennej TstringList wpisując poszczególne znaki do dowolnej kolumny. Sam wiem, że najlepiej uczyć się z przykładów i to działających kodów źródłowych i kończyć to co się zaczęło. Pozdrowienia dla wszystkich, którzy śledzili ten wątek, a z ilości osób odwiedzających widać, że problem jest. Kończąc życzyłbym sobie dalszej współpracy z wami. Mimo wszystko nie poradziłby sobie, gdyby nie osoby, które chcą się podzielić swoją wiedzą i nie chcą za to "kasiorki" to miłe.

Pozdrawiam
Dłuższy

P.S.

Rozwinięcie tego projekciku to możliwość wczytywania danych ze zmiennej TStringList (nie wczytywania poklei danych ze zmiennej np 1234 tylko np. 2413 ) do dowolnego pola bazy danych:

Przykład - mam dane np.:

LST.Add('237');
LST.Add('546');
Foo.AppendData(LST,'D_1;D_2;D_3');

przypisujemy np. tak:
LST = 2 przypisać kolumnie D_2
LST = 3 przypisać kolumnie D_1
LST = 7 przypisać kolumnie D_3

LST = 7 przypisać kolumnie D_2
LST = 4 przypisać kolumnie D_1
LST = 6 przypisać kolumnie D_3

inny przypadek

LST = 7 przypisać kolumnie D_1
LST = 3 przypisać kolumnie D_3
LST = 2 przypisać kolumnie D_2

LST = 5 przypisać kolumnie D_1
LST = 4 przypisać kolumnie D_2
LST = 6 przypisać kolumnie D_3

Nie wiem czy się da, czy TStringList musi być czytane od lewej do prawej i przechodzi do następnego wiersza, ale to już taki gadżet jak by się dało to czemu nie.

0
dluzszy napisał(a):

**Szanowni Koledzy, a może Koleżanki. **

W dniu w którym Polska reprezentacja wygrała inauguracyjny mecz z Serbami 3:0 zapamiętam długo. Z góry przepraszam za taką informację, ale dzięki wam rozwiązałem swoją bolączkę. Moje podziękowania jeszcze raz kieruję do:

1.** user2324 ** - serdeczne dzięki;
2. wloochacz - serdeczne dzięki;

Mimo, że panowie lub panie moją wiedzę ocenialiście różnie - ja tego nigdy nie robię, bez waszej pomocy, nie udało by mi się rozwiązać mojego problemu. Przypominam wszystkim tytuł mojego wątku:

**Jak załadować TStringList do bazy PostgreSQL? ** Czas najwyższy podzielić się sposobem w jakim to zostało osiągnięte. Wszystkie uwagi kolegów/koleżanek ( sorki, że tak piszę po pseudonimach wnoszę, że to Panowie, ale że nie jestem pewien to pozwalam sobie na trochę żartu) brałem do serca i dziś mogę powiedzieć - Dzięki.

Teraz do rzeczy:

  1. Dzięki user2324 dostaliśmy klasę parsująca ( separująca znaki w zmiennej TStringList)
  2. Dzięki wloochacz dostaliśmy sposób łączenia się z bazą danych i wczytywaniem TStringList z pliku. To nic, że z FireBirdem, choć pytanie było skierowane o Postgresql.
  3. Sygnalizowałem w ostatnim poście, że mam problem połączenia się z bazą Postgrsql. Oto dlaczego nie mogłem tego zrobić:

a) **Linia błędna: **

lCommand.CommandText := Format('insert into test(%s) values(%s)', [ParseFields(AFields), ParseFields(AFields, ':')]);  

b) **Linia poprawna: **

 lCommand.CommandText := Format('insert into "Test"(%s) values(%s)', [ParseFields(AFields), ParseFields(AFields, ':')]);

c) Wyjaśnienie:
nazwa tabeli w bazie danych w tym wypadku **test ** była wpisana [małymi literami i bez cudzysłowowa] w bazie miałem zdefiniowaną z dużej litery tj. Test

Ale to jest TWÓJ błąd i to po stronie kreacji tabeli - po co Ci te cudzysłowy w nazwie tabeli? Czy masz świadomość co się zmienia, jak to zrobisz?
Ale co ja tam wiem, na PostgreSQL nie znam się w ogóle - ale tyle to wiem;-)
Poza tym to co podałeś to też jest błędna linia, poprawna wygląda powinna tak:

 lCommand.CommandText := Format('insert into {id Test}(%s) values(%s)', [ParseFields(AFields), ParseFields(AFields, ':')]);

A co to jest i dlaczego - znajdziesz w dokumentacji FireDAC'a.

kolejny błąd:

d) **Linia błędna: **
SS_Klasa.AppendData(LST, 'D_1;D_2;D_3;D_4');

e) **Linia poprawna: **
SS_Klasa.AppendData(LST, '"D_1";"D_2";"D_3";"D_4"');

Jak widać pola bazy muszą być ujęte w cudzysłów i oto cała tajemnica Postgresql-a.

NIEPRAWDA, żeby nie powiedzieć bzdura...
Zacytuję z innej strony:
"Database objects in Postgres are all expected to be lowercase.
Totally untrue. Postgresql will consider a name to be case insensitive if it isn't quoted, that is CREATE TABLE SomeTable (), which causes the symbol "SomeTable" to be represented as "sometable", and it will match any casing in any statement. If you quote the name, i.e. 'CREATE TABLE "SomeTable"', now it's case sensitive and has to be specified as "SomeTable" in any statement."

**Kolejny błąd: **

f) dotyczy pola id_test we wcześniejszych postach było to pole id_eksploatacje. Pamiętajcie, aby typ tego pola był typu serial lub musicie stworzyć autoinkrementację bezpośrednio w kodzie inaczej nie pójdzie.

Przepraszam, ale co Ty piszesz? Co nie pójdzie w kodzie i dlaczego nie pójdzie? Wszystko można zrobić w kodzie.
A w moim przykładzie wartość tego pola była nadawana przez bazę, dokładnie tak samo jak u Ciebie.

W katalogu bin dorzuciłem Clienta Postgrsql - tak na wszelki wypadek.

W załączniku macie gotowy program, który wykorzystuje technologię FireDac do zapisu i odczytu bazy danych Postgresql ze zmiennej TstringList wpisując poszczególne znaki do dowolnej kolumny. Sam wiem, że najlepiej uczyć się z przykładów i to działających kodów źródłowych i kończyć to co się zaczęło. Pozdrowienia dla wszystkich, którzy śledzili ten wątek, a z ilości osób odwiedzających widać, że problem jest.

eeee... tam, chciałbym mieć takie problemy z programowaniem, życie znowu byłoby proste :)

Kończąc życzyłbym sobie dalszej współpracy z wami. Mimo wszystko nie poradziłby sobie, gdyby nie osoby, które chcą się podzielić swoją wiedzą i nie chcą za to "kasiorki" to miłe.

Pierwsza wersja jest za darmo, ale następne już mogą być inaczej rozliczane ;-)
</quote>

Pozdrawiam
Dłuższy
P.S.
Rozwinięcie tego projekciku to możliwość wczytywania danych ze zmiennej TStringList (nie wczytywania poklei danych ze zmiennej np 1234 tylko np. 2413 ) do dowolnego pola bazy danych:

Wiesz wszystko można zrobić, tylko nie rozumiem po co to w ogóle piszesz. Nie mam pojęcia kogo mogłoby to zainteresować poza Tobą, no ale może nie mam racji...

byłoby

Przykład - mam dane np.:

LST.Add('237');
LST.Add('546');
Foo.AppendData(LST,'D_1;D_2;D_3');

przypisujemy np. tak:
LST = 2 przypisać kolumnie D_2
LST = 3 przypisać kolumnie D_1
LST = 7 przypisać kolumnie D_3

LST = 7 przypisać kolumnie D_2
LST = 4 przypisać kolumnie D_1
LST = 6 przypisać kolumnie D_3

inny przypadek

LST = 7 przypisać kolumnie D_1
LST = 3 przypisać kolumnie D_3
LST = 2 przypisać kolumnie D_2

LST = 5 przypisać kolumnie D_1
LST = 4 przypisać kolumnie D_2
LST = 6 przypisać kolumnie D_3

Nie wiem czy się da, czy TStringList musi być czytane od lewej do prawej i przechodzi do następnego wiersza, ale to już taki gadżet jak by się dało to czemu nie.

Wszystko się da, wystarczy dodać mapę (mapowanie znaku na kolumnę, np. tak: 1:D_1 --> będzie oznaczać, wpisz pierwszy znak do pola D_1 - to jest banalne w implementacji) do parametrów wejściowych i po sprawie.
Można też użyć wyrażeń, które byłby obliczane dla każdego wiersza TStringList i w zależności od wyniku wyrażenia, działoby się z nim coś tam =- np. przypisanie do określonej kolumny. Do obliczania wyrażeń można wykorzystać samego FireDAC'a - no ale to już temat na inną bajkę i na pewno nie znajdziesz tego w dokumentacji ;-)

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