CertSafari
    Snowflake SnowPro Advanced: Data Analyst (DAA-C01)· Lessons

    Domain 1 · Lesson 1/19

    Unstructured Files and Synthetic Data Generation in Snowflake

    Use a collection system to retrieve data.

    12 min read
    2.43% of exam
    8 sources
    Published 5 Oct 2026
    Docs as of 4 Oct 2026

    What you will be able to do

    • Choose between scoped, file and pre-signed URLs for retrieving unstructured files
    • Generate synthetic rows with GENERATOR, SEQ1/2/4/8, UNIFORM and RANDOM, and predict their output
    • Use GENERATE_SYNTHETIC_DATA to produce statistically similar copies of sensitive tables, within its limits

    1.Unstructured data: retrieving files through URLs

    Unstructured data does not fit a predefined data model or schema. It is often text-heavy, such as form responses and social media conversations, and it also covers images, video and audio. Industry file types such as VCF (genomics), KDF (semiconductors) and HDF5 (aeronautics) belong here as well. Snowflake can securely access these files in cloud storage (Amazon S3, Google Cloud Storage or Microsoft Azure) and share URLs to them. It can load the URLs and other file metadata into tables, and it can process the files. Both external stages and internal stages support unstructured data.

    You do not parse a video into rows. You retrieve it through a URL, and Snowflake offers three kinds. A scoped URL is an encoded URL that gives temporary access to a staged file without granting any privileges on the stage. It is the recommended way for file administrators to give specific roles access, usually through a view that returns scoped URLs. Snowflake records in the query history who used a scoped URL and when. A file URL is permanent and names the database, schema, stage and file path. Custom applications send it in a GET request to the REST API, together with an authorization token. A pre-signed URL is a plain HTTPS link that works without signing in to Snowflake, which suits BI and reporting tools that display file contents.

    The three URL types for unstructured files compared
    URL typeHow to generateWho can use itExpirationUsable by consumers through secure views in a share
    Scoped URLBUILD_SCOPED_FILE_URLOnly the user who generated itWhen the query results cache expires (currently 24 hours)Yes
    File URLQuery the stage's directory table, or call BUILD_STAGE_FILE_URLA role with USAGE (external stage) or READ (internal stage)PermanentNo
    Pre-signed URLGET_PRESIGNED_URLAnyone who has the URL, for the life of the tokenSet by the expiration_time argumentYes

    Checkpoint 1 of 7· Check yourself

    A data provider wants share consumers to open staged PDF contracts from a column in a shared secure view. Which URL type can NOT be used for this?

    Sources1

    2.Synthetic rows from nothing: GENERATOR, SEQ, UNIFORM and RANDOM

    Sometimes the source you need does not exist yet, so you make one. GENERATOR is a system-defined table function for this. It creates rows from a row count (ROWCOUNT), a time budget in seconds (TIMELIMIT), or both. With ROWCOUNT alone you get exactly that many rows. With TIMELIMIT alone, the query generates as many rows as it can in that time, so the count is not fully deterministic. With both, whichever limit is reached first wins. If you give neither, GENERATOR returns 0 rows. GENERATOR only supplies the rows. The functions in the SELECT list decide what each row contains.

    GENERATOR provides 10 rows; SEQ4 and UNIFORM fill themsql
    SELECT seq4(), uniform(1, 10, RANDOM(12)) FROM TABLE(GENERATOR(ROWCOUNT => 10)) v ORDER BY 1;

    SEQ1, SEQ2, SEQ4 and SEQ8 return monotonically increasing integers. The digit is the integer width in bytes, and the sequence wraps around after the largest number that width can hold. The values are unique and increasing, but on large data they can have gaps. When you need a fully ordered sequence with no gaps, use ROW_NUMBER. UNIFORM(min, max, gen) returns a uniformly distributed number between min and max, inclusive. If both bounds are integers, the result is an integer. If either bound is a float, the result is a float. The gen argument is the source of randomness, usually RANDOM. If you pass a constant instead, every row gets the same value. RANDOM returns a pseudo-random 64-bit integer and accepts an optional seed. Its values are not guaranteed to be unique, and rerunning a statement can give different values even with a seed. For unique values, use a sequence.

    Checkpoint 2 of 7· Check yourself

    You run SELECT COUNT(seq4()) FROM TABLE(GENERATOR(TIMELIMIT => 10)). Which statement is correct?

    Checkpoint 3 of 7· Check yourself

    What does SELECT uniform(1, 10, 42) FROM TABLE(GENERATOR(ROWCOUNT => 10)) return?

    Sources234

    3.Synthetic copies of real tables: GENERATE_SYNTHETIC_DATA

    GENERATOR builds data from nothing. The stored procedure SNOWFLAKE.DATA_PRIVACY.GENERATE_SYNTHETIC_DATA starts from real tables instead. For each source table, it creates an output table with the same column names and data types, filled with artificial data that is statistically similar. The output has the same number of rows or fewer. Use it to test or share workloads when the original data is too sensitive. The output keeps the approximate distributions and correlations of the source, but no synthetic row links back to a source row. Synthetic data also appears in the data lineage graph.

    Each non-join-key column is handled according to its type. Numbers, Booleans, dates, times and timestamps get new values of the same type, similar to the originals. A categorical string column has fewer unique values than half the row count, and its output reuses actual source values. A non-categorical string column has more unique values than half the row count. Its values are redacted unless you specify an output format with the replace option. To run joins on the synthetic data, mark every join column with join_key. Join key values stay consistent across all tables within one run. To keep them consistent across separate runs, supply a consistency_secret (this works for string columns only). Setting 'similarity_filter': True removes output rows that are too similar to the input. With the filter on, a NULL in any non-string column makes the procedure fail.

    One call that synthesizes two tables, with patient_id and age marked as join keys so the outputs stay joinablesql
    CALL SNOWFLAKE.DATA_PRIVACY.GENERATE_SYNTHETIC_DATA({
      'datasets':[
          {
            'input_table': 'CLINICAL_DB.PUBLIC.PATIENTS1',
            'output_table': 'MY_DB.PUBLIC.PATIENTS1',
            'columns': { 'patient_id': {'join_key': TRUE}, 'age':{'join_key': TRUE}}
          },
          {
            'input_table': 'CLINICAL_DB.PUBLIC.PATIENTS2',
            'output_table': 'MY_DB.PUBLIC.PATIENTS2',
            'columns': { 'patient_id': {'join_key': TRUE}, 'age':{'join_key': TRUE}}
          }
        ],
        'replace_output_tables': TRUE
    });

    The procedure has firm limits. One call accepts up to five inputs, and each must have at least 20 distinct rows, at most 100 columns and at most 14M rows. The inputs can be regular, temporary, dynamic or transient tables, or regular, materialized, secure or secure materialized views. External, Iceberg and hybrid tables, and streams, are not supported. A column of an unsupported data type, such as TIMESTAMP_TZ, returns NULL for every value. The Anaconda terms must also be accepted in the account.

    Checkpoint 4 of 7· Check yourself

    A 1,000-row source table has an email column with 950 distinct values. You call GENERATE_SYNTHETIC_DATA and give no options for that column. What does the output email column contain?

    Checkpoint 5 of 7· Check yourself

    A team wants synthetic copies of four sources in one GENERATE_SYNTHETIC_DATA call. Which source makes the call unable to use it?

    Sources5

    4.Semi-structured data: JSON and XML in VARIANT and OBJECT

    Snowflake imports semi-structured data from JSON, Avro, ORC, Parquet and XML. For JSON, Avro, ORC and Parquet, each top-level complete object is loaded as a separate row. For XML, each top-level element is a separate row. Such tables usually hold a single VARIANT column. If an individual value needs more than about 128 MB of storage space, you can split the data across several columns instead. XML is queried with XMLGET, which needs an OBJECT (or a VARIANT containing an OBJECT), such as one produced by PARSE_XML or by loading XML data. It does not work directly on a VARCHAR.

    Checkpoint 6 of 7· Exam question

    A vendor exports a 120 MB JSON file that holds a single top-level array of order objects. A `COPY INTO` into a table with one `VARIANT` column fails because the value exceeds the maximum size of a VARIANT. What change to the load fixes this so that every order becomes its own row?

    Checkpoint 7 of 7· Exam question

    An analyst loads XML documents into a `VARIANT` column named `doc` and needs to pull out the child element `<customer>` from each record. Which function retrieves a child element of an XML value by its tag name?

    Sources67

    Exam traps

    Each one states something that sounds right. Open it to see what is actually true.

    1. 1.SEQ4() in a GENERATOR query always produces a gap-free sequence, so it can stand in for row numbers.Why is that wrong?

      SEQ functions produce unique, increasing integers, but gaps can appear on large data. Use ROW_NUMBER when you need a sequence with no gaps.

      Covered in Synthetic rows from nothing: GENERATOR, SEQ, UNIFORM and RANDOM

    2. 2.RANDOM() is a good way to create unique synthetic IDs.Why is that wrong?

      RANDOM values are not guaranteed to be unique. For unique values the docs recommend a sequence.

      Covered in Synthetic rows from nothing: GENERATOR, SEQ, UNIFORM and RANDOM

    3. 3.Join keys marked with join_key stay consistent every time you rerun GENERATE_SYNTHETIC_DATA.Why is that wrong?

      Without a consistency_secret, join keys are consistent only across the tables in a single run.

      Covered in Synthetic copies of real tables: GENERATE_SYNTHETIC_DATA

    4. 4.A scoped URL works like a pre-signed link: anyone you pass it to can open the file.Why is that wrong?

      Only the user who generated a scoped URL can use it. Anyone holding a pre-signed URL can use it.

      Covered in Unstructured data: retrieving files through URLs

    Practise it for real

    Use GENERATOR with the data generation functions to build a small synthetic data set, and confirm how each function behaves.

    1. 1.Run: SELECT seq4(), uniform(1, 10, RANDOM(12)) FROM TABLE(GENERATOR(ROWCOUNT => 10)) v ORDER BY 1;

      Why: GENERATOR supplies the rows, and SEQ4 and UNIFORM fill them.

      You should see: 10 rows: a SEQ4 column running from 0 to 9 and integers between 1 and 10 in the second column.

    2. 2.Run: SELECT seq4(), uniform(1, 10, 42) FROM TABLE(GENERATOR(ROWCOUNT => 10)) v ORDER BY 1;

      Why: Replacing the RANDOM generator with a constant shows what UNIFORM's third argument does.

      You should see: The UNIFORM column holds the same value on every row.

    3. 3.Run: SELECT seq4(), uniform(1, 10, RANDOM(12)) FROM TABLE(GENERATOR()) v ORDER BY 1;

      Why: This checks what GENERATOR does with neither ROWCOUNT nor TIMELIMIT.

      You should see: Zero rows are returned.

    4. 4.Run: SELECT ROW_NUMBER() OVER (ORDER BY seq4()) FROM TABLE(generator(rowcount => 10));

      Why: ROW_NUMBER is the recommended way to get a sequence with no gaps.

      You should see: The integers 1 to 10, with no gaps.

    Stuck? Get a nudge

    If two runs of a seeded RANDOM give different numbers, nothing is wrong: the docs do not guarantee the same values across executions, even with a seed.

    Sources

    Every claim above is drawn from one of these pages, quoted as it was written on the date shown.

    1. 1.
      “Unstructured data is information that does not fit into a predefined data model or schema.”
      ↩︎ Unstructured data: retrieving files through URLs
      “Both external (external cloud storage) and internal (i.e. Snowflake) stages support unstructured data.”
      ↩︎ Unstructured data: retrieving files through URLs
      “Encoded URL that permits temporary access to a staged file without granting privileges to the stage.”
      ↩︎ Unstructured data: retrieving files through URLs
      “Any person who has the pre-signed URL can access the referenced file for the life of the token.”
      ↩︎ Unstructured data: retrieving files through URLs
      “Only the user who generates a scoped URL can use the URL to access the referenced file.”
      ↩︎ Exam trap 4
      “Unstructured data files cannot be accessed by data consumers via column values of this type in secure views shared by data providers.”
      ↩︎ Checkpoint
    2. 2.
      “This system-defined table function enables synthetic row generation.”
      ↩︎ Synthetic rows from nothing: GENERATOR, SEQ, UNIFORM and RANDOM
      “The content of the rows is determined by the functions in the projection clause, not by the GENERATOR function itself.”
      ↩︎ Synthetic rows from nothing: GENERATOR, SEQ, UNIFORM and RANDOM
      “If both parameters (ROWCOUNT and TIMELIMIT) are omitted, the GENERATOR function returns 0 rows.”
      ↩︎ Synthetic rows from nothing: GENERATOR, SEQ, UNIFORM and RANDOM
      “generating as many rows as possible within the time frame”
      ↩︎ Checkpoint
    3. 3.
      “Wrap-around occurs after the largest representable integer of the integer width (1, 2, 4, or 8 byte).”
      ↩︎ Synthetic rows from nothing: GENERATOR, SEQ, UNIFORM and RANDOM
      “If a fully ordered, gap-free sequence is required, consider using the ROW_NUMBER window function.”
      ↩︎ Exam trap 1
    4. 4.
      “Generates a uniformly-distributed pseudo-random number in the inclusive range [min, max].”
      ↩︎ Synthetic rows from nothing: GENERATOR, SEQ, UNIFORM and RANDOM
      “This example shows that if the gen argument is a constant, then the output is a constant:”
      ↩︎ Checkpoint
    5. 5.
      “producing a table with the same number of columns as the source table, but with statistically similar artificial data.”
      ↩︎ Synthetic copies of real tables: GENERATE_SYNTHETIC_DATA
      “the synthetic data resembles the original data statistically but does not have a direct reference or link to any row from the original data.”
      ↩︎ Synthetic copies of real tables: GENERATE_SYNTHETIC_DATA
      “The privacy filter removes rows from the output table if the rows are too similar to the input data set.”
      ↩︎ Synthetic copies of real tables: GENERATE_SYNTHETIC_DATA
      “You can specify up to five input tables per procedure call.”
      ↩︎ Synthetic copies of real tables: GENERATE_SYNTHETIC_DATA
      “You must accept the Anaconda terms and conditions in your Snowflake account in order to enable this feature.”
      ↩︎ Synthetic copies of real tables: GENERATE_SYNTHETIC_DATA
      “the join key values will be consistent across all tables in a single run, but not across multiple runs.”
      ↩︎ Exam trap 3
      “Redacted in the output unless you specify an output format with the replace option in GENERATE_SYNTHETIC_DATA.”
      ↩︎ Checkpoint
      “External, Apache Iceberg™, and hybrid tables Streams”
      ↩︎ Checkpoint
    6. 6.
      “The XMLGET function does not operate directly on a VARCHAR expression even if that VARCHAR contains valid XML text.”
      ↩︎ Semi-structured data: JSON and XML in VARIANT and OBJECT
    7. 7.
      “an individual value requires more than about 128 MB of storage space”
      ↩︎ Semi-structured data: JSON and XML in VARIANT and OBJECT

    Also cited

    Ready to test yourself?

    Practise the 8 questions on this subdomain.

    Spotted a mistake, or was something unclear? Tell us.