{"id":3948,"date":"2015-09-05T00:59:13","date_gmt":"2015-09-04T19:29:13","guid":{"rendered":"http:\/\/sqlhints.com\/?p=3948"},"modified":"2015-09-05T08:49:03","modified_gmt":"2015-09-05T03:19:03","slug":"recursive-cte-sql-server","status":"publish","type":"post","link":"https:\/\/sqlhints.com\/2015\/09\/05\/recursive-cte-sql-server\/","title":{"rendered":"Recursive CTE &#8211; Sql Server"},"content":{"rendered":"<p style=\"text-align: justify;\">This is the second article in the series of articles on Common Table Expression in Sql Server. Below are the other articles in this series:<\/p>\n<p style=\"text-align: justify;\">\n<a href=\"https:\/\/sqlhints.com\/2015\/09\/05\/introduction-to-common-table-expression-a-k-a-cte-in-sql-server\/\" target=\"_blank\">Introduction to Common Table Expression (a.k.a CTE)<\/a><br \/>\n<a href=\"https:\/\/sqlhints.com\/2015\/09\/05\/multiple-ctes-in-a-single-query-sql-server\/\" target=\"_blank\">Multiple CTEs in a Single Query<\/a><br \/>\n<a href=\"https:\/\/sqlhints.com\/2015\/09\/05\/nested-common-table-expressions-i-e-cte-sql-server\/\" target=\"_blank\">Nested Common Table Expressions<\/a>\n<\/p>\n<h3>Recursive Common Table Expression<\/h3>\n<p style=\"text-align: justify;\">CTEs provide a mechanism to write easy to understand, more readable and maintainable <strong>recursive queries<\/strong>. Prior to CTEs only mechanism to write recursive query is by means of recursive function or stored procedure. And these recursive functions or stored procedures support only up-to 32 levels of recursion. By default CTEs support a maximum recursion level of 100. CTEs also provide an option to set a MAXRECURSION level value between 0 to 32,767. Specifying it&#8217;s value as 0 means no limit to the recursion level, you agreed for a risk in case of a poorly written query resulting in infinite recursion level.<\/p>\n<h3>Recursive CTE Example:<\/h3>\n<p style=\"text-align: justify;\">Below is a very basic example of a recursive CTE generating numbers between 1 to 10:<\/p>\n<p><a href=\"https:\/\/sqlhints.com\/wp-content\/uploads\/2015\/08\/RecursiveCTE-Basic-Example.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/sqlhints.com\/wp-content\/uploads\/2015\/08\/RecursiveCTE-Basic-Example.jpg\" alt=\"RecursiveCTE Basic Example\" width=\"508\" height=\"333\" class=\"alignnone size-full wp-image-3869\" srcset=\"https:\/\/sqlhints.com\/wp-content\/uploads\/2015\/08\/RecursiveCTE-Basic-Example.jpg 508w, https:\/\/sqlhints.com\/wp-content\/uploads\/2015\/08\/RecursiveCTE-Basic-Example-300x197.jpg 300w\" sizes=\"auto, (max-width: 508px) 100vw, 508px\" \/><\/a><\/p>\n<pre class=\"brush: sql; gutter: false\">WITH NumbersCTE AS\r\n(\r\n\tSELECT  1 AS Number\r\n\tUNION ALL\r\n\tSELECT Number + 1 FROM NumbersCTE\r\n\tWHERE Number &lt; 10\r\n )\r\nSELECT * FROM NumbersCTE<\/pre>\n<p><strong>RESULT:<\/strong><br \/>\n<a href=\"https:\/\/sqlhints.com\/wp-content\/uploads\/2015\/08\/Recursive-CTE-Basic-Example-result.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/sqlhints.com\/wp-content\/uploads\/2015\/08\/Recursive-CTE-Basic-Example-result.jpg\" alt=\"Recursive CTE Basic Example result\" width=\"276\" height=\"383\" class=\"alignnone size-full wp-image-3871\" srcset=\"https:\/\/sqlhints.com\/wp-content\/uploads\/2015\/08\/Recursive-CTE-Basic-Example-result.jpg 276w, https:\/\/sqlhints.com\/wp-content\/uploads\/2015\/08\/Recursive-CTE-Basic-Example-result-216x300.jpg 216w\" sizes=\"auto, (max-width: 276px) 100vw, 276px\" \/><\/a><\/p>\n<h3>Example of Recursive CTE to get Managers and employees reporting to them<\/h3>\n<p style=\"text-align: justify;\">This example uses the <strong>Employees<\/strong> table created in the previous article <a href=\"https:\/\/sqlhints.com\/2015\/09\/05\/introduction-to-common-table-expression-a-k-a-cte-in-sql-server\/\" target=\"_blank\">Introduction to Common Table Expression (a.k.a CTE)<\/a>. You can visit the link to create the table, if you have not created it already.<\/p>\n<pre class=\"brush: sql; gutter: false\">\r\nWITH EmpRecursiveCTE(ManagerId, EmployeeId, Name, Level) AS \r\n(\r\n    SELECT ManagerId, Id, Name, 0 AS Level\r\n    FROM dbo.Employees \r\n    WHERE ManagerId IS NULL\r\n\t\tUNION ALL\r\n    SELECT E.ManagerId, E.Id, E.Name, Level + 1\r\n    FROM dbo.Employees E\r\n        INNER JOIN EmpRecursiveCTE EmpCTE\r\n        ON E.ManagerID = EmpCTE.EmployeeId \r\n)\r\nSELECT EmployeeId, Name, ManagerID, Level \r\nFROM EmpRecursiveCTE\r\nORDER BY ManagerID\r\n<\/pre>\n<p><strong>RESULT:<\/strong><br \/>\n<a href=\"https:\/\/sqlhints.com\/wp-content\/uploads\/2015\/08\/Recursive-CTE-Basic-Example-result-Employee-Hierarchy.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/sqlhints.com\/wp-content\/uploads\/2015\/08\/Recursive-CTE-Basic-Example-result-Employee-Hierarchy.jpg\" alt=\"Recursive CTE Basic Example result Employee Hierarchy\" width=\"420\" height=\"441\" class=\"alignnone size-full wp-image-3898\" srcset=\"https:\/\/sqlhints.com\/wp-content\/uploads\/2015\/08\/Recursive-CTE-Basic-Example-result-Employee-Hierarchy.jpg 420w, https:\/\/sqlhints.com\/wp-content\/uploads\/2015\/08\/Recursive-CTE-Basic-Example-result-Employee-Hierarchy-286x300.jpg 286w\" sizes=\"auto, (max-width: 420px) 100vw, 420px\" \/><\/a><\/p>\n<h3>MAXRECURSION hint in Recursive CTE<\/h3>\n<p style=\"text-align: justify;\">By default maximum recursion level supported by CTE is 100. But CTE provides an option to change it by means of the MAXRECURSION hint. MAXRECURSION hint value can be between 0 to 32,767. Specifying it&#8217;s value as 0 means no limit.<\/p>\n<p style=\"text-align: justify;\">Let us understand MAXRECURSION hint in a Recursive CTE by the below examples:<\/p>\n<p><strong>CTEs default maximum recursion level<\/strong><\/p>\n<p style=\"text-align: justify;\">Try to generate numbers between 1 to 200 by using a recursive CTE by the following script:<\/p>\n<pre class=\"brush: sql; gutter: false\">\r\nWITH NumbersCTE AS\r\n(\r\n    SELECT  1 AS Number\r\n    UNION ALL\r\n    SELECT Number + 1 FROM NumbersCTE\r\n    WHERE Number &lt; 200\r\n )\r\nSELECT * FROM NumbersCTE<\/pre>\n<p><strong>RESULT:<\/strong><\/p>\n<p style=\"text-align: justify;color:Red;\">Msg 530, Level 16, State 1, Line 1<br \/>\nThe statement terminated. The maximum recursion 100 has been exhausted before statement completion.<\/p>\n<p style=\"text-align: justify;\">From the above result it is clear that, the CTEs default maximum recursion level is 100.<\/p>\n<p><strong>How to change CTEs default maximum recursion level?<\/strong> <\/p>\n<p style=\"text-align: justify;\">We can change the CTEs default maximum recursion by specifying the MAXRECURSION query hint. Change the previous recursive CTE to generate numbers between 1 to 200 by specifying the MAXRECURSION hint value as 210 as below and verify the result:<\/p>\n<pre class=\"brush: sql; gutter: false\">WITH NumbersCTE AS\r\n(\r\n    SELECT  1 AS Number\r\n    UNION ALL\r\n    SELECT Number + 1 FROM NumbersCTE\r\n    WHERE Number &lt; 200\r\n )\r\nSELECT * FROM NumbersCTE\r\nOPTION (MAXRECURSION 210)<\/pre>\n<p><strong>RESULT:<\/strong><br \/>\n<a href=\"https:\/\/sqlhints.com\/wp-content\/uploads\/2015\/08\/Recursive-CTE-with-MAXRECURSION-hint.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/sqlhints.com\/wp-content\/uploads\/2015\/08\/Recursive-CTE-with-MAXRECURSION-hint.jpg\" alt=\"Recursive CTE with MAXRECURSION hint\" width=\"267\" height=\"378\" class=\"alignnone size-full wp-image-3906\" srcset=\"https:\/\/sqlhints.com\/wp-content\/uploads\/2015\/08\/Recursive-CTE-with-MAXRECURSION-hint.jpg 267w, https:\/\/sqlhints.com\/wp-content\/uploads\/2015\/08\/Recursive-CTE-with-MAXRECURSION-hint-212x300.jpg 212w\" sizes=\"auto, (max-width: 267px) 100vw, 267px\" \/><\/a><\/p>\n<p style=\"text-align: justify;\">From the above result it is clear that we can change the CTEs default maximum recursion by means of MAXRECURSION query hint.<\/p>\n<p><strong>MAXRECURSION query hint is helpful to terminate the poorly written recursive CTE<\/strong><\/p>\n<p style=\"text-align: justify;\">MAXRECURSION hint is very helpful in a scenario where poorly written CTE is resulting in an infinite recursion level, in such cases MAXRECURSION terminates the CTE once the defined recursion crosses. For example below is an infinite recursive CTE, but because of the MAXRECURSION hint value 210 it terminates the CTE execution once it reaches the recursion level of 210.<\/p>\n<pre class=\"brush: sql; gutter: false\">\r\nWITH NumbersCTE AS\r\n(\r\n    SELECT  1 AS Number\r\n    UNION ALL\r\n    SELECT Number + 1 FROM NumbersCTE   \r\n )\r\nSELECT * FROM NumbersCTE\r\nOPTION (MAXRECURSION 210)<\/pre>\n<p><strong>RESULT:<\/strong><br \/>\n<a href=\"https:\/\/sqlhints.com\/wp-content\/uploads\/2015\/08\/Infinite-Recursive-CTE-with-MAXRECURSION-hint.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/sqlhints.com\/wp-content\/uploads\/2015\/08\/Infinite-Recursive-CTE-with-MAXRECURSION-hint.jpg\" alt=\"Infinite Recursive CTE with MAXRECURSION hint\" width=\"511\" height=\"247\" class=\"alignnone size-full wp-image-3910\" srcset=\"https:\/\/sqlhints.com\/wp-content\/uploads\/2015\/08\/Infinite-Recursive-CTE-with-MAXRECURSION-hint.jpg 511w, https:\/\/sqlhints.com\/wp-content\/uploads\/2015\/08\/Infinite-Recursive-CTE-with-MAXRECURSION-hint-300x145.jpg 300w\" sizes=\"auto, (max-width: 511px) 100vw, 511px\" \/><\/a><br \/>\n<strong>Maximum recursion level that we can specify with MAXRECURSION query hint is 32,767<\/strong><\/p>\n<p style=\"text-align: justify;\">Try to generate the numbers between 1 to 40000 by the below script, by specifying the MAXRECURSION query hint value as 40000.<\/p>\n<pre class=\"brush: sql; gutter: false\">\r\nWITH NumbersCTE AS\r\n(\r\n    SELECT  1 AS Number\r\n    UNION ALL\r\n    SELECT Number + 1 FROM NumbersCTE  \r\n\tWHERE  Number &lt; 40000\r\n )\r\nSELECT * FROM NumbersCTE\r\nOPTION (MAXRECURSION 40000)\r\n<\/pre>\n<p><strong>RESULT:<\/strong><\/p>\n<p style=\"text-align: justify; color:red\">Msg 310, Level 15, State 1, Line 9<br \/>\nThe value 40000 specified for the MAXRECURSION option exceeds the allowed maximum of 32767.<\/p>\n<p style=\"text-align: justify;\">From the above result it is clear that the maximum recursion level we can specify with the MAXRECURSION query hint is 32,767. <\/p>\n<p><strong>How to support the recursion level greater than the maximum recursion level 32,767?<\/strong><\/p>\n<p style=\"text-align: justify;\">If we come across a scenario, where we need to have recursion level greater than 32,767, in such scenarios we can achieve this by specifying MAXRECURSION value as 0. MAXRECURSION query hint value 0 means no limit to the recusion level, if we are specifying this we should make sure that our query is not resulting in an infinite recursion level. So, we can re-write the previous recursive CTE as below:<\/p>\n<pre class=\"brush: sql; gutter: false\">WITH NumbersCTE AS\r\n(\r\n    SELECT  1 AS Number\r\n    UNION ALL\r\n    SELECT Number + 1 FROM NumbersCTE  \r\n\tWHERE  Number &lt; 40000\r\n )\r\nSELECT * FROM NumbersCTE\r\nOPTION (MAXRECURSION 0)<\/pre>\n<p><strong>RESULT:<\/strong><br \/>\n<a href=\"https:\/\/sqlhints.com\/wp-content\/uploads\/2015\/08\/Recursive-CTE-MAXIMUM-Recursion-Level-0.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/sqlhints.com\/wp-content\/uploads\/2015\/08\/Recursive-CTE-MAXIMUM-Recursion-Level-0.jpg\" alt=\"Recursive CTE MAXIMUM Recursion Level 0\" width=\"302\" height=\"357\" class=\"alignnone size-full wp-image-3954\" srcset=\"https:\/\/sqlhints.com\/wp-content\/uploads\/2015\/08\/Recursive-CTE-MAXIMUM-Recursion-Level-0.jpg 302w, https:\/\/sqlhints.com\/wp-content\/uploads\/2015\/08\/Recursive-CTE-MAXIMUM-Recursion-Level-0-254x300.jpg 254w\" sizes=\"auto, (max-width: 302px) 100vw, 302px\" \/><\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>This is the second article in the series of articles on Common Table Expression in Sql Server. Below are the other articles in this series: Introduction to Common Table Expression (a.k.a CTE) Multiple CTEs in a Single Query Nested Common Table Expressions Recursive Common Table Expression CTEs provide a mechanism to write easy to understand, &hellip; <a href=\"https:\/\/sqlhints.com\/2015\/09\/05\/recursive-cte-sql-server\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Recursive CTE &#8211; Sql Server<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[3],"tags":[794,783,807,810,804,805,811,797,802,801,813,799,800,809,803,796,795,321,798,792,793,986,499,808,806,812],"class_list":["post-3948","post","type-post","status-publish","format-standard","hentry","category-sql-server","tag-common-table-expression","tag-cte","tag-cte-maximum-recursion","tag-level-15","tag-level-16","tag-line-1","tag-line-9","tag-maxrecursion","tag-maxrecursion-cte","tag-maxrecursion-hint-in-recursive-cte","tag-maxrecursion-option-exceeds-the-allowed-maximum-of-32767","tag-maxrecursion-sql","tag-maxrecursion-sql-server","tag-msg-310","tag-msg-530","tag-recursive-cte-in-sql-server","tag-recursive-cte-sql","tag-sql","tag-sql-maxrecursion","tag-sql-recursion","tag-sql-recursive-cte","tag-sql-server","tag-state-1","tag-the-maximum-recursion-100-has-been-exhausted-before-statement-completion","tag-the-statement-terminated-the-maximum-recursion-100-has-been-exhausted-before-statement-completion","tag-the-value-40000-specified-for-the-maxrecursion-option-exceeds-the-allowed-maximum-of-32767"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p3xNAz-11G","_links":{"self":[{"href":"https:\/\/sqlhints.com\/wp-json\/wp\/v2\/posts\/3948","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/sqlhints.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sqlhints.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sqlhints.com\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/sqlhints.com\/wp-json\/wp\/v2\/comments?post=3948"}],"version-history":[{"count":24,"href":"https:\/\/sqlhints.com\/wp-json\/wp\/v2\/posts\/3948\/revisions"}],"predecessor-version":[{"id":3999,"href":"https:\/\/sqlhints.com\/wp-json\/wp\/v2\/posts\/3948\/revisions\/3999"}],"wp:attachment":[{"href":"https:\/\/sqlhints.com\/wp-json\/wp\/v2\/media?parent=3948"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sqlhints.com\/wp-json\/wp\/v2\/categories?post=3948"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sqlhints.com\/wp-json\/wp\/v2\/tags?post=3948"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}