Pergunta

Estou executando a seguinte consulta:

Select guiPolygonID, dbo.fn_Yval(p1X, p1Y, p2X, p2Y, 4.003318)
From [vPolygonSegments]
Where dbo.fn_Yval(p1X, p1Y, p2X, p2Y, 4.003318) > 0

As partes importantes da função fn_Yval (todos os parâmetros são do tipo float):

set @m = (@p2Y - @p1Y)/(@p2X - @p1X)
set @b = @p1Y - (@m*@p1X)
set @result = (@m*@xval+@b)

Os vPolygonSegments vista não contém registos onde P1X = p2X (os registros são excluídos). No entanto, quando eu executar minha consulta, o SQL Server retorna um erro: "Divide por zero erro encontrado." Curiosamente, se eu executar apenas as duas primeiras linhas (sem a cláusula onde), os resultados da consulta retorna apenas multa.

Como faço para corrigir isso, e / ou o que está causando esse comportamento?

Editar: Aqui é o meu ponto de vista:

Select P1.guiPolygonID,
    P1.decX as p1X, P1.decY as p1Y,
    P2.decX as p2X, P2.decY as p2Y
From PolygonPoints P1, PolygonPoints P2
Where P1.guiPolygonID = P2.guiPolygonID
    and (
        P1.lPointNumber - P2.lPointNumber = 1
        or (
            -- Some other unimportant code
        )
    )
    and P1.decX <> P2.decX
Foi útil?

Solução

O problema aqui é que a função na causa select é avaliada antes da função na cláusula where é avaliada. Esta condição é muito rara, mas é possível, então você precisa de código contra ela. Gostaria de sugerir que você modificar a função para que ele possa lidar com segurança com divisão por zero circunstâncias. Altere esta linha:

set @m = (@p2Y - @p1Y)/(@p2X - @p1X)

Para isto:

set @m = (@p2Y - @p1Y)/NullIf((@p2X - @p1X), 0)

Quando @ p2x - @ P1X = 0, a função NULLIF retornará NULL. Subsequentemente, @m será nula, assim como todos os outros valores. Muito provavelmente, a função retornará NULL.

Na sua cláusula onde, você tem ...

Where dbo.fn_Yval(p1X, p1Y, p2X, p2Y, 4.003318) > 0

Quando o NULL função retorna, ele não vai comparar a 0 e vai acabar ficando filtrados de qualquer maneira.

Outras dicas

Como Joel Coehoorn apontou, que é a questão provável. A consulta a seguir devem evitar o problema, mas o problema é mais fixo dentro de sua própria função:

Select guiPolygonID, dbo.fn_Yval(p1X, p1Y, p2X, p2Y, 4.003318)
From [vPolygonSegments]
Where p2X <> p1X and dbo.fn_Yval(p1X, p1Y, p2X, p2Y, 4.003318) > 0

Eu suspeito que isso tem a ver com a forma como a visão se materializa para a consulta. Acrescentando que a função para a cláusula onde essencialmente adiciona à consulta de origem para a vista, de tal forma que o otimizador pode optar por aplicar esse filtro para os dados de origem antes P1.decX <> P2.decX.

De qualquer forma, você não sabe quando você vai querer re-uso essa função em outro lugar que não tem a mesma restrição. Melhor ter um plano de como lidar com dados ruins na frente. As sugestões NullIf parece ser um bom neste caso.

O problema ocorre quando @ p2X = @ P1X. O que você espera que aconteça nesse caso?

Eu não sei que isso vai responder à pergunta de qualquer maneira, mas você está avaliando fn_Yval duas vezes para cada registro. Por que não fazer o resultado da função de uma coluna no modo de exibição? Então, seu onde cláusula poderia ser algo como "onde yval> 0".

Edit:? A título de curiosidade, fn_Yval não tem quaisquer efeitos secundários, não é

Eu achei que era problemático para tentar remover dados que podem causar divisão por zero erros usando uma cláusula WHERE quando uma junção ou vista está envolvido. De qualquer filtro os dados na cláusula de junção ou filtro-lo na função.

Atualização: para apenas o tipo de razões "G Mastros", escreveu.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top