我们正在尝试通过 Node JS 运行以下 MSSQL 查询:
--CREATE PROCEDURE SPTatTimeTable
--AS
--START: Takes Query And Creates MetricsTable Variable Table--
SET NOCOUNT ON
DECLARE @MetricTable Table
(
[NoteCreatedDate] DATETIME,
[ServiceRequestNumber] BIGINT,
[WorkOrderNumber] INT,
[ActionEvent] VARCHAR(50)
)
INSERT INTO @MetricTable
--START: Solidifies Query into Table for MetricsTable--
SELECT MetricsTable.[NoteCreatedDate]
,MetricsTable.[ServiceRequestNumber]
,MetricsTable.[WorkOrderNumber]
,MetricsTable.[ActionEvent]
--START: Query To Pull All Customer Notes From Last 3Months And Assign Generic Codes(ActionEvent)--
FROM ( SELECT UN.created_date AS [NoteCreatedDate]
,WO.po_sr AS [ServiceRequestNumber]
,WO.work_order_id AS [WorkOrderNumber]
,CASE WHEN UN.note_description = 'Work Order Created' THEN 'Work Order Created'
WHEN UN.note_description = 'Generated Confirmation Email' OR un.note_description LIKE '%Generated Confirmation Email' THEN 'Replacement Confirmed'
WHEN UN.note_description LIKE '%Replacement Ordered%' OR un.note_description LIKE '%Replacement Ordered – ETA Date:%' THEN 'Replacement Ordered'
WHEN UN.note_description LIKE 'Closed Work Order: Escalated%' THEN 'Escalated'
Else 'Inserted Note'
END AS [ActionEvent]
FROM CRM.CRM.work_order WO
LEFT JOIN crm.crm.user_note UN ON WO.id = UN.work_order_id
WHERE WO.work_order_id IN ( SELECT work_order_id
FROM [CRM].[CRM].[work_order]
WHERE created_date >= '2019-01-01 00:00:000' AND wo_status_code = 'CLSD' AND wo_sub_status_code = 'SHP' AND rma = 0 AND dealer = 'ATT ASURION')
--END: Query To Pull All Customer Notes From Last 3Months And Assign Generic Codes(Events)--
) AS [MetricsTable]
--END: Solidifies Query into Table for MetricsTable--
--END: Takes Query And Creates MetricsTable Variable Table--
WHERE MetricsTable.[ActionEvent] NOT IN ('Inserted Note')
DECLARE @TatTimeTable Table
(
ID INT IDENTITY(1,1) PRIMARY KEY,
ServiceRequestNumber BIGINT,
WorkOrderNumber INT DEFAULT(-1),
WorkOrderType VARCHAR(50),
WorkOrderCreated DATETIME,
ConfirmedStart DATETIME,
OrderedStart DATETIME,
WorkOrderStop DATETIME,
LastEvent VARCHAR(50)
)
--START: Cursor Variables--
DECLARE @NoteCreated DATETIME;
DECLARE @ServiceRequestNumber BIGINT;
DECLARE @WorkOrderNumber INT;
DECLARE @ActionEvent VARCHAR(50);
--END: Cursor Variables--
--START: Variables--
DECLARE @ID INT;
DECLARE @LastWorkOrder INT;
SET @LastWorkOrder = -1;
DECLARE @WorkOrderStart DATETIME;
DECLARE @LastNoteDate DATETIME;
DECLARE @LastEvent VARCHAR(50);
--END: Variables--
--END: Creates TatTimeTable Variable Table--
--START: TatTime Cursor--
DECLARE TatTimeCursor Cursor
FOR SELECT t.[NoteCreatedDate]
,t.[ServiceRequestNumber]
,t.[WorkOrderNumber]
,t.[ActionEvent]
FROM @MetricTable t
ORDER BY t.[WorkOrderNumber],t.[NoteCreatedDate]
OPEN TatTimeCursor;
FETCH NEXT FROM TatTimeCursor
INTO @NoteCreated, @ServiceRequestNumber, @WorkOrderNumber, @ActionEvent;
While @@Fetch_Status = 0
BEGIN
IF @WorkOrderNumber != @LastWorkOrder and @LastWorkOrder != -1 --Only Runs When the WorkOrder is First Inserted Into Cursor
BEGIN
UPDATE @TatTimeTable
SET LastEvent = @LastEvent
WHERE ID = @ID;
UPDATE @TatTimeTable
SET WorkOrderStop = @LastNoteDate
WHERE WorkOrderNumber = @LastWorkOrder;
END
SET @LastWorkOrder = @WorkOrderNumber;
SET @LastNoteDate = @NoteCreated;
SET @LastEvent = @ActionEvent;
IF @ActionEvent = 'Work Order Created'
BEGIN
SET @WorkOrderStart = @NoteCreated
INSERT INTO @TatTimeTable (ServiceRequestNumber,WorkOrderNumber,WorkOrderType,WorkOrderCreated) VALUES (@ServiceRequestNumber,@WorkOrderNumber,'WorkOrder',@NoteCreated)
SET @ID = @@IDENTITY;
END
FETCH NEXT FROM TatTimeCursor
INTO @NoteCreated, @ServiceRequestNumber, @WorkOrderNumber, @ActionEvent;
END
CLOSE TatTimeCursor
DEALLOCATE TatTimeCursor
UPDATE @TatTimeTable
SET LastEvent = @LastEvent
WHERE ID = @ID;
UPDATE @TatTimeTable
SET WorkOrderStop = @LastNoteDate
WHERE WorkOrderNumber = @LastWorkOrder;
--END: TatTime Cursor--
USE CRM
SELECT
'Universal Pictures' AS [Client]
,'Talent Scouts' AS [Program]
,crm.getMHDWorkDays(WorkOrderCreated,WorkOrderStop) AS [Opened-Closed TAT]
,CASE WHEN crm.getMHDWorkDays(WorkOrderCreated,WorkOrderStop) <= 3 THEN '0-3 Days'
WHEN crm.getMHDWorkDays(WorkOrderCreated,WorkOrderStop) > 3 AND crm.getMHDWorkDays(WorkOrderCreated,WorkOrderStop) <= 5 THEN '4-5 Days'
WHEN crm.getMHDWorkDays(WorkOrderCreated,WorkOrderStop) > 5 AND crm.getMHDWorkDays(WorkOrderCreated,WorkOrderStop) <= 8 THEN '6-8 Days'
ELSE '+9 Days'
END AS [Opened-Closed TAT Group]
,CASE WHEN ConfirmedStart IS NULL THEN crm.getMHDWorkDays(OrderedStart,WorkOrderStop)
ELSE crm.getMHDWorkDays(ConfirmedStart,WorkOrderStop)
END AS [Confirmed/Ordered-Shipped TAT]
,CASE WHEN ConfirmedStart IS NULL THEN (CASE WHEN crm.getMHDWorkDays(OrderedStart,WorkOrderStop) <= 3 THEN '0-3 Days'
WHEN crm.getMHDWorkDays(OrderedStart,WorkOrderStop) > 3 AND crm.getMHDWorkDays(OrderedStart,WorkOrderStop) <= 5 THEN '4-5 Days'
WHEN crm.getMHDWorkDays(OrderedStart,WorkOrderStop) > 5 AND crm.getMHDWorkDays(OrderedStart,WorkOrderStop) <= 8 THEN '6-8 Days'
ELSE '+9 Days'
END)
ELSE (CASE WHEN crm.crm.getMHDWorkDays(ConfirmedStart,WorkOrderStop) <= 3 THEN '0-3 Days'
WHEN crm.getMHDWorkDays(ConfirmedStart,WorkOrderStop) > 3 AND crm.getMHDWorkDays(ConfirmedStart,WorkOrderStop) <= 5 THEN '4-5 Days'
WHEN crm.getMHDWorkDays(ConfirmedStart,WorkOrderStop) > 5 AND crm.getMHDWorkDays(ConfirmedStart,WorkOrderStop) <= 8 THEN '6-8 Days'
ELSE '+9 Days'
END)
END AS [Confirmed/Ordered-Shipped TAT Group]
FROM crm.work_order wo
LEFT OUTER JOIN @TatTimeTable ON wo.work_order_id = @TatTimeTable.WorkOrderNumber
基本上,我们创建一些临时表和变量,包括。 @TatTimeTable,我们将其加入到用于输出数据表的主要(底部)选择查询中的永久表。然而,当我们尝试运行我们的脚本时,Node.JS 抛出异常:
RequestError: Must declare the scalar variable "@TatTimeTable".
尽管@TatTimeTable 似乎已正确声明。该错误由最后一个 LEFT OUTER JOIN 行触发。 (我们通过注释掉它来计算)。这是怎么回事?我们需要在运行主查询之前创建该临时表。
最佳答案
与临时表 (#) 不同,SQL 服务器不允许表变量 (@) 本身在访问其列时用作 别名
,即使是在简单的 SELECT
声明。
此外,错误与 USE
语句无关,因为它是 SQL 批处理中的有效语句(但如果您打算这样做,则不能在存储过程中使用它 --在这种情况下,请按照其他人的建议使用由 3 部分组成的名称)
您可以尝试以下示例并通过启用/禁用标记为 UNCOMMENT & TRY
的部分来亲眼看看。您也可以改为阅读代码中的注释。
USE tempdb;
CREATE TABLE RealTable --- yes, you can have real tables in tempdb. they disappear after SQL server restarted
(
[Col1] INT,
[Col2] INT
);
INSERT INTO RealTable
VALUES (1, 1), (1,2)
SELECT *
INTO #TempTable --- this time actual temp table (#)
FROM RealTable;
DECLARE @tableVar Table --- and a table variable (@)
(
[Col1] INT,
[Col2] INT
);
INSERT INTO @tableVar
SELECT *
FROM RealTable;
-- USE master; ---- UNCOMMENT & TRY: switching to another database does not cause this error. try it with enabling this
SELECT *
FROM
tempdb..RealTable t
INNER JOIN #TempTable ON #TempTable.Col1 = t.Col1 ---- temp tables (#) works without an alias
INNER JOIN @tableVar tv ON tv.Col1 = t.Col1 ---- table variables (@) works ONLY with an alias
-- INNER JOIN @tableVar ON @tableVar.Col1 = t.Col1 ---- UNCOMMENT & TRY: without an alias, table variables (@) will give error: Must declare the scalar variable "@tableVar".
--- The intellisense in SSMS does NOT work in this case and also, the linter shows red squiggly lines on @tableVar, showing the same error
-- SELECT * FROM @tableVar WHERE @tableVar.Col1 = 1 ---- UNCOMMENT & TRY: Even this simple SELECT statement gives the same error. So it's not about the JOIN. It's about using table variable itself as the alias
--- The same result with the intellisense and the linter as above
/*
---- ENABLE THIS SECTION TO RETRY or CLEAN-UP
---- ONLY if you're sure no such tables already exist in your tempdb for another reason (better safe than sorry)
---- drop tables if exist
IF OBJECT_ID('tempdb..RealTable', 'U') IS NOT NULL
DROP TABLE tempdb..RealTable
IF OBJECT_ID('tempdb..#TempTable', 'U') IS NOT NULL
DROP TABLE #TempTable
*/
关于javascript - 请求错误: must declare scalar variable in complex MSSQL query,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63308801/