2011-08-25 8 views
5

Tenemos un SQL que realiza una función CAST (para FLOTAR) en ColumnA. El SQL tiene un filtro que al final filtrará indirectamente aquellas filas que tienen valores no numéricos en ColumnA. Sin embargo, debido a lo que creo que se debe a la ejecución de partes del SQL en paralelo, creo que CAST incluso se aplica a las filas que se filtran y esto hace que el SQL falle "no se puede emitir valor como flotante ... "incapaz de emitir valor como float

sé que si me quedo con un proc añadiendo la sugerencia de consulta

OPTION (MAXDOP 1) 

que el SQL se ejecuta como se esperaba. Sospecho que al ejecutar en 1 proc, se fuerza la aplicación del filtro para eliminar la fila con los valores no numéricos en la columna A, de modo que la CASTING de sus valores tenga éxito. También he encontrado que el uso de la sugerencia de consulta

OPTION (FORCE ORDER) 

corrige el problema, estoy asumiendo becausethis también asegura que el filtro se aplica por primera vez y me da mucho mejor rendimiento de las consultas que se ejecutan en un cilindro.

Me estoy inclinando hacia torwards para solucionar el problema usando la segunda opción. Si tengo ideas erróneas sobre lo que está sucediendo aquí o si alguien quisiera exponer mi comprensión general o hacer una recomendación, lo agradecería.

estoy corriendo en

Microsoft SQL Server 2008 R2 (RTM) - 10.50.1720.0 (X64) jul 12 2010 01:34:59 Derechos de autor (c) Microsoft Corporation Enterprise Edition (64- bits) en Windows NT 5.2 (Build 3790: Service pack 2)

una ocurrencia tardía:

parece que sería bueno es T-SQL tenía las siguientes funciones para comprobar si una cadena podía ser conve conectado a un tipo de datos particular.

IsFloat IsNumeric EsEntero etc

soy realmente molesto por el número de columnas de todo tipo de datos que encuentro en nuestra base de datos que se definen como varchar (255). ¡Creo que la solución es "no hacer eso!"

+2

¿Puede mostrar el SQL? – MatBailie

+1

Nos está pidiendo que ayudemos a reparar su automóvil sin ver el automóvil. Muéstranos el auto por favor. – JNK

+0

T-SQL tiene IsNumeric – MatBailie

Respuesta

4

En cuanto a su pensamiento tardío.

Parece que sería bueno es T-SQL tenía las siguientes funciones para comprobación para ver si una cadena se puede convertir a un tipo de datos en particular.

SQL Server 2012 introduce TRY_CONVERT para esta necesidad. Por lo tanto, la siguiente consulta devolvería NULL en lugar de un error.

SELECT TRY_CONVERT (FLOAT, 'Fish') 

no hay garantía incluso con planes de serie que la cláusula WHERE va a pasar antes de evaluar la SELECT. Como se explica en in this blog post desde SQL Server 2005 en adelante, es más probable que esto suceda que en versiones anteriores. El Behavior Changes to Database Engine Features in SQL Server 2005 llama específicamente esto de la siguiente manera.

SQL Server 2005 veces evalúa las expresiones en las consultas antes de lo cuando se evalúan en SQL Server 2000. Este comportamiento proporciona los siguientes beneficios importantes :

  • La capacidad para que coincida con índices en columnas calculadas a expresiones en una consulta que son las mismas que la expresión de columna calculada.
  • La prevención del cálculo redundante de resultados de expresiones.

Más discusión acerca de este comportamiento está en otra buena entrada en el blog por Craig Freedman Conversion and Arithmetic Errors.

En las versiones anteriores a 2012 y TRY_CONVERT debe ajustar el CAST AS FLOAT en una declaración CASE. p.ej.

SELECT CASE WHEN ISNUMERIC(Col)=1 THEN CAST(Col AS FLOAT) END AS Col 
    FROM Table 
    WHERE ISNUMERIC(Col)=1 

Esto todavía no está garantizado en absoluto para evitar que conseguir de errores como ISNUMERIC sí solo comprueba que el valor echaría a uno de los tipos de datos numéricos y no específicamente a flotar An example of an input that would fail is '.'

CASE se ha documentado que la mayoría cortocircuito en libros en línea (some exceptions are discussed here)

también puede encontrar discusión/quejas adicionales acerca de esto en el elemento de conexión y una SQL Server should not raise illogical errorsgood explanation of a similar issue por SQLKiwi

1

Creo que tiene razón. La función CONVERT() se está aplicando antes de que los predicados "filtren indirectamente" las filas.

Para evitar la excepción, tiene razón, un enfoque es tratar de obtener un poco de control sobre el orden de las operaciones en el plan de ejecución. Si la sugerencia de la declaración funciona para usted, entonces puede ir con eso. (Personalmente, los consejos son un último recurso para mí.)

Tenga en cuenta que SQL Server tiene una función IsNumeric.

La función IsNumeric es algo inadecuada, en el sentido de que hay algunos valores que "pasarán" una prueba IsNumeric pero que generarán una excepción cuando se conviertan a un tipo de datos numérico.

En lo personal, yo tendería a ir con este enfoque:

select convert(float,case when isnumeric(t.foo)=1 then t.foo else null end) 

en lugar de a nivel de declaración consejos.

O, especificaría los otros predicados que deberían "filtrar" los valores que no deberían convertirse.

select convert(float,case when t.fi in ('fo','fum') then t.foo else null end) 
Cuestiones relacionadas