delphi-firedac
Skill1 starsChanged 13 days agoMITView on GitHub
Use when a Delphi program talks to a database through FireDAC - connecting, running queries, binding parameters, reading rows, transactions - for SQLite, SQL Server, MySQL or PostgreSQL. Trigger words - TFDConnection, TFDQuery, TFDTransaction, FDConnection.Params, DriverName, ParamByName, ExecSQL, StartTransaction, TFDPhysSQLiteDriverLink, FireDAC.
2 other projects use a version of this.
Adopted by
Most recently taken up by
- danieleteti/delphi-ai-skillstheir own version, first seen Nov 8, 2026
- adrianosantostreina/delphi-devtheir own version, first seen Nov 1, 2026
Other versions2 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 2
- adrianosantostreina/delphi-dev★ 87same name
- danieleteti/delphi-ai-skills★ 23same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository30 other files it gives its agents.
- angular-crud-gotchasSkill
- aws-lightsail-container-deploySkill
- bannerlord-decompileSkill
- codegen-t4-templatesSkill
- csharpSkill
- delphi-code-smellsSkill
- delphiSkill
- delphi-types-and-unitsSkill
- difftasticSkill
- dockerSkill
- efcore-aspnet-reviewSkill
- git-bash-editingSkill
- github-issue-creatorSkill
- microsoft-docsSkill
- minimal-comments-and-docsSkill
- msbuildSkill
- mssqlSkill
- mstest-assertionsSkill
- mysqlSkill
- nginx-config-testingSkill
- odata-generated-gridsSkill
- postgresSkill
- powershellSkill
- react-crud-gotchasSkill
- sanitize-for-open-sourceSkill
- self-contained-deploymentSkill
- skill-writerSkill
- ui-conventionsSkill
- verify-in-running-appSkill
- winui3Skill
The file
Files
Delphi FireDAC: connection, queries, parameters, transactions
Written from the FireDAC documentation and the unit layout; not compiled (see "How this was verified"). Check every identifier against the user's installed units or the docwiki before relying on it, and say which you used. The generic Delphi rules (try/finally, Free, strings) are in the delphi skill; the SQL dialect facts are in the mssql, mysql and postgres skills.
Units to put in uses
| Need | Unit |
TFDConnection, TFDQuery, TFDTransaction, TFDStoredProc, TFDMemTable | FireDAC.Comp.Client |
TFDParams, ftString parameter types | FireDAC.Stan.Param |
dtInt32, TFDDataType | FireDAC.Stan.Intf |
| The driver for the database (it must be linked in, or the connection fails at run time) | one of FireDAC.Phys.SQLite, FireDAC.Phys.MSSQL, FireDAC.Phys.MySQL, FireDAC.Phys.PG |
| Console programs, no UI | FireDAC.ConsoleUI.Wait, and FireDAC.Stan.Def, FireDAC.Stan.Async, FireDAC.DApt |
| VCL programs | FireDAC.VCLUI.Wait (the IDE adds it when you drop a TFDGUIxWaitCursor) |
A missing FireDAC.Phys.* unit gives "[FireDAC][Phys]-... Driver not found" only when the program runs, never at build time. The Community edition ships the .dcu files for FireDAC but not their source, so you cannot read the component code to check a signature: use the docwiki.
Connect
lConn := TFDConnection.Create(nil);
try
lConn.DriverName := 'SQLite'; // 'MSSQL', 'MySQL', 'PG'
lConn.Params.Values['Database'] := 'C:\data\app.db';
lConn.LoginPrompt := False; // else a dialog may appear
lConn.Connected := True;
...
finally
lConn.Free; // closes it
end;| Database | DriverName | Typical params |
| SQLite | SQLite | Database (file path), optional LockingMode=Normal |
| SQL Server | MSSQL | Server, Database, OSAuthent=Yes or User_Name + Password |
| MySQL | MySQL | Server, Database, User_Name, Password, Port; needs the MySQL client library (libmysql.dll) beside the exe or on the path |
| PostgreSQL | PG | Server, Database, User_Name, Password, Port; needs libpq.dll |
- Passwords come from an environment variable or a prompt, never from a literal in the source, a
.dprojor a saved connection definition in a repository. - A named connection definition (
ConnectionDefName) lives inFDConnectionDefs.inioutside the repository; keep passwords out of it too. - Set
Params.Values[...]beforeConnected := True; changing a parameter of an open connection does nothing until it reconnects.
Query and read rows
lQuery := TFDQuery.Create(nil);
try
lQuery.Connection := lConn;
lQuery.SQL.Text := 'select Id, Name from Customer where Active = :Active order by Name';
lQuery.ParamByName('Active').AsBoolean := True;
lQuery.Open;
while not lQuery.Eof do
begin
Writeln(lQuery.FieldByName('Name').AsString);
lQuery.Next;
end;
finally
lQuery.Free;
end;Openis for a statement that returns rows;ExecSQLis forinsert,update,deleteand DDL. CallingOpenon anupdateraises "Cannot open a command that does not return a result set";ExecSQLon aselectdiscards the rows.lQuery.RowsAffectedafterExecSQLis the count the driver reports.- Cache a
TFieldoutside the loop (lName := lQuery.FieldByName('Name')) when reading many rows:FieldByNamedoes a name lookup each call. FetchOptions.ModeandRowsetSizecontrol how many rows are fetched at once; leave the defaults until a measured problem.RecordCountmay force a full fetch, so do not call it in a loop.- One-off scalar:
lConn.ExecSQLScalar('select count(*) from Customer'), andlConn.ExecSQL('delete from Log')for a statement with no result.
Parameters
| Wrong | Right | Why |
SQL.Text := 'select * from T where Name = ''' + lName + '''' | where Name = :Name and ParamByName('Name').AsString := lName | Concatenating user text is SQL injection and breaks on a quote character |
ParamByName('D').Value := lDate with an untyped value | Set DataType first (ftDate, ftDateTime) or use AsDate / AsDateTime | An untyped parameter takes its type from the first value and a null can leave it ftUnknown |
Setting a null with Value := '' | ParamByName('X').Clear or Value := Null (System.Variants) | An empty string is a value, not null |
A literal containing a colon in the SQL text ('12:30') | Pass the value as a parameter | FireDAC scans the text for :Name and may read the literal as a parameter |
A where ... in (:List) bound to a list | Build :P1, :P2, ... one parameter per element | A parameter is one value |
- FireDAC macros (
!Name) substitute text, not values: never fill a macro from user input. - For many rows, set the parameter arrays (
lQuery.Params.ArraySize := N,Params[0].AsStrings[i] := ...) and calllQuery.Execute(N): one round trip instead of N.
Transactions
lConn.StartTransaction;
try
lConn.ExecSQL('update Account set Balance = Balance - 10 where Id = 1');
lConn.ExecSQL('update Account set Balance = Balance + 10 where Id = 2');
lConn.Commit;
except
lConn.Rollback;
raise;
end;- By default a
TFDConnectionruns in auto-commit: each statement commits alone.StartTransactionsuspends that untilCommitorRollback. - Pair every
StartTransactionwithCommitorRollbackon every path; a transaction left open holds locks (on SQL Server, until the connection closes). lConn.InTransactiontells whether one is open. NestedStartTransactioncalls are counted by FireDAC (TxOptions); do not rely on partial rollback inside one.- Queries that must share a transaction share one
TFDConnection, or oneTFDTransactionset as each query'sTransaction. - A read-only report can use
TxOptions.Isolation := xiReadCommitted(the default) or the database's snapshot mode; set it beforeStartTransaction.
Threads
A TFDConnection and the datasets on it belong to one thread. Give each thread its own connection (or use TFDManager connection pooling with Pooled=True in the connection definition) and open and free it inside that thread. Sharing one connection across threads gives errors that look random.
Reporting what you could and could not check
End an answer about FireDAC with: what ran (nothing, if you could not compile), which units and driver parameters you took from the docwiki or the user's code, and which database client library the user needs installed.
How this was verified
- This machine has Delphi 12 Athens Community edition (
bds.exeproduct namePersonal). The FireDAC.dcufiles are present underStudio\23.0\lib\win32\release, and only three FireDAC.pasfiles ship as source (FireDAC.Phys.pas,FireDAC.Phys.SQLGenerator.pas,FireDAC.Phys.SQLPreprocessor.pas), so the component classes could not be read. - The command-line compiler refuses to run in this edition ("This version of the product does not support command line compiling"), and an MSBuild run of a small project compiled nothing. No example here was compiled or run.
- The docwiki returned HTTP 403 to the fetch tool, so the statements above come from the FireDAC documentation as remembered, not from a page read in this session.
What this does not prove
- That an example compiles, or that a parameter name (
OSAuthent,User_Name) is spelled as the installed driver expects. - Behavior on other Delphi versions, other FireDAC editions or other drivers than the four listed.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

