如何摆脱以下动态SQL中的多个转换函数?
IF @MediaTypeID > 0 or @MediaGroupID > 0
BEGIN
SET @SQL = @SQL + 'INNER JOIN (SELECT lmc.ID FROM Lookup_MediaChannels (nolock) lmc
INNER JOIN Lookup_SonarMediaTypes (nolock) lsmt ON lmc.SonarMediaTypeID = lsmt.ID
WHERE (ISNULL('+ CONVERT(VARCHAR(10),@MediaTypeID) +',0) = 0 OR lsmt.ID = '+ CONVERT(VARCHAR(10),@MediaTypeID) +')
AND (ISNULL('+ CONVERT(VARCHAR(10),@MediaGroupID)+',0) = 0 OR lsmt.SonarMediaGroupID = '+ CONVERT(VARCHAR(10),@MediaGroupID) +'))t ON t.ID = lmc.ID '
我尝试先转换它们并使用变量而不是转换调用,如下所示
IF @MediaTypeID > 0 or @MediaGroupID > 0
BEGIN
SET @TypeID = CONVERT(VARCHAR(10),@MediaTypeID)
SET @GroupID = CONVERT(VARCHAR(10),@MediaGroupID)
SET @SQL = @SQL + 'INNER JOIN (SELECT lmc.ID FROM Lookup_MediaChannels (nolock) lmc
INNER JOIN Lookup_SonarMediaTypes (nolock) lsmt ON lmc.SonarMediaTypeID = lsmt.ID
WHERE (ISNULL('+ @TypeID +',0) = 0 OR lsmt.ID = '+ @TypeID +')
AND (ISNULL('+ @GroupID+',0) = 0 OR lsmt.SonarMediaGroupID = '+ @GroupID +'))'
END
但它给了我这个错误
Msg 245,Level 16,State 1,Line 13
将varchar值',0)= 0或lsmt.ID ='转换为数据类型int时转换失败。
答案 0 :(得分:1)
您可以重新编写WHERE
子句以消除查询正文中的ISNULLS,方法是将它们移动到代码块开头的变量计算中。
所以,而不是:
SET @TypeID = CONVERT(Varchar(10), @MediaTypeID)
做的:
SET @TypeID = CAST( COALESCE(@MediaTypeID, 0) AS Varchar)
这样,转换就不必在查询本身中发生。
答案 1 :(得分:1)
您获得的错误是因为您尝试将变量MediaTypeID和MediaGroupID从int转换为varchar。该操作不会失败,它不会发生。问题是两者仍然是整数,您试图在动态代码中添加导致错误。所以我所做的是声明2个新变量,这应该可以解决问题。如果你查看你没有包含的代码,你应该注意到MediaTypeID和MediaGroupID都是数字最有可能的整数。
IF @MediaTypeID > 0 or @MediaGroupID > 0
BEGIN
DECLARE @TypeID2 VARCHAR(10)
DECLARE @GroupID2 VARCHAR(10)
SET @TypeID2 = NULLIF(CONVERT(VARCHAR(10),@MediaTypeID ), 0)
SET @GroupID2 = NULLIF(CONVERT(VARCHAR(10),@MediaGroupID), 0)
SET @SQL = @SQL + 'INNER JOIN (SELECT lmc.ID FROM Lookup_MediaChannels (nolock) lmc
INNER JOIN Lookup_SonarMediaTypes (nolock) lsmt ON lmc.SonarMediaTypeID = lsmt.ID
WHERE '+
coalesce( @TypeID2 +' = lsmt.ID', '1=1') +
coalesce( 'AND' + @GroupID2+' = lsmt.SonarMediaGroupID', '') + ')t ON t.ID = lmc.ID '
END
答案 2 :(得分:1)
您获得的错误可能是由NULL @MediaTypeID或@MediaGroupID值引起的,因为您的代码无法正确处理NULLS。
但是,在WHERE子句中使用OR条件对性能有害,因为它会阻止查询优化器使用索引。我建议重写它以避免OR(这也减少了CONVERT的数量:
IF @MediaTypeID > 0 or @MediaGroupID > 0
BEGIN
SET @SQL = @SQL + 'INNER JOIN (SELECT lmc.ID FROM Lookup_MediaChannels (nolock) lmc
INNER JOIN Lookup_SonarMediaTypes (nolock) lsmt ON lmc.SonarMediaTypeID = lsmt.ID
WHERE 1=1 '
IF @MediaTypeID > 0
SET @SQL = @SQL + ' AND lsmt.ID = ' + CONVERT(VARCHAR(10),@MediaTypeID)
IF @MediaGroupID > 0
SET @SQL = @SQL + ' AND lsmt.SonarMediaGroupID = ' + CONVERT(VARCHAR(10),@MediaGroupID)
SET @SQL = @SQL + ') t ON t.ID = lmc.ID '
END