Databáze > MySQL

Firedac TFDUpdateSQL + LAST_INSERT_ID

(1/1)

chaloup:
Netuší někdo jak právně napsat InsertSQL aby to načetlo AUTO_INCREMENT u MySQL? Našel jsem v příkladech, kde to používají
https://github.com/Embarcadero/RADStudio12Demos/tree/main/Object%20Pascal/Database/FireDAC/Samples/Comp%20Layer/TFDQuery/CachedUpdates/OnUpdateRecord
tam je to udělaný takto, ale to nefunguje:

--- Kód: ---INSERT INTO {id Products} (
ProductName, SupplierID, CategoryID,
QuantityPerUnit, UnitPrice, UnitsInStock, UnitsOnOrder,
ReorderLevel, Discontinued)
VALUES (
:NEW_ProductName, :NEW_SupplierID,
:NEW_CategoryID, :NEW_QuantityPerUnit, :NEW_UnitPrice,
:NEW_UnitsInStock, :NEW_UnitsOnOrder, :NEW_ReorderLevel,
:NEW_Discontinued
)
{IF MySQL} select LAST_INSERT_ID() as ProductID {FI}

--- Konec kódu ---

rholecek:
Přiznám se, že jsem nikdy nepoužíval komponentu TFDUpdateSQL. Vždy jsem SQL řešil jen přes TFDQuery. Předpokládám ale, že se Ti to v jedné proceduře nepodaří, protože pro update dat (vkládání, update, delete) používáš příkaz ExecSQL, který nevrací žádná data. Pro získání posledního ID potřebuješ mít klasický dotaz "SELECT LAST_INSERT_ID as product_id", který zároveň bude navázán na dataset. Uděláš aktivní dotaz, přečteš ID a dotaz ukončíš.
Já jsem měl něco takového:

function TFormHlavni.LastID : integer;
begin;
 QLastID.Active := true;
 result := DSLastID.DataSet.FieldByName('cislo').AsInteger;
 QLastID.Active := false;
end;

s tím, že na začátku aplikace jsem do QLastID (což právě byla komponenta TFDQuery) vložil QLastID.Sql.Add('SELECT LAST_INSERT_ID() as cislo'); a na QLastID mám navázanou komponentu TDataSource.
Tuto funkci jsem pak volal kdykoliv, když jsem vkládal data.

chaloup:
Není třeba používat nějaké specifické MySQL věci, Delphi mají podle dokumentace snad od XE5
funkci která provede podle nastaveného typu connection patřičná volání a vrátí poslední AutoGenValue:

--- Kód: ---function FireDAC.Comp.Client.TFDCustomConnection.GetLastAutoGenValue(const AName: String): Variant;

--- Konec kódu ---
https://docwiki.embarcadero.com/Libraries/Athens/en/FireDAC.Comp.Client.TFDCustomConnection.GetLastAutoGenValue

Mě jde o to, jak jedním příkazem vytáhnout tohle z MySQL, v dokumentaci k TFDUpdateSQL:
https://docwiki.embarcadero.com/Libraries/Athens/en/FireDAC.Comp.Client.TFDUpdateSQL.InsertSQL
jsou příklady:

--- Kód: ---// SQL Server sample
FDUpdateSQL1.InsertSQL := 'INSERT INTO [Shippers] (COMPANYNAME, PHONE) ' +
  'VALUES (:NEW_COMPANYNAME, :NEW_PHONE); SELECT SCOPE_IDENTITY() AS SHIPPERID';

// Oracle sample
FDUpdateSQL1.InsertSQL := 'INSERT INTO ADDEMO."Shippers" (COMPANYNAME, PHONE) ' +
  'VALUES (:NEW_COMPANYNAME, :NEW_PHONE) RETURNING SHIPPERID INTO :NEW_SHIPPERID';
FDUpdateSQL1.Commands[arInsert].ParamByName('NEW_SHIPPERID').ParamType := ptOutput;

--- Konec kódu ---
funguje mě i volání pro FirebirdSQL, ale na MySQL na to nemůžu pořád přijít...

v příkladu, který jsem uváděl je:

--- Kód: ---'INSERT INTO {id Products} (
ProductName, SupplierID, CategoryID,
QuantityPerUnit, UnitPrice, UnitsInStock, UnitsOnOrder,
ReorderLevel, Discontinued)
VALUES (
:NEW_ProductName, :NEW_SupplierID,
:NEW_CategoryID, :NEW_QuantityPerUnit, :NEW_UnitPrice,
:NEW_UnitsInStock, :NEW_UnitsOnOrder, :NEW_ReorderLevel,
:NEW_Discontinued
)'
{IF MSSQL} select :NEW_ProductID = @@identity {FI}
{IF MSAcc} select @@identity as ProductID {FI}
{IF MySQL} select LAST_INSERT_ID() as ProductID {FI}
{IF IB} returning ProductID {into :NEW_ProductID} {FI}
{IF PG} returning ProductID {into :NEW_ProductID} {FI}
{IF SQLite}; select LAST_INSERT_ROWID() as ProductID {FI}
{IF Ora} returning ProductID into :NEW_ProductID {FI}

--- Konec kódu ---
to bohužel nefunguje, zkoušel jsem nějaký kombinace, ale nic mě nefugovalo, hlásilo to chybu nebo to nevracelo správný data

jediný co mě napadlo a rozchodil jsem to je volat si Insert ručně v eventu UpdateRecord
a udělat po Insertu další volání výše uvedené fuknce a aktualizovat id ručně... zdá se mě to ale takový kostrbatý

rholecek:
Tak podle všeho Firebird umí toto:
insert into tabulka (sloupec) values(:data) returning ID;
čímž v jednom příkazu opravdu získáš last ID.

MySQL toto neumí. Takže to musíš na 2x. Jednou Insert a podruhé Select. Anebo využít tu fci GetLastAutoGenValue (neznal jsem, nemám zkušenosti).

Navigace

[0] Seznam témat

Přejít na plnou verzi