{"id":6754,"date":"2026-07-12T02:06:37","date_gmt":"2026-07-12T10:06:37","guid":{"rendered":"https:\/\/www.gudusoft.com\/sql-server-data-lineage\/"},"modified":"2026-07-12T02:06:37","modified_gmt":"2026-07-12T10:06:37","slug":"sql-server-data-lineage","status":"publish","type":"page","link":"https:\/\/www.gudusoft.com\/es\/sql-server-data-lineage\/","title":{"rendered":"SQL Server Data Lineage: T-SQL, Stored Procedures, and Dynamic SQL"},"content":{"rendered":"<p><strong>SQL Server data lineage<\/strong> is the column-level map of how data moves through your T-SQL code: which source columns feed each target table, view, or report, and what happens along the way inside stored procedures, temp tables, <code>MERGE<\/code> statements, and dynamic SQL. <a href=\"https:\/\/www.gudusoft.com\/es\/sql-data-lineage-tool\/\">Flujo de SQL de Gudu<\/a> builds that map automatically by parsing T-SQL with a dedicated SQL Server procedural parser, so lineage does not stop at the object level the way SSMS dependency views do.<\/p>\n\n\n\n<div class=\"wp-block-group alignfull has-background is-layout-constrained\" style=\"background-color:#eef7fb;padding-top:24px;padding-bottom:24px\"><div class=\"wp-block-group__inner-container\">\n\n<p><strong>Try it now:<\/strong> paste a T-SQL stored procedure into the <a href=\"https:\/\/sqlflow.gudusoft.com\/?utm_source=gudusoft&amp;utm_medium=website&amp;utm_campaign=sql-server-data-lineage\" target=\"_blank\" rel=\"noreferrer noopener\">free SQL Server lineage visualizer<\/a> and get a column-level lineage diagram in seconds.<\/p>\n\n<\/div><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Why SQL Server data lineage is harder than it looks<\/h2>\n\n\n\n<p>On most SQL Server estates, the transformation logic that actually matters does not live in tidy views. It lives in stored procedures that stage data through <code>#temp<\/code> tables, upsert into fact tables with <code>MERGE<\/code>, branch on parameters, and assemble SQL strings at runtime with <code>sp_executesql<\/code> o <code>EXEC<\/code>. Any lineage approach that only reads object definitions from the catalog sees the procedure as a black box: it knows the proc exists, but not which columns flow through it.<\/p>\n\n\n\n<p>Getting real lineage out of that code means parsing T-SQL the way the database engine does: building a semantic model of every statement in the procedure body, tracking columns as they pass through temp tables and table variables, and resolving the SQL hidden inside string variables. That is a compiler problem, not a metadata-query problem, and it is exactly what SQLFlow&#8217;s T-SQL parser is built for.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">What SSMS dependency views can and cannot tell you<\/h2>\n\n\n\n<p>SQL Server ships useful dependency tooling, and it is the right first stop for quick object-level questions. <code>sys.sql_expression_dependencies<\/code>, <code>sys.dm_sql_referenced_entities<\/code>, and the &#8220;View Dependencies&#8221; dialog in SSMS reliably tell you that procedure A references table B. What they cannot tell you:<\/p>\n\n\n\n<ul><li><strong>Column-level flow.<\/strong> Catalog dependencies stop at the object level. They show that <code>usp_load_fact_sales<\/code> touches <code>staging.sales<\/code> y <code>dw.fact_sales<\/code>, but not that <code>fact_sales.amount<\/code> is derived from <code>staging.sales.amount<\/code> through a <code>CAST<\/code> while <code>staging.sales.load_date<\/code> only filters rows.<\/li>\n<li><strong>Direction of flow.<\/strong> A reference is not a dataflow. Reading from a table and writing to it produce the same dependency row; lineage needs to know which is source and which is target.<\/li>\n<li><strong>Dynamic SQL.<\/strong> Statements built in a string and run through <code>sp_executesql<\/code> o <code>EXEC<\/code> are invisible to the dependency catalog entirely, because they do not exist until runtime.<\/li>\n<li><strong>Temp table hops.<\/strong> <code>#temp<\/code> tables live in <code>tempdb<\/code> and are not tracked as dependency endpoints, so any lineage that passes through one is cut in half.<\/li><\/ul>\n\n\n\n<p>Answering &#8220;what breaks downstream if I retype this column&#8221; or &#8220;which source fields feed this regulated report&#8221; requires parsing the T-SQL bodies themselves. That is the layer SQLFlow adds on top of what the catalog already gives you.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">How SQLFlow traces lineage through T-SQL procedures<\/h2>\n\n\n\n<p>SQLFlow is built on the <a href=\"https:\/\/www.sqlparser.com\/\">General SQL Parser (GSP)<\/a>, a commercial SQL compiler front-end developed since the mid-2000s and validated against roughly 13,600 per-dialect SQL test fixtures. Its SQL Server support is a dedicated T-SQL grammar, not a generic ANSI parser with exceptions bolted on, and it includes a full procedural parser for stored procedure bodies. Inside a procedure, SQLFlow resolves:<\/p>\n\n\n\n<ul><li><strong>Temp tables and table variables.<\/strong> Columns are tracked through <code>SELECT ... INTO #staging<\/code>, <code>INSERT INTO @rows<\/code>, and every subsequent read, so a three-hop pipeline through <code>tempdb<\/code> appears as one continuous lineage path.<\/li>\n<li><strong><code>MERGE<\/code> statements.<\/strong> Each <code>WHEN MATCHED THEN UPDATE<\/code> y <code>WHEN NOT MATCHED THEN INSERT<\/code> branch is analyzed, mapping source columns to target columns and treating the <code>ON<\/code> condition as indirect lineage.<\/li>\n<li><strong>Dynamic SQL.<\/strong> SQL assembled into variables and executed via <code>sp_executesql<\/code> o <code>EXEC<\/code> is resolved and parsed rather than skipped \u2014 one of the most common blind spots in lineage tooling.<\/li>\n<li><strong>Procedure parameters.<\/strong> Lineage flows through parameter values into the statements that use them.<\/li>\n<li><strong>The call graph.<\/strong> When procedures call other procedures, SQLFlow renders an interactive procedure-to-procedure call graph, so you can see the whole ETL chain, not one proc at a time.<\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Worked example: staging to fact table via MERGE<\/h2>\n\n\n\n<p>Here is the kind of procedure every SQL Server warehouse contains \u2014 a load proc that cleans staging rows into a temp table, then merges them into a fact table:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>CREATE PROCEDURE dbo.usp_load_fact_sales\nAS\nBEGIN\n    SELECT s.order_id,\n           s.customer_id,\n           CAST(s.amount AS DECIMAL(18,2)) AS amount\n    INTO   #clean_sales\n    FROM   staging.sales s\n    WHERE  s.load_date = CAST(GETDATE() AS DATE);\n\n    MERGE dw.fact_sales AS tgt\n    USING #clean_sales  AS src\n       ON tgt.order_id = src.order_id\n    WHEN MATCHED THEN\n        UPDATE SET tgt.amount = src.amount\n    WHEN NOT MATCHED THEN\n        INSERT (order_id, customer_id, amount)\n        VALUES (src.order_id, src.customer_id, src.amount);\nEND<\/code><\/pre>\n\n\n\n<p>Run this through SQLFlow and the diagram shows <code>dw.fact_sales.amount<\/code> fed by <code>staging.sales.amount<\/code> through a <code>CAST<\/code>, with <code>#clean_sales<\/code> visible as the intermediate hop. It also shows two relationships a catalog query can never produce: <code>staging.sales.load_date<\/code> as indirect lineage into every output column (it decides which rows load), and <code>order_id<\/code> doing double duty \u2014 direct lineage into the inserted key and indirect lineage through the <code>MERGE ... ON<\/code> match condition.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Direct vs indirect lineage in T-SQL<\/h2>\n\n\n\n<p>SQLFlow distinguishes <strong>direct lineage<\/strong> (a source column&#8217;s value lands in a target column) from <strong>indirect lineage<\/strong> (a column shapes the result through a <code>WHERE<\/code> clause, <code>JOIN<\/code> o <code>MERGE ON<\/code> condition, <code>GROUP BY<\/code>, or aggregate). The two are separately toggleable in the diagram. This matters in T-SQL work more than most dialects, because load procedures are full of filter columns \u2014 batch dates, status flags, watermark columns \u2014 that never appear in the output but silently control what data arrives. Most lineage tools do not model this distinction at all; for impact analysis on a load procedure, it is often the half that bites you.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Getting SQL Server lineage: inputs and deployment<\/h2>\n\n\n\n<p>You can feed SQL Server code to SQLFlow several ways, depending on how locked down your environment is:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Aporte<\/th><th>How it works<\/th><th>Good for<\/th><\/tr><\/thead><tbody>\n<tr><td>Paste or upload T-SQL<\/td><td>Scripts, DDL, and procedure definitions as files or pasted text<\/td><td>Quick analysis, code review, one procedure at a time<\/td><\/tr>\n<tr><td>Live metadata over JDBC<\/td><td>SQLFlow pulls DDL, view and procedure definitions from the instance<\/td><td>Whole-database lineage that stays current<\/td><\/tr>\n<tr><td>Grabit metadata extraction<\/td><td>Offline extraction utility ships metadata to SQLFlow<\/td><td>Environments where the lineage server cannot reach the database<\/td><\/tr>\n<\/tbody><\/table><\/figure>\n\n\n\n<p>In every case the analysis is static: SQLFlow reads SQL code and schema metadata, never the rows in your tables. For regulated environments, <a href=\"https:\/\/www.gudusoft.com\/es\/version-local-de-sqlflow\/\">SQLFlow local<\/a> runs on Docker or Kubernetes inside your network \u2014 air-gapped if required \u2014 so T-SQL source never leaves your infrastructure. Enterprise deployments batch-scan estates of 100+ databases and over a million columns with incremental scans, and export lineage to DataHub, Microsoft Purview, and OpenMetadata, so SQL Server lineage can flow into the catalog you already run. Pricing: the Cloud edition starts free ($49.99\/month premium); On-Premise is $500\/month or $4,800 one-time per database type \u2014 details on the <a href=\"https:\/\/www.gudusoft.com\/es\/precios\/\">pricing page<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">What about open-source parsers and catalog platforms?<\/h2>\n\n\n\n<p>Open-source libraries like <code>sqllineage<\/code> y <code>sqlglot<\/code> parse individual queries well, and for plain SELECT and INSERT statements they may be all you need. T-SQL procedural code is where the gap opens: procedure bodies with control flow, <code>#temp<\/code> table state across statements, <code>MERGE<\/code> branch analysis, and dynamic SQL resolution are hard parser engineering that generic tools skip. Catalog-first platforms are strong at organizing metadata across many systems; for column lineage through stored procedure logic they typically need a parsing engine underneath \u2014 which is the role SQLFlow plays, standalone or as the lineage feed into those platforms. The honest test: take your longest production procedure and run it through each candidate.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Related lineage guides<\/h2>\n\n\n\n<ul><li><a href=\"https:\/\/www.gudusoft.com\/es\/azure-sql-data-lineage\/\">Azure SQL data lineage<\/a> \u2014 the same T-SQL analysis applied to Azure SQL Database and Managed Instance.<\/li>\n<li><a href=\"https:\/\/www.gudusoft.com\/es\/herramienta-de-linaje-de-datos-de-oracle\/\">Herramienta de linaje de datos de Oracle<\/a> \u2014 PL\/SQL procedural lineage, the Oracle counterpart to this page.<\/li>\n<li><a href=\"https:\/\/www.gudusoft.com\/es\/sql-data-lineage-tool\/\">SQL data lineage tool overview<\/a> \u2014 how SQLFlow works across all 39 supported dialects.<\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Frequently asked questions<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Can SQLFlow trace lineage through SQL Server dynamic SQL?<\/h3>\n\n\n<p>Yes. SQL assembled in string variables and executed with <code>sp_executesql<\/code> o <code>EXEC<\/code> is resolved and parsed inside the procedure analysis, so the tables and columns it touches appear in the lineage graph. Catalog-based dependency views cannot see dynamic SQL at all.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Does SQLFlow handle #temp tables and table variables?<\/h3>\n\n\n<p>Yes. Columns are tracked through <code>#temp<\/code> tables and table variables across statements, so a pipeline that stages data in <code>tempdb<\/code> shows up as one continuous column-level path from source table to final target.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">How is this different from View Dependencies in SSMS?<\/h3>\n\n\n<p>SSMS dependency views report object-level references: procedure A mentions table B. SQLFlow parses the T-SQL bodies and reports column-level dataflow with direction \u2014 which source columns feed which target columns, through which transformations \u2014 including flows through temp tables, <code>MERGE<\/code>, and dynamic SQL that the catalog does not track.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Does SQLFlow need access to my SQL Server data?<\/h3>\n\n\n<p>No. SQLFlow performs static analysis of SQL code and optionally reads schema metadata such as table and procedure definitions. It never reads table row data, and the On-Premise edition keeps SQL text inside your network.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Can I see which stored procedures call which?<\/h3>\n\n\n<p>Yes. SQLFlow renders an interactive call graph of procedure-to-procedure invocations alongside the column lineage, so you can navigate a multi-procedure ETL chain end to end.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Is there a free way to try SQL Server lineage?<\/h3>\n\n\n<p>Yes. <a href=\"https:\/\/sqlflow.gudusoft.com\/?utm_source=gudusoft&amp;utm_medium=website&amp;utm_campaign=sql-server-data-lineage\">Nube SQLFlow<\/a> has a free tier: paste T-SQL in the browser and get a column-level lineage diagram. Premium is $49.99\/month for larger inputs and API access.<\/p>\n\n\n\n<div class=\"wp-block-group alignfull has-background is-layout-constrained\" style=\"background-color:#60d5f6;padding-top:32px;padding-bottom:32px\"><div class=\"wp-block-group__inner-container\">\n\n<h2 class=\"wp-block-heading\">Map your SQL Server lineage now<\/h2>\n\n\n<p>Paste your gnarliest stored procedure into the free visualizer, or talk to us about scanning your whole SQL Server estate.<\/p>\n\n\n<div class=\"wp-block-buttons is-layout-flex\">\n<div class=\"wp-block-button\"><a class=\"wp-block-button__link wp-element-button\" href=\"https:\/\/sqlflow.gudusoft.com\/?utm_source=gudusoft&amp;utm_medium=website&amp;utm_campaign=sql-server-data-lineage\" target=\"_blank\" rel=\"noreferrer noopener\">Try SQLFlow free<\/a><\/div>\n<\/div>\n\n\n<div class=\"wp-block-buttons is-layout-flex\">\n<div class=\"wp-block-button\"><a class=\"wp-block-button__link wp-element-button\" href=\"https:\/\/www.gudusoft.com\/es\/contacto\/\">Request an enterprise demo<\/a><\/div>\n<\/div>\n\n<\/div><\/div>\n\n\n\n<script type=\"application\/ld+json\">{\n    \"@context\": \"https:\\\/\\\/schema.org\",\n    \"@graph\": [\n        {\n            \"@type\": \"SoftwareApplication\",\n            \"name\": \"Gudu SQLFlow\",\n            \"applicationCategory\": \"DeveloperApplication\",\n            \"applicationSubCategory\": \"SQL Server Data Lineage Tool\",\n            \"operatingSystem\": \"Web, Linux, Windows, macOS\",\n            \"url\": \"https:\\\/\\\/www.gudusoft.com\\\/sql-server-data-lineage\\\/\",\n            \"description\": \"Automated SQL Server data lineage tool with a dedicated T-SQL procedural parser: column-level lineage through stored procedures, temp tables, MERGE, and dynamic SQL, plus a procedure call graph.\",\n            \"featureList\": \"T-SQL stored procedure lineage, dynamic SQL resolution (sp_executesql\\\/EXEC), temp table and table variable tracking, MERGE analysis, procedure call graph, direct vs indirect lineage, JDBC metadata import, DataHub\\\/Purview\\\/OpenMetadata export\",\n            \"softwareVersion\": \"8.2.3\",\n            \"offers\": [\n                {\n                    \"@type\": \"Offer\",\n                    \"name\": \"SQLFlow Cloud Free\",\n                    \"price\": \"0\",\n                    \"priceCurrency\": \"USD\"\n                },\n                {\n                    \"@type\": \"Offer\",\n                    \"name\": \"SQLFlow Cloud Premium\",\n                    \"price\": \"49.99\",\n                    \"priceCurrency\": \"USD\",\n                    \"priceSpecification\": {\n                        \"@type\": \"UnitPriceSpecification\",\n                        \"price\": \"49.99\",\n                        \"priceCurrency\": \"USD\",\n                        \"billingIncrement\": 1,\n                        \"unitText\": \"MONTH\"\n                    }\n                },\n                {\n                    \"@type\": \"Offer\",\n                    \"name\": \"SQLFlow On-Premise\",\n                    \"price\": \"4800\",\n                    \"priceCurrency\": \"USD\"\n                }\n            ],\n            \"publisher\": {\n                \"@type\": \"Organization\",\n                \"name\": \"Gudu Software\",\n                \"url\": \"https:\\\/\\\/www.gudusoft.com\\\/\"\n            }\n        },\n        {\n            \"@type\": \"FAQPage\",\n            \"mainEntity\": [\n                {\n                    \"@type\": \"Question\",\n                    \"name\": \"Can SQLFlow trace lineage through SQL Server dynamic SQL?\",\n                    \"acceptedAnswer\": {\n                        \"@type\": \"Answer\",\n                        \"text\": \"Yes. SQL assembled in string variables and executed with sp_executesql or EXEC is resolved and parsed inside the procedure analysis, so the tables and columns it touches appear in the lineage graph. Catalog-based dependency views cannot see dynamic SQL at all.\"\n                    }\n                },\n                {\n                    \"@type\": \"Question\",\n                    \"name\": \"Does SQLFlow handle #temp tables and table variables?\",\n                    \"acceptedAnswer\": {\n                        \"@type\": \"Answer\",\n                        \"text\": \"Yes. Columns are tracked through #temp tables and table variables across statements, so a pipeline that stages data in tempdb shows up as one continuous column-level path from source table to final target.\"\n                    }\n                },\n                {\n                    \"@type\": \"Question\",\n                    \"name\": \"How is this different from View Dependencies in SSMS?\",\n                    \"acceptedAnswer\": {\n                        \"@type\": \"Answer\",\n                        \"text\": \"SSMS dependency views report object-level references: procedure A mentions table B. SQLFlow parses the T-SQL bodies and reports column-level dataflow with direction \\u2014 which source columns feed which target columns, through which transformations \\u2014 including flows through temp tables, MERGE, and dynamic SQL that the catalog does not track.\"\n                    }\n                },\n                {\n                    \"@type\": \"Question\",\n                    \"name\": \"Does SQLFlow need access to my SQL Server data?\",\n                    \"acceptedAnswer\": {\n                        \"@type\": \"Answer\",\n                        \"text\": \"No. SQLFlow performs static analysis of SQL code and optionally reads schema metadata such as table and procedure definitions. It never reads table row data, and the On-Premise edition keeps SQL text inside your network.\"\n                    }\n                },\n                {\n                    \"@type\": \"Question\",\n                    \"name\": \"Can I see which stored procedures call which?\",\n                    \"acceptedAnswer\": {\n                        \"@type\": \"Answer\",\n                        \"text\": \"Yes. SQLFlow renders an interactive call graph of procedure-to-procedure invocations alongside the column lineage, so you can navigate a multi-procedure ETL chain end to end.\"\n                    }\n                },\n                {\n                    \"@type\": \"Question\",\n                    \"name\": \"Is there a free way to try SQL Server lineage?\",\n                    \"acceptedAnswer\": {\n                        \"@type\": \"Answer\",\n                        \"text\": \"Yes. SQLFlow Cloud has a free tier: paste T-SQL in the browser and get a column-level lineage diagram. Premium is $49.99\\\/month for larger inputs and API access.\"\n                    }\n                }\n            ]\n        }\n    ]\n}<\/script>","protected":false},"excerpt":{"rendered":"<p>SQL Server data lineage is the column-level map of how data moves through your T-SQL code: which source columns feed each target table, view, or report, and what happens along the way inside stored procedures, temp tables, MERGE statements, and dynamic SQL. Gudu SQLFlow builds that map automatically by parsing T-SQL with a dedicated SQL Server procedural parser, so lineage does not stop at the object level the way SSMS dependency views do. Try it now: paste a T-SQL stored procedure into the free SQL Server lineage visualizer and get a column-level lineage diagram in seconds. Why SQL Server data\u2026<\/p>","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":[],"blocksy_meta":{"styles_descriptor":{"styles":{"desktop":"","tablet":"","mobile":""},"google_fonts":[],"version":5}},"_links":{"self":[{"href":"https:\/\/www.gudusoft.com\/es\/wp-json\/wp\/v2\/pages\/6754"}],"collection":[{"href":"https:\/\/www.gudusoft.com\/es\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.gudusoft.com\/es\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.gudusoft.com\/es\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.gudusoft.com\/es\/wp-json\/wp\/v2\/comments?post=6754"}],"version-history":[{"count":0,"href":"https:\/\/www.gudusoft.com\/es\/wp-json\/wp\/v2\/pages\/6754\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.gudusoft.com\/es\/wp-json\/wp\/v2\/media?parent=6754"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}