Хранимая процедура в базе данных aspnet, ошибка 217: предел (32) превышен? - PullRequest
0 голосов
/ 29 марта 2011

Я новичок в хранимых процедурах и пытаюсь создать один для школьного проекта. Я написал инструкцию SQL, которая делает то, что я хочу, и просто преобразовал ее в хранимую процедуру (возможно, это плохая хакерская работа, но у нас заканчивается время и у нас есть куча других дел). Мы используем aspnet Membership Services и всю встроенную базу данных.

Что я хочу сделать Я использую 1 таблицу (TimesheetEntry). Я хочу получить все табели всех сотрудников, суммировать часы в будний день, чтобы получить часы / неделю, и повторить это за последние 4 недели (неделя 1 неделя 4 ниже) и за последние 4 месяца (месяц 1 месяц 4) ниже. Для этого я использовал вложенные операторы select.

Вот полное сообщение об ошибке:

Ошибка 217: превышен максимальный уровень вложенности хранимой процедуры, функции, триггера или представления (предел 32).

Вот полная хранимая процедура:

CREATE PROCEDURE sp_GetTimesheetSummaryReport2
@dateFor DATETIME
AS
SELECT CONVERT(VARCHAR, DATEADD(DAY, -7, GETDATE()), 111) AS startDate,
    CONVERT(VARCHAR, GETDATE(), 111) AS currentDate,
    projId, wpId, empId, 
    (
        SELECT (SUM(mon) + Sum(tue) + Sum(wed) + Sum(thu) + SUM(fri) + SUM(sat) + SUM(sun)) AS Week
        FROM TimesheetEntry
        WHERE empId = t.empId AND tsDate BETWEEN @dateFor AND DATEADD(DAY, -7, @dateFor)
        GROUP BY empId, projId, wpId
    ) AS week1,
    (
        SELECT (SUM(mon) + Sum(tue) + Sum(wed) + Sum(thu) + SUM(fri) + SUM(sat) + SUM(sun)) AS Week
        FROM TimesheetEntry
        WHERE empId = t.empId AND tsDate BETWEEN DATEADD(DAY, -7, @dateFor) AND DATEADD(DAY, -14, @dateFor)
        GROUP BY empId, projId, wpId
    ) AS week2,
    (
        SELECT (SUM(mon) + Sum(tue) + Sum(wed) + Sum(thu) + SUM(fri) + SUM(sat) + SUM(sun)) AS Week
        FROM TimesheetEntry
        WHERE empId = t.empId AND tsDate BETWEEN DATEADD(DAY, -14, @dateFor) AND DATEADD(DAY, -21, @dateFor)
        GROUP BY empId, projId, wpId
    ) AS week3,
    (
        SELECT (SUM(mon) + Sum(tue) + Sum(wed) + Sum(thu) + SUM(fri) + SUM(sat) + SUM(sun)) AS Week
        FROM TimesheetEntry
        WHERE empId = t.empId AND tsDate BETWEEN DATEADD(DAY, -21, @dateFor) AND DATEADD(DAY, -28, @dateFor)
        GROUP BY empId, projId, wpId
    ) AS week4,
    (
        SELECT (SUM(mon) + Sum(tue) + Sum(wed) + Sum(thu) + SUM(fri) + SUM(sat) + SUM(sun)) AS Month
        FROM TimesheetEntry
        WHERE empId = t.empId AND MONTH(tsDate) = MONTH(@dateFor)
        GROUP BY empId, projId, wpId
    ) AS month1,
    (
        SELECT (SUM(mon) + Sum(tue) + Sum(wed) + Sum(thu) + SUM(fri) + SUM(sat) + SUM(sun)) AS Month
        FROM TimesheetEntry
        WHERE empId = t.empId AND MONTH(tsDate) = MONTH(DATEADD(MONTH, -1, @dateFor))
        GROUP BY empId, projId, wpId
    ) AS month2,
    (
        SELECT (SUM(mon) + Sum(tue) + Sum(wed) + Sum(thu) + SUM(fri) + SUM(sat) + SUM(sun)) AS Month
        FROM TimesheetEntry
        WHERE empId = t.empId AND MONTH(tsDate) = MONTH(DATEADD(MONTH, -2, @dateFor))
        GROUP BY empId, projId, wpId
    ) AS month3,
    (
        SELECT (SUM(mon) + Sum(tue) + Sum(wed) + Sum(thu) + SUM(fri) + SUM(sat) + SUM(sun)) AS Month
        FROM TimesheetEntry
        WHERE empId = t.empId AND MONTH(tsDate) = MONTH(DATEADD(MONTH, -3, @dateFor))
        GROUP BY empId, projId, wpId
    ) AS month4
FROM TimesheetEntry t
GROUP BY t.empId, t.projId, t.wpId
ORDER BY t.projId, t.wpId, t.empId;

EXECUTE sp_GetTimesheetSummaryReport '2011/02/01';

Мои вопросы

  1. Почему я получаю эту ошибку? Есть я превысил стек, там тоже многие хранятся процедуры / триггеры / функции в база данных, мое вложение слишком глубокое?

  2. Как я могу решить это? Мой хранится процедура настолько ужасна, что я должен перезапустить, используя лучший синтаксис?

Ответы [ 3 ]

1 голос
/ 30 марта 2011

Ну, я бы никогда не допустил этого в одной из моих баз данных, потому что в ней есть коррелированные подзапросы, которые выполняются строка за строкой и работают очень медленно. Вместо этого он использовал бы CTE или производные таблицы.

Является ли запись расписания случайно представлением, которое вызывает другие представления? Они могут легко попасть на уровень рекурсии, особенно если их вызвать несколько раз, и вы вызываете этот график по крайней мере 9 раз, что я вижу (не считая запускаемого процесса).

Или что делает прок, который вы называете? Может ли это быть источником рекурсии?

1 голос
/ 30 марта 2011

Является ли вызов sp_GetTimesheetSummaryReport внутри sp_GetTimesheetSummaryReport2?Если это так, что это делает?

Я думаю, что у вас здесь происходят бесконечные циклы вызовов - процессы, которые в конечном итоге называют себя вложенными слишком глубоко.

0 голосов
/ 30 марта 2011

Я до сих пор не вижу никакой рекурсии. Чтобы упростить ваш запрос, могу ли я порекомендовать сделать:

totalhours AS (mon + tue + wed + thu + fri + sat + sun) PERSISTED

в вычисляемый столбец (возможно, сохраненный) в вашей таблице. Тогда вы не будете ни повторять логику, ни вызывать дорогостоящую пользовательскую функцию, но получите лучшую ремонтопригодность.

Затем он дает:

    SELECT (SUM(totalhours)) AS Week
    SELECT (SUM(totalhours)) AS Month

Я также заметил, что в вашем запросе есть такие вещи:

(
    SELECT (SUM(totalhours)) AS Week
    FROM TimesheetEntry
    WHERE empId = t.empId AND tsDate BETWEEN @dateFor AND DATEADD(DAY, -7, @dateFor)
    GROUP BY empId, projId, wpId
) AS week1,

Который вернет ошибку, если есть более одной строки - т.е. если у emp есть более одного proj или wp. Потому что вы рассматриваете это как коррелированный скалярный подзапрос.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...