2013-07-20 3 views
2

Как избавиться от нескольких функций преобразования в следующем динамическом SQL?минимизация вызовов функций внутри динамического 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, строка 13
Ошибка преобразования при преобразовании значения varchar ', 0) = 0 ИЛИ lsmt.ID =' в тип данных int.

ответ

1

Ошибка, которую вы получаете, заключается в том, что вы пытаетесь преобразовать переменные MediaTypeID и MediaGroupID из int в varchar. Эта операция не терпит неудачу, ее просто не бывает. Проблема в том, что оба они по-прежнему являются целыми числами, которые вы пытаетесь добавить в динамический код, вызывающий ошибку. Так что я сделал, чтобы объявить две новые переменные, которые должны решить проблему. Если вы посмотрите на код, который вы не указали, вы должны заметить, что 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 
1

Вы можете повторно корабль своего пункта WHERE для устранения ISNULLS в теле запроса, перемещая их до переменного расчета в начале блока кода.

Таким образом, вместо того, чтобы:

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

сделать:

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

Таким образом, преобразование не должно случиться в самом запросе.

1

ошибка, вы получаете, возможно, были вызваны NULL @MediaTypeID или @MediaGroupID значений, потому что ваш код не обрабатывает NULLS.

Однако условие OR, подобное этому в предложении WHERE, плохо для производительности, поскольку оно не позволяет оптимизатору запросов использовать индекс. Я бы предложил переписать его, чтобы избежать 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 
Смежные вопросы