2

如何摆脱以下动态 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

但它给了我这个错误

消息 245,级别 16,状态 1,第 13
行将 varchar 值 ',0) = 0 或 lsmt.ID = ' 转换为数据类型 int 时转换失败。

4

3 回答 3

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
于 2013-07-20T14:00:01.167 回答
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
于 2013-07-20T20:18:37.113 回答
1

您可以重新设计您的WHERE子句以消除查询主体中的 ISNULLS,方法是将它们上移到代码块开头的变量计算中。

所以,而不是:

SET @TypeID = CONVERT(Varchar(10), @MediaTypeID)

做:

SET @TypeID =  CAST( COALESCE(@MediaTypeID, 0) AS Varchar)

这样,转换不必在查询本身中发生。

于 2013-07-20T13:51:19.173 回答