Importing Data Overview
BCCL makes it straightforward to import data into any Business Central table from the command line. The PUTDATA task reads data from an input file, matches each record against the target table's primary key, and either inserts a new record or modifies an existing one. This page covers the fundamentals of the import process, supported formats, and the key parameters you need to get started.
The PUTDATA Task
You invoke data import by specifying -t putdata as the task parameter. PUTDATA is designed for bulk data operations and handles both creating new records and updating existing ones in a single pass.
bccl -t putdata -i customers.csv -m mapping.json -s table=18
At minimum, you need to provide:
| Parameter | Flag | Description |
|---|---|---|
| Task | -t putdata |
Tells BCCL to perform a data import |
| Input file | -i filename |
The file containing your data |
| Target table | -s table=N |
The Business Central table number to import into |
A mapping file (-m) is optional but strongly recommended. Without one, BCCL expects the columns in your input file to match the target table's fields exactly in order and count.
Using a Mapping File with PUTDATA
Mapping files are supported and normal for putdata. The same mapping file can be used for a getdata → putdata round trip, for example to copy records between environments:
BCCL -w <webservice-url> -t getdata -s table=349 "view=WHERE(Field1=1(CONTRACT))" -o <output.json> -f json -m <mapping.json> -v
BCCL -w <webservice-url> -t putdata -s table=349 -i <output.json> -f json -m <mapping.json> -v
(with <webservice-url> of the form http://<server>:<port>/<instance>/WS/<company>/Codeunit/bccl).
If a putdata run fails with a mapping file but succeeds without it, the problem is in the mapping file, most commonly a "Function":"CONST(...)" entry on a validated field whose value is already in the input data, not in the putdata command itself. See Import (PUTDATA) Errors.
How Insert and Modify Works
PUTDATA uses a simple rule to decide whether to insert or modify a record:
- BCCL reads the primary key fields from your input data.
- It attempts to insert a new record with those primary key values.
- If a record with that primary key already exists, BCCL modifies the existing record instead.
This means you can safely run the same import multiple times. The first run inserts the records, and subsequent runs update them with any changed values. There is no need for separate "create" and "update" commands.
Understanding the Result
After the import completes, BCCL returns a JSON result showing what happened:
{"Table":18,"Inserted":3,"Modified":0}
| Field | Description |
|---|---|
Table |
The table number that was targeted |
Inserted |
Number of new records created |
Modified |
Number of existing records updated |
If the same data is imported a second time without changes, you would typically see:
{"Table":18,"Inserted":0,"Modified":3}
This tells you that all three records already existed and were updated (even if the values did not change).
Supported Input Formats
BCCL supports four input file formats:
| Format | Extension | Notes |
|---|---|---|
| CSV | .csv |
Comma-separated values with header row |
| JSON | .json |
Array of JSON objects |
| XML | .xml |
XML document with repeating record elements |
| Excel | .xlsx |
Excel 2007+ workbook (not .xls) |
BCCL auto-detects the format based on the file extension. If your file does not use a standard extension, you can force the format with the -f parameter:
bccl -t putdata -i data.txt -f csv -m mapping.json -s table=18
Mapping Files
A mapping file is a JSON document that controls how columns in your input file correspond to fields in the Business Central table. Mapping files give you precise control over:
- Which fields are included in the import
- Column-to-field assignment via the
MappedNameproperty - Validation behavior for individual fields and the record as a whole
- Automatic stub record creation for related tables
- Custom functions like constants and dimension handling
Generating a Mapping File
The easiest way to create a mapping file is to use the MAPPING task:
bccl -t mapping -s table=18 -o customer_mapping.json
This generates a default mapping file for the specified table with all fields included. You then edit the file to keep only the fields you need and adjust the MappedName values to match your input data's column names.
Mapping File Structure
A typical mapping file looks like this:
{
"Customer": [
{"FieldNo":1,"FieldName":"No.","MappedName":"Number","Validate":true},
{"FieldNo":2,"FieldName":"Name","MappedName":"Name","Validate":true},
{"FieldNo":5,"FieldName":"Address","MappedName":"Address","Validate":false}
],
"ValidateOnInsert": true,
"ValidateOnModify": true
}
The first property is the table name containing an array of field definitions. The ValidateOnInsert and ValidateOnModify settings control whether Business Central's built-in record-level validation triggers fire during import.
Validation Settings
BCCL provides two levels of validation:
Field-Level Validation
Set "Validate": true on individual fields in the mapping file. When enabled, BCCL calls the field's Validate() trigger after assigning the value. This fires any AL code associated with the OnValidate trigger for that field.
Record-Level Validation
The ValidateOnInsert and ValidateOnModify properties at the root of the mapping file control whether the Insert(true) or Modify(true) calls pass true to Business Central. When set to true, the OnInsert and OnModify triggers on the table fire during the operation.
Tip: For maximum speed on large imports where you trust the data, set all validation to
false. For imports where data integrity is critical, enable validation to let Business Central enforce its business rules.
Delayed Insert (-d)
By default BCCL assigns the primary key fields, inserts the record, and then assigns the remaining fields. If the target table's OnInsert trigger requires a non-primary-key field to already be filled, the insert fails with an error such as <Field> must have a value in <Table>: <primary key values>. It cannot be zero or empty. even though the field is present in your input data. The -d (--delayedinsert) parameter makes BCCL assign all mapped fields first and insert afterwards, which is exactly what such tables need:
bccl -t putdata -i data.json -m mapping.json -s table=<N> -d
-d changes when the record is inserted, not whether validation runs, so it is independent of the Validate and ValidateOnInsert/ValidateOnModify settings. It corresponds to "DelayedInsert": true in the verbose (-v) settings output. Prefer -d over setting ValidateOnInsert to false. See Advanced Import Features and Import (PUTDATA) Errors.
Automatic Number Series
If you want Business Central to assign numbers automatically (for example, customer numbers from a number series), simply omit the primary key field from your mapping file. When BCCL inserts a record without specifying the primary key, Business Central's number series logic generates the value automatically.
{
"Customer": [
{"FieldNo":2,"FieldName":"Name","MappedName":"Name","Validate":true},
{"FieldNo":7,"FieldName":"City","MappedName":"City","Validate":true}
],
"ValidateOnInsert": true,
"ValidateOnModify": true
}
In this example, the No. field (FieldNo 1) is not in the mapping. BCCL inserts each record with the number series assigning the customer number.
Paging for Large Files
When you import large files, BCCL automatically splits the data into batches (pages). Each batch is sent to Business Central independently and committed as a separate transaction.
The default page size is 1000 records per batch. You can adjust this with the -z parameter:
bccl -t putdata -i large_dataset.csv -m mapping.json -s table=18 -z 500
Important: If an error occurs mid-import, records from already-committed batches remain in the database. Only the current failing batch is rolled back.
Basic Import Example
Here is a complete example that imports customer data from a CSV file into table 18 (Customer):
Step 1: Generate a mapping file:
bccl -t mapping -s table=18 -o customer_mapping.json
Step 2: Edit the mapping file to include only the fields you need, and set MappedName to match your CSV column headers.
Step 3: Run the import:
bccl -t putdata -i customers.csv -m customer_mapping.json -s table=18
Step 4: Review the result:
{"Table":18,"Inserted":3,"Modified":0}
Command-Line Parameters Reference
The following table summarizes all parameters relevant to the PUTDATA task:
| Parameter | Flag | Default | Description |
|---|---|---|---|
| Task | -t putdata |
(required) | Specifies the import task |
| Input file | -i |
(required) | Path to the data file |
| Table | -s table=N |
(required) | Target table number |
| Mapping | -m |
(none) | Path to the mapping file |
| Format | -f |
(auto) | Force format: csv, json, xml, xlsx |
| Delayed insert | -d |
false | Assign all fields before inserting (for tables whose OnInsert requires non-key fields) |
| Binary fields | -b |
false | Include blob/media fields |
| Page size | -z |
1000 | Records per batch |
| Header | -h |
true | CSV files have header row |
| Delimiter | -l |
, |
CSV delimiter character |
| Quote char | -c |
" |
CSV quote character |
| Ignore quotes | -q |
false | Ignore quotes in CSV |
| Excel sheet | -x |
(none) | Excel sheet name |
| Excel range | -y |
(none) | Excel data range (A2..C50) |
| XML record | -r |
(none) | XML record element path |
| Verbose | -v |
false | Show debug output |
Tips and Best Practices
- Always generate a mapping file with the MAPPING task first, then customize it. This prevents typos in field numbers and names.
- Test imports with a small subset of data before running large imports.
- Use
-v(verbose mode) to see detailed information about what BCCL sends to Business Central when troubleshooting. - For repeated imports, use
--rememberto store your connection settings so you only need to specify the task-specific parameters. - If you need Business Central to generate primary key values (like customer numbers), remove the primary key field from the mapping file entirely.