问题
I have a query that is returning an error with the maximum levels of recursion exceeded.
I know how to fix this by adding OPTION (maxrecursion 0)
to the query however, I have tried adding this at various places in the query and I cant find where to put it where the syntax is valid.
Can anyone give me any pointers as to where in my view the query hint needs to be inserted?
/****** Object: View [dbo].[SiconCFMContractLinesDetailByDayView] Script Date: 16/12/2016 12:02:35 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE VIEW [dbo].[SiconCFMContractLinesDetailByDayView]
AS
WITH dateRange as
(
SELECT [Date] = DATEADD(dd, 1, DATEADD(dd, -1,[SiconCFMContractLinesOutstandingView].[NextDueDate])),
[Frequency] = [SiconCFMContractLinesOutstandingView].[FrequencyValue],
[EndDate] = DATEADD(yy,5, [SiconCFMContractLinesOutstandingView].[NextDueDate]),
[SiconCFMContractLinesOutstandingView].[SiconContractLineID]
FROM [SiconCFMContractLinesOutstandingView]
WHERE DATEADD(mm, [SiconCFMContractLinesOutstandingView].[FrequencyValue], [SiconCFMContractLinesOutstandingView].[NextDueDate]) < DATEADD(mm, [SiconCFMContractLinesOutstandingView].[FrequencyValue], DATEADD(yy,5, [SiconCFMContractLinesOutstandingView].[NextDueDate]))
UNION ALL
SELECT DATEADD(mm, [Frequency], [Date]) [Date],
[Frequency],
[EndDate],
[SiconContractLineID]
FROM dateRange
WHERE DATEADD(mm, [Frequency], [Date]) < DATEADD(mm, [Frequency],[EndDate])
)
SELECT
(
SELECT CASE
WHEN dbo.fnSiconCFMGetSettingValue('UseAverageTimeToPay') = 'True'
THEN
CASE [SiconCFMSLCustomerAverageTimeToPayView].[AvgTimeToPayDateLastUpdated]
WHEN NULL THEN dbo.fnSiconCFMDateByPaymentTerms([SLCustomerAccount].[SYSPaymentTermsBasisID], [SLCustomerAccount].[PaymentTermsInDays], dateRange.[Date])
ELSE DATEADD([DD],[SiconCFMSLCustomerAverageTimeToPayView].[Days],dateRange.[Date])
END
ELSE dbo.fnSiconCFMDateByPaymentTerms([SLCustomerAccount].[SYSPaymentTermsBasisID], [SLCustomerAccount].[PaymentTermsInDays], dateRange.[Date])
END
)
AS [DueDate],
[StockItem].[Name] AS [Title],
[SiconCFMContractLinesOutstandingView].[Description] AS [Description],
[SiconCFMContractLinesOutstandingView].[UnitBillCoverPriceIncDisc] AS [Value],
[SiconCFMContractLinesOutstandingView].[SiconContractID],
[SiconCFMContractLinesOutstandingView].[SiconContractLineID],
[SiconCFMContractLinesOutstandingView].[SiconContractLineID] AS [ForecastDateForeignID],
'SiconContractLine' AS [ForecastDateSource],
(
SELECT
CASE WHEN EXISTS
(
SELECT [SiconCFMMemo].[SiconCFMMemoID]
FROM [SiconCFMMemo]
WHERE [SiconCFMMemo].[Deleted]=0
AND [SiconCFMMemo].[IsActive]=1
AND [SiconCFMMemo].[MemoSource]='SiconContractLine'
AND [SiconCFMMemo].[MemoForeignID]=[SiconCFMContractLinesOutstandingView].[SiconContractLineID]
)
THEN 1
ELSE 0
END
) AS [HasMemos]
FROM dateRange
INNER JOIN [SiconCFMContractLinesOutstandingView]
ON dateRange.[SiconContractLineID]
= [SiconCFMContractLinesOutstandingView].[siconContractLineID]
INNER JOIN [StockItem]
ON [StockItem].[ItemID]
= [SiconCFMContractLinesOutstandingView].[ItemID]
INNER JOIN [SLCustomerAccount]
ON [SLCustomerAccount].[SLCustomerAccountID]
= [SiconCFMContractLinesOutstandingView].[SLCustomerAccountID]
INNER JOIN [SiconCFMSLCustomerAverageTimeToPayView]
ON [SiconCFMSLCustomerAverageTimeToPayView].[SLCustomerAccountID]
= [SLCustomerAccount].[SLCustomerAccountID]
GO
as suggested I have added OPTION (maxrecursion 0) to just above the last GO statement, however when within the create view statement it is giving a syntax error. If I run the query on its own, outside of a create view statement it works
回答1:
Usually, At the end of the select statement that uses the recurcive cte.
However, inside a view that will not work.
A quick search got me to this post - that explains the correct way to do it.
Turns out you can't use the query hint inside the view, but you can and should use it in the query that calls the view.
Sample table:
CREATE TABLE T
(
id int,
parent int
)
INSERT INTO T VALUES (1, NULL), (2, 1), (3, 1), (4, 2), (5, 2), (6, 3), (7, 4), (8, 5);
GO
Create the view:
CREATE VIEW V
AS
WITH CTE AS
(
SELECT id, parent
FROM T
WHERE parent IS NULL
UNION ALL
SELECT t.id, t.parent
FROM T
INNER JOIN CTE ON t.parent = cte.id
)
SELECT *
FROM CTE
GO
Execute the view:
SELECT *
FROM V
OPTION (MAXRECURSION 2);
回答2:
there is a very nice script that I use to check foreign keys recursively by Ann Lewkowicz
However, I once had a database which had plenty of constraints, including foreign key constraints in some of the tables.
and while running the script above I got the following error:
The statement terminated. The maximum recursion 32767 has been exhausted before statement completion.
then I limited the output of the script using top
and it all went out fine
select top 100 *
from recurseWithFields
--OPTION (MAXRECURSION 32767);
来源:https://stackoverflow.com/questions/41183822/sql-server-the-maximum-recursion-100-has-been-exhausted-before-statement-compl