0

我正在将现有的静态查询改造成动态的。为什么我需要两次声明变量?一次位于文件顶部(用于后续的不变查询),再次位于动态 SQL 语句中。这与动态 SQL 的行为方式有关吗?

我的代码是这样的:

DECLARE @columns NVARCHAR(MAX) = ''
DECLARE @sql     NVARCHAR(MAX) = ''
DECLARE @Offset int = 0
DECLARE @Limit int = 10
DECLARE @TeamCode NVARCHAR(50) = 'Team1'

SELECT 
    @columns+=QUOTENAME(status_name) + ','
FROM 
    my_db.job_statuses
ORDER BY 
    id;

-- remove the last comma
SET @columns = LEFT(@columns, LEN(@columns) - 1);

-- construct dynamic SQL
SET @sql ='
DECLARE @Offset int = 0
DECLARE @Limit int = 10
DECLARE @TeamCode NVARCHAR(50) = ''Team1''
SELECT P.*, TSC.TOTAL_STATUS_COUNT FROM 
(
    SELECT * FROM   
    (
        SELECT 
            EJI.planning_item_id,
            S.status_name
        FROM my_db.jobs J
        INNER JOIN my_db.job_statuses S ON J.status = S.ID
        INNER JOIN my_db.extra_job_information EJI ON EJI.job_id = J.job_id
        WHERE (@TeamCode IS NULL OR ASSIGNED_TO LIKE @TeamCode)
        AND (Planning_item_id IS NOT NULL)
        GROUP BY status_name, planning_item_id, J.job_id 
    ) T 

    PIVOT(
        COUNT(status_name) 
        FOR status_name IN ('+ @COLUMNS +')
    ) AS PIVOT_TABLE
    ORDER BY planning_item_id
    OFFSET @Offset ROWS FETCH NEXT @Limit ROWS ONLY
    
) P
INNER JOIN
(
    SELECT
        EJI.planning_item_id,
        COUNT(J.status) TOTAL_STATUS_COUNT
    FROM my_db.extra_job_information EJI
    INNER JOIN my_db.jobs J ON J.JOB_ID = EJI.JOB_ID 
    WHERE (@TeamCode IS NULL OR ASSIGNED_TO LIKE @TeamCode)
    AND (Planning_item_id IS NOT NULL)
    GROUP BY planning_item_id
) TSC ON TSC.planning_item_id = P.planning_item_id';

-- execute the dynamic SQL
EXECUTE sp_executesql @sql;

仅供参考,我只有“my_db”的读取权限。
我使用https://www.sqlservertutorial.net/sql-server-basics/sql-server-pivot/来透视动态查询

4

2 回答 2

0

答案在这里找到: https ://stackoverflow.com/a/49191777/11534833 ;我需要在执行阶段声明额外的变量。
EXECUTE sp_executesql @sql, N'@TeamCodeDynamic nvarchar(50), @OffsetDynamic INT, @LimitDynamic INT', @TeamCodeDynamic = @TeamCode, @OffsetDynamic = @Offset, @LimitDynamic = @Limit;

于 2020-09-09T14:46:53.527 回答
0

出于同样的原因:

  • 在存储过程中声明变量
  • 该过程调用第二个过程
  • 在第一个过程中声明的变量在第二个过程中不可访问。

换句话说:范围。动态代码是作为它自己的批处理、进程、会话...执行的,很抱歉,但我不知道 SQL 使用的确切技术术语。

查看 sp_ExecuteSQL 对参数的支持。它既繁琐又复杂,但允许您将参数值传入(和传出!)动态 SQL。

于 2020-09-09T14:54:48.380 回答