第一次发布海报,长期粉丝。 我已经查看了关于这个主题的所有其他答案,找不到任何解决问题的方法。
我有一些SQL,它使用动态数据透视区域返回一个资格矩阵。我有正确的代码,带回所有行,但现在我想使用过滤器。
错误代码位于WHERE子句中:T3.TrainingTypeID = ' + @TrainingID + '
如果我硬编码T3.TrainingTypeID
的值(这是tlkpTrainingType.ID
的别名),(200,比如说),我会返回一行,这就是我想要的但是如果我将相同的值分配给变量@TrainingID INT
,我收到上面的错误信息。
我检查了tlkpTrainingType.ID
的数据类型,它绝对是INT(并且Select Max(Len(TlkpTrainingType.ID)) From TlkpTrainingType
返回3)。
我不确定我是否理解触发器,但考虑到我只是从数据库中读取,我认为它与此处无关?
我错过了一些完全明显的东西吗? 所有的见解都很受欢迎,我是一个相对新手!
这是我的代码,相关的WHERE子句在底部附近:
DECLARE @TrainingID AS INT, @cols AS NVARCHAR(MAX), @cols2 AS NVARCHAR(MAX), @cols3 AS NVARCHAR(MAX), @query AS NVARCHAR(MAX)
SET @cols = STUFF((SELECT distinct ',' + QUOTENAME(tlkpRegion.RegionName)
FROM tlkpRegion FOR XML PATH(''), TYPE ).value('.', 'NVARCHAR(MAX)')
,1,1,'');
SET @cols2 = STUFF((SELECT distinct ', ISNULL(' + QUOTENAME(tlkpRegion.RegionName) + ',0) as' + QUOTENAME(tlkpRegion.RegionName) FROM tlkpRegion FOR XML PATH(''), TYPE ).value('.', 'NVARCHAR(MAX)')
,1,1,'');
SET @cols3 = STUFF((SELECT distinct ', SUM(' + QUOTENAME(tlkpRegion.RegionName) + ') as ' + QUOTENAME(tlkpRegion.RegionName) FROM tlkpRegion FOR XML PATH(''), TYPE ).value('.', 'NVARCHAR(MAX)')
,1,1,'');
SET @TrainingID = 200;
SET @query = '
SELECT
T3.TrainingType,
T3.TrainingTypeID,
' + @cols3 + '
FROM
(SELECT
tlkpTrainingType.Name AS TrainingType,
tlkpTrainingType.ID AS TrainingTypeID, ' + @cols2 + '
FROM
tlkpTrainingType
LEFT OUTER JOIN
(SELECT
TrainingType,
TrainingTypeID, ' + @cols + '
FROM
(SELECT
R0.RegionID,
R0.RegionName,
T0.TrainingType,
T0.TrainingTypeID,
T0.CountQuals
FROM
tlkpRegion AS R0
LEFT OUTER JOIN
(SELECT
tlkpTrainingType.Name AS TrainingType,
tlkpTrainingType.ID AS TrainingTypeID,
tlkpTrainingType.ID AS CountQuals,
tlkpRegion.RegionName,
tlkpRegion.RegionID
FROM
tblTechnicianTraining
INNER JOIN tlkpTrainingType ON tlkpTrainingType.ID = tblTechnicianTraining.TrainingTypeRef
LEFT OUTER JOIN tblTechnician ON tblTechnician.TechnicianID = tblTechnicianTraining.TechnicianRef
INNER JOIN tlkpRegion ON tlkpRegion.RegionID = tblTechnician.RegionRef
WHERE
tlkpTrainingType.Deleted = 0 AND
tblTechnician.CurrentlyEmployed = 1 AND
tblTechnicianTraining.ExpiryDate > GetDate()
) AS T0
ON T0.RegionID = R0.RegionID
)
AS T1
PIVOT
(COUNT(CountQuals)
for RegionName IN (' + @cols + ')
) AS P
GROUP BY
TrainingType,
TrainingTypeID, ' + @cols + ') AS T2
ON T2.TrainingTypeID = tlkpTrainingType.ID
) AS T3
WHERE T3.TrainingTypeID = ' + @TrainingID + '
GROUP BY
T3.TrainingType,
T3.TrainingTypeID
'
EXECUTE (@query)
这是我所追求的结果的一个例子:
TrainingType ¦ TrainingTypeID ¦ CAD ¦ CSD ¦ DVT ¦ FIN ¦ ITS ¦ IWK
HedgeCutter ¦ 200 ¦ 0 ¦ 2 ¦ 0 ¦ 7 ¦ 1 ¦ 0
答案 0 :(得分:1)
我很惊讶这一点起作用,因为你是连接一个INT变量和一个NVARCHAR(MAX)变量,例如:如果我跑:
DECLARE @i INT = 0,
@n NVARCHAR(MAX);
SET @n = N'This is a test' + @i;
我收到错误:
Msg 245,Level 16,State 1,Line 4
转换nvarchar值时转换失败'这是对数据类型int的测试'。
为了应用过滤器,最好使用sp_executesql
和参数,而不是连接您的值并使用EXEC
:
所以而不是:
SET @Query = '....
WHERE T3.TrainingTypeID = ' + @TrainingID + '
...'
EXEC (@Query);
您可以使用:
SET @Query = '....
WHERE T3.TrainingTypeID = @TrainingID
...';
EXECUTE sp_executesql @Query, N'@TrainingID INT', @TrainingID;
这更加类型安全,意味着您不必将int变量强制转换为nvarchar以使其进入查询并允许更好的查询计划缓存。