2010-06-30 11 views
5

Me pregunto por qué la siguiente falla:¿Hay alguna razón por la que no puede seleccionar una declaración como un bit en SQL Server?

SELECT price<500 as PriceIsCheap 

y le obliga a hacer lo siguiente:

SELECT CASE WHEN (price<500) THEN 1 ELSE 0 END as PriceIsCheap 

Cuando, as per the answer to this related question, la conversion table dice que una conversión implícita debe ocurrir.

+0

Editar: Se modificó la condición del ejemplo porque aparentemente '1 = 1' como marcador de posición hace que la pregunta sea artificial. –

+1

Dar un ejemplo mínimo de un problema es una buena práctica, normalmente, es bastante obvio que no quieres 'SELECT 1 'porque entonces hubieras escrito exactamente eso. – Amadan

+0

Hasta hace unas versiones, el tipo 'bit' en SQL Server no podía ser anulable. Como una comparación puede dar como resultado VERDADERO, FALSO o DESCONOCIDO, no había forma de representar DESCONOCIDO. Y si no considera que UNKNOWN es lo mismo que NULL, todavía no hay forma de representarlo. – Gabe

Respuesta

6

No hay ningún tipo de datos Boolean en SQL, BIT es una especie de truco, pero el principal problema es que, debido al concepto de SQL de NULL cierto boolean logic es imposible (por ejemplo, ¿cuál sería su declaración de consulta si price fue NULL ?)

Tenga en cuenta que no estoy diciendo que no son posibles formas de implementar la lógica booleana que "la mayoría" de trabajo (por ejemplo, se podría decir que es TRUE OR NULLNULL o lo que sea) sólo que la gente que diseñó el estándar SQL no pudo decidir sobre La única representación verdadera para la lógica booleana (por ejemplo, también podría argumentar que TRUE OR NULL es TRUE, ya que TRUE OR <anything> es TRUE).

Las expresiones booleanas (=, = <, > =, etc.) sólo son válidos en ciertos lugares (en particular, WHERE cláusulas y CASE etiquetas) y no en cualquier otro lugar.

+1

Cool, I desear que ahora ese bit pueda ser anulable, lo arreglarían, porque obviamente * han * decidido la Representación Verdadera de la lógica booleana para propósitos de evaluación. Curiosamente, no se pueden comparar booleanos - (SELECCIONAR CASO CUANDO (1 = 1) = (1 = 1) ENTONCES 1 ELSE 0 END) falla –

+1

AFAIC, 'TRUE OR NULL' =' TRU E', no desconocido (lo que MS dijo). http://dev.mysql.com/doc/refman/5.0/en/logical-operators.html y http://www.postgresql.org/docs/8.2/static/functions-logical.html están de acuerdo conmigo. A pesar de que SQL no lo define, es tan útil que no hay excusa para que una implementación en particular no lo haga. – Amadan

+0

Eso es interesante de tener en cuenta al convertir declaraciones SQL entre proveedores. –

0

No soy persona MSSQL, pero me encontré con el mismo problema con Oracle. La respuesta trivial es, porque Boolean no es un tipo de columna válido en esas bases de datos. Ahora, por qué decidieron que no necesitas booleanos ya que los valores no se pueden adivinar.

@paxdiablo, eso es perder el punto ... El ejemplo de OP es solo un ejemplo mínimo. Esto es aún simplista, pero el ejemplo del mundo real: Considere una tabla de Personas, que contiene nombres y edades. Desea llegar a todas las personas, pero también quiere saber si son menores de edad. En tanto MySQL y PostgreSQL, puede escribir

SELECT name, age < 18 AS minor FROM people 
+0

Lo molesto es que * puedes * hacer CASE WHEN (intColumn) THEN truthValue ELSE falseValue END. Por lo tanto, puede convertir un int a boolean, pero no un boolean a bit. –

+1

De hecho. Acabo de comprobar los documentos de TSQL - el resultado de '<' es booleano ('VERDADERO' o' FALSO', pero ese tipo de datos ni siquiera se menciona en el artículo "Tipos de datos", ¡pero tienen un entero de 1 bit! Odiaba a Oracle , y ahora odio MSSQL también (incluso nunca he trabajado con él) – Amadan

+0

No tengo idea de por qué alguien votó negativamente para contrarrestarme. –

3

Bien También encontrará que no se puede si tiene una columna llamada poco IsCheap hacer SELECT * FROM STUFF WHERE IsCheap, que tiene que hacer WHERE IsCheap=1.

La razón es simple, el tipo de datos es un poco, no un bool. Es cierto que básicamente es el único uso que le pondrás y se convierte implícitamente en casi cualquier marco de acceso a datos, pero técnicamente sigue siendo un poco con 0 o 1 en lugar de un bool con verdadero o falso. Hay una conexión obvia que todos podemos ver, pero SQL no se escribió con esta suposición, por lo que debemos proporcionar la lógica para convertir verdadero/falso en 1/0.

+0

Me gusta este ejemplo también. Otros proveedores (MySQL/PostgreSQL) lo administran –

2

La expresión price < 500 devuelve valor lógico: VERDADERO, FALSO o DESCONOCIDO. No es un valor de datos, por lo que debe usar una expresión CASE para devolver un valor de datos correspondiente.


Fwiw el motor de base de datos Microsoft Access en efecto, el tratamiento de los resultados de las expresiones como por ejemplo los valores de datosusted puede pedir todo tipo de preguntas extravagantes tales como:

SELECT 1 = 1, 1 = NULL, 1 <> NULL, 1 IN (NULL) 
    FROM Foo; 

... y también irá dar respuestas, pero por supuesto esto sólo demuestra que el acceso no implementa el lenguaje SQL!

Cuestiones relacionadas