#sql-server #sql-server-2005 #tsql #stored-procedures
#sql-server #sql-server-2005 #tsql #хранимые процедуры
Вопрос:
У меня необычная ошибка с хранимой процедурой, которую я написал для генерации статистики телефонии. Я запускаю этот sproc в кластеризованной среде SQL Server 2005. Процедура вызывается около 40 раз последовательно (один раз на очередь вызовов) для заполнения временной таблицы, а затем вставки этой временной таблицы в таблицу, которая хранит одну строку в день на очередь.
Я понимаю, что есть исправление для применения к полям sql, однако я хотел проверить, было ли что-то не так с моим sproc, прежде чем заставлять сетевых пользователей устанавливать исправления и т. Д
Основной sproc можно увидеть ниже (это кошмар с длинным кодом). Она использует 5 представлений, которые подключены к основной базе данных телефонии через связанный сервер (это система телефонии Cisco UCCX).
Ошибка, с которой я сталкиваюсь, заключается в следующем:
СООБЩЕНИЕ ОБ ОШИБКЕ
Сообщение 0, уровень 11, состояние 0, строка 0
В текущей команде произошла серьезная ошибка. Результаты, если таковые имеются, следует отбросить
Сообщение 0, уровень 20, статистика 0, строка 0
В текущей команде произошла серьезная ошибка. Результаты, если таковые имеются, следует отбросить
ПРОЦЕДУРА, КОТОРАЯ ВЫЗЫВАЕТ ОСНОВНУЮ ХРАНИМУЮ ПРОЦЕДУРУ
-- North
EXEC [dbo].[SP_GetStatsMain_ByCSQName] @starttime = @OfficeOpen, @endtime = @OfficeClose, @queue = N'CSQ-N003A', @date = @runDate
EXEC [dbo].[SP_GetStatsMain_ByCSQName] @starttime = @OfficeOpen, @endtime = @OfficeClose, @queue = N'CSQ-N004A', @date = @runDate
EXEC [dbo].[SP_GetStatsMain_ByCSQName] @starttime = @OfficeOpen, @endtime = @OfficeClose, @queue = N'CSQ-N005A', @date = @runDate
ОСНОВНАЯ ХРАНИМАЯ ПРОЦЕДУРА
ALTER PROCEDURE [dbo].[SP_GetStatsMain_ByCSQName]
-- Add the parameters for the stored procedure here
@starttime DATETIME,
@endtime DATETIME,
@queue varchar(50),
@date DATETIME
AS
BEGIN
SET NOCOUNT ON;
DECLARE @start DATETIME, @end DATETIME/*, @date DATETIME
set @date = getdate()-1*/
set @start = DATEADD(ms, DATEDIFF(ms, 0, @starttime), DATEADD(dd, 0, DATEDIFF(dd, 0, @date)))
set @end = DATEADD(ms, DATEDIFF(ms, 0, @endtime), DATEADD(dd, 0, DATEDIFF(dd, 0, @date)))
IF OBJECT_ID('tempdb..#temp') IS NOT NULL DROP TABLE #temp
CREATE TABLE #Temp(
[CSQName] [varchar](50) NULL,
[Presented] [int] NULL,
[Handled] [int] NULL,
[Abandonded] [int] NULL,
[Dequeued] [int] NULL,
[HandledSLA] [float] NULL,
[AbandondedSLA] [float] NULL,
[AvgTalkTime] [float] NULL,
[AvgWaitTime] [float] NULL,
[Date] [datetime] NULL
) ON [PRIMARY]
insert into #Temp([CSQName])
SELECT DISTINCT CSQ.CSQName
FROM CSQ INNER JOIN Queues ON CSQ.CSQName = Queues.CSQName
WHERE ((dateInactive IS NULL)
OR (dateInactive < GETDATE() - 1)) AND Queues.csqname = @queue
UPDATE #temp
SET [Date] = dateadd(dd,0, datediff(dd,0,@Date))
UPDATE #temp
SET [Presented] = 0,
[Handled] = 0,
[Abandonded] = 0,
[Dequeued] = 0,
[HandledSLA] = 0,
[AbandondedSLA] = 0,
[AvgTalkTime] = 0,
[AvgWaitTime] = 0
UPDATE #temp
SET Handled =
(
SELECT COUNT(CQD.targetType)
FROM ACD
INNER JOIN CCD ON ACD.sessionID = CCD.sessionID AND ACD.sessionSeqNum = CCD.sessionSeqNum
AND ACD.nodeID = CCD.nodeID
AND ACD.profileID = CCD.profileID
INNER JOIN CQD ON ACD.sessionID = CQD.sessionID
AND ACD.sessionSeqNum = CQD.sessionSeqNum
AND ACD.profileID = CQD.profileID
AND ACD.nodeID = CQD.nodeID
INNER JOIN CSQ ON CQD.targetID = CSQ.recordID
AND CQD.profileID = CSQ.profileID
INNER JOIN Queues ON CSQ.CSQName = Queues.csqname
INNER JOIN #temp on CSQ.CSQName = #Temp.CSQName
WHERE
(CCD.startDateTime > CONVERT(DATETIME, @start, 102))
AND (CCD.startDateTime < CONVERT(DATETIME, @end, 102))
AND (CCD.contactDisposition = 2)
AND (ACD.talkTime > 0)
AND (CQD.targetType = 0)
AND (CQD.disposition = 2)
AND Queues.csqname = @queue
)
FROM ACD
INNER JOIN CCD ON ACD.sessionID = CCD.sessionID AND ACD.sessionSeqNum = CCD.sessionSeqNum
AND ACD.nodeID = CCD.nodeID
AND ACD.profileID = CCD.profileID
INNER JOIN CQD ON ACD.sessionID = CQD.sessionID
AND ACD.sessionSeqNum = CQD.sessionSeqNum
AND ACD.profileID = CQD.profileID
AND ACD.nodeID = CQD.nodeID
INNER JOIN CSQ ON CQD.targetID = CSQ.recordID
AND CQD.profileID = CSQ.profileID
INNER JOIN Queues ON CSQ.CSQName = Queues.csqname
INNER JOIN #temp on CSQ.CSQName = #Temp.CSQName
WHERE
(CCD.startDateTime > CONVERT(DATETIME, @start, 102))
AND (CCD.startDateTime < CONVERT(DATETIME, @end, 102))
AND (CCD.contactDisposition = 2)
AND (ACD.talkTime > 0)
AND (CQD.targetType = 0)
AND (CQD.disposition = 2)
AND Queues.csqname = @queue
UPDATE #temp
SET Presented =
(
SELECT COUNT(CQD.sessionID) AS [Calls Presented]
FROM CQD INNER JOIN
CCD ON CQD.sessionID = CCD.sessionID AND CQD.sessionSeqNum = CCD.sessionSeqNum AND CQD.profileID = CCD.profileID AND
CQD.nodeID = CCD.nodeID INNER JOIN
CSQ ON CQD.profileID = CSQ.profileID AND CQD.targetID = CSQ.recordID INNER JOIN
Queues ON CSQ.CSQName = Queues.csqname INNER JOIN #temp on CSQ.CSQName = #Temp.CSQName
WHERE (CCD.startDateTime > CONVERT(DATETIME, @start, 102)) AND (CCD.startDateTime < CONVERT(DATETIME, @end, 102))
AND Queues.csqname = @queue
)
FROM CQD INNER JOIN
CCD ON CQD.sessionID = CCD.sessionID AND CQD.sessionSeqNum = CCD.sessionSeqNum AND CQD.profileID = CCD.profileID AND
CQD.nodeID = CCD.nodeID INNER JOIN
CSQ ON CQD.profileID = CSQ.profileID AND CQD.targetID = CSQ.recordID INNER JOIN
Queues ON CSQ.CSQName = Queues.csqname INNER JOIN #temp on CSQ.CSQName = #Temp.CSQName
WHERE (CCD.startDateTime > CONVERT(DATETIME, @start, 102)) AND (CCD.startDateTime < CONVERT(DATETIME, @end, 102))
AND Queues.csqname = @queue
UPDATE #temp
SET Abandonded =
(
SELECT COUNT(CQD.sessionSeqNum) AS [Calls Abandonded]
FROM CCD INNER JOIN
CQD ON CCD.sessionID = CQD.sessionID AND CCD.sessionSeqNum = CQD.sessionSeqNum AND CCD.nodeID = CQD.nodeID AND
CCD.profileID = CQD.profileID INNER JOIN
CSQ ON CQD.profileID = CSQ.profileID AND CQD.targetID = CSQ.recordID INNER JOIN
Queues ON CSQ.CSQName = Queues.csqname INNER JOIN #temp on CSQ.CSQName = #Temp.CSQName
WHERE (CQD.targetType = 0) AND (CQD.disposition = 1) AND (CCD.startDateTime > CONVERT(DATETIME, @start, 102)) AND (CCD.startDateTime < CONVERT(DATETIME, @end, 102))
AND Queues.csqname = @queue
)
FROM CCD INNER JOIN
CQD ON CCD.sessionID = CQD.sessionID AND CCD.sessionSeqNum = CQD.sessionSeqNum AND CCD.nodeID = CQD.nodeID AND
CCD.profileID = CQD.profileID INNER JOIN
CSQ ON CQD.profileID = CSQ.profileID AND CQD.targetID = CSQ.recordID INNER JOIN
Queues ON CSQ.CSQName = Queues.csqname INNER JOIN #temp on CSQ.CSQName = #Temp.CSQName
WHERE (CQD.targetType = 0) AND (CQD.disposition = 1) AND (CCD.startDateTime > CONVERT(DATETIME, @start, 102)) AND (CCD.startDateTime < CONVERT(DATETIME, @end, 102))
AND Queues.csqname = @queue
UPDATE #temp
SET Dequeued =
(
SELECT COUNT(CQD.sessionSeqNum) AS [Calls Dequeued]
FROM CCD INNER JOIN
CQD ON CCD.sessionID = CQD.sessionID AND CCD.sessionSeqNum = CQD.sessionSeqNum AND CCD.nodeID = CQD.nodeID AND
CCD.profileID = CQD.profileID INNER JOIN
CSQ ON CQD.profileID = CSQ.profileID AND CQD.targetID = CSQ.recordID INNER JOIN
Queues ON CSQ.CSQName = Queues.csqname INNER JOIN #temp on CSQ.CSQName = #Temp.CSQName
WHERE (CCD.startDateTime > CONVERT(DATETIME, @start, 102)) AND (CCD.startDateTime < CONVERT(DATETIME, @end, 102))
AND (CQD.targetType = 0) AND (CQD.disposition = 3)
AND Queues.csqname = @queue
)
FROM CCD INNER JOIN
CQD ON CCD.sessionID = CQD.sessionID AND CCD.sessionSeqNum = CQD.sessionSeqNum AND CCD.nodeID = CQD.nodeID AND
CCD.profileID = CQD.profileID INNER JOIN
CSQ ON CQD.profileID = CSQ.profileID AND CQD.targetID = CSQ.recordID INNER JOIN
Queues ON CSQ.CSQName = Queues.csqname INNER JOIN #temp on CSQ.CSQName = #Temp.CSQName
WHERE (CCD.startDateTime > CONVERT(DATETIME, @start, 102)) AND (CCD.startDateTime < CONVERT(DATETIME, @end, 102))
AND (CQD.targetType = 0) AND (CQD.disposition = 3)
AND Queues.csqname = @queue
UPDATE #temp
SET AbandondedSLA =
(
SELECT COUNT(CQD.sessionSeqNum) AS [Calls Abandonded SLA]
FROM CCD INNER JOIN
CQD ON CCD.sessionID = CQD.sessionID AND CCD.sessionSeqNum = CQD.sessionSeqNum AND CCD.nodeID = CQD.nodeID AND
CCD.profileID = CQD.profileID INNER JOIN
CSQ ON CQD.profileID = CSQ.profileID AND CQD.targetID = CSQ.recordID INNER JOIN
Queues ON CSQ.CSQName = Queues.csqname INNER JOIN #temp on CSQ.CSQName = #Temp.CSQName
WHERE (CQD.targetType = 0) AND (CQD.disposition = 1) AND (CCD.startDateTime > CONVERT(DATETIME, @start, 102)) AND (CCD.startDateTime < CONVERT(DATETIME, @end, 102))
AND (CQD.metServiceLevel =1)
AND Queues.csqname = @queue
)
FROM CCD INNER JOIN
CQD ON CCD.sessionID = CQD.sessionID AND CCD.sessionSeqNum = CQD.sessionSeqNum AND CCD.nodeID = CQD.nodeID AND
CCD.profileID = CQD.profileID INNER JOIN
CSQ ON CQD.profileID = CSQ.profileID AND CQD.targetID = CSQ.recordID INNER JOIN
Queues ON CSQ.CSQName = Queues.csqname INNER JOIN #temp on CSQ.CSQName = #Temp.CSQName
WHERE (CQD.targetType = 0) AND (CQD.disposition = 1) AND (CCD.startDateTime > CONVERT(DATETIME, @start, 102)) AND (CCD.startDateTime < CONVERT(DATETIME, @end, 102))
AND (CQD.metServiceLevel =1)
AND Queues.csqname = @queue
UPDATE #temp
SET HandledSLA =
(
SELECT COUNT(CQD.targetType) AS [Calls Handled SLA]
FROM ACD INNER JOIN
CCD ON ACD.sessionID = CCD.sessionID AND ACD.sessionSeqNum = CCD.sessionSeqNum AND ACD.nodeID = CCD.nodeID AND
ACD.profileID = CCD.profileID INNER JOIN
CQD ON ACD.sessionID = CQD.sessionID AND ACD.sessionSeqNum = CQD.sessionSeqNum AND ACD.profileID = CQD.profileID AND
ACD.nodeID = CQD.nodeID INNER JOIN
CSQ ON CQD.targetID = CSQ.recordID AND CQD.profileID = CSQ.profileID INNER JOIN
Queues ON CSQ.CSQName = Queues.csqname INNER JOIN #temp on CSQ.CSQName = #Temp.CSQName
WHERE (CCD.startDateTime > CONVERT(DATETIME, @start, 102)) AND (CCD.startDateTime < CONVERT(DATETIME, @end, 102)) AND
(CCD.contactDisposition = 2) AND (ACD.talkTime > 0) AND (CQD.targetType = 0) AND (CQD.disposition = 2) AND (CQD.metServiceLevel = 1)
AND Queues.csqname = @queue
)
FROM ACD INNER JOIN
CCD ON ACD.sessionID = CCD.sessionID AND ACD.sessionSeqNum = CCD.sessionSeqNum AND ACD.nodeID = CCD.nodeID AND
ACD.profileID = CCD.profileID INNER JOIN
CQD ON ACD.sessionID = CQD.sessionID AND ACD.sessionSeqNum = CQD.sessionSeqNum AND ACD.profileID = CQD.profileID AND
ACD.nodeID = CQD.nodeID INNER JOIN
CSQ ON CQD.targetID = CSQ.recordID AND CQD.profileID = CSQ.profileID INNER JOIN
Queues ON CSQ.CSQName = Queues.csqname INNER JOIN #temp on CSQ.CSQName = #Temp.CSQName
WHERE (CCD.startDateTime > CONVERT(DATETIME, @start, 102)) AND (CCD.startDateTime < CONVERT(DATETIME, @end, 102)) AND
(CCD.contactDisposition = 2) AND (ACD.talkTime > 0) AND (CQD.targetType = 0) AND (CQD.disposition = 2) AND (CQD.metServiceLevel = 1)
AND Queues.csqname = @queue
UPDATE #temp
SET AvgTalkTime =
(
SELECT (SUM(CQD.queueTime)/Count(CQD.queueTime)) AS [AverageQueueTime]
FROM CCD INNER JOIN
CQD ON CCD.sessionID = CQD.sessionID AND CCD.sessionSeqNum = CQD.sessionSeqNum AND CCD.nodeID = CQD.nodeID AND
CCD.profileID = CQD.profileID INNER JOIN
CSQ ON CQD.targetID = CSQ.recordID AND CQD.profileID = CSQ.profileID INNER JOIN
Queues ON CSQ.CSQName = Queues.csqname INNER JOIN #temp on CSQ.CSQName = #Temp.CSQName
WHERE (CQD.targetType = 0) AND (CCD.startDateTime > CONVERT(DATETIME, @start, 102)) AND (CCD.startDateTime < CONVERT(DATETIME, @end, 102)) AND Queues.csqname = @queue
)
FROM CCD INNER JOIN
CQD ON CCD.sessionID = CQD.sessionID AND CCD.sessionSeqNum = CQD.sessionSeqNum AND CCD.nodeID = CQD.nodeID AND
CCD.profileID = CQD.profileID INNER JOIN
CSQ ON CQD.targetID = CSQ.recordID AND CQD.profileID = CSQ.profileID INNER JOIN
Queues ON CSQ.CSQName = Queues.csqname INNER JOIN #temp on CSQ.CSQName = #Temp.CSQName
WHERE (CQD.targetType = 0) AND (CCD.startDateTime > CONVERT(DATETIME, @start, 102)) AND (CCD.startDateTime < CONVERT(DATETIME, @end, 102)) AND Queues.csqname = @queue
UPDATE #temp
SET AvgWaitTime =
(
SELECT (SUM(ACD.talkTime) / COUNT(CQD.targetType)) AS [AverageTalkTime]
FROM ACD INNER JOIN
CCD ON ACD.sessionID = CCD.sessionID AND ACD.sessionSeqNum = CCD.sessionSeqNum AND ACD.nodeID = CCD.nodeID AND
ACD.profileID = CCD.profileID INNER JOIN
CQD ON ACD.sessionID = CQD.sessionID AND ACD.sessionSeqNum = CQD.sessionSeqNum AND ACD.profileID = CQD.profileID AND
ACD.nodeID = CQD.nodeID INNER JOIN
CSQ ON CQD.targetID = CSQ.recordID AND CQD.profileID = CSQ.profileID INNER JOIN
Queues ON CSQ.CSQName = Queues.csqname INNER JOIN #temp on CSQ.CSQName = #Temp.CSQName
WHERE (CCD.startDateTime > CONVERT(DATETIME, @start, 102)) AND (CCD.startDateTime < CONVERT(DATETIME, @end, 102)) AND
(CCD.contactDisposition = 2) AND (ACD.talkTime > 0) AND (CQD.targetType = 0) AND (CQD.disposition = 2)
AND Queues.csqname = @queue
)
FROM ACD INNER JOIN
CCD ON ACD.sessionID = CCD.sessionID AND ACD.sessionSeqNum = CCD.sessionSeqNum AND ACD.nodeID = CCD.nodeID AND
ACD.profileID = CCD.profileID INNER JOIN
CQD ON ACD.sessionID = CQD.sessionID AND ACD.sessionSeqNum = CQD.sessionSeqNum AND ACD.profileID = CQD.profileID AND
ACD.nodeID = CQD.nodeID INNER JOIN
CSQ ON CQD.targetID = CSQ.recordID AND CQD.profileID = CSQ.profileID INNER JOIN
Queues ON CSQ.CSQName = Queues.csqname INNER JOIN #temp on CSQ.CSQName = #Temp.CSQName
WHERE (CCD.startDateTime > CONVERT(DATETIME, @start, 102)) AND (CCD.startDateTime < CONVERT(DATETIME, @end, 102)) AND
(CCD.contactDisposition = 2) AND (ACD.talkTime > 0) AND (CQD.targetType = 0) AND (CQD.disposition = 2)
AND Queues.csqname = @queue
INSERT INTO [db_cra].[dbo].[CallData]
([CSQName]
,[Presented]
,[Handled]
,[Abandonded]
,[Dequeued]
,[HandledSLA]
,[AbandondedSLA]
,[AvgTalkTime]
,[AvgWaitTime]
,[Date])
SELECT * FROM #Temp
END
Комментарии:
1. Содержат ли журналы SQL Server или сообщение об ошибке какие-либо дополнительные сведения? например, ошибка утверждения или что-то в этомроде.
2. Не по теме вопроса, но корректен ли этот бит
OR (dateInactive < GETDATE() - 1))
(при первоначальном заполнении#Temp
), учитывая, что все остальное имеет дело с переданным параметром @date.3. Здесь нужно переписать так много битов, что я не знаю, с чего начать. Например, если
@starttime
это, как следует из названия, просто время (с датой, заданной по умолчанию19000101
), то@start
это время добавляется к дате, переданной как@date
. Но везде, где она@start
используется, она находится внутриCONVERT
функции, которая собирается удалить компонент time. Идентичные повторяющиеся запросы (один вSET
, другой вFROM
) не должны быть необходимыми. Почти идентичные запросы должны быть заменены наCOUNT(CASE WHEN Conditiion1 is true THEN 1 ELSE 0 END)
и т.д.4. @Damien_The_Unbeliever — спасибо за это. Следует использовать параметр, а не getdate()-1.
5. @Damien_The_Unbeliever — Кроме того, я в значительной степени новичок в SQL, так что это первый, хотя и сложный процесс для получения нужных мне данных. Я работал с консультантом shudder , чтобы получить повторяющийся НАБОР ИЗ stuff working, поскольку изначально я подписывал группу by. Я не совсем уверен, что вы имеете в виду, говоря о почти идентичных запросах? В любом случае, я думаю, что один из сетевых разработчиков собирается исправить кластер 🙂 но я все равно хотел бы в конечном итоге переписать это!