问题
The following CTE Query throws "The statement terminated. The maximum recursion 100 has been exhausted before statement completion."
WITH MyCTE
AS (
SELECT o.organizationid,
organization AS organization
FROM organization o
INNER JOIN store s ON s.organizationid = o.organizationid
UNION ALL
SELECT store.storeid,
CAST(storeNAme AS NVARCHAR(50)) AS storeNAme
FROM store
INNER JOIN MyCTE ON store.organizationid = MyCTE.organizationid)
SELECT DISTINCT
Organization
FROM MyCTE
when executing the subquery before and after the union all, the followig result is gained.
Anchor query:- SELECT o.organizationid, organization AS organization FROM organization o INNER JOIN store s ON s.organizationid = o.organizationid Result:-
organizationid |organization
--------------------------------
3 | Org1
query after union all:-
SELECT store.storeid, CAST(storeNAme AS NVARCHAR(50)) AS storeNAme FROM store
Result:-
StoreId |StoreName
--------------------------------
3 | Warehouse1
May I know the reason why ?
回答1:
Specify the maxrecursion option at the end of the query:
...
from MyCTE
option (maxrecursion 0)
That allows you to specify how often the CTE can recurse before generating an error. Maxrecursion 0 allows infinite recursion.
回答2:
When you are running recursive query, you allow a query to call itself. It doesn't matter how many rows query returns, but how many times a query will call itself. Therefore there is a risk it might go into infinite loop while. SQL Server in order to prevent this situation from happening have a setting which will determine how many recursions are allowed. Default value for this setting is 100 - therefore you will get this message when your query exceeds 100 recursions (self calls).
You can override this setting by adding OPTION (MAXRECURSION nn)
at the end of query. When nn is new maximum.
You can also remove protection completely by setting this value to 0 - it will looks like this then: OPTION (MAXRECURSION 0)
however this is not recommended since when running it will keep consuming resources.
OP asked for suggestion how to avoid potential infinite loop, and create exit criteria for recursion.
As far as I can see you are trying to build data hierarchy. You might consider introducing additional column with hierarchy level and stop at some level (I choose 10 in example):
WITH MyCTE
AS (
SELECT o.organizationid,
organization AS organization,
1 lvl
FROM organization o
INNER JOIN store s ON s.organizationid = o.organizationid
UNION ALL
SELECT store.storeid,
CAST(storeNAme AS NVARCHAR(50)) AS storeNAme,
lvl+1
FROM store
INNER JOIN MyCTE ON store.organizationid = MyCTE.organizationid
WHERE lvl<10
)
SELECT DISTINCT
Organization
FROM MyCTE
来源:https://stackoverflow.com/questions/45408509/cte-query-throws-recursion-exhausted-error