> ## Documentation Index
> Fetch the complete documentation index at: https://docs.narrative.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Register Your First Snowflake Dataset

> Turn a Snowflake table into a Narrative dataset from a SQL worksheet, without opening the Native App Configuration screen

In this tutorial, you'll register a Snowflake table as a Narrative dataset using nothing but a SQL worksheet. By the end you'll have a live dataset on the platform, and a call you can drop into the pipeline that builds the table.

<Info>
  This tutorial assumes the Snowflake Native App is already installed in your account. If it isn't, work through [Install the Snowflake Native App](/guides/data-planes/snowflake-native-app-installation) first — that one-time setup creates the [data plane](/concepts/primitives/data-planes) this dataset attaches to.
</Info>

## Prerequisites

* The Snowflake Native App installed and configured, with its external access integration set up

* A warehouse granted to the application, which an `ACCOUNTADMIN` does once:

  ```sql theme={null}
  grant usage on warehouse my_warehouse to application narrative_data_collaboration;
  ```

* A Snowflake role that can grant application roles, for step 2 — `ACCOUNTADMIN`, or the role that installed the app

## What you'll learn

* How to point your session at the application, which every call depends on
* How to grant the role that allows dataset registration
* How to register a table with one procedure call
* How to confirm the dataset exists, from both Snowflake and the platform

## Steps

<Steps>
  <Step title="Set your session context">
    Open a Snowflake worksheet and run:

    ```sql theme={null}
    use warehouse my_warehouse;
    use database narrative_data_collaboration;
    ```

    The second line is the one that matters. The registration procedures read your Narrative API token through a reference that resolves against your session's *current* database, so a call made from any other database fails — even if you spell out the full procedure name. Every step below assumes this is still set.
  </Step>

  <Step title="Grant yourself the registration role">
    `dataset_registration` carries the two registration procedures and read access to the application's record of what it has registered. Nothing else.

    ```sql theme={null}
    grant application role narrative_data_collaboration.dataset_registration to role my_role;
    ```

    <Tip>
      `app_admin` works too, since it contains `dataset_registration`. Prefer the smaller role — see [Register a Snowflake Dataset from SQL](/guides/data-planes/register-a-snowflake-dataset) for what each one carries.
    </Tip>
  </Step>

  <Step title="Create a table to register">
    Any table or view you can read will do. If you'd rather not use real data yet, build a small one:

    ```sql theme={null}
    create or replace table mydb.myschema.tutorial_events (
      user_id     string,
      email       string,
      event_count number,
      score       float,
      is_active   boolean,
      event_ts    timestamp_tz
    );

    insert into mydb.myschema.tutorial_events
      values ('u-1', 'ada@example.com', 12, 0.87, true, current_timestamp());
    ```

    Creating this table switches your current database to `mydb`, so set it back before the next step:

    ```sql theme={null}
    use database narrative_data_collaboration;
    ```
  </Step>

  <Step title="Register the table">
    One call describes the object, derives its schema, and creates the dataset:

    ```sql theme={null}
    call narrative_data_collaboration.code.register_dataset(
      'TABLE',
      system$reference('table', 'mydb.myschema.tutorial_events', 'persistent', 'select', 'references'),
      'Tutorial Events'
    );
    ```

    `system$reference` hands the application a binding to this one object, scoped to `select` and `references` and nothing else. It runs as your role, so you need those privileges on the table yourself. `'persistent'` is what keeps the binding alive after the statement ends — the shorter-lived scopes are no use to a job that runs tomorrow.

    The call returns the dataset's `dataset_id`, the `schema` it inferred, and `source_kind`, which reads `reference` when you pass a fresh `system$reference` like this one. Note the `dataset_id`.
  </Step>

  <Step title="Confirm it registered">
    The application records what it has registered in `data.mappings`:

    ```sql theme={null}
    select display_name, table_or_view, reference_alias, narrative_dataset_id
    from narrative_data_collaboration.data.mappings;
    ```

    You should see one row for **Tutorial Events**, carrying the same dataset id the call returned.
  </Step>
</Steps>

## Verify it worked

Open `https://app.narrative.io/platform/my-data/dataset/{id}#overview`, substituting the `dataset_id` from step 4.

The dataset is active, and its **Schema** tab lists the six columns with the types Narrative inferred from Snowflake: `user_id` and `email` as `string`, `event_count` as `long`, `score` as `double`, `is_active` as `boolean`, and `event_ts` as `timestamptz`. Column names are upper-case, which is how Snowflake reported them.

Your data hasn't moved. The dataset points at the table through the reference you minted, and the app queries it in place when Narrative runs a job.

## What you accomplished

* Registered a Snowflake table as a Narrative dataset without leaving a SQL worksheet
* Granted the application read access to exactly one object, through a reference you control
* Confirmed the dataset from Snowflake and from the platform

## Next steps

<CardGroup cols={2}>
  <Card title="Register a Snowflake Dataset from SQL" icon="snowflake" href="/guides/data-planes/register-a-snowflake-dataset">
    Every argument, schema overrides, and what each error means
  </Card>

  <Card title="Normalize with Rosetta Stone" icon="language" href="/getting-started/normalize-data">
    Map your dataset to Narrative's standard schema
  </Card>

  <Card title="Run Your First NQL Query" icon="terminal" href="/getting-started/first-nql-query">
    Query the dataset you just registered
  </Card>

  <Card title="Data Planes" icon="server" href="/concepts/primitives/data-planes">
    How a customer-hosted data plane executes work
  </Card>
</CardGroup>
