# Virtual Foreign Keys

> Source: https://docs.synthesized.io/tdk/latest/user_guide/020_guides/managing_data_properties/virtual_foreign_keys
> For the complete documentation index, see [llms.txt](https://docs.synthesized.io/llms.txt).

The Synthesized platform is able to automatically understand and maintain the relationships defined using foreign keys. If tables are linked with foreign key constraints, any synthetic data will retain those links.

However, some systems define these links at the application layer rather than at the database layer. In such cases, Synthesized provides the option to define virtual foreign keys. This means that referential integrity can be preserved without any changes to the source database.

> **NOTE**
> Virtual foreign keys are only needed for situations where the foreign keys are missing from the database. Foreign keys present in the database are handled automatically.

> **WARNING**
> Configuration-defined foreign keys follow the same rules as database-defined foreign keys. Importantly, that means each virtual foreign key should refer to a combination of one or more columns that identify one unique row.

## Adding a virtual foreign key

Each workflow script can contain a `metadata` element that contains all virtual foreign keys.

The structure is like this:

metadata:
  tables:
    - table\_name\_with\_schema: "DEPENDENT\_SCHEMA.DEPENDENT\_TABLE"
      foreign\_keys:
        NAME\_OF\_THE\_VIRTUAL\_FOREIGN\_KEY:
          referred\_schema: "REFERRED\_SCHEMA"
          referred\_table: "REFERRED\_TABLE"
          columns:
            - column: "DEPENDENT\_COLUMN\_NAME"
              referred\_column: "REFERRED\_COLUMN\_NAME"

For example, a business has decided that rather than asking customers for their surname, they will use the staff member’s id instead. This is a business rule, rather than logic in the database.

default\_config:
  target\_ratio: 1
  mode: GENERATION

metadata:
  tables:
    - table\_name\_with\_schema: "public.customer"
      foreign\_keys:
        fk\_surname\_using\_staff\_id:
          referred\_schema: "public"
          referred\_table: "staff"
          columns:
            - column: "last\_name"
              referred\_column: "staff\_id"

<table class="tableblock frame-none grid-rows stretch output_table"><caption class="title"><strong>Output</strong>: public.customer</caption> <colgroup><col style="width: 33.3333%;"> <col style="width: 33.3333%;"> <col style="width: 33.3334%;"></colgroup><tbody><tr><td class="tableblock halign-left valign-top"><p class="tableblock"><strong>id</strong></p></td><td class="tableblock halign-left valign-top"><p class="tableblock"><strong>last_name</strong></p></td><td class="tableblock halign-left valign-top"><p class="tableblock"><strong>store_id</strong></p></td></tr><tr><td class="tableblock halign-left valign-top"><p class="tableblock">0</p></td><td class="tableblock halign-left valign-top"><p class="tableblock">91</p></td><td class="tableblock halign-left valign-top"><p class="tableblock">26</p></td></tr><tr><td class="tableblock halign-left valign-top"><p class="tableblock">1</p></td><td class="tableblock halign-left valign-top"><p class="tableblock">19</p></td><td class="tableblock halign-left valign-top"><p class="tableblock">48</p></td></tr><tr><td class="tableblock halign-left valign-top"><p class="tableblock">2</p></td><td class="tableblock halign-left valign-top"><p class="tableblock">218</p></td><td class="tableblock halign-left valign-top"><p class="tableblock">46</p></td></tr></tbody></table>

<table class="tableblock frame-none grid-rows stretch output_table"><caption class="title"><strong>Output</strong>: public.staff</caption> <colgroup><col style="width: 50%;"> <col style="width: 50%;"></colgroup><tbody><tr><td class="tableblock halign-left valign-top"><p class="tableblock"><strong>staff_id</strong></p></td><td class="tableblock halign-left valign-top"><p class="tableblock"><strong>store_id</strong></p></td></tr><tr><td class="tableblock halign-left valign-top" colspan="2"><p class="tableblock">…​</p></td></tr><tr><td class="tableblock halign-left valign-top"><p class="tableblock">19</p></td><td class="tableblock halign-left valign-top"><p class="tableblock">25</p></td></tr><tr><td class="tableblock halign-left valign-top" colspan="2"><p class="tableblock">…​</p></td></tr><tr><td class="tableblock halign-left valign-top"><p class="tableblock">91</p></td><td class="tableblock halign-left valign-top"><p class="tableblock">0</p></td></tr><tr><td class="tableblock halign-left valign-top" colspan="2"><p class="tableblock">…​</p></td></tr><tr><td class="tableblock halign-left valign-top"><p class="tableblock">218</p></td><td class="tableblock halign-left valign-top"><p class="tableblock">86</p></td></tr></tbody></table>

The metadata section adds a foreign key from `public.customer.last_name` to `public.staff.staff_id`, and refers to it as `fk_surname_using_staff_id`. All of the `last_name` values in the `customer` table come from the `staff_id` column of the `staff` table.

## Referencing multiple columns

Virtual foreign keys can reference multiple columns. In the previous example, the customer’s `store_id` wasn’t linked to the linked staff member’s `store_id`. This can be fixed by referencing multiple columns in the foreign key.

default\_config:
  target\_ratio: 1
  mode: GENERATION

metadata:
  tables:
    - table\_name\_with\_schema: "public.customer"
      foreign\_keys:
        fk\_surname\_using\_staff\_id:
          referred\_schema: "public"
          referred\_table: "staff"
          columns:
            - column: "last\_name"
              referred\_column: "staff\_id"
            - column: "store\_id"
              referred\_column: "store\_id"

<table class="tableblock frame-none grid-rows stretch output_table"><caption class="title"><strong>Output</strong>: public.customer</caption> <colgroup><col style="width: 33.3333%;"> <col style="width: 33.3333%;"> <col style="width: 33.3334%;"></colgroup><tbody><tr><td class="tableblock halign-left valign-top"><p class="tableblock"><strong>id</strong></p></td><td class="tableblock halign-left valign-top"><p class="tableblock"><strong>last_name</strong></p></td><td class="tableblock halign-left valign-top"><p class="tableblock"><strong>store_id</strong></p></td></tr><tr><td class="tableblock halign-left valign-top"><p class="tableblock">0</p></td><td class="tableblock halign-left valign-top"><p class="tableblock">91</p></td><td class="tableblock halign-left valign-top"><p class="tableblock">0</p></td></tr><tr><td class="tableblock halign-left valign-top"><p class="tableblock">1</p></td><td class="tableblock halign-left valign-top"><p class="tableblock">19</p></td><td class="tableblock halign-left valign-top"><p class="tableblock">25</p></td></tr><tr><td class="tableblock halign-left valign-top"><p class="tableblock">2</p></td><td class="tableblock halign-left valign-top"><p class="tableblock">218</p></td><td class="tableblock halign-left valign-top"><p class="tableblock">86</p></td></tr></tbody></table>

<table class="tableblock frame-none grid-rows stretch output_table"><caption class="title"><strong>Output</strong>: public.staff</caption> <colgroup><col style="width: 50%;"> <col style="width: 50%;"></colgroup><tbody><tr><td class="tableblock halign-left valign-top"><p class="tableblock"><strong>staff_id</strong></p></td><td class="tableblock halign-left valign-top"><p class="tableblock"><strong>store_id</strong></p></td></tr><tr><td class="tableblock halign-left valign-top" colspan="2"><p class="tableblock">…​</p></td></tr><tr><td class="tableblock halign-left valign-top"><p class="tableblock">19</p></td><td class="tableblock halign-left valign-top"><p class="tableblock">25</p></td></tr><tr><td class="tableblock halign-left valign-top" colspan="2"><p class="tableblock">…​</p></td></tr><tr><td class="tableblock halign-left valign-top"><p class="tableblock">91</p></td><td class="tableblock halign-left valign-top"><p class="tableblock">0</p></td></tr><tr><td class="tableblock halign-left valign-top" colspan="2"><p class="tableblock">…​</p></td></tr><tr><td class="tableblock halign-left valign-top"><p class="tableblock">218</p></td><td class="tableblock halign-left valign-top"><p class="tableblock">86</p></td></tr></tbody></table>

Now that the foreign key refers to both `staff_id` and `store_id`, the customer’s `store_id` matches the `store_id` of the staff member they have been linked to.

For the full reference docs, please see [Configuration Reference: Metadata](https://docs.synthesized.io/tdk/latest/user_guide/040_reference/configuration/configuration_reference#AdditionalMetadata).
