Autor Téma: Získanie práve vytvoreného ID  (Přečteno 18274 krát)

Offline Stanislav Hruška

  • Padawan
  • ******
  • Příspěvků: 7430
  • Karma: 44
    • Verze Delphi: W11 + D11.3.1
Re:Získanie práve vytvoreného ID
« Odpověď #15 kdy: 01-11-2012, 09:55:16 »
select gen_id(COUNTRY_GEN,1) from RDB$DATABASE

Tu padla poznámka, že to vždy nefunguje.
Mne sa to riešenie so získaním ID v BeforePost veľmi páči. Mimochodom, je to v návode IB6.
Win11 64b, Delphi 12.2, FireBird 4.01
Expert na kladenie nejasne formulovaných otázok.

Offline Petr P.

  • Nováček
  • *
  • Příspěvků: 29
  • Karma: 1
    • Verze Delphi: Turbo Delphi 2006
Re:Získanie práve vytvoreného ID
« Odpověď #16 kdy: 01-11-2012, 10:15:22 »
select gen_id(COUNTRY_GEN,1) from RDB$DATABASE

Tu padla poznámka, že to vždy nefunguje.
Mne sa to riešenie so získaním ID v BeforePost veľmi páči. Mimochodom, je to v návode IB6.
Nevím proč by to nemělo fungovat, je to stejný jako volat  v gen_id(COUNTRY_GEN,1) v SP.
Tenhle postup píšou všude včetně Pavla Císaře.

To že vždy nefunguje psal Pepak o získání posledního čísla bez zvýšení o 1  (COUNTRY_GEN,0).
select gen_id(COUNTRY_GEN,0) from RDB$DATABASE.
Myslel tím asi, že mezitím jinej uživatel mezi tím zvýší generátor a u tebe zůstane původní číslo.

Jinak v BeforePost se to použije podobně. Rozdíl je akorát v tom že nepotřebuješ SP.
« Poslední změna: 01-11-2012, 11:12:44 od Petr P. »

Offline pepak

  • Padawan
  • ******
  • Příspěvků: 1574
  • Karma: 37
    • Pepak.net
Re:Získanie práve vytvoreného ID
« Odpověď #17 kdy: 01-11-2012, 10:29:02 »
select gen_id(COUNTRY_GEN,1) from RDB$DATABASE

Tu padla poznámka, že to vždy nefunguje.
Ne, to tedy nepadla. Padla poznámka, že
Kód: SQL [Vybrat]
  1. SELECT gen_id(COUNTRY_GEN,0) FROM RDB$DATABASE
volané po provedení INSERTu nefunguje správně.
Kód: SQL [Vybrat]
  1. SELECT gen_id(COUNTRY_GEN,1) FROM RDB$DATABASE
volané před provedením INSERTu je naprosto v pořádku.

Offline Stanislav Hruška

  • Padawan
  • ******
  • Příspěvků: 7430
  • Karma: 44
    • Verze Delphi: W11 + D11.3.1
Re:Získanie práve vytvoreného ID
« Odpověď #18 kdy: 01-11-2012, 11:02:07 »
Takto som to tam nevidel.  :( Aj my to bolo čudné. S vysvetlením to je jasné.
Win11 64b, Delphi 12.2, FireBird 4.01
Expert na kladenie nejasne formulovaných otázok.

Offline Stanislav Hruška

  • Padawan
  • ******
  • Příspěvků: 7430
  • Karma: 44
    • Verze Delphi: W11 + D11.3.1
Re:Získanie práve vytvoreného ID
« Odpověď #19 kdy: 07-01-2013, 10:43:48 »
A mám problém. Použil som riešenie zo dňa 31-10-2012, 11:25:16. Ďalej úplne zjednodušený kód

actInsertExecute
MasterDataSet.Insert;
DetailDataSet.Insert;

actPostExecute
DetailDataSet.Post;
xx) MasterDataSet.FieldValues['myFKField'] := newPrKey; // Získaný v DetailDataSet.onBeforePost. Je správny
MasterDataSet.Post; // Chyba Hodnota newPrKey sa nenachádza v DetailDataSet

Skutočná hodnota DetailDataSet.IDmyField = newPrKey +1.
Pre IDmyField mám trigger s generátorom s podmienkou na new.IDmyField = null or new.IDmyField = 0. A ten sa spustí, akokeby som tam nemal riadok xx).
 
Všetky moje pokusy zlyhali. Považujem to za zásadný problém. To ešte nemám viacnásobný prístup k DB.

Win11 64b, Delphi 12.2, FireBird 4.01
Expert na kladenie nejasne formulovaných otázok.

Offline pepak

  • Padawan
  • ******
  • Příspěvků: 1574
  • Karma: 37
    • Pepak.net
Re:Získanie práve vytvoreného ID
« Odpověď #20 kdy: 07-01-2013, 11:28:59 »
Co kdybys postnul skutečný použitý kód se všemi relevantními částmi? Ty máš totiž dost tendenci prasit kód, jak tě napadne, vynechávat si části, které se ti zrovna nelíbí nebo přidávat části, které se ti líbí - tudíž bych tak nějak očekával, že i teď to je stejný případ a prostě sis tam něco "upravil". Protože to, co je popsané v tom "riešeniu zo dňa 31-10-2012, 11:25:16", by ti fungovat mělo.

Btw., nechtěl bys zvážit drobnou časovou investici do naučení se tagů [code=delphi] a [quote], aby tvoje příspěvky byly rozumně čitelné? Pokud je neumíš z hlavy, tak nepiš do "Rychlá odpověď", ale klikni si na "Odpověď" a pak si ty tagy zadávej klikáním myší v editoru. Díky.

Offline Stanislav Hruška

  • Padawan
  • ******
  • Příspěvků: 7430
  • Karma: 44
    • Verze Delphi: W11 + D11.3.1
Re:Získanie práve vytvoreného ID
« Odpověď #21 kdy: 07-01-2013, 12:00:20 »
Ja som si to doma tak pekne a poriadne prípravil, ale som si skopíroval iný súbor  :(
Kód: [Vybrat]
FB
CREATE OR ALTER TRIGGER ENTRIES_BI FOR ENTRIES
ACTIVE BEFORE INSERT POSITION 0
as
begin
  if ((new.identries is null) or (new.identries = 0)) then
    new.identries = gen_id("GEN_ID",1);
end
create or alter procedure SP_ID
returns (
    ID bigint)
AS
begin
  ID = gen_id("GEN_ID",1);
end
procedure TdmMain.ibdtstFlatBeforePost(DataSet: TDataSet);
begin
  If(DataSet.state = dsinsert) then
  begin
    ibspID.ExecProc;
    NewPrKey := ibspID.ParamByName('ID').AsInteger;
    DataSet.FieldByName('idflats').Value := NewPrKey;
    MasterDataset.FieldByName('FKFlat').Value := NewPrKey;
  end;
end;
// Podľa IB6 Developer's guide str. 34 - 35
procedure TfrmLandlord.actInsertExecute(Sender: TObject);
var
  I, idxcbbCod, idxcbbEntry: integer;
  DateFrom: TDate;
begin
  MasterDataset.Insert;
  FlatDataset.Insert;
// Predvolené údaje a pod.
end
procedure TfrmLandlord.actSaveExecute(Sender: TObject);
begin
  LandlordPost;
  EnableActions(MasterDataset, MasterVST, actmgr1);
end;
procedure TfrmLandlord.LandlordPost;
begin
  with frmLandlord  do
  begin
    with FlatDataset do
    begin
    Kontrola údajov
    end
   
    with MasterDataset do
    begin
    Kontrola údajov
    end;
   
    // MasterDataset.FieldByName('FKFlat').Value := NewPrKey; Skúšal som aj tu
    with FlatDataset do
    begin
      FieldValues['HotArea'] := StrToCurr(cledtHotArea.Text);
      ...
      Post;
    end;
   
    MasterDataset.Post; // Chyba
  end;
Win11 64b, Delphi 12.2, FireBird 4.01
Expert na kladenie nejasne formulovaných otázok.

Offline pepak

  • Padawan
  • ******
  • Příspěvků: 1574
  • Karma: 37
    • Pepak.net
Re:Získanie práve vytvoreného ID
« Odpověď #22 kdy: 07-01-2013, 14:20:46 »
No, v první řade by asi bylo hezké, kdybys nám tu ujasnil, co je v master datasetu a co v detail datasetu. Tak, jak to máš udělané, to vypadá, jako kdyby k jednomu záznamu v detail datasetu mělo existovat libovolné množství záznamů v master datasetu, a to rozhodně není obvyklý přístup. Kromě toho je krajně nejasné, ke které z těch tabulek se vztahuje ten trigger a ta událost BeforePost.

Offline Stanislav Hruška

  • Padawan
  • ******
  • Příspěvků: 7430
  • Karma: 44
    • Verze Delphi: W11 + D11.3.1
Re:Získanie práve vytvoreného ID
« Odpověď #23 kdy: 07-01-2013, 15:01:10 »
MasterDataSet = Landlords - vlastník bytu
FlatDataSet = Flats - byt

Landlords = IDLandlords, FKFlat...
Flats = IDFlats...

// ke které z těch tabulek se vztahuje ten trigger a ta událost BeforePost.
Samozrejme, pri kopírovaní som klikol vedľa. Oba (vlastne všetko, celá debata) sa vzťahujú na Flats.
1 - Vyvolám Flats.Post. Vo Flats.onBeforePost získam newPrKey. Napríklad 10.
2 - Vložím ho do Landlords.FKFlat.
3 - Potom nasleduje Landlords.Post s chybou.
Vo (ak vynechám Landlords.Post) Flats.IDFlats je hodnota 11.
Neviem, prečo sa vyvolá trigger, ak som tam predtým použil Landlords.FieldValues['FKFlat'] := newPrKey. Zjavne FB o tom nič nevie. Žeby to bolo poradím vo vykovávaní jednotlivých udalostí? V nastaveniach transakcií som nič nemenil.
Inde problém nemám, ale čo nie je môže byť.
Všetko je v štádiu návrhu a mám teraz iba zopár záznamov 1:1.
 
« Poslední změna: 07-01-2013, 15:02:50 od Stanislav Hruška »
Win11 64b, Delphi 12.2, FireBird 4.01
Expert na kladenie nejasne formulovaných otázok.

Offline pepak

  • Padawan
  • ******
  • Příspěvků: 1574
  • Karma: 37
    • Pepak.net
Re:Získanie práve vytvoreného ID
« Odpověď #24 kdy: 07-01-2013, 17:52:30 »
2 - Vložím ho do Landlords.FKFlat.
To je samozřejmě blbě. Tím říkáš, že každý byt může mít libovolný počet vlastníků (to by až tak nevadilo) a že každý vlastník může mít nejvýše jeden byt (to už je takové neobvyklé, zvlášť když se pak snažíš dělat vlastníky jako Master tabulku).

Citace
3 - Potom nasleduje Landlords.Post s chybou.
To se nedivím, protože v době, kdy Postuješ do Landlords, ještě neexistuje záznam ve Flats. Tedy aspoň jsi to domýšlím, protože jsi nějak nenapsal nic o tom, kdy nastává skutečný Post do Flats.

Citace
Vo (ak vynechám Landlords.Post) Flats.IDFlats je hodnota 11.
To mě taky nepřekvapuje, protože sekvence jsou mimotransakční a pořád narůstají, bez ohledu na to, jestli se jejich hodnota někde použije.

Citace
Žeby to bolo poradím vo vykovávaní jednotlivých udalostí?
Určitě. Postup by měl být:
1) Uspořádej si pořádně datové struktury. Z toho, co píšeš, je zřejmé, že v Landlords máš ukazatel na Flats, ve Flats nemáš nic (nebo tam možná máš ukazatel na Landlords, aby to bylo zajímavější). Máš to mít tak, že v Landlords nemáš nic a ve Flats máš ukazatel na Landlords.
2) Založ záznam v Landlords. To by mělo být bez problémů.
3) Získej ID v Landlords. Klidně tak, že při zakládání (krok 2) v BeforePost zavoláš tu svou proceduru, která ti to ID vypočítá, a ty si ho kromě do políčka v Landlords uložíš do nějaké proměnné.
4) Použij toto ID pro založení záznamu ve Flats.

Offline Stanislav Hruška

  • Padawan
  • ******
  • Příspěvků: 7430
  • Karma: 44
    • Verze Delphi: W11 + D11.3.1
Re:Získanie práve vytvoreného ID
« Odpověď #25 kdy: 08-01-2013, 09:41:46 »
2 // Tím říkáš, že každý byt může mít libovolný počet vlastníků.
Áno. Ber to v určitom časovom rozsahu. Jeden byt predá a iný ho kúpi.
// že každý vlastník může mít nejvýše jeden byt
Pre moje potreby áno. Ak mal dva byty, tak som to doteraz riešil 1. byt - Janko Hraško, 2. byt - Janko Hraško 2. Toto si viem riešiť ako potrebujem. Aj vzťahom M:N. Ešte som to tak podrobne neanalyzoval. Hlavne to nemá vplyv na predmet otázky.

3 Citujem sa:
1 - Vyvolám Flats.Post. Vo Flats.onBeforePost získam newPrKey. Napríklad 10.
2 - Vložím ho do Landlords.FKFlat.
3 - Potom nasleduje Landlords.Post s chybou.
Takže záznam by už mal existovať.

// Venujme sa len tomuto
Ja to vidím takto.
LandlordsDataSet i FlatsDataSet sú v stave Insert

a - Vyvolám FlatsDataSet.Post. Neviem ako sa to správa. Nikde som nenarazil na popis.
b - FB spustí trigger Flats Before Insert
c - Vo FlatsDataset.onBeforePost získam v procedúre FB hodnotu IDFlats uložením do newPrKey. Potiaľ to je v priadku.
d - Vložím ju do LandlordDataset.FKFlats := newPrKey;
e - Vyvolám LandlordDataset.Post s danou chybou.
f - FB jednoznačne opäť vyvolá trigger Flats Before Insert. Tu je kameň úrazu. Prečo ho spustí, ak
.  1 - už raz spustený bol pomocou DataSet-u
.  2 - hodnotu pre FKFlats som tam dal?

Mne to vychádza, že je problém v obsluhe udalostí DataSet a transakcii. Ako keby o sebe nevedeli. Čo je nezmysel. To by z FB bol dávno popol.
Ja potrebujem dosiahnuť, aby nedochádzalo k druhému spusteniu trigger-u Flats Before Insert
// Venujme sa len tomuto - Koniec

K poslednému odseku.
// Máš to mít tak, že v Landlords nemáš nic a ve Flats máš ukazatel na Landlords.
To nie je vhodné riešenie. Počas roka dôjde zmene vlastníka a ja ich musím mať k dispozícii oboch - ročné zúčtovanie nákladov.

Nateraz zakladám majiteľa a byt v jednom kroku. Asi bude najrozumnejšie to rozdeliť na dva kroky. Tam problém nebude. Napr. samostatne nadefinujem byty i vlastníkov a až potom ich spárujem.
Ďakujem za čas a ochotu čo mi venuješ.
Win11 64b, Delphi 12.2, FireBird 4.01
Expert na kladenie nejasne formulovaných otázok.

Offline pepak

  • Padawan
  • ******
  • Příspěvků: 1574
  • Karma: 37
    • Pepak.net
Re:Získanie práve vytvoreného ID
« Odpověď #26 kdy: 08-01-2013, 10:34:55 »
2 // Tím říkáš, že každý byt může mít libovolný počet vlastníků.
Áno. Ber to v určitom časovom rozsahu. Jeden byt predá a iný ho kúpi.
V tom případě máš ale blbě master-detail vztah - Flats by měly být master a Landlords detail.

Citace
3 Citujem sa:
1 - Vyvolám Flats.Post. Vo Flats.onBeforePost získam newPrKey. Napríklad 10.
2 - Vložím ho do Landlords.FKFlat.
3 - Potom nasleduje Landlords.Post s chybou.
Takže záznam by už mal existovať.
Za prvé to záleží na tom, v jakém přesně pořadí ty Posty probíhají (jestli například doběhne celý Flats.Post a teprve potom začne Landlords.Post), a za druhé mám vážné podezření, že vyplňuješ špatná políčka (že si pomocí procedury vytáhneš ID, ale potom ho přepíšeš v triggeru, nebo že si vytáhneš ID, ale zapíšeš ho do jiného pole, než jaké je referencované tím cizím klíčem). Docela dobrá taktika v takových případech je, smazat cizí klíč, zkusit zapsat záznam (teď to proběhne, protože už není nic, co by ho mělo blokovat) a pak se podívat, co jsi kam skutečně zapsal po provedení všech triggerů.

Citace
a - Vyvolám FlatsDataSet.Post. Neviem ako sa to správa. Nikde som nenarazil na popis.
b - FB spustí trigger Flats Before Insert
c - Vo FlatsDataset.onBeforePost získam v procedúre FB hodnotu IDFlats uložením do newPrKey. Potiaľ to je v priadku.
d - Vložím ju do LandlordDataset.FKFlats := newPrKey;
e - Vyvolám LandlordDataset.Post s danou chybou.
Jinými slovy, v tuto chvíli jsi ještě ve stavu FlatsDataset.BeforePost. Skutečný zápis do DB proběhne až později a potom se ti zavolá FlatsDataset.AfterPost.

Citace
f - FB jednoznačne opäť vyvolá trigger Flats Before Insert. Tu je kameň úrazu. Prečo ho spustí, ak
.  1 - už raz spustený bol pomocou DataSet-u
.  2 - hodnotu pre FKFlats som tam dal?
Trigger se spouští v databázi. Databáze neví nic o tom, co dělá nebo nedělá aplikace, a ani ji to nezajímá. Prostě se podívá: "Mám tu trigger pro aktuálně prováděnou událost? Ano. Je ten trigger aktivní? Ano. Tak ho spustím." Je tvoje zodpovědnost, abys trigger napsal tak, aby případně nic nědělal - tedy třeba na začátku provést nějaký vhodný IF a pokračovat, jen pokud operace ještě neproběhla.

Podle mě máš blbě datový model. Jak souvisí hodnota FKFlats (která je v tabulce Landlords) s triggerem na tabulce Flats? Trigger na tabulce Flats se má zabývat výhradně údaji v tabulce Flats, nemá co se zabývat cizími klíči cizích tabulek.

Citace
Ja potrebujem dosiahnuť, aby nedochádzalo k druhému spusteniu trigger-u Flats Before Insert
Jsem si stoprocentně jistý, že nedochází k druhému spuštění Before Insert triggeru na Flats. Before Insert nastane právě jednou, a to v okamžiku, kdy databáze narazí na INSERT INTO tabulka. A to platí i v případě, že to INSERT INTO tabulka neděláš ty, ale dělají ho tvoje komponenty pro přístup k DB.

Takže špatně vyhodnocuješ, co se děje. Možností je víc, ale podle mě děláš jednu z následujících věcí:
a) Vygeneruješ hodnotu procedurou, tu si uložíš, zapíšeš ji do tabulky a pak ji v tabulce přepíšeš hodnotou vygenerovanou v triggeru - tzn. máš blbě podmínku v triggeru.
b) Vygeneruješ hodnotu procedurou, tu si uložíš, zapíšeš ji do tabulky do špatného sloupce a pak trigger pochopitelně vygeneruje novou hodnotu, protože podmínka "hodnota v poli X ještě nebyla vygenerována" je splněna.

Dost blbě se odhaduje, co z toho, protože jsi sice vypsal relevantní části kódu, ale už jsi nenapsal struktury jednotlivých tabulek a vztahy mezi nimi - asi nejlíp příslušný CREATE TABLE příkaz.

Citace
K poslednému odseku.
// Máš to mít tak, že v Landlords nemáš nic a ve Flats máš ukazatel na Landlords.
To nie je vhodné riešenie. Počas roka dôjde zmene vlastníka a ja ich musím mať k dispozícii oboch - ročné zúčtovanie nákladov.
V tom případě prosím dej jako Master tabulku Flats a jako Detail tabulku Landlords. A do všech popisků k tomuto problému zdůrazňuj, že mezi Flats a Landlords je vztah 1:N, protože jinak je to strašně matoucí - běžné bývá spíš to, že jeden majitel má víc bytů, ne že jeden byt má víc majitelů.
(Vůbec by možná bylo nejlepší udělat to jako M:N s tím, že spojovací tabulka bude mít ID bytu, ID vlastníka a období [datum od, datum do], pro které to platí.)

Citace
2. Toto si viem riešiť ako potrebujem. Aj vzťahom M:N. Ešte som to tak podrobne neanalyzoval. Hlavne to nemá vplyv na predmet otázky.
Má. Poměrně podstatný, aspoň podle mě je docela vhodné důkladně pochopit popisovanou realitu a z ní odvozovat řešení, než střílet různé myšlenky od boku a doufat, že se nějaká trefí.

Offline Stanislav Hruška

  • Padawan
  • ******
  • Příspěvků: 7430
  • Karma: 44
    • Verze Delphi: W11 + D11.3.1
Re:Získanie práve vytvoreného ID
« Odpověď #27 kdy: 08-01-2013, 12:08:44 »
Toto bol popis tabuliek - zjednodušený, ale ostatné je teraz nepodstatné
Landlords = IDLandlords, FKFlat...
Flats = IDFlats...

CREATE TABLE LANDLORDS (
    IDLANDLORDS  PRIMARYKEY /* PRIMARYKEY = BIGINT NOT NULL */,
    FKSVB        FOREIGNKEY /* FOREIGNKEY = BIGINT NOT NULL */,
    FKFLAT       FOREIGNKEY /* FOREIGNKEY = BIGINT NOT NULL */,
Foreign Keys
ALTER TABLE LANDLORDS ADD CONSTRAINT FK_LANDLORDS_1 FOREIGN KEY (FKSVB) REFERENCES SVBS (IDSVBS);
ALTER TABLE LANDLORDS ADD CONSTRAINT FK_LANDLORDS_2 FOREIGN KEY (FKFLAT) REFERENCES FLATS (IDFLATS);
Citace
Za prvé to záleží na tom, v jakém přesně pořadí ty Posty probíhají (jestli například doběhne celý Flats.Post a teprve potom začne Landlords.Post),
To netuším. Je to v správe transakcie. A o tom neviem nič. Preto uvažujem rozložiť to na dva samostatné kroky.
Citace
a za druhé mám vážné podezření, že vyplňuješ špatná políčka
To je na 100% správne.
Citace
Jsem si stoprocentně jistý, že nedochází k druhému spuštění Before Insert triggeru na Flats. Before Insert nastane právě jednou, a to v okamžiku, kdy databáze narazí na INSERT INTO tabulka. A to platí i v případě, že to INSERT INTO tabulka neděláš ty, ale dělají ho tvoje komponenty pro přístup k DB.
Tiež si to myslím, ale všetko mi nasvedčuje, že sa tak deje. Ešte to preskúmam.
Citace
tzn. máš blbě podmínku v triggeru.
if ((new.idflats is null) or (new.idflats = 0)) then
.    new.idflats = gen_id("GEN_ID",1);

To nie je zle. Takúto podmienku mám všade.
Citace
aspoň podle mě je docela vhodné důkladně pochopit popisovanou realitu a z ní odvozovat řešení, než střílet různé myšlenky od boku a doufat, že se nějaká trefí.
Tak toto ma presne vystihuje. Trápim sa niekoľko hodín. Potom vezmem papier a ceruzu a behom 5 minút to je vybavené. Viem o tom a robím to i tak.
Na dnes stačilo.
Win11 64b, Delphi 12.2, FireBird 4.01
Expert na kladenie nejasne formulovaných otázok.

Offline pepak

  • Padawan
  • ******
  • Příspěvků: 1574
  • Karma: 37
    • Pepak.net
Re:Získanie práve vytvoreného ID
« Odpověď #28 kdy: 08-01-2013, 13:24:13 »
Citace
Za prvé to záleží na tom, v jakém přesně pořadí ty Posty probíhají (jestli například doběhne celý Flats.Post a teprve potom začne Landlords.Post),
To netuším. Je to v správe transakcie. A o tom neviem nič. Preto uvažujem rozložiť to na dva samostatné kroky.
S tím nemá transakce nic společného. Všechny Posty probíhají v Delphi, transakce je až za tím.

Citace
Citace
tzn. máš blbě podmínku v triggeru.
if ((new.idflats is null) or (new.idflats = 0)) then
.    new.idflats = gen_id("GEN_ID",1);

To nie je zle. Takúto podmienku mám všade.
Přesto je to úplně blbě. Ne zápisem (ten je v pořádku*), ale logikou. Vždyť co děláš: "Pokud při insertu do tabulky s detailem zjistím, že nemá vyplněný cizí klíč do master tabulky, tak vygeneruju nové dosud nepoužité ID do master tabulky." Je dobře, žeš to sem takhle vypsal, protože předtím se to utopilo v ostatních informacích, ale když to vypíšeš takhle extra a přeložíš si do slov, co to dělá, tak už je úplně jasné, proč ti to chodí špatně...

Znovu ti radím, vyhoď ten cizí klíč úplně, vynuluj generátor, nech proběhnout jednu sérii INSERTů, a pak si zkontroluj, co se ti do tabulek skutečně zapsalo. Z toho už ti snad bude zřejmé, kde se to pokazilo.

*) Snad. Já obvykle používám GEN_ID(NAZEV_SEKVENCE, 1), ale třeba to jde i s tím názvem sekvence v uvozovlkách nebo apostrofech. Ale když tak jde jen o překlep.
« Poslední změna: 08-01-2013, 13:26:04 od pepak »

Offline Stanislav Hruška

  • Padawan
  • ******
  • Příspěvků: 7430
  • Karma: 44
    • Verze Delphi: W11 + D11.3.1
Re:Získanie práve vytvoreného ID
« Odpověď #29 kdy: 09-01-2013, 10:26:58 »
Som z toho totálny magor. Zrušil som väzbu medzi tabuľkami. Dvakrát som spustil založenie nových záznamov. Dostal som rad neprerušenej postupnosti ID 601 až 606. Viď obrázok.

Predpoklady:
1) Nie sú žiadne výnimky - vo všeobecnosti
2) Obe tabuľky majú trigger Befor Insert a udalosť OnBeforePost, ktoré sú konštrukčne zhodné. Nič iné. Udalosť OnBeforePost volá procedúru s telom "ID = gen_id("GEN_ID",1);" a zapisuje práve generovanú hodnotu ID do tabuľky ako PK.

Úvaha 1 - tak ako to je napísané (hrám sa na počítač).
Najprv sa dvakrát volá trigger Befor Insert. Nakoľko je podmienka splnená, tak sa 2x spustí generátor. Potom sa dvakrát volá OnBeforePost. Nemá pomienku, tak sa 2x spustí generátor.
Výsledkom je 4x spustený generátor. V skutočnosti sa generátor spustil 3x a v inom poradí. Hľadám ďalej.

Úvaha 2 - poznám výsledok a z neho hľadám riešenie
I. Najprv sa vykoná OnBeforePost pre Detail. Prečo? Veď prvý je INSERT! Generuje sa hodnota 601 - OK.

II. Nalseduje trigger Befor Insert pre Detail. Generuje sa hodnota 602 - OK. Ale prečo sa generuje ID, keď v OnBeforePost sa zapisuje hodnota pre ID?

III. Vykoná sa OnBeforePost pre Master. Generuje sa hodnota 603 - OK.

IV. Nalseduje trigger Befor Insert pre Master. Podľa II. by sa malo generovať ID. Ale negeneruje sa. To zas posdporuje názor, že hodnota pre ID bola zapísaná v OnBeforePost pre Master. To je v rozpore s II.

Je zrejmé, že mi chýba nejaká podstatná vedomosť. Čo to je a kde si o tom môžem prečítať?
Mám k dispozícii túto literatúru:
IB6 Language Ref, IB6 Developer's guide, IB6 API, IBE Book 05-2005, IB Expert Firebird Guide, FB od Císařa
Win11 64b, Delphi 12.2, FireBird 4.01
Expert na kladenie nejasne formulovaných otázok.