为什么我需要声明变量两次:在动态查询中和不在动态查询中?
Why do I need to declare variables twice: within and without the dynamic query?
我正在将现有静态查询改造成动态查询。为什么我需要声明变量两次?一次位于文件顶部(用于后续不变的查询),一次位于动态 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/ 来转换动态查询
答案在这里找到:
;
我需要在执行阶段声明额外的变量。
EXECUTE sp_executesql @sql, N'@TeamCodeDynamic nvarchar(50), @OffsetDynamic INT, @LimitDynamic INT', @TeamCodeDynamic = @TeamCode, @OffsetDynamic = @Offset, @LimitDynamic = @Limit;
出于同样的原因:
- 在存储过程中声明了一个变量
- 该过程调用第二个过程
- 在第一个过程中声明的变量在第二个过程中不可访问。
换句话说:范围。动态代码作为它自己的批处理、进程、会话...执行,对不起,我不知道 SQL.
使用的确切技术术语
查看 sp_ExecuteSQL 对参数的支持。它繁琐而复杂,但允许您将参数值传递到(和传出!)您的动态 SQL.
我正在将现有静态查询改造成动态查询。为什么我需要声明变量两次?一次位于文件顶部(用于后续不变的查询),一次位于动态 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/ 来转换动态查询
答案在这里找到:
EXECUTE sp_executesql @sql, N'@TeamCodeDynamic nvarchar(50), @OffsetDynamic INT, @LimitDynamic INT', @TeamCodeDynamic = @TeamCode, @OffsetDynamic = @Offset, @LimitDynamic = @Limit;
出于同样的原因:
- 在存储过程中声明了一个变量
- 该过程调用第二个过程
- 在第一个过程中声明的变量在第二个过程中不可访问。
换句话说:范围。动态代码作为它自己的批处理、进程、会话...执行,对不起,我不知道 SQL.
使用的确切技术术语查看 sp_ExecuteSQL 对参数的支持。它繁琐而复杂,但允许您将参数值传递到(和传出!)您的动态 SQL.