javascript - 请求错误: must declare scalar variable in complex MSSQL query

标签 javascript sql node.js sql-server

我们正在尝试通过 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/

相关文章:

Java DBUnit AmbigouslyTableNameException 错误抛出

javascript - 代码在 chrome 控制台中工作但不在页面中

javascript - 测试JQuery的 "on"方法触发回调函数

javascript - 如何防止AngularJS中的元素触发容器中的ng-click

javascript - 自动写入输入

Mysql 多表请求

sql - Linq to SQL "not like"运算符

javascript - 脚本有效但不适用于 node.js

Node.js Express-Session 代理选项有什么作用?

javascript - 未处理的 JS 异常 : Requiring unknown module "9"