Blog

Airtable: Create Records in One Table Based on Data from Another Table

FE
Filla EditorialintermediateNov 21, 2025

Create records from different table data

You have data in one table and need to automatically create new records in a different table based on that data. AI fields won't do this automatically—you need automations.


The problem

AI fields can extract and transform data within a record, but they cannot automatically create new records in different tables. For example:

  • You add an interview record
  • You want topics and posts automatically created in separate tables
  • Nothing happens automatically

This requires an automation workflow.


Solution: Automation with Generate Structured Data

The best approach is using Airtable's "Generate Structured Data" automation action, which can create multiple records at once.

Example: Interview → Topics → Posts

Let's say you have:

  • Interviews table: Contains interview transcripts
  • Topics table: Should contain extracted topics
  • Posts table: Should contain suggested social media posts

Step 1: Set up the trigger

Create an automation that triggers when:

  • A new interview record is created, OR
  • A specific field (like "Transcript") is filled in

Trigger: "When record matches conditions"

  • Field: Transcript
  • Condition: Is not empty

Step 2: Generate structured data

Use the "Generate Structured Data" action:

  1. Action: "Generate structured data with AI"
  2. Input: Reference the transcript field from the triggering record
  3. Prompt: Tell AI what structure you want

Example prompt:

Extract all topics discussed in this interview transcript. 
Return a JSON array where each topic has:
- name: the topic name
- description: a brief description

Return ONLY valid JSON, no other text.

Step 3: Create records from structured data

After generating structured data, use a "Run a script" action to create records:

// Get the structured data from previous step
const structuredData = input.config().structuredData
const topicsTable = base.getTable("Topics")
const interviewsTable = base.getTable("Interviews")
const triggerRecordId = input.config().triggerRecordId

// Parse the JSON array
const topics = JSON.parse(structuredData)

// Create a record for each topic
for (const topic of topics) {
  await topicsTable.createRecordAsync({
    "Name": topic.name,
    "Description": topic.description,
    "Interview": [{ id: triggerRecordId }] // Link back to interview
  })
}

Step 4: Create posts from topics

Add another automation step to generate posts based on the created topics:

  1. Trigger: "When record is created" in Topics table
  2. Action: "Generate structured data with AI"
  3. Prompt: Generate social media post suggestions based on the topic

Alternative: Using repeating lists

If you prefer not to use structured data, you can use repeating lists with scripts:

Step 1: Generate text with AI

  1. Action: "Generate text with AI"
  2. Input: Transcript field
  3. Prompt: Extract topics as a comma-separated list

Step 2: Split into repeating list

Use a formula or script to split the comma-separated list into a repeating list field.

Step 3: Create records from list

Use a script to iterate through the repeating list and create records:

const topicsList = input.config().topicsList // Repeating list field
const topicsTable = base.getTable("Topics")
const triggerRecordId = input.config().triggerRecordId

for (const topic of topicsList) {
  await topicsTable.createRecordAsync({
    "Name": topic,
    "Interview": [{ id: triggerRecordId }]
  })
}

Complete automation example

Here's a full automation workflow for the interview analysis use case:

Automation: Extract Topics from Interview

Trigger:

  • When: Record matches conditions
  • Table: Interviews
  • Condition: Transcript is not empty

Action 1: Generate Structured Data

  • Input: {Transcript} (from triggering record)
  • Prompt:
Analyze this interview transcript and extract all discussed topics.
Return a JSON array where each object has:
{
  "name": "topic name",
  "description": "brief description"
}
Return ONLY valid JSON array, no other text.

Action 2: Run Script

const structuredData = input.config().structuredData
const topicsTable = base.getTable("Topics")
const interviewsTable = base.getTable("Interviews")
const triggerRecordId = input.config().triggerRecordId

try {
  const topics = JSON.parse(structuredData)
  
  for (const topic of topics) {
    await topicsTable.createRecordAsync({
      "Name": topic.name,
      "Description": topic.description,
      "Interview": [{ id: triggerRecordId }]
    })
  }
} catch (error) {
  console.error("Error parsing or creating topics:", error)
}

Automation: Generate Posts from Topics

Trigger:

  • When: Record is created
  • Table: Topics

Action 1: Generate Structured Data

  • Input: {Name} and {Description} from triggering topic
  • Prompt:
Based on this topic, suggest 3 social media post ideas.
Return a JSON array where each object has:
{
  "content": "post text",
  "summary": "brief summary",
  "hashtags": "suggested hashtags"
}
Return ONLY valid JSON array.

Action 2: Run Script

const structuredData = input.config().structuredData
const postsTable = base.getTable("Posts")
const triggerRecordId = input.config().triggerRecordId

try {
  const posts = JSON.parse(structuredData)
  
  for (const post of posts) {
    await postsTable.createRecordAsync({
      "Content": post.content,
      "Summary": post.summary,
      "Suggested Hashtags": post.hashtags,
      "Topic": [{ id: triggerRecordId }]
    })
  }
} catch (error) {
  console.error("Error parsing or creating posts:", error)
}

Best practices

Structure your prompts clearly

Be specific about the JSON structure you want:

Return a JSON array where each object has:
{
  "field1": "value",
  "field2": "value"
}
Return ONLY valid JSON, no other text.

Handle errors gracefully

Always wrap JSON parsing in try-catch blocks:

try {
  const data = JSON.parse(structuredData)
  // Process data
} catch (error) {
  console.error("Error:", error)
  // Handle error or skip
}

Link records back

Always link created records back to the source:

await newTable.createRecordAsync({
  "Field": value,
  "Source Record": [{ id: triggerRecordId }] // Link back
})

Test with sample data

Before deploying, test your automation with:

  • Sample records
  • Edge cases (empty fields, malformed data)
  • Multiple records

Use conditions to prevent duplicates

Add conditions to prevent creating duplicate records:

Condition: Check if records already exist

  • Find records in Topics table
  • Where Interview matches triggering record
  • Only create if no records found

Common use cases

Extract items from text

Use case: Extract a list of items mentioned in a text field

Example: Extract hobbies from a notes field

// Prompt: Extract all hobbies mentioned. Return JSON array of strings.
const hobbies = JSON.parse(structuredData)
for (const hobby of hobbies) {
  await hobbiesTable.createRecordAsync({
    "Name": hobby,
    "Source": [{ id: triggerRecordId }]
  })
}

Break down complex data

Use case: Split a single record with multiple values into separate records

Example: One order with multiple line items → separate line item records

Generate related content

Use case: Create related records based on analysis

Example: Interview → Topics → Posts (as shown above)


Limitations and alternatives

Airtable automation limits

  • AI actions: Limited by your plan's AI credits
  • Script execution time: 30 seconds max
  • Record creation rate: Consider rate limits for large batches

When to use external tools

Consider Make, Zapier, or custom scripts when:

  • You need to process large volumes
  • You need more complex logic
  • You need to handle errors more robustly
  • You need to create records across multiple bases

External tool example (Make)

  1. Trigger: Webhook or Airtable watch
  2. Action: AI module to extract data
  3. Action: Create records in Airtable via API
  4. Error handling: Retry logic and logging

Troubleshooting

Records not being created

Check:

  • Automation is enabled
  • Trigger conditions are met
  • AI field has data (if using AI field as trigger)
  • Script has proper error handling
  • JSON parsing is working correctly

Duplicate records

Solution: Add a condition to check if records already exist before creating:

// Find existing records
const existing = await topicsTable.selectRecordsAsync({
  filterByFormula: `{Interview} = "${triggerRecordId}"`
})

if (existing.records.length === 0) {
  // Create records
}

Malformed JSON

Solution: Improve your prompt and add error handling:

try {
  // Clean the response (remove markdown code blocks if present)
  let cleaned = structuredData.replace(/```json\n?/g, '').replace(/```\n?/g, '').trim()
  const data = JSON.parse(cleaned)
} catch (error) {
  console.error("JSON parse error:", error)
}

Quick reference

Task Method Action
Extract list from text Generate Structured Data Returns JSON array
Create multiple records Run Script Loop through array
Link back to source Create Record Include link field
Prevent duplicates Find Records Check before creating
Handle errors Try-Catch Wrap JSON parsing

Tips

  • Start simple: Test with one record before scaling
  • Use structured data: Prefer "Generate Structured Data" over text parsing
  • Link everything: Always link created records back to source
  • Test prompts: Refine AI prompts for better JSON output
  • Monitor usage: Track AI credits and automation runs
  • Document workflows: Keep notes on what each automation does

References

Community discussion on creating records from different table data: Create Records based on data in a different table

Airtable: Create Records in One Table Based on Data from Another Table