为你的数据库添加初始数据
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:
1insert into countries2 (name, code)3values4 ('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.sql 和 cities.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]2enabled = true3sql_paths = ['./countries.sql', './cities.sql']或者要包含特定文件夹下的所有 .sql 文件,你可以这样做:
🌐 Or to include all .sql files under a specific folder you can do:
1[db.seed]2enabled = true3sql_paths = ['./seeds/*.sql']CLI 会按照在 sql_paths 数组中声明的顺序处理种子文件。如果使用了通配符模式并匹配到多个文件,则这些文件会按字典顺序排序,以确保执行的一致性。此外:
🌐 The CLI processes seed files in the order they are declared in the sql_paths array. If a glob pattern is used and matches multiple files, those files are sorted in lexicographic order to ensure consistent execution. Additionally:
- 模式匹配的基础文件夹是
supabase,所以./countries.sql会搜索supabase/countries.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在2024年作为一家公司结束运营,并将其工具开源。@snaplet/seed现在由社区维护,地址在supabase-community/seed,只会偶尔收到修复更新,所以把它当作可选的便利工具,而不是工作流程中必须的部分。
🌐 Snaplet wound down as a company in 2024 and open-sourced its tooling. @snaplet/seed is now community-maintained at supabase-community/seed and receives only occasional fixes, so treat it as an optional convenience rather than a required part of the workflow.
要使用 Snaplet,你需要安装 Node.js 和 npm。你可以在项目目录中运行 npm init -y 来将 Node.js 添加到你的项目中。
🌐 To use Snaplet, you need to have Node.js and npm installed. You can add Node.js to your project by running npm init -y in your project directory.
如果这是你第一次使用 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:
1npx @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.
在 init 期间,如果你没有使用对象关系映射器(ORM)或你的 ORM 不在支持的列表中,请选择 node-postgres。
🌐 During init if you are not using an Object Relational Mapper (ORM) or your ORM is not in the supported list, choose node-postgres.
在大多数情况下,你只想为特定的模式或表生成数据。这是通过 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:
1export 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 schema10 select: ['!*', 'public.*'],11})假设你有一个如下模式的数据库:
🌐 Suppose you have a database with the following schema:
这个示例模式有三个表。一个 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。
1import { copycat } from '@snaplet/copycat'2import { createSeedClient } from '@snaplet/seed'34async function main() {5 const seed = await createSeedClient({ dryRun: true })67 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 ])1920 process.exit()21}2223main()运行 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"`2insert into "User" (name, email) values ('John Snow', 'snow@acme.org');34-- - A `Post` with the title `"There is a lot of snow around here!"`5insert into "Post" (title, content, createdBy)6values7 ('There is a lot of snow around here!', 'Lorem ipsum dolar', 1);89-- - Three `Post.Comment` from three different users.10insert into "User" (name, email) values ('Stephanie Shadow', 'shadow@domain.com');11insert into "Comment" (text, userId, postId) values ('I love cheese', 2, 1);1213insert into "User" (name, email) values ('John Rambo', 'rambo@trymore.dev');14insert into "Comment" (text, userId, postId) values ('Lorem ipsum dolar sit', 3, 1);1516insert into "User" (name, email) values ('Steven Plank', 's@plank.org');17insert 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:
1npx @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:
1OPENAI_API_KEY=<your_openai_api_key>2GROQ_API_KEY=<your_groq_api_key>设置好环境变量后,运行以下命令来同步并生成种子数据:
🌐 After setting the environment variables, run the following commands to sync and generate the seed data:
1npx @snaplet/seed sync2npx tsx seed.ts > supabase/seed.sql想了解更多信息,请查看 Snaplet Seed 仓库。
🌐 For more information, see the Snaplet Seed repository.