我有一个模板,可用于所有通过电子邮件发送的数据库邮件作业,但我偶然发现了最新的一个问题,该问题是由于使用变量而引起的,下面是代码:
SET QUOTED_IDENTIFIER ON
DECLARE @CODE NVARCHAR(MAX),
@CODE_ROW_COUNT INT,
@s VARCHAR(MAX),
@WorkI NVARCHAR(MAX),
@WorkC NVARCHAR(MAX),
@DailyMin INT
SET @s = 'Daily Cutting Schedule for ' + DATENAME(dw, GETDATE()) + ', ' + CONVERT(VARCHAR(12),GETDATE(),107)
IF OBJECT_ID('tempdb..##DailyCutSched') IS NOT NULL
BEGIN
DROP TABLE ##DailyCutSched
END
SET @WorkI = '100'
IF @WorkI = '100'
BEGIN
SET @WorkC = 'Cutting'
END
IF @WorkI = '125'
BEGIN
SET @WorkC = 'Framing'
END
IF @WorkI = '150'
BEGIN
SET @WorkC = 'Assembly'
END
IF @WorkI = '200'
BEGIN
SET @WorkC = 'Grinding'
END
IF @WorkI = '350'
BEGIN
SET @WorkC = 'Painting'
END
IF @WorkI = '400'
BEGIN
SET @WorkC = 'Glazing'
END
IF @WorkI = '450'
BEGIN
SET @WorkC = 'Locknprep'
END
IF @WorkI = '500'
BEGIN
SET @WorkC = 'Packaging'
END;
SET @DailyMin =
(SELECT
w.CapacityFactor*(w.UtilizationPct/100)*7.67*60 AS [Units]
FROM WorkCntr w
WHERE w.WorkCntr = @WorkI);
WITH CTE AS
(
SELECT TOP 10000
ds.WorkCntr,
ds.JobNo,
r.PartNo,
r.StepNo AS [Step],
CAST(o.PartDesc AS NVARCHAR(MAX)) AS [Description],
r.CycleTime*o.QtyOrdered AS [Estimate],
SUM(r.CycleTime*o.QtyOrdered) OVER (PARTITION BY ds.WorkCntr
ORDER BY o.Priority DESC,
CAST(SUBSTRING(r.PartNo, CHARINDEX('.',r.PartNo)+1, CHARINDEX('.',r.PartNo+'.',CHARINDEX('.',r.PartNo)+1) - CHARINDEX('.',r.PartNo)-1) as INT),
r.PartNo) AS [CumulativeMinutes],
o.Priority
FROM
Scheduling ds
JOIN dbo.OrderRouting r ON ds.JobNo = r.JobNo AND ds.WorkCntr = @WorkC
JOIN dbo.OrderDet o ON ds.JobNo = o.JobNo
LEFT JOIN dbo.TimeTicketDet t ON ds.JobNo = t.JobNo AND t.WorkCntr = @WorkI
WHERE
r.WorkCntr = @WorkC
AND r.OrderNo NOT IN ('44444', '77777')
GROUP BY ds.WorkCntr, ds.JobNo, r.PartNo, r.StepNo, CAST(o.PartDesc AS NVARCHAR(MAX)), r.CycleTime, o.QtyOrdered, o.Priority
ORDER BY o.Priority DESC, CAST(SUBSTRING(r.PartNo, CHARINDEX('.',r.PartNo)+1, CHARINDEX('.',r.PartNo+'.',CHARINDEX('.',r.PartNo)+1) - CHARINDEX('.',r.PartNo)-1) as INT), r.PartNo
),
CTE2 AS(
SELECT
c.WorkCntr,
c.JobNo,
CAST(SUBSTRING(c.PartNo, CHARINDEX('.',c.PartNo)+1, CHARINDEX('.',c.PartNo+'.',CHARINDEX('.',c.PartNo)+1) - CHARINDEX('.',c.PartNo)-1) as INT) AS [ItemNo],
c.PartNo,
c.Step,
c.Description,
c.Estimate,
c.Priority
FROM CTE c
WHERE CumulativeMinutes < @DailyMin
UNION
SELECT TOP 1
c.WorkCntr,
c.JobNo,
CAST(SUBSTRING(c.PartNo, CHARINDEX('.',c.PartNo)+1, CHARINDEX('.',c.PartNo+'.',CHARINDEX('.',c.PartNo)+1) - CHARINDEX('.',c.PartNo)-1) as INT) AS [ItemNo],
c.PartNo,
c.Step,
c.Description,
c.Estimate,
c.Priority
FROM CTE c
WHERE CumulativeMinutes > @DailyMin
ORDER BY c.Priority DESC, CAST(SUBSTRING(c.PartNo, CHARINDEX('.',c.PartNo)+1, CHARINDEX('.',c.PartNo+'.',CHARINDEX('.',c.PartNo)+1) - CHARINDEX('.',c.PartNo)-1) as INT)
)
SELECT
c2.WorkCntr,
c2.JobNo,
c2.PartNo,
c2.Step,
c2.Description,
c2.Estimate
INTO ##DailyCutSched
FROM CTE2 c2
ORDER BY c2.Priority DESC, CAST(SUBSTRING(c2.PartNo, CHARINDEX('.',c2.PartNo)+1, CHARINDEX('.',c2.PartNo+'.',CHARINDEX('.',c2.PartNo)+1) - CHARINDEX('.',c2.PartNo)-1) as INT), c2.PartNo
SELECT @CODE_ROW_COUNT = @@ROWCOUNT
IF(@CODE_ROW_COUNT > 0)
BEGIN
SET @CODE =
N'
DECLARE @WorkI NVARCHAR(MAX) = ''100''
DECLARE @WorkC NVARCHAR(MAX)
DECLARE @DailyMin INT
IF @WorkI = ''100''
BEGIN
SET @WorkC = ''Cutting''
END
IF @WorkI = ''125''
BEGIN
SET @WorkC = ''Framing''
END
IF @WorkI = ''150''
BEGIN
SET @WorkC = ''Assembly''
END
IF @WorkI = ''200''
BEGIN
SET @WorkC = ''Grinding''
END
IF @WorkI = ''350''
BEGIN
SET @WorkC = ''Painting''
END
IF @WorkI = ''400''
BEGIN
SET @WorkC = ''Glazing''
END
IF @WorkI = ''450''
BEGIN
SET @WorkC = ''Locknprep''
END
IF @WorkI = ''500''
BEGIN
SET @WorkC = ''Packaging''
END;
SET @DailyMin =
(SELECT
w.CapacityFactor*(w.UtilizationPct/100)*7.67*60 AS [Units]
FROM WorkCntr w
WHERE w.WorkCntr = @WorkI);
WITH CTE AS
(
SELECT TOP 10000
ds.WorkCntr,
ds.JobNo,
r.PartNo,
r.StepNo AS [Step],
CAST(o.PartDesc AS NVARCHAR(MAX)) AS [Description],
r.CycleTime*o.QtyOrdered AS [Estimate],
SUM(r.CycleTime*o.QtyOrdered) OVER (PARTITION BY ds.WorkCntr
ORDER BY o.Priority DESC,
CAST(SUBSTRING(r.PartNo, CHARINDEX(''.'',r.PartNo)+1, CHARINDEX(''.'',r.PartNo+''.'',CHARINDEX(''.'',r.PartNo)+1) - CHARINDEX(''.'',r.PartNo)-1) as INT),
r.PartNo) AS [CumulativeMinutes],
o.Priority
FROM
Scheduling ds
JOIN dbo.OrderRouting r ON ds.JobNo = r.JobNo AND ds.WorkCntr = @WorkC
JOIN dbo.OrderDet o ON ds.JobNo = o.JobNo
LEFT JOIN dbo.TimeTicketDet t ON ds.JobNo = t.JobNo AND t.WorkCntr = @WorkI
WHERE
r.WorkCntr = @WorkC
AND r.OrderNo NOT IN (''44444'', ''77777'')
GROUP BY ds.WorkCntr, ds.JobNo, r.PartNo, r.StepNo, CAST(o.PartDesc AS NVARCHAR(MAX)), r.CycleTime, o.QtyOrdered, o.Priority
ORDER BY o.Priority DESC, CAST(SUBSTRING(r.PartNo, CHARINDEX(''.'',r.PartNo)+1, CHARINDEX(''.'',r.PartNo+''.'',CHARINDEX(''.'',r.PartNo)+1) - CHARINDEX(''.'',r.PartNo)-1) as INT), r.PartNo
),
CTE2 AS(
SELECT
c.WorkCntr,
c.JobNo,
CAST(SUBSTRING(c.PartNo, CHARINDEX(''.'',c.PartNo)+1, CHARINDEX(''.'',c.PartNo+''.'',CHARINDEX(''.'',c.PartNo)+1) - CHARINDEX(''.'',c.PartNo)-1) as INT) AS [ItemNo],
c.PartNo,
c.Step,
c.Description,
c.Estimate,
c.Priority
FROM CTE c
WHERE CumulativeMinutes < @DailyMin
UNION
SELECT TOP 1
c.WorkCntr,
c.JobNo,
CAST(SUBSTRING(c.PartNo, CHARINDEX(''.'',c.PartNo)+1, CHARINDEX(''.'',c.PartNo+''.'',CHARINDEX(''.'',c.PartNo)+1) - CHARINDEX(''.'',c.PartNo)-1) as INT) AS [ItemNo],
c.PartNo,
c.Step,
c.Description,
c.Estimate,
c.Priority
FROM CTE c
WHERE CumulativeMinutes > @DailyMin
ORDER BY c.Priority DESC, CAST(SUBSTRING(c.PartNo, CHARINDEX(''.'',c.PartNo)+1, CHARINDEX(''.'',c.PartNo+''.'',CHARINDEX(''.'',c.PartNo)+1) - CHARINDEX(''.'',c.PartNo)-1) as INT)
)
SELECT
c2.WorkCntr,
c2.JobNo,
c2.PartNo,
c2.Step,
c2.Description,
c2.Estimate
FROM CTE2 c2
ORDER BY c2.Priority DESC, CAST(SUBSTRING(c2.PartNo, CHARINDEX(''.'',c2.PartNo)+1, CHARINDEX(''.'',c2.PartNo+''.'',CHARINDEX(''.'',c2.PartNo)+1) - CHARINDEX(''.'',c2.PartNo)-1) as INT), c2.PartNo'
DECLARE @html nvarchar(MAX);
EXEC spQueryToHtmlTable
@html = @html OUTPUT,
@query = @CODE
EXEC msdb.dbo.sp_send_dbmail
@profile_name = 'Sample Company',
@recipients = 'abc@fakecompany.com',
@subject = @s,
@body = @html,
@body_format = 'HTML',
@query_no_truncate = 1,
@attach_query_result_as_file = 0,
@execute_query_database = 'Database1';
END
IF OBJECT_ID('tempdb..##DailyCutSched') IS NOT NULL
BEGIN
DROP TABLE ##DailyCutSched
END
因此,这段代码基本上是在运行查询,如果行数大于0,则执行第二部分,并且收件人列表中的电子邮件会收到一封电子邮件。现在我知道第一部分没有问题,因为我已经测试过了,问题出在以下的BEGIN语句上:
SELECT @CODE_ROW_COUNT = @@ROWCOUNT
IF(@CODE_ROW_COUNT > 0)
我读到动态部分有它自己的作用域,所以我只是尝试在那里声明所有变量,但是我不断收到语法错误,不确定如何继续。我不知道我是否有一个简单的语法错误,或者是否必须执行某种解决方法才能使其正常工作。感谢您的帮助,谢谢
编辑:这是我遇到的错误:
第156条消息,第15级,状态1,第6行 关键字“ DECLARE”附近的语法不正确。 讯息102,第15级,州1,第114行 ')'附近的语法不正确。
答案 0 :(得分:1)
在动态SQL之前的代码的最后一部分,您正在将最终结果选择到全局临时文件中。
SELECT
c2.WorkCntr,
c2.JobNo,
c2.PartNo,
c2.Step,
c2.Description,
c2.Estimate
INTO ##DailyCutSched
FROM CTE2 c2
ORDER BY c2.Priority DESC, CAST(SUBSTRING(c2.PartNo, CHARINDEX('.',c2.PartNo)+1, CHARINDEX('.',c2.PartNo+'.',CHARINDEX('.',c2.PartNo)+1) - CHARINDEX('.',c2.PartNo)-1) as INT), c2.PartNo
这样做之后,您只需将@code
更改为临时表中的查询结果即可,而不必重复并再次查询每个表。
SET @CODE =
N'SELECT
c2.WorkCntr,
c2.JobNo,
c2.PartNo,
c2.Step,
c2.Description,
c2.Estimate
FROM ##DailyCutSched c2'