2010-01-05 8 views

Respuesta

12

Las UDF en MSSQL no pueden tener efectos secundarios, lo que BOL define como "cambiar el estado de la base de datos". Eso es una descripción bastante vaga, pero MSSQL aparentemente considera errores para cambiar el estado de base de datos - esto UDF no se compila:

create function dbo.foo() 
returns int 
as 
begin 
    raiserror('Foo', 16, 1) 
    return 1 
end 
go 

El mensaje de error es:

Msg 443, nivel 16, estado 14 , Procedimiento foo, Línea 5 Uso no válido de un operador de efecto secundario 'RAISERROR' dentro de una función.

Si se considera que generar un error cambia el estado de la base de datos, es probable que interceptar y manejar uno sea también. Lo cual no es una gran explicación, lo admito.

En términos prácticos, sin embargo, a menudo es mejor dejar que la persona que llama decida cómo manejar los errores de todos modos. Supongamos que escribe una función como esta:

create function dbo.divide (@x int, @y int) 
returns float 
as 
begin 
return @x/cast(@y as float) 
end 

¿Cómo manejaría el caso en que una aplicación pasa a cero para @y? Si atrapas la excepción de dividir por cero, ¿qué vas a hacer a continuación? ¿Qué valor puede devolver de la función que tiene sentido para la persona que llama, teniendo en cuenta que ni siquiera puede saber qué aplicación llama a su función de todos modos?

Puede pensar en devolver NULL, pero ¿estarían de acuerdo los desarrolladores de aplicaciones que usan su función? ¿Consideran todas sus aplicaciones un error dividir por cero para tener el mismo impacto o importancia? Sin mencionar que los valores NULL en ciertos lugares pueden cambiar por completo los resultados de una consulta, tal vez en formas que el desarrollador de la aplicación no desea en absoluto.

Si usted es el único desarrollador, tal vez no sea un problema, pero con más personas se convierte rápidamente en uno.

+1

Quería reproducir el comportamiento de TRY_CAST escribiendo mi propia UDF: –

1

Como solución temporal, me gustaría llamar al UDF de TRY/CATCH dentro de un procedimiento almacenado.

+2

Gracias por la respuesta, pero cuando estás escribiendo un FDU, generalmente es reutilizado por otras personas. Su solución funciona si escribo tanto la función como la persona que llama, pero nunca puede estar seguro de que otros llamarán a su procedimiento de la manera correcta. –

+0

cierto ... creo que ck hizo un buen punto sobre el potencial de que se llame miles de veces, por lo que la sobrecarga de un try/catch podría ser enorme. – kevchadders

1

Tal vez sea porque la sobrecarga es demasiado - se podría llamar a una función escalar en una columna como parte de una selección y llamarla miles de veces. Si hubiera una sobrecarga razonable para permitir la prueba/captura, la ralentizaría terriblemente.

+0

+1 buen punto sobre los gastos generales – kevchadders

+3

Sí, ck, pero podríamos decir lo mismo para muchos otros aspectos de la programación (los cursores vienen a la mente). Yo diría que depende del desarrollador que escriba la función para decidir si su implementación y el posible uso serán gastos generales, y el código en consecuencia. –

Cuestiones relacionadas