Skip to content
Local Development

为你的数据库添加初始数据

Populate your database with initial data for reproducible environments across local and testing.

什么是种子数据? #

🌐 What is seed data?

填充是向数据库中添加初始数据的过程,通常用于提供测试和开发所需的示例或默认记录。你可以用它来为本地开发、预演环境和生产环境创建“可复现的环境”。

🌐 Seeding is the process of populating a database with initial data, typically used to provide sample or default records for testing and development purposes. You can use this to create "reproducible environments" for local development, staging, and production.

使用种子文件 #

🌐 Using seed files

种子文件会在你第一次运行 supabase start 以及每次运行 supabase db reset 时执行。种子操作发生在所有数据库迁移完成之后。作为最佳实践,种子文件中只包含数据插入操作,避免添加模式语句。

🌐 Seed files are executed the first time you run supabase start and every time you run supabase db reset. Seeding occurs after all database migrations have been completed. As a best practice, only include data insertions in your seed files, and avoid adding schema statements.

默认情况下,如果没有提供特定配置,系统会查找与模式 supabase/seed.sql 匹配的种子文件。这保持了与早期版本的向后兼容性,早期版本的种子文件放在 supabase 文件夹中。

🌐 By default, if no specific configuration is provided, the system will look for a seed file matching the pattern supabase/seed.sql. This maintains backward compatibility with earlier versions, where the seed file was placed in the supabase folder.

你可以在这个文件中添加任何 SQL 语句。例如:

🌐 You can add any SQL statements to this file. For example:

1
insert into countries
2
(name, code)
3
values
4
('United States', 'US'),
5
('Canada', 'CA'),
6
('Mexico', 'MX');

如果你想管理多个种子文件或将它们组织到不同的文件夹中,你可以在你的 config.toml 中配置额外的路径或通配符模式(详情请参见下一节)。

🌐 If you want to manage multiple seed files or organize them across different folders, you can configure additional paths or glob patterns in your config.toml (see the next section for details).

拆分你的种子文件 #

🌐 Splitting up your seed file

为了更好的模块化和可维护性,你可以把种子数据拆分到多个文件中。例如,你可以按表来组织种子数据,并包含像 countries.sqlcities.sql 这样的文件。在 config.toml 中这样配置它们:

🌐 For better modularity and maintainability, you can split your seed data into multiple files. For example, you can organize your seeds by table and include files such as countries.sql and cities.sql. Configure them in config.toml like so:

1
[db.seed]
2
enabled = true
3
sql_paths = ['./countries.sql', './cities.sql']

或者要包含特定文件夹下的所有 .sql 文件,你可以这样做:

🌐 Or to include all .sql files under a specific folder you can do:

1
[db.seed]
2
enabled = true
3
sql_paths = ['./seeds/*.sql']

生成种子数据 #

🌐 Generating seed data

对于大多数项目来说,手写 supabase/seed.sql(见上面的 使用种子文件)是最简单、最可靠的方法。如果你需要大量真实的数据,可以用 Snaplet Seed 来生成。

🌐 For most projects, a hand-written supabase/seed.sql (see Using seed files above) is the simplest and most reliable approach. If you need large volumes of realistic data, you can generate it with Snaplet Seed.

如果这是你第一次使用 Snaplet 来初始化你的项目,你需要用以下命令来设置 Snaplet:

🌐 If this is your first time using Snaplet to seed your project, you'll need to set up Snaplet with the following command:

1
npx @snaplet/seed init

这个命令会分析你的数据库及其结构,然后生成一个 JavaScript 客户端,你可以用它来通过代码精确定义数据的生成方式。init 命令生成一个配置文件,seed.config.ts 和一个示例脚本 seed.ts,作为起点。

🌐 This command will analyze your database and its structure, and then generate a JavaScript client which can be used to define exactly how your data should be generated using code. The init command generates a configuration file, seed.config.ts and an example script, seed.ts, as a starting point.

在大多数情况下,你只想为特定的模式或表生成数据。这是通过 select 定义的。这里有一个 seed.config.ts 配置文件示例:

🌐 In most cases you only want to generate data for specific schemas or tables. This is defined with select. Here is an example seed.config.ts configuration file:

1
export default defineConfig({
2
adapter: async () => {
3
const client = new Client({
4
connectionString: 'postgresql://postgres:postgres@localhost:54322/postgres',
5
})
6
await client.connect()
7
return new SeedPg(client)
8
},
9
// We only want to generate data for the public schema
10
select: ['!*', 'public.*'],
11
})

假设你有一个如下模式的数据库:

🌐 Suppose you have a database with the following schema:

User PK bigint id text email text name Post PK bigint id text title text content FK bigint createdBy Comment PK bigint id text text FK bigint userId FK bigint postId createdBy userId postId

这个示例模式有三个表。一个 User 可以创建很多 Post 行(Post.createdBy 引用 User.id)和很多 Comment 行(Comment.userId 引用 User.id),而每个 Post 可以有很多 Comment 行(Comment.postId 引用 Post.id)。换句话说,用户可以发表帖子和评论,每条评论都属于一个帖子。

🌐 This example schema has three tables. A User can author many Post rows (Post.createdBy references User.id) and many Comment rows (Comment.userId references User.id), and each Post can have many Comment rows (Comment.postId references Post.id). In other words, users create posts and comments, and every comment belongs to a post.

你可以使用 Snaplet seed.ts 生成的种子脚本示例来定义你想要生成的值。例如:

🌐 You can use the seed script example generated by Snaplet seed.ts to define the values you want to generate. For example:

  • 一个标题为 "There is a lot of snow around here!"Post
  • 电子邮件地址以 "@acme.org" 结尾的 Post.createdBy 用户
  • 来自三个不同用户的三个 Post.comments
1
import { copycat } from '@snaplet/copycat'
2
import { createSeedClient } from '@snaplet/seed'
3
4
async function main() {
5
const seed = await createSeedClient({ dryRun: true })
6
7
await seed.Post([
8
{
9
title: 'There is a lot of snow around here!',
10
createdBy: {
11
email: (ctx) =>
12
copycat.email(ctx.seed, {
13
domain: 'acme.org',
14
}),
15
},
16
Comment: (x) => x(3),
17
},
18
])
19
20
process.exit()
21
}
22
23
main()

运行 npx tsx seed.ts > supabase/seed.sql 会在你的 supabase/seed.sql 文件中生成相关的 SQL 语句:

🌐 Running npx tsx seed.ts > supabase/seed.sql generates the relevant SQL statements inside your supabase/seed.sql file:

1
-- The `Post.createdBy` user with an email address ending in `"@acme.org"`
2
insert into "User" (name, email) values ('John Snow', 'snow@acme.org');
3
4
-- - A `Post` with the title `"There is a lot of snow around here!"`
5
insert into "Post" (title, content, createdBy)
6
values
7
('There is a lot of snow around here!', 'Lorem ipsum dolar', 1);
8
9
-- - Three `Post.Comment` from three different users.
10
insert into "User" (name, email) values ('Stephanie Shadow', 'shadow@domain.com');
11
insert into "Comment" (text, userId, postId) values ('I love cheese', 2, 1);
12
13
insert into "User" (name, email) values ('John Rambo', 'rambo@trymore.dev');
14
insert into "Comment" (text, userId, postId) values ('Lorem ipsum dolar sit', 3, 1);
15
16
insert into "User" (name, email) values ('Steven Plank', 's@plank.org');
17
insert into "Comment" (text, userId, postId) values ('Actually, that''s not correct...', 4, 1);

每当你的数据库结构发生变化时,你需要重新生成 @snaplet/seed 来让它与新的结构保持同步。你可以通过运行以下命令来完成:

🌐 Whenever your database structure changes, you will need to regenerate @snaplet/seed to keep it in sync with the new structure. You can do this by running:

1
npx @snaplet/seed sync

你可以通过使用大型语言模型生成更真实的数据来进一步增强你的种子脚本。要启用此功能,请在你的 .env 文件中设置以下其中一个环境变量:

🌐 You can further enhance your seed script by using Large Language Models to generate more realistic data. To enable this feature, set one of the following environment variables in your .env file:

1
OPENAI_API_KEY=<your_openai_api_key>
2
GROQ_API_KEY=<your_groq_api_key>

设置好环境变量后,运行以下命令来同步并生成种子数据:

🌐 After setting the environment variables, run the following commands to sync and generate the seed data:

1
npx @snaplet/seed sync
2
npx tsx seed.ts > supabase/seed.sql

想了解更多信息,请查看 Snaplet Seed 仓库

🌐 For more information, see the Snaplet Seed repository.