[delphi] jak odczytac numer ID z bazy ostatnio dodanegoWpisu

0

Mam taki problem.
Wpisuje np jakies zamowienie i mam pozycje zamowienia. Czyli wpisuje jakies dane firmy np firma ABCD i do tej firmy przypisane sa np dane pozycje: czyli kiedy wcisne Dodaj zamowienie do bazy to powinno sie wykonac tak:

Do bazy dodaje sie wpis ze jest nowa zamowienie czyli Firma ABCD jest dodana do bazy pole ID to serial wiec automatycznie rosnie. teraz pod numer ID tej nowododanej firmy powinny byc pozycje zamowienia w drugiej tabelce ale jak mam zdobyc ten numer po wpisaniu firmy zebym wiedzial pod jaki ID podpiac te kolejne pozycje. Uzywam POSTGRESA i komponentow z delphi

mam jedna teorie ale troche to chyba kiepskie zeby dodajac do bazy firme np ABCD dodawac jednoczesnie do tej tabeli losowy klucz MD5 i zaraz zadac zapytanie SELECT md5 FROM tabela WHERE md5 = ten nowy md5 wtedy dostane to nowe ID i moge podpiac pod pozycje. ale nie ma jakiegos komponentu co zwraca wynik zapytan np czy sie dobrze dodalo czy zle czy moze samo autoamtycznie zwraca ID czy cos?

0

Po co piszesz ten sam post w przeciągu kilku dni?
Szukaj tamten.

0

nigdy wczesniej nie pisalem tego postu...nigdy. mam zakladki na tematy wiec obserwuje wszystkie. wczesniej pisalem ze jak klikne na dbgrid to wykrywa mi nr ID jaki jest w bazie a teraz mi chodzi o to jak zwrocic ostatnie ID po dodaniu do bazy danych:
w mysql`u to jest taka funkcja:
mysql_insert_id -- Podaje numer ID wygenerowany podczas ostatniej operacji INSERT

i chce spytac jak zrobic to w delphi

0

dodawanie nagłówka zamówienia zrób w procedurze wbudowanej, która zwróci Ci id, coś jak

CREATE OR REPLACE FUNCTION nazwa(pole1 typ1, ... ...) RETURNS int8 AS
$BODY$
DECLARE
  id INTEGER;
BEGIN
  id = nextval('nazwa_sekwencji'::regclass);
  INSERT INTO nazwa_tabeli VALUES(Id, pola);
  RETURN Id;
END;
$BODY$
  LANGUAGE 'plpgsql' VOLATILE;

NIGDY w takim wypadku nie powinno się używać mysql_insert_id bo wartość odczytana przez tą funkcje wcale NIE musi być ID, które Ty wstawiłeś i w efekcie możesz dodać pozycje do całkiem innego zamówienia!!!

0

Dzieki wielkie. ta nazwa sekwencji to co to jest ?
te funkcje wywolac z query pozniej?

0
widmo3 napisał(a)

Dzieki wielkie. ta nazwa sekwencji to co to jest ?

tak naprawdę w postgresie nie ma pola typu SERIAL - jak ustalisz mu taki typ to podczas kompilacji zapytania (tworzenia tabeli) pole to dostaje typ Int4, tworzona jest sekwencja o nazwie nazwatabeli_nazwapolaseq i pole to dostaje jako wartość default nextval('nazwatabelinazwapola_seq'::regclass)
Jak się ona u CIebie nazywa możesz sprawdzić klikając w pgAdminie na tabelę i odczytując jej nazwę w dolnym polu, np. u mnie wygląda to tak:
user image

te funkcje wywolac z query pozniej?

w query piszesz

SELECT nazwa_procedury(parametr1, parametr2, ...) AS Id
0

Heh mam ten sam problem ale z MSSQLem... żeby to zrobić też muszę mieć napisaną Stored Procedure?

0

pod mssql masz zmienną @@identity i jej pokrewne (F1 się kłania)

0

Ok poszukałem... pokrewne

i mam kolejne pytanie a co w przypadku jeśli mam możliwość dostępu wielu klientów do bazy

czy umieszczając w transakcję insert coś tam i select @@identity nie dostanę id już nasępnego wpisu (od innego klienta.

0

100% da Ci jedynie jedynie taki sposób

  1. pobrać ID równocześnie zwiększając licznik (w IB/FB jest to generator, w postgresie sekwencja, jak to jest w mysqlu nie wiem)
  2. wstawić nowy rekord z pobranym wcześniej ID
  3. dodać powiązane rekordy z ID, które odczytałeś wcześniej

W postgresie (w IB / FB zresztą wygląda to prawie tak samo) bardzo ładnie się to robi w procedurze składowanej (przykład wyżej), można to też rozbić na dwa niezależne zapytania - bez różnicy jedynie mniej wygodne i uniwersalne

0
Misiekd napisał(a)

NIGDY w takim wypadku nie powinno się używać mysql_insert_id

ee?

int mysql_insert_id ( [resource identyfikator_połączenia] )

mysle, ze jednak mozna polegac na tej funkcji ;). Chyba, ze o czyms nie wiem :P

0

mysql_insert_id() zwraca ID wygenerowane dla pola z własnością AUTO_INCREMENT. Funkcja zwróci ID wygenerowane automatycznie przez ostatnią operację INSERT używającą podanego identyfikatora_połączenia . Jeżeli identyfikator_połączenia nie został podany, wykorzystywane jest ostatnio otwarte połączenie.

jeśli identyfikatora_połączenia się zmieni lub nie zostanie podany wartość zwrócona będzie zafałszowana.

0
Misiekd napisał(a)

identyfikatora_połączenia się zmieni

rownie dobrze po odczytaniu wartosci moze sie ona sama zmienic ;)

inaczej: przeciez w skrypcie PHP jak pobierzesz id polaczenia (polaczysz sie) to dopoki sie nie rozlaczysz, albo skrypt sie nie zakonczy, identyfikator sie nie zmienia :). Przypominam, ze (przy normalnie skonfigurowanym serwerze) przy pojedynczym wykonaniu skryptu PHP, wszystkie zapytania sa wywolywane w trakcie jednego polaczenia, o ile nie dasz tego:

bool mysql_close ( [resource identyfikator_połączenia] )

i dla lepszego zrozumienia mojej wypowiedzi:

resource mysql_pconnect ( [string serwer [, string użytkownik [, string hasło]]] )

połączenie z serwerem SQL nie zostanie zamknięte po zakończeniu wykonywania skryptu. Zamiast tego połączenie pozostanie otwarte do późniejszego użycia

EDIT:

Misiekd napisał(a)

lub nie zostanie podany

programista jest istota rozumna i jak mu zalezy, to poda ten identyfikator ;)

0

to wszystko prawda, tylko zważ, że to dział Delphi a nie PHP :>, wiesz jak będzie wyglądała sprawa tego identyfikatora np. w ZEOSach? Bo przypuszczam, że jest on stały dla całego połączenia
A co jeśli ZEOSy (lub inne ustrojstwo) samo zerwie połączenie (przy długich połączeniach jest to dość częste jeśli chodzi o MySQL). A jak się mają transakcje do tego? Czy jeśli zatwierdzę transakcję to ten identyfikator się nie zmieni?

Po prostu wg mnie rozwiązanie z MySQLa jest dziwne, dużo bardziej praktyczne jest podejście jak w IF/FB czy postgresie - najpierw pobrać a potem zapisać i mieć pewność, że jest OK niż najpierw zapisać a potem szukać, który to.

0
chesti napisał(a)

i mam kolejne pytanie a co w przypadku jeśli mam możliwość dostępu wielu klientów do bazy

czy umieszczając w transakcję insert coś tam i select @@identity nie dostanę id już nasępnego wpisu (od innego klienta.

W helpie masz jasno napisane - zmienna ważna w zakresie wywołujacej go aplikacji. @@identity jest odporne na wielu klientów jednocześnie wstawiających dane.

0

ja uzywam ZEOSA i co mozna zaradzic na zrywanie polaczen chodzi o postgresa czy dac co 10 minut jakies zapytanie timerze ?

0
ŁF napisał(a)

W helpie masz jasno napisane - zmienna ważna w zakresie wywołujacej go aplikacji. @@identity jest odporne na wielu klientów jednocześnie wstawiających dane.

Dla pewności dodałem jeszcze to:

     ADOQuery1.SQL.Add('BEGIN TRAN T1');
     ADOQuery1.SQL.Add('Insert ...');
     AdoQuery1.SQL.Add('SELECT @@IDENTITY AS ''id''');
     ADOQuery1.SQL.Add('COMMIT TRAN T1');

Teraz powinienem mieć pewność. A może ktoś się nie zgadza

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