[Delphi6Ent/Interbase]Formularz Master-Detail

0

Witam!!!
Mam taki problem, otóż stworzyłem sobie formularz(master-detail) do wprowadzania danych(coś takiego jak faktura z pozycjami), formularz skałda sie z DbNavigatora i paru DBEditów polączonych z jedną tabelą i DBGrig polączony z drugą tabela. Wszystko pięknie działa jak wpisze dane i zatwierdzam przyciskiem Post z DBNawigatora, ale ja chcąc sobie troche utrudnić sprawę postanowiłem zrobić własny przycisk do zatwierdzania wprowadzonych danych, tylko że ładnie wprowadza mi to co wpisze w DbEdity(czyli to co jest połączone z pierwsza tabelą) ,a problem tkwi w tym że chcąc zatwierdzić drugą tabele np. IBTable2.Post potrzebuje do wszystkich zatwierdzanych/wpisywanych rekordów do DBGrida numer aktualnego rekordu z pierwszej tabeli.

procedure TTest.BitBtn1Click(Sender: TObject);
Begin
if not DataModule.IBTransaction1.InTransaction then
 DataModule.IBTransaction1.StartTransaction;
proceduraInsert('INSERT INTO Tabela (a,b,c) VALUES('a','''+Edit1.text+''',....,...);'); //procedura wprowadzająca dane do pierwszej tabeli.
 DataModule.IBTransaction1.Commit;
 DataModule.IBTable1.Open;
Test.Close;
End;

Dodam tylko że "a" jest to pole(klucz główny) zwiększane o jeden podczas dodawania nowego rekordu.
Mam nadzieję że wystarczająco opisałem mój problem;
Z góry dziekuje za pomoc i Pozdrawiam:)

0

Spróbuje troche przybliżyć problem na podstawie prób jakie wykonałem:

Mam min. dwie tabele w mojej bazie z takimi polami:
table1:
a integer not null;
b char;
c char;
primary key(a);

table 2
d integer not null;
a integer;
e char;
f char;
primary key(d)

i taka referencja miedzy tymi tabelami:
ALTER TABLE "table2" ADD FOREIGN KEY ("a") REFERENCES table1 ("a");

Na podstawie tych dwóch tabel zrobiłem sobie formularz master_detail tak jak opisałem powyżej;
Oprogramowałem tez dwa zdaczenia NewRekord w ten sposób(może nie najlepszy ale powinno zadziałać)
Zdarzenie OnNewRekord tabeli1;

   try
      a:=StrToInt(proceduraSelect('SELECT MAX(a) AS ID FROM table1......'));//procedura liczaca max z   pola "a"//
      a:=a+1;
    except
      on EConvertError do a:=1;
    end;

Zdarzenie OnNewRekord tabeli2;

procedure TDataModule.IBTable2NewRecord(DataSet: TDataSet);
begin
 IBTable2.FieldByName('a').AsInteger:=a;
end;

I jak próbuje podczas wpisywania w DBGrig dodać 1 rekord to nie ma problemu wszystko ładnie liczy i przydziela polu "a" tabeli2 odpowiedni numer według procedurki OnNewRekord tabeli2; ,a jak już chcĘ dodać kolejny rekord to pojawia sie błąd:
Violation of Foreign Key constraint integer 77 on table "Table2"

I kompletnie nie mam pojęcia jak temu sprostać.
Jak usunę relacje z tabeli to wszystko pięknie hula. Czyżbym źle zrobił relacje???
Z góry dziękuje za podpowiedź
Pozdrawiam:)

0

zostawić TIBTable w spokoju, zamiast nich TIBQuery (i zamiast TDBEdit TEdit), dodawanie nagłówka procedurą, która zwraca ID dodanego nagłówka, parametry w SQLu a nie dziwne konstrukcje

0

Dziękuje Misiekd za odpowiedź, ale wydaje mi sie że właśnie tak robię jak Ty piszesz. Dane do IBTable1 wpisywane sa z Editów/DBEditów i zatwierdzane przyciskiem/procedurą:

procedure TTest.BitBtn1Click(Sender: TObject);

dodawanie nagłówka procedurą, która zwraca ID dodanego nagłówka

Dodawanie nagłówka nie wiem czy dobrze rozumiem ale chyba chodzi tu o klucz główny tabeli odbywa sie w procedurze dodawania nowego rekordu do tabeli za pomocą procedurki opartej właśnie na zapytaniach SQL:

a:=StrToInt(proceduraSelect('SELECT MAX(a) AS ID FROM table1......'));//procedura liczaca max z   pola "a"//

A ta procedurka wyglada tak:

procedure Select(zapytanie:String; IBQuery:TIBQuery; IBDataBase:TIBDataBase);
begin
    IBQuery.Close;               
    IBQuery.SQL.Clear;           
    IBQuery.SQL.Add(zapytanie);  
    IBQuery.Open;                 
end;

Także wpisywanie do pierwszej tabeli jest ok-chyba że sie mylę.
Wpisywanie do drugiej odbywa sie za pomocą zatwierdzenia IBTable2.Post ponieważ jest połączony z DBgridem, no chyba tak najłatwiej, tylko jedno pole(własnie to nieszczęsne a(klucz główny IBTable1)) wstawiane do każdego rekordu IBTable2 stwarza mi problem podczas próby wpisania 2 rekordu do DbGrida.
Bardzo chetnie dowiedziałbym sie jak to prosciej zrobić bez tych

dziwne konstrukcje

.
Z góry dziękuje za odpowiedź.
Pozdrawiam:)

0

chodziło mi o procedurę wbudowaną na serwerze, coś na kształt

CREATE PROCEDURE DODAJ_NAGLOWEK (
    POLE_1 Typ,
    POLE_2 Typ,
    ...)
RETURNS (
    NAGLOWEK_ID INTEGER)
AS
DECLARE VARIABLE ID INTEGER;
begin
  id = gen_id(nazwa_generatora_id_dla_tabeli_naglowki, 1);
  INSERT INTO tabela (pole_id, pole1, pole2, ...) VALUES (:id, pole_1, pole_2, ...);
end

i potem

with IBQuery, SQL do
begin
  Clear;
  Add('SELECT * FROM DODAJ_NAGLOWEK(:a, :b, ...)');
  ParamByName('a').AsTyp := edit1.text;
  ParamByName('b').AsTyp := edit2.text;
  ParamByName('...').AsTyp := editx.text;
  Open;
end;

a co do pozbycia się TIBTabel to miałem na myśli pozbycie się całkowicie także przy dodawaniu pozycji

0

Ok, przestudiowałem troche zagadnienie procedur/wyzwalaczy, i zastosowałem w swoim programiku, ale nadal nie moge rozgryźć tego problemu "z nadawaniem klucza obcego IBtable2". Jak mając 2 tabele i jeden formularz(taki master/detail czyli dane o fakturze(IBTable1) z kilkoma pozycjami wpisywanymi w DBGrid(IBTable2)), dodawać kolejne rekordy w DBGridzie, tak aby każdy rekord wpisany w DBGrida dostał automatycznie numer ID faktury(czyli klucz głowny IBTable1) do której będą należały te pozycje i wszystko zatwierdzić jednym przyciskiem np BitBtn.
Wiem, że da sie to zrobic bo przeciez na tej zasadzie są wystawiane wszystkie dokumenty(faktury, dokumenty magazynowe, przesunięcia magazynowe itp.)
Pozdrawiam:)

0

piszę to po raz ostatni zostaw IBTable i dodawaj pozycje "ręcznie" SQLem!

0

Rozumiem, tylko jak dodać np. 2 wiersze wpisane do DBGrida, do tabeli za pomocą SQLa.
Dziękuję za pomoc!!!
Pozdrawiam:)

0

masz dwa wyjścia

  1. przed dodaniem jakiejkolwiek pozycji MUSISZ dodać nagłówek - wtedy masz ID nagłówka
  2. zamiast wpisywać pozycje do bazy zapisujesz je sobie na jakiejś liście (tablica rekordów czy cuś), wyświetlasz np. w StringGridzie i dopiero przy zatwierdzeniu faktury (bo mowa była o fakturach, ale dotyczy wszystkiego co jest tak skonstruowane) dodajesz nagłówek i potem pozycje

wniosek jest jeden - jak byś nie robił najpierw musisz dodać NAGŁÓWEK dlatego wg mnie pomysł z dodatkową listą pozycji jest najlepszy

0

Wielkie DDDzięki Misiekd, troche pokombinowałem z tym StringGridem i coś już pomalutku zaczyna pasować!!!
Pozdrawiam:)

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