Pergunta

Em nosso aplicativo, permitiremos que os usuários digitem expressões aritméticas (+ - * /) usando outras colunas do banco de dados para números, que seriam então analisadas pelo aplicativo e gravadas no banco de dados como uma coluna computada.

No entanto, surgem problemas ao permitir que os usuários criem expressões que podem causar exceções quando você select * tabela, como divisão por zero, estouro aritmético e possíveis outros que ainda não encontrei (embora eu pensar são todos eles).

Fazer com que o banco de dados lance uma exceção select * seria absolutamente devastador.Prefiro tentar reescrever a expressão deles em algo que falharia normalmente se eles tivessem dados propensos a erros.

Para dividir por zero a solução é bastante direta:

add [Col] as case {divisor} when 0 then N'DIVIDE-BY-ZERO' else {expression} end

Minha pergunta é o que posso fazer para o estouro aritmético?Mostrar dados falsos ou obviamente errados na coluna não seria um problema, mas lançar exceções seria.

Foi útil?

Solução

Odeio ver você aceitar uma resposta que realmente não o aproxima de seu objetivo.

Como uma resposta separada que pode ajudá-lo um pouco, você pode fazer colunas computadas chamarem uma UDF escalar (determinística).

Veja, por exemplo, aqui

Portanto, se você for criar uma coluna computada, faça com que ela passe as colunas para uma UDF gerada (ou várias UDFs) e faça o trabalho lá.Em uma UDF escalar, você pode ter bastante código para detectar os problemas, mas ainda não pode usar TRY/CATCH.O que você pode fazer em sua UDF escalar é capturar casos e retornar respostas apropriadas (provavelmente gerando NULLs).

Mas o desempenho será muito pobre em UDFs escalares (não tenho certeza sobre colunas computadas embutidas não persistentes vs.UDFs, usamos principalmente persistidos), então você pode considerar seriamente tornar a coluna persistida, o que usará espaço no banco de dados e tornará as inserções e atualizações um pouco mais lentas.Essa é uma grande troca.

Outras dicas

Como você possui tecnologia de análise, você pode reescrever as expressões para capturar todos os possíveis problemas com um monte de instruções CASE - dividir por zero, estourar, fazer upcast para tipos diferentes, etc.

Mas eu não faria isso, porque não acho que colocá-los no banco de dados como parte do esquema seja uma ótima ideia, a menos que esta ferramenta seja uma ferramenta de geração de código e os usuários sejam responsáveis ​​por revisar e testar as expressões para edge condições como se estivessem incluídas no design original do banco de dados.

Se você já estiver analisando a expressão, eu também compilaria isso no lado do cliente e trataria o erro linha por linha.

Capturando a exceção usando TENTE / PEGUE é um cenário de tudo ou nada, não linha por linha.

Que tal capturar as exceções?Parece difícil tentar detectar todas as possíveis causas de overflows aritméticos, muito menos exceções em geral.

Em exceções, você pode retornar um conjunto de resultados sem sentido que seja compatível com o conjunto original definido pelo usuário:

begin try
    select exp(999)
end try
begin catch
    select 1
end catch 

Se o desempenho for importante, use um gatilho ou visualização indexada para armazenar os cálculos quando os dados forem inseridos, atualizados ou excluídos.

Se o desempenho não for importante, use uma função com valor escalar.

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