DAO Database Collection FAQ

Last updated June 21, 2025. Copyright © 2025 WINSOFT. All rights reserved.
This FAQ provides guidance for developers using the DAO Database Collection components in Delphi and C++Builder.
How to Identify the Installed DAO Library
try
  ShowMessage('DAO ' + GetDBEngine(dvDAO35).Version + ' installed');
except
  ShowMessage('DAO 3.5 not installed');
end;

try
  ShowMessage('DAO ' + GetDBEngine(dvDAO36).Version + ' installed');
except
  ShowMessage('DAO 3.6 not installed');
end;

try
  ShowMessage('ACEDAO ' + GetDBEngine(dvACE12).Version + ' installed');
except
  ShowMessage('ACEDAO not installed');
end;
You can also use the DAO Detect and DAO Detect 64 utilities included with the DAO components to quickly identify installed versions without writing code.
Latest Available DAO Versions
The most recent versions of the Data Access Objects (DAO) libraries are:
DAO 3.6 - used primarily with Microsoft Jet 4.0 databases (.mdb format)
ACEDAO 16.0 - part of the Microsoft Access Database Engine, used with Access 2007 and later (.accdb format)
If you're working with modern Access applications, ACEDAO 16.0 is the recommended library, as it supports newer features and file formats.
Where to Download the Latest Microsoft Access Runtime
You can download and install the Microsoft 365 Access Runtime for free from Microsoft’s official support page:
Download and install Microsoft 365 Access Runtime
It’s available in both 32-bit and 64-bit versions and supports all major languages. This runtime allows users to run Access applications without needing the full version of Microsoft Access installed.
Tip: Choose the bit version that matches your installed version of Office. If you're unsure, Microsoft recommends the 32-bit version for compatibility.
How to Check Which DAO ISAM Drivers Are Installed
To check which ISAM (Indexed Sequential Access Method) drivers are installed, inspect the Windows Registry using the REGEDIT.EXE utility.
Jet 3.5 ISAM drivers used by DAO 3.5 and DAO 3.51:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Jet\3.5\ISAM Formats
Jet 4.0 ISAM drivers used by DAO 3.6:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Jet\4.0\ISAM Formats
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Jet\4.0\ISAM Formats
ACEDAO ISAM drivers used by ACEDAO 12.0–16.0 (Access Database Engine):
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office\14.0\Access\Access Connectivity Engine\ISAM Formats
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office\14.0\Access Connectivity Engine
Tip: On 64-bit systems, both native and Wow6432Node paths may be present depending on whether the drivers were installed for 32-bit or 64-bit applications.
Where to Access More DAO Resources
DAO documentation: DAO35.HLP file in folder C:\Program Files\Common Files\Microsoft Shared\DAO.
Newsgroup: microsoft.public.vb.database.dao at msnews.microsoft.com
Microsoft Jet Database Engine
Microsoft Access Tips for Serious Users
ACC97: CommitTrans Help Topic Uses dbFlushOSCacheWrites Constant
HOWTO: Redistributing DAO with Your Visual C++ 5.0 Application
ACC97: How to Read .LDB Files
PRB: Error "The Jet VBA File... Failed to Initialize When Called"
PRB: The Jet VBA File VBAJet32.dll Failed to Initialize
How To Redistribute DAO 3.6
PRB: Jet 4.0 Row-Level Locking Is Not Available with DAO 3.60
HOWTO: Ensure Jet 3.5 Is Installed Correctly (Part I)
HOWTO: Ensure Jet 3.5 Is Installed Correctly (Part II)
Creating a New Microsoft Access Database
GetDBEngine.CreateDatabase('C:\database.mdb', dbLangGeneral, EmptyParam);
Compacting a Microsoft Access Database
You can use the CompactDatabase method to reduce file size, convert formats, apply encryption, or change locale settings.
// Basic compaction
GetDBEngine.CompactDatabase('C:\database.mdb', 'C:\newdb.mdb', EmptyParam, EmptyParam, EmptyParam);

// Uses the Czech locale for the new database
GetDBEngine.CompactDatabase('C:\database.mdb', 'C:\newdb.mdb', dbLangCzech, EmptyParam, EmptyParam);

// Encrypts the database during compaction
GetDBEngine.CompactDatabase('C:\database.mdb', 'C:\newdb.mdb', ';pwd=NewPassword', dbEncrypt, EmptyParam);

// Decrypts the database during compaction
GetDBEngine.CompactDatabase('C:\database.mdb', 'C:\newdb.mdb', EmptyParam, dbDecrypt, ';pwd=ExistingPassword');

// dbVersion10 - Jet 1.0 format
// dbVersion11 - Jet 1.1 format
// dbVersion20 - Jet 2.0 format
// dbVersion30 - Jet 3.0 and 3.5 formats
// dbVersion40 - Jet 4.0 format // Converts the database to Jet 3.0/3.5 format GetDBEngine.CompactDatabase('C:\database.mdb', 'C:\newdb.mdb', '', dbVersion30, EmptyParam); // Compact a password-protected database using the original password GetDBEngine.CompactDatabase('C:\database.mdb', 'C:\newdb.mdb', EmptyParam, EmptyParam, ';pwd=ExistingPassword'); // Compact the database and assign a new password to the destination file (no encryption applied) GetDBEngine.CompactDatabase('C:\database.mdb', 'C:\newdb.mdb', ';pwd=NewPassword', EmptyParam, EmptyParam);
Repairing a Corrupted Microsoft Access Database
GetDBEngine.RepairDatabase('C:\database.mdb');
This method tries to recover the database by validating system tables and indexes. Any unrecoverable data will be discarded.
Important notes:
- The database must be closed and not in use by any other application or user.
- This method is primarily intended for Jet-format databases (.mdb).
- After repairing, it's recommended to run CompactDatabase to defragment the file and reclaim disk space.
Tip: If RepairDatabase fails or is unavailable in your environment, consider using CompactDatabase as an alternative recovery method.
Deleting a Table from an Access Database
DAODatabase.DeleteTable('MyTable');
This removes the table named 'MyTable' from the database. Make sure the table is not open or in use when attempting deletion.
Note: This action is permanent and cannot be undone. Always back up your database before deleting tables.
Deleting All Records from a Table
DAODatabase.EraseTable('MyTable');
This clears the contents of 'MyTable' without deleting the table structure itself.
Important: This operation is irreversible. Make sure to back up your data before erasing table contents.
Listing Tables and Queries Dynamically During Execution
// List all table names
with DAODatabase.TableDefs do
  for I := 0 to Count - 1 do
    ShowMessage('Table: ' + Item[I].Name);

// List all query names
with DAODatabase.QueryDefs do
  for I := 0 to Count - 1 do
    ShowMessage('Query: ' + Item[I].Name);
Tip: You can filter out system or hidden tables by checking the Attributes property of each TableDef.
Managing DAO Exceptions Without Displaying Alerts
To prevent DAO exceptions from being displayed to the user at runtime, handle the OnDAOError event and set the action to daAbort:
procedure TForm1.DAODatasetDAOError(DataSet: TDataSet; E: EDatabaseError; var Action: TDataAction);
begin
  // suppress the exception and stop further error handling
  Action := daAbort;
end;
This approach silently aborts the operation without showing an error dialog. You can also log the exception or display a custom message if needed.
Tip: Use this technique when you want to gracefully handle expected errors (e.g., missing tables or locked records) without interrupting the user experience.
Microsoft Access Limitations for Developers and Users
Access specifications
Microsoft Access Specifications and Limitations
Using Multiword Table Names in SQL Queries
When referencing table names that contain spaces or special characters, enclose them in square brackets:
DAODataSet.SQL.Text := 'SELECT * FROM [Financial Reports]';
This ensures the SQL parser treats the entire phrase as a single identifier, even if it includes spaces or reserved keywords.
Tip: This syntax also applies to field names - use [Field Name] when necessary.
Specifying Date Values in DAO Filter Expressions
When filtering by date in DAO SQL expressions, enclose date literals in # characters:
// Filter for a specific date
DAODataSet.Filter := 'MyDate = #10/14/2024#';

// Filter for a date range
DAODataSet.Filter := 'MyDate >= #10/14/2024# and MyDate < #10/20/2024#';
Tip: Always use the U.S. date format mm/dd/yyyy regardless of your system locale, as DAO interprets dates in this format by default.
Using DAO Components Safely in Multithreaded Applications
DAO relies on COM, which is not thread-safe by default. To safely use DAO components in multiple threads, you must initialize and uninitialize COM in each thread individually:
uses ActiveX;

procedure MyThread.Execute;
begin
  CoInitialize(nil); // Initialize COM for this thread
  try
    // Your DAO-related code here
  finally
    CoUninitialize; // Clean up COM before the thread exits
  end;
end;
Important: Every thread that uses DAO must call CoInitialize (or CoInitializeEx) before accessing any COM-based objects, and must call CoUninitialize when done. Failing to do so can lead to unpredictable behavior or crashes.
Tip: Avoid sharing DAO objects across threads. Instead, create and use them within the same thread where CoInitialize was called.
Specifying an Index in the DAODataSet Component
You don't need to manually specify an index when using DAODataSet. DAO components behave like queries in Microsoft Access - simply set the Sort property to define the desired order:
DAODataSet.Sort := 'LastName, FirstName';
The Microsoft Jet Engine will automatically choose the most appropriate index to optimize sorting. If no suitable index exists, it will still sort the records in memory, so sorting is not limited to indexed fields.
Tip: For large datasets, creating an index on frequently sorted fields can significantly improve performance.
Sorting Records in Descending Order
To sort records in descending order using the DAODataSet component, append the DESC keyword to the field name in the Sort property:
DAODataSet.Sort := 'Name DESC';
This sorts the dataset by the Name field in descending (Z–A) order.
Tip: You can sort by multiple fields by separating them with commas, e.g. 'LastName DESC, FirstName ASC'.
Creating a Multiline SQL Statement at Runtime
When building a multiline SQL statement dynamically, you may need to temporarily disable parameter checking to avoid premature parsing errors. Use the ParamCheck property to control this behavior:
with DAODataSet do
begin
  ParamCheck := False; // Disable parameter parsing temporarily
  SQL.Clear;
  SQL.Add('SELECT Name');
  SQL.Add('FROM MyTable');
  ParamCheck := True; // Re-enable parameter parsing
  SQL.Add(''); // Trigger parameter refresh
  Open;
end;
Why is SQL.Add('') used? Adding an empty string after re-enabling ParamCheck forces the component to re-parse the SQL and refresh the Params collection. Without this step, parameters might not be recognized correctly.
Why do I get the error message: "Can't start your application. The workgroup information file is missing or opened exclusively by another user"?
This error typically occurs when your application tries to open a secured Access database using the wrong authentication method.
If your database is encrypted with a password, do not use the DAODatabase.Password property to supply it. Instead, specify the password directly in the DatabaseConnect property, like this:
DAODatabase.DatabaseConnect := ';pwd=Erik'; // For a database encrypted with password 'Erik'
The DAODatabase.Password property is intended for user-level security, where individual user credentials are stored in a workgroup information file (with a .mdw extension). If this file is missing, inaccessible, or locked by another user, the error message will appear.
How to Set the Number of Threads in DAO 3.5
You can configure the number of internal threads used by the Jet 3.5 engine by modifying the Windows Registry. The default value is 3.
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Jet\3.5\Engines\Jet 3.5\Threads
Important: This setting controls the number of threads used internally by the Jet engine. It does not enable multithreading in your application code. DAO 3.5 follows the OLE apartment threading model and is not inherently thread-safe.
How do I use DAO 3.5 functions in C++Builder?
C++Builder converts DAO interface unit, originally created in Delphi, so return value of Delphi function is converted as the last parameter of C++ function and C++ functions always return HRESULT type.

For example CreateDatabase function in declared in Delphi as:
function CreateDatabase(const Name: WideString; const Locale: WideString, Option: OleVariant): Database;
C++Builder converts this function to:
HRESULT CreateDatabase(const System::WideString Name, const System::WideString Locale, const System::OleVariant Option, _di_Database &CreateDatabase_result);
To call this function, you need to add the last parameter:
_di_Database db;
GetDBEngine()->CreateDatabase("C:\\database.mdb", dbLangGeneral, EmptyParam, db);
All DAO functions (DAO 3.5 interface) are declared in dao.hpp file.
Why can't I link table from one mdb database to another?
dbAttachedTable constant is incorrectly defined in DAO, it should be zero:
with DAODatabase.Handle do
begin
  TableDef := CreateTableDef('MyLinkTable', 0 {dbAttachedTable}, 'COUNTRY', ';DATABASE=C:\db.mdb');
  TableDefs.Append(TableDef);
end;
Why can't I enter time without date into date/time field?
Delphi requires entering date into TDateTime fields. You should add SetText and GetText events to your TDateField field to enable entering and proper formatting of time values:
procedure TForm1.DAODataSet1TestTimeGetText(Sender: TField; var Text: string; DisplayText: Boolean);
begin
  Text := TimeToStr(Sender.AsDateTime);
end;

procedure TForm1.DAODataSet1TestTimeSetText(Sender: TField; const Text: string);
begin
  Sender.AsDateTime := StrToTime(Text);
end;
How do I refresh DAO 3.5 cache?
GetDBEngine.Idle(dbRefreshCache);
How do I create an index?
DAODatabase.ExecSQL('CREATE UNIQUE INDEX MyIndex ON MyTable (Name, Age)');
Can I use MS Access 95 databases with DAO 3.5?
Yes, MS Access 95 database format is compatible with DAO 3.5, so you can use MS Access 95 databases without any changes.
How do I import data from an external table?
DAODatabase.ExecSQL('INSERT INTO DestTable SELECT * FROM SrcTable IN "" "dBase III;DATABASE=C:\"');
Has DAO 3.5 support for record locking?
No DAO 3.5 always locks 2kB pages.
How can I link dBase table to MS Access database?
var TableDef: DAO.TableDef;

with DAODatabase.Handle do
begin
  TableDef := CreateTableDef('MyLinkedTable', EmptyParam, EmptyParam, EmptyParam);

  TableDef.Connect := 'dBase III;DATABASE=C:\';
  TableDef.SourceTableName := 'industry.dbf';

  TableDefs.Append(TableDef);
end;
How do I create custom database property?
with DAODatabase.Handle do
  Properties.Append(CreateProperty('PropertyName', dbText, 'PropertyValue', False));
How can I change database password?
DAODatabase.ChangePassword('OldPassword', 'NewPassword');
Note: DAODatabase must be opened in Exclusive mode.
To remove database password, use empty string as a NewPassword.
To set a new database password using DAO 3.6:
DAODatabase.ChangePassword(#0, 'NewPassword');
How do I specify MS Excell range of cells to access?
DAODataSet.TableName := 'COUNTRY$A2:C4';
How do I switch off header in MS Excell worksheet?
DAODataSet.DatabaseConnect := 'Excel 8.0;HDR=NO';
What limitations have text tables?
Max fields in table: 255
Max size of field name: 64
Max field width: 32766
Max rows: 65000
Is it possible to use separate directories for database file and lock file?
No.
Can I use HTML Import and HTML Export directly from/to my website?
Yes, you can specify website URL:
DAODataset.DatabaseConnect := 'HTML Import';
DAODataset.DatabaseName := 'https://localhost/webpage.htm';
Has DAO 3.5 support for multi-threading on Windows 95?
DAO 3.5 supports only Unicode interfaces for multi-threading. Because Microsoft Windows 95 does not fully suports Unicode, DAO can not be used in multiple threads on Windows 95.
Which threading model supports DAO 3.5?
DAO 3.5 supports OLE apartment threading model.
Can I use URL for specifying mdb database location?
No.
How do I use heterogenous queries on databases protected with password?
DAODataSet.SQL.Text := 'SELECT * FROM Country IN "" ";DATABASE=C:\SIMPLE.MDB;PWD=MyPassword"';
DAODataSet.Open;
How do I get a list of all relationships in a database?
with DAODatabase.Relations do
  for i := 0 to Count - 1 do
  begin
    ShowMessage('Relation name: ' + Item[i].Name);
    ShowMessage('Master table: ' + Item[i].Table);
    ShowMessage('Detail table: ' + Item[i].ForeignTable);
    ShowMessage('Fields: ');
    with Item[i].Fields do
      for j := 0 to Count - 1 do
        ShowMessage(Item[j].Name + ':' + Item[j].ForeignName);
  end;
How do I get a list of all fields in a table?
with DAODataset.Recordset.Fields do
  for i := 0 to Count - 1 do
    ShowMessage(Item[i].Name);
How do I get a list of all users?
with DAODatabase.Users do
  for i := 0 to Count - 1 do
    ShowMessage(Item[i].Name);
How do I get a list of all user groups?
with DAODatabase.Groups do
  for i := 0 to Count - 1 do
    ShowMessage(Item[i].Name);
How do I create or delete a new user or user group?
DAODatabase.CreateUser('NewUser', 'NewUserPID', 'NewUserPassword');
DAODatabase.DeleteUser('NewUser');

DAODatabase.CreateGroup('NewGroup', 'NewGroupPID');
DAODatabase.DeleteGroup('NewGroup');

DAODatabase.AddUserToGroup('NewUser', 'NewGroup');
DAODatabase.RemoveUserFromGroup('NewUser', 'NewGroup');
How do I access an mdb database on CD/DVD?
Set exclusive access, so lock file (ldb) will not be created:
DAODatabase.Exclusive := True;
DAODatabase.Open;
How do I export table to Excel worksheet?
DAODatabase.ExecSQL('SELECT * INTO MySheet IN "" "Excel 8.0;DATABASE=C:\MyFile.xls" FROM MyTable');
How do I export table to comma-delimited text file?
Use this code to export table to text format:
DAODatabase.ExecSQL('SELECT * INTO MyText#TXT IN "" "Text;DATABASE=C:\MyDir" FROM MyTable');
If comma-delimited text file is required, change line in SCHEMA.INI file from
Format=Delimited(;)
to
Format=Delimited(,)
and start export again.
How do I get a list of users currently connected to database?
Use Msldbusr.dll
ACC: Microsoft Jet Utilities Available in Download Center
ACC97: How to Read .LDB Files
How do I change name of field?
DAODatabase.TableDefs.Item['MyTable'].Fields.Item['OldFieldName'].Name := 'NewFieldName';
How do I change type of field?
This is not possible directly with DDL statements or DAO objects. You need to add a new field, copy data from old field to the new field (for example using UPDATE statement) and then delete old field.
How do I create a relation?
var
  Relation: DAO.Relation;
  Field: DAO.Field;
begin
  with DAODatabase.Handle do
  begin
    // create relation
    Relation := CreateRelation('MyRelation', 'MasterTable', 'DetailTable', 0);

    // add fields to relation (don't forget to set their ForeignName property)
    Field := Relation.CreateField('MasterID', dbInteger, 0);
    Field.ForeignName := 'DetailID';
    Relation.Fields.Append(Field);

    // append created relation to collection of all relations
    Relations.Append(Relation);
  end;
end;
How do I create an autoincrement field?
var DAOField: DAO.Field;

DAOField := CreateField(Name, DAO.dbLong, EmptyParam);
DAOField.Attributes := DAOField.Attributes or dbAutoIncrField;
Why my parameterized query doesn't work?
Parameter names in SQL statements can't begin with ":"
SELECT * FROM MyTable WHERE MyField = MyParameter
How do I use master-detail relationship in queries with equal field names?
Use PARAMETERS clause to declare parameters to avoid parameter name conflict:
PARAMETERS ID LONG;
SELECT * FROM MyTable WHERE MasterID = ID
Is it possible to undelete deleted records in MS Access database?
No.
How secure are password encrypted MS Access databases?
MS Acess databases aren't secure. Both database encryption password and admin passwords can be easily retrieved.
How do I get database properties like Title, Author and Company?
with DAODatabase1.Containers.Item['Databases'].Documents.Item['SummaryInfo'].Properties do
begin
  try ShowMessage('Title: ' + Item['Title'].Value); except end;
  try ShowMessage('Author: ' + Item['Author'].Value); except end;
  try ShowMessage('Company: ' + Item['Company'].Value); except end;
  try ShowMessage('Subject: ' + Item['Subject'].Value); except end;
  try ShowMessage('Manager: ' + Item['Manager'].Value); except end;
end;
How can I improve DAO performance?
Use DML (Data Manipulation Language) SQL statements instead of loops. For example deleting records with SQL statement 'DELETE FROM MyTable' is much faster than deleting each record separately with TDAOTable.Delete statement in loop. Jet database engine contains very sophisticated cost-based query optimizer. You can activate function ShowPlan to see created plan of execution for each query:
Create this key in registry database:
MyComputer\HKEY_LOCAL_MACHINE\SOFTWARE\MICROSOFT\Jet\3.5\Engines\Debug
Under this key create a new string value with name JETSHOWPLAN and data ON.
You can later turn off this function by setting data to OFF.
How do I select records where some field begins with given character? My SQL statement "SELECT * FROM MyTable WHERE Name = 'T%'" doesn't work.
Use LIKE operator:
SELECT * FROM MyTable WHERE Name LIKE 'T*'
How do I copy table to another Access database?
Connect DAODataSet to the first database (db1.mdb). Then use this SQL statement:
SELECT * INTO MyDstTable IN "" ";DATABASE=db2.mdb"  FROM MySrcTable
To append records to the existing table in the second database use:
INSERT INTO MyDstTable IN "" ";DATABASE=db2.mdb" SELECT * FROM MySrcTable
How do I retrieve DAO error code?
Use this code, you can place it in OnDAOError event handler:
with GetDBEngine.Errors do
  for i := 0 to Count - 1 do
    with Item[i] do
      ShowMessage(
        'Description: ' + Description + #13 +
        'Number: ' + IntToStr(Number) + #13 +
        'Source: ' + Source + #13 +
        'HelpContext: ' + IntToStr(HelpContext) + #13 +
        'HelpFile: ' + HelpFile);
How do I convert MS Access database to newer format?
Use CompactDatabase method, see How do I compact an Access database?
How do I get a list of table indexes?
with DAODatabase.Handle.TableDefs.Item['MyTable'].Indexes do
  for i := 0 to Count - 1 do
  begin
    ShowMessage('Index: ' + Item[i].Name);
      with Item[i] do
        for j := 0 to Fields.Count - 1 do
          ShowMessage('Field: ' + Fields.Item[j].Name);
  end;
How do I get the date/time when the table was created?
ShowMessage(DAODatabase.Handle.TableDefs.Item['MyTable'].DateCreated);
How do I get the date/time when the table was last modified?
ShowMessage(DAODatabase.Handle.TableDefs.Item['MyTable'].LastUpdated);
How do I create a new table with Boolean field?
var TableDef: DAO.TableDef;

with DAODatabase1.Handle do
begin
  TableDef := CreateTableDef('MyTable', EmptyParam, EmptyParam, EmptyParam);
  with TableDef do
    Fields.Append(CreateField('MyBoolField', DAO.dbBoolean, EmptyParam));
  TableDefs.Append(TableDef);
end;
How can I add a new Boolean field to existing table?
var TableDef: DAO.TableDef;

with DAODatabase1.Handle do
begin
  TableDef := TableDefs.Item['MyTable'];
  with TableDef do
    Fields.Append(CreateField('MyBoolField', DAO.dbBoolean, EmptyParam));
end;
How do I use regional-formatted date/time values?
Use MS Access CDate function:
DAODataSet.Filter := 'MyDate=CDate("30.10.1999 10:20:30")'; // Slovak regional settings
How do I create 'True/False' formatted boolean field?
Set Format property of this field to 'True/False' value:
with DAODatabase.Handle.TableDefs.Item['MyTable'].Fields.Item['MyBooleanField'] do
begin
  // try to remove old Format property
  try Properties.Delete('Format') except end;

  // create new Format property
  Properties.Append(CreateProperty('Format', dbText, 'True/False', EmptyParam));
end;
How do I retrieve caption of the field?
DAO 3.6:
ShowMessage(DAODataSet.Recordset.Fields['MyField'].Properties['Caption'].Value);
DAO 3.5:
ShowMessage(DAODataSet.Recordset.Fields.Item['MyField'].Properties.Item['Caption'].Value);
How can I directly use DAO for very fast record insertion?
Delphi code:
var
  I: Integer;
  Field: DAO.Field;

with DAODataSet.Recordset do
try
  Parent.BeginTrans;

  Field := Fields[0];

  for I := 1 to 1000 do
  begin
    AddNew;
    Field.Value := I;
    Update(dbUpdateRegular, False);
  end;

  Parent.CommitTrans(dbForceOSFlush);
except
  Parent.Rollback;
  raise;
end;
C++Builder code:
Dao::Recordset *Recordset = DAODataSet->Recordset;

try
{
  Recordset->Parent->BeginTrans();

  Variant Field = ((Variant)(IDispatch *)Recordset->Fields).OlePropertyGet("Item", 0);

  for (int i = 0; i < 1000; ++i)
  {
    Recordset->AddNew();
    Field.OlePropertySet("Value", i);
    Recordset->Update(dbUpdateRegular, false);
  }

  Recordset->Parent->CommitTrans(dbForceOSFlush);
}
catch (Exception &exception)
{
  Recordset->Parent->Rollback();
  throw;
}
How do I create/delete/enumerate Access queries?
// create query
DAODatabase.Handle.CreateQueryDef('MyQuery', 'SELECT * FROM MyTable');

// delete query
DAODatabase.Handle.DeleteQueryDef('MyQuery');

// enumerate queries
with DAODatabase.Handle do
  for i := 0 to QueryDefs.Count - 1 do
    ShowMessage(QueryDefs[i].Name + ': ' + QueryDefs[i].SQL);
How do I refresh TableDefs collection?
DAODatabase.TableDefs.Refresh;
How do I retrieve Access containers and documents?
with DAODatabase do
  for i := 0 to Containers.Count - 1 do
    with Containers[i] do
      for j := 0 to Documents.Count - 1 do
        ShowMessage('Container: ' + Containers[i].Name + ' Document: ' + Documents[j].Name);
How do I retrieve table permissions?
var Permissions: Integer;

Permissions := DAODatabase.Containers['Tables'].Documents['MyTable'].Permissions;
if Permissions = dbSecNoAccess then ShowMessage('NoAccess');
if Permissions and dbSecFullAccess = dbSecFullAccess then ShowMessage('FullAccess');
if Permissions and dbSecDelete = dbSecDelete then ShowMessage('Delete');
if Permissions and dbSecReadSec = dbSecReadSec then ShowMessage('ReadSec');
if Permissions and dbSecWriteSec = dbSecWriteSec then ShowMessage('WriteSec');
if Permissions and dbSecDBCreate = dbSecDBCreate then ShowMessage('DBCreate');
if Permissions and dbSecDBOpen = dbSecDBOpen then ShowMessage('DBOpen');
if Permissions and dbSecDBExclusive = dbSecDBExclusive then ShowMessage('DBExclusive');
if Permissions and dbSecDBAdmin = dbSecDBAdmin then ShowMessage('DBAdmin');
if Permissions and dbSecCreate = dbSecCreate then ShowMessage('Create');
if Permissions and dbSecReadDef = dbSecReadDef then ShowMessage('ReadDef');
if Permissions and dbSecWriteDef = dbSecWriteDef then ShowMessage('WriteDef');
if Permissions and dbSecRetrieveData = dbSecRetrieveData then ShowMessage('RetrieveData');
if Permissions and dbSecInsertData = dbSecInsertData then ShowMessage('InsertData');
if Permissions and dbSecReplaceData = dbSecReplaceData then ShowMessage('ReplaceData');
if Permissions and dbSecDeleteData = dbSecDeleteData then ShowMessage('DeleteData');
Use UserName property to retrieve permissions for specified user or group:
with DAODatabase.Containers['Tables'].Documents['MyTable'] do
begin
  UserName := 'MyUserName';
  MyPermissions := Permissions;
end;
How do I change table permissions?
DAODatabase.Containers['Tables'].Documents['MyTable'].Permissions := dbSecFullAccess;
Use UserName property to change permissions for specified user or group:
with DAODatabase.Containers['Tables'].Documents['MyTable'] do
begin
  UserName := 'MyUserName';
  Permissions := dbSecFullAccess;
end;
How do I retrieve records from external MS Access database?
SELECT * FROM MyTable IN "C:\MyDB.mdb"
Insert records to a new table:
SELECT * INTO DestTable IN "C:\DestDB.mdb" FROM SrcTable
SELECT * INTO DestTable FROM SrcTable IN "C:\SrcDB.mdb"
Insert records to an existing table:
INSERT INTO DestTable IN "C:\DestDB.mdb" SELECT * FROM SrcTable
INSERT INTO DestTable SELECT * FROM SrcTable IN "C:\SrcDB.mdb"
How do I rename a table?
DAODatabase.TableDefs['OldTableName'].Name := 'NewTableName';
How can I set Unicode Compression for given field?
with DAODatabase.TableDefs['MyTable'].Fields['MyField'] do
try
  Properties['UnicodeCompression'].Value := -1; // 0 switches off Unicode compression
except
  Properties.Append(CreateProperty('UnicodeCompression', dbBoolean, -1, False)); // 0 switches off Unicode compr.
end;
How can I change an existing user's password?
DAODatabase.Users.Item['UserName'].NewPassword('OldPassword', 'NewPassword');
How can I set Required field attribute?
DAODatabase.TableDefs['MyTable'].Fields['MyField'].Required := True;
How do I create a new field with default value?
var Field: DAO.Field;

Field := TableDef.CreateField('Name', DAO.dbText, 24);
Field.DefaultValue := 'Erik';
TableDef.Fields.Append(Field);
How do I create a new field with validation rule?
var Field: DAO.Field;

Field := TableDef.CreateField('Size', DAO.dbInteger, EmptyParam);
Field.ValidationRule := '>= 10 AND <= 1000';
Field.ValidationText := 'Size must be between 10 and 1000';
TableDef.Fields.Append(Field);
How do I set "Format" property to "Short Date" for a Date/Time field?
with DAODatabase.Handle.TableDefs.Item['MyTable'].Fields.Item['MyDateField'] do
begin
  // try to remove old Format property
  try Properties.Delete('Format') except end;

  // create new Format property
  Properties.Append(CreateProperty('Format', dbText, 'Short Date', EmptyParam));
end;
How do I update connection information for a linked table?
with DAODatabase.Handle.TableDefs['MyLinkedTable'] do
begin
  ShowMessage('Current connect: ' + Connect);

  // change connect
  Connect := 'Excel 5.0;HDR=YES;IMEX=2;DATABASE=' + GetCurrentDir + '\MyData.XLS';

  // refresh link
  RefreshLink;

  ShowMessage('New connect: ' + Connect);
end;