<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Darshana Bagwe on Medium]]></title>
        <description><![CDATA[Stories by Darshana Bagwe on Medium]]></description>
        <link>https://medium.com/@darshanabagwe03?source=rss-57281082d107------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*lmt2Uw3aC3jAAiojBNnfGg@2x.jpeg</url>
            <title>Stories by Darshana Bagwe on Medium</title>
            <link>https://medium.com/@darshanabagwe03?source=rss-57281082d107------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sat, 23 May 2026 12:24:45 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@darshanabagwe03/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[SCD 2 using Snowflake STREAMS]]></title>
            <link>https://medium.com/@darshanabagwe03/scd-2-using-snowflake-streams-8cf13e4b9a30?source=rss-57281082d107------2</link>
            <guid isPermaLink="false">https://medium.com/p/8cf13e4b9a30</guid>
            <dc:creator><![CDATA[Darshana Bagwe]]></dc:creator>
            <pubDate>Tue, 07 Jan 2025 21:08:10 GMT</pubDate>
            <atom:updated>2025-01-08T00:23:36.406Z</atom:updated>
            <content:encoded><![CDATA[<p>The objective of this article is to demonstrate the actual implementation of Snowflake Streams and validate how effectively it can be utilized for maintaining Slowly Changing Dimension ( Type-2)</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/715/1*87F4HyEtbSpSHbmywIOEEA.jpeg" /></figure><h3><strong>What is the Agenda ???</strong></h3><p>In the previous article we had a simple walkthrough about how <a href="https://medium.com/@darshanabagwe03/snowflake-stream-c8fac7358c13">STREAM</a> object works in Snowflake. However, understanding it’s working would completely suffice if we are thorough with it’s implementation and practically check whether it can really help us with the “Change Data Capture”.</p><h3>What steps do we follow implementing Snowflake Streams end to end ???</h3><p>In the below demonstration, We are considering Standard stream and source object as table-Customer which stores Customer’s latest Location (City).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/862/0*K1Foc3xXo-kZ89sj" /></figure><p>We create Stream object on source table/view. At this point the Stream object is mere capable of tracking changes on source.</p><pre>CREATE OR REPLACE STREAM STREAM_CUST ON TABLE CUST;</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/862/0*kIg5Ae4dGNyrpU0W" /></figure><p>We reference the created Stream object into another DML statement. (Typically INSERT/MERGE). The intent is to prepare a query for utilizing the Stream object ( the data it holds) for processing/loading the captured changes in another downstream object/table.</p><pre>MERGE INTO CUST_TARGET AS TARGET<br>USING<br>(<br> SELECT ID,<br>        NAME,<br>        CITY,<br>        METADATA$ACTION,<br>        METADATA$ISUPDATE<br>    FROM STREAM_CUST<br>) AS SOURCE<br>ON  TARGET.ID   = SOURCE.ID <br>AND TARGET.CITY = SOURCE.CITY<br><br>/*Use case: Process Records newly Inserted in Source*/<br><br>WHEN NOT MATCHED AND SOURCE.METADATA$ACTION = &#39;INSERT&#39;  THEN<br>INSERT (ID,NAME,CITY,START_DATE,END_DATE,ACTIVE_FLAG)<br>VALUES(SOURCE.ID,SOURCE.NAME,SOURCE.CITY,TO_TIMESTAMP_NTZ(CURRENT_TIMESTAMP),TO_TIMESTAMP_NTZ(&#39;31-DEC-9999&#39;),&#39;Y&#39; )<br><br>/*Use case: Process Records Updated in Source*/<br><br>WHEN MATCHED AND SOURCE.METADATA$ACTION = &#39;DELETE&#39; AND SOURCE.METADATA$ISUPDATE = TRUE  THEN<br>UPDATE SET TARGET.END_DATE    = TO_TIMESTAMP_NTZ(CURRENT_TIMESTAMP),<br>           TARGET.ACTIVE_FLAG = &#39;N&#39;   <br><br>/*Use case: Handle Records Deleted in Source*/<br><br>WHEN MATCHED AND SOURCE.METADATA$ACTION = &#39;DELETE&#39; AND SOURCE.METADATA$ISUPDATE = FALSE  THEN<br>UPDATE SET TARGET.END_DATE    = TO_TIMESTAMP_NTZ(CURRENT_TIMESTAMP),<br>           TARGET.ACTIVE_FLAG = &#39;D&#39;  <br><br>/* Use case: Reprocess records which were earlier Deleted in Source <br>and subsequently flagged in-active in Target*/<br><br>WHEN MATCHED AND SOURCE.METADATA$ACTION = &#39;INSERT&#39; AND SOURCE.METADATA$ISUPDATE = FALSE  THEN<br>UPDATE SET <br>           TARGET.START_DATE  = TO_TIMESTAMP_NTZ(CURRENT_TIMESTAMP),<br>           TARGET.END_DATE    = TO_TIMESTAMP_NTZ(&#39;31-DEC-9999&#39;),<br>           TARGET.ACTIVE_FLAG = &#39;Y&#39;; </pre><h3>What’s the need of scheduling Streams ???</h3><p>The question lies couldn’t we simply execute the above DML statement manually and process our records into downstream table. <strong>Of course</strong> !!!</p><p>Having said that, are we manually going to query the stream object every time to check whether it has new data. <strong>Not really</strong> !!!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/862/0*8mY1bWG3nw2Rfr2C" /></figure><p>Here comes the role of another brilliant Snowflake feature called ‘<strong>TASKS’ </strong>which is capable of running SQL statements on a schedule. Thus, We can invoke Stream using Tasks and without manual intervention.</p><p><strong>Note</strong>: There is so much more to ‘TASKS’ and it’s types. The scope of this article is with respect to Streams hence we would stick to see what is the best ‘TASK’ type we could use for invoking Stream object.</p><pre>CREATE OR REPLACE TASK TRIGGEREDTASK  <br>WAREHOUSE = COMPUTE_WH  <br>USER_TASK_MINIMUM_TRIGGER_INTERVAL_IN_SECONDS = 15<br>  WHEN SYSTEM$STREAM_HAS_DATA(&#39;STREAM_CUST&#39;)<br>  AS<br>&lt;DML-STATEMENT&gt;;<br><br><br>ALTER TASK TRIGGEREDTASK RESUME;</pre><p><strong>Key considerations from STEP 3</strong>:</p><p><strong>Triggered task</strong>: It works great for continuous ELT workflows to process recently changed table rows. If the underlying stream has no data the Triggered Tasks don’t use compute resources and the task run is skipped.</p><p><strong><em>USER_TASK_MINIMUM_TRIGGER_INTERVAL_IN_SECONDS</em></strong>: Time in seconds for trigger task to execute. This property can address latency issues.</p><p><strong><em>SYSTEM$STREAM_HAS_DATA</em></strong>: If the specified stream contains no change data, the task skips the current run. The stream can never go stale if this function is being invoked provided the stream should be empty and thus returning a FALSE value.</p><h3>Demo on utilizing Snowflake Streams for maintaining Slowly Changing Dimension (Type-2)</h3><p>So far, we have created stream object and scheduled underlying DML statement using Task object to consume stream data into downstream target table. Let’s validate below test cases.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*WJl98zfIeZ7Y7TvP" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*EIRDPk01d_v4pnOwty_l1w.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*xOQnIMiPPoKUvgRL" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*F1aS1Z6nJo6sjYwKpyRhig.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*7wpHobU59ph3GR96" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*RXniLB71ycStwP81WxS0mQ.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*h_q0jzs71fxd_eyW" /></figure><p>We would reprocess records which have been earlier deleted from Source and subsequently flagged in-active in Target but currently active in source.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*OSad9wFO5QqvV55eoLlUzA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*fucIcdmN94N9YYIJ" /></figure><p>This test case is specific to validate the date range maintained and check whether historical records are still preserved when record from source has been updated multiple times.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*uTUNSAz6b9lyu09KP6Z4og.png" /></figure><p>Thus with this demonstration and validation of uses cases, we can conclude Snowflake streams along with Tasks can have a fine grain control in performing ‘Change Data Capture’ and even can be leveraged for orchestrating ELT loads with minimum latency and maintain Slowly changing Dimensions in Snowflake.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=8cf13e4b9a30" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Snowflake STREAM]]></title>
            <link>https://medium.com/@darshanabagwe03/snowflake-stream-c8fac7358c13?source=rss-57281082d107------2</link>
            <guid isPermaLink="false">https://medium.com/p/c8fac7358c13</guid>
            <category><![CDATA[snowflake]]></category>
            <category><![CDATA[change-data-capture]]></category>
            <category><![CDATA[snowflake-streams]]></category>
            <dc:creator><![CDATA[Darshana Bagwe]]></dc:creator>
            <pubDate>Fri, 20 Dec 2024 17:07:43 GMT</pubDate>
            <atom:updated>2024-12-20T20:13:39.889Z</atom:updated>
            <content:encoded><![CDATA[<h4>The objective of this post is to give you an simplest overview of what is STREAM object in snowflake and how does it work.</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*lGXz3MkEve4ZrU2DqUeA_w.jpeg" /></figure><h3><strong>What is Snowflake Stream</strong> ???</h3><p>To begin with and at an higher level we could think of Snowflake STREAM as an bookmark been placed inside a book which indicates how many pages of book we have read so far and what is the next point of reference to start reading new content from the book. Thus each time we consume the book content we even advance or place this bookmark at a next position (offset) from where we need to read the upcoming pages.</p><p>Similarly coming to Snowflake, Stream Object is used to track the DML operations (Inserts/Updates/Deletes) on Tables/Views and to further implement Change Data Capture. In simple terms we can create the Stream object on top of these respective tables/views. For now let’s also make a note that there are different types of streams that we could create.</p><h3>So what are the different Stream types??</h3><ol><li>Standard/Delta Stream</li></ol><p>It captures all Insert, Update, Delete on the source table.</p><pre>Syntax:  CREATE OR REPLACE STREAM &lt;STREAM-NAME&gt; ON TABLE &lt;TABLE-NAME&gt;;<br>Example: CREATE OR REPLACE STREAM STREAM_CUST  ON TABLE CUSTOMER;</pre><p>2. Append only Stream</p><p>If we wish to track only the Insert operations on the source table, we could use the option below. However the Change Data Capture is limits to only Inserts ignoring the Updates and Deletes.</p><pre>Syntax:  CREATE OR REPLACE STREAM &lt;STREAM-NAME&gt; ON TABLE &lt;TABLE-NAME&gt; append only = true;<br>Example: CREATE OR REPLACE STREAM STREAM_CUST ON TABLE CUSTOMER append only = true;</pre><p>3. Insert only Stream</p><p>This stream type is quite similar to Append-Only stream and tracks row inserts only, however it is for external tables created on top of files in cloud storage. This type of stream is even supports Iceberg tables.</p><pre>Syntax:  CREATE OR REPLACE STREAM &lt;STREAM-NAME&gt; ON TABLE &lt;EXTERNAL TABLE-NAME&gt; insert only = true;<br>Example: CREATE OR REPLACE STREAM STREAM_EXT_CUST  ON TABLE EXT_CUSTOMER insert only = true;</pre><p>So let’s now address “HOW DOES STREAM OBJECT WORK ???”. We will go ahead with ‘Standard stream’ and ‘Table’ object as an example.</p><h3>What actually happens post creating a stream object ???</h3><p>When there are any DML ( Insert/Update/Delete) operations on a source table and we query this source table at an instance it will certainly populate all records however when we query the stream object which has been created on top of source table it will only reflect the changed/newly inserted/deleted records.</p><pre># We can query a stream object similar to querying a Table/View.<br><br>Syntax: SELECT * FROM &lt;stream-name&gt;;<br>        SELECT * FROM stream_cust;</pre><p>When we create stream object on a source table 3 additional hidden metadata fields are tagged on top of source table that helps to track DML operations. However, These fields are not visible when we query the source table directly but we can view them once we query the stream object created on top of the source table.</p><h3>What are these additional metadata fields ???</h3><pre>1. METADATA$ACTION: The action on the source table [ Values are INSERT/DELETE]<br><br>2. METADATA$UPDATE: Evaluates to TRUE only for updates on source table<br><br>3. METADATA$ROWID: Uniquely generated to identify a row. <br>All changes for a particular record could be tracked using this metadata field.</pre><h3><strong>What is the significance of these metadata fields ???</strong></h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*u82XQBrNWL6SZ7vi" /><figcaption>For each DML operation on source table the metadata fields are updated accordingly</figcaption></figure><p>NOTE: For all Insert &amp; Delete operations in source table only 1 entry each is maintained in the stream object respectively whereas for an Updated record 2 entries are typically maintained in the stream table.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*ajFU1kMPZbtUhZVt" /><figcaption>Sample dataset</figcaption></figure><h3>How Stream works ???</h3><p>In the below demonstration, We will Consider a source table — Customer which tracks customer location (city). We will go through how standard stream works while processing multiple DML operations until consumed in downstream table.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*-kcOxI2ugjbXiKZf" /><figcaption>Standard stream processing DML operations.</figcaption></figure><h3>What are the Takeaways ???</h3><p>Stream object will perform as per the configured stream type (whether it is insert/append = true), depending upon the metadata action of source table (insert/update/delete) and the offset mechanism.</p><p><strong>What is offset mechanism ???</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*aCr2bMFoAwYb_Qe-" /><figcaption>Overview of OFFSET</figcaption></figure><p>Do you think stream object stores data. No it doesn’t. Instead it creates an snapshot ( a logical one) of every row in the source table (source object) by initializing an offset which is moreover like a position/pointer of stream at an instance of time.</p><p>There could be N number of DML operations/transactions between one offset until its next one. However only after these set of operations are consumed in DML statement (Inserts/merge) the next offset gets initialized.</p><h3>Let’s consider an example:</h3><p>We create a standard stream on the source table. If an instance of time Say 10:00 AM we insert 3 new records in the source table. The source table will reflect existing data as well the newly inserted 3 records. If we query the stream object, it will reflect 3 newly inserted records.</p><p>Next, if we consume the inserts of the stream into a DML operation (to load into downstream table) and we query the stream object, no data is returned since the offset advances and the data has been consumed.</p><p>We started this post comparing streams with an bookmark, so can we keep multiple bookmarks in a book if it has to be read by different individuals. Of course. Similarly, we can even create multiple streams on similar source object and it an preserve same metadata but different offsets.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c8fac7358c13" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>