> This page is for Structured Data Models Client.

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.nvidia.com/sdgm/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.nvidia.com/sdgm/_mcp/server.

# Configure Table Metadata

> Review and correct inferred Kumo Relational keys, timestamps, and semantic types

After you build a schema, review the inferred metadata for every table. Access a table through `schema["table_name"]` and a column through `schema["table_name"]["column_name"]`; you do not need to construct table or column objects directly.

## Inspect inferred metadata

```python
print(schema)                 # Schema(3 tables: ['customers', 'orders', 'products'], 2 relationships)
print(schema["orders"])       # Table('orders', 3 rows, 5 columns, primary_key='order_id', time_column='order_time')
print(schema["orders"]["customer_id"])  # Column('customer_id', dtype='int64', stype='ID')
```

Continue with the schema built in [Build a Schema](/sdgm/kumo-relational/user-guide/build-a-relational-graph/graph-creation):

```python
customers_table = schema["customers"]
orders_table = schema["orders"]
products_table = schema["products"]
```

> **Note**
>
> A table built with `Schema.from_source()` holds column metadata and keys, but no rows — it reports its column count the same way, with no row count to show. Its columns are still inspected and corrected the same way as a table built with `Schema.from_data()`.

## Configure keys and timestamps

```python
customers_table.primary_key = "customer_id"
orders_table.primary_key = "order_id"
orders_table.time_column = "order_time"
products_table.primary_key = "product_id"
```

The time column should represent when an event became available to the prediction workflow. Kumo Relational has no supported way to also declare when a row stopped being valid — see [Time Columns](/sdgm/kumo-relational/user-guide/prepare-data/time-columns).

Tables can use composite primary keys when one column is not sufficient to identify a row:

```python
customers_table.primary_key = ("customer_id", "region")
```

Every component must be present, non-null, and use a foldable physical type; a floating-point column cannot be part of a composite key. A composite key is refused if it has duplicates beyond a small tolerance, or if any component is null.

## Correct semantic types

```python
customers_table["customer_id"].stype = "ID"
orders_table["order_id"].stype = "ID"
orders_table["customer_id"].stype = "ID"
orders_table["product_id"].stype = "ID"
orders_table["order_time"].stype = "timestamp"
products_table["product_id"].stype = "ID"
```

A semantic type assignment must be compatible with the column's physical data type; an incompatible assignment raises immediately rather than being accepted and refused later. Refer to [Data Types and Semantic Types](/sdgm/kumo-relational/user-guide/prepare-data/data-types) for the supported combinations.

> **Note**
>
> Assigning a table's `primary_key` automatically types every component `ID`, and assigning `time_column` automatically types that column `timestamp`. You still need to correct any *other* column inference got wrong, such as an identifier-shaped number that should be `categorical`.

## Metadata checklist

* Each table's primary key values are non-null and unique.
* Foreign-key columns use values and physical data types that are compatible with those of the referenced keys.
* The time column represents when an event became available to the prediction workflow.
* Identifier columns use the `ID` semantic type.
* Free-form language uses the `text` semantic type, and low-cardinality labels use the `categorical` semantic type.

Inspect the result after making corrections:

```python
print(schema)
```

Next, [review and define relationships](/sdgm/kumo-relational/user-guide/build-a-relational-graph/graph-definitions).