Acquire / file · All operations

Load a CSV kept with the project

A variant of Read a CSV or delimited file

Load a static CSV file stored alongside the pipeline code into the warehouse as a table.

Status

In arcform

Runs as a SQL step

arcform carries it as a sql: step today.

The DuckDB step

Load a CSV kept with the project as a table, typed and replaced on every run

SQL
-- the seed file sits beside the pipeline code; it is written here only so the proof has one to read
COPY (SELECT * FROM (VALUES ('north', '007', 5000.00), ('south', '012', 4200.50), ('east', '103', NULL), ('west', '018', 3100.00)) t(region, code, target))
  TO '<your_scratch_dir>/seed_regions.csv' (HEADER);
CREATE OR REPLACE TABLE seed_regions AS
SELECT * FROM read_csv('<your_scratch_dir>/seed_regions.csv', header = true, columns = {'region': 'VARCHAR', 'code': 'VARCHAR', 'target': 'DECIMAL(10, 2)'});
-- a second run replaces the table and does not append to it
CREATE OR REPLACE TABLE seed_regions AS
SELECT * FROM read_csv('<your_scratch_dir>/seed_regions.csv', header = true, columns = {'region': 'VARCHAR', 'code': 'VARCHAR', 'target': 'DECIMAL(10, 2)'});
SELECT * FROM seed_regions;
SELECT CASE WHEN ((SELECT count(*) FROM duckdb_tables() WHERE table_name = 'seed_regions') = 1 AND (SELECT count(*) = 4 AND count(target) = 3 AND sum(target) = 12300.50 AND max(code) FILTER (WHERE region = 'north') = '007' FROM seed_regions) AND (SELECT list(column_type) FROM (DESCRIBE seed_regions)) = ['VARCHAR', 'VARCHAR', 'DECIMAL(10,2)']) THEN 'as expected' ELSE error('the seed did not load as one table of 4 rows with the code 007 kept as text and the target a decimal') END AS verdict;

Replace <your_scratch_dir> with a directory of your own that you can write to before running the statement.

  • The statement writes seed_regions.csv itself, in <your_scratch_dir>.
  • It needs nothing installed beyond DuckDB itself.
  • The statement checks its own result and raises an error when it is wrong: “the seed did not load as one table of 4 rows with the code 007 kept as text and the target a decimal”.
  • It passed on DuckDB v2.0.0 (Cyanoptera) d54cbbe3df.

What other tools call it

Meridian's classification; an independent blind rating agreed on 95.7% of 324 rows (variant, version 3).

Bruin (1)
  • Seed assets (family)read 2026-09-27

    15 platform types (bq.seed, duckdb.seed, …) loading a CSV, Parquet, JSON, JSONL, NDJSON or Avro file

dbt-utils (1)
  • seedread 2026-09-27

    Load a CSV file kept in the project into the warehouse as a table

SQLMesh (1)
  • SEEDread 2026-09-27

    Load a static CSV file in the project into a physical table

Background

In dbt, seeds are comma-separated values (CSV) files in a dbt project that dbt can load into the data warehouse using the dbt seed command.[1][2] In SQLMesh, a SEED model sources its data from a static CSV file that is part of the project, with a physical table in the warehouse reflecting its contents.[3] Because a dbt seed file is located in the dbt repository, it is version controlled and code reviewable.[1]

When to use it

In dbt, seeds are best suited to static data which changes infrequently, such as a list of mappings of country codes to country names.[1] SQLMesh seed models are a good fit for static datasets that change infrequently or not at all.[3] In dbt, seeds should not be used to load raw data such as large CSV exports from a production database, and loading CSVs with dbt's seed functionality is not performant for large files.[1] In dbt, production data containing sensitive information, such as personal identifiable information and passwords, is listed as a poor use of seeds.[1] Keep seeds for small lists the team edits by hand, and load data that arrives from elsewhere from its source instead. (Meridian's view)

In dbt, a seed's column_types configuration sets the database type of its columns, and without it dbt infers each column's type from its values.[4] A dbt seed's zipcode column can be given the type varchar(5) through column_types to preserve its leading zeros.[4] If dbt seed has been run before, a change to column_types takes effect only after running dbt seed --full-refresh.[4] In SQLMesh, a seed's table is created with column types inferred by Pandas unless the model definition specifies the schema.[3] Declare the type of every code-like column in a seed rather than leave it to inference. (Meridian's view)

The method

Seeds can be referenced in downstream dbt models the same way as models, by using the ref function.[1] In dbt, the --full-refresh flag forces a full reload of seed data, rather than an incremental update, when seed tables need rebuilding from scratch.[5]

A SQLMesh SEED model is defined in a .sql file in the models directory, with a path attribute giving the location of the seed's CSV file.[3] SQLMesh captures changes to a seed's CSV file during planning and versions them using the same fingerprinting mechanism as its other models.[3] SQLMesh passes a seed's csv_settings to the Pandas read_csv function, for files with special quoting rules or delimiters.[3] In SQLMesh, a schema given in the model definition takes precedence over the column names in the CSV file's header, so its columns must be listed in the file's order.[3]