Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't comparison work in CONVERT?

Is it possible to use a comparison operator in a CONVERT or CAST function?

I've got a statement that looks like this:

SELECT
    ...
    CASE field
        WHEN 'Y' THEN 1  # If Y then True
        ELSE 0           # Anything else is False
    END
    ...
FROM ...

A similar thing happens for a few fields, so I would like to change it to a shorter version:

SELECT
    ...
    CONVERT(BIT, field = 'Y')
    ...
FROM ...

But MSSQL is giving an error Incorrect syntax near '='.

My interpretation of the help is that it should work:

  • CONVERT ( data_type [ ( length ) ] , expression [ , style ] )
  • expression: expression { binary_operator } expression
  • binary_operator: Is an operator that defines the way two expressions are combined to yield a single result. binary_operator can be an arithmetic operator, the assignment operator (=), a bitwise operator, a comparison operator, a logical operator, the string concatenation operator (+), or a unary operator.
  • comparison operator: ( = | > | < | >= | <= | <> | != | !< | !> )

I ran a few tests and got these results:

SELECT CONVERT(BIT, 0)       // 0
SELECT CONVERT(BIT, 1)       // 1
SELECT CONVERT(BIT, 1+2)     // 1
SELECT CONVERT(BIT, 1=2)     // Error
SELECT CONVERT(BIT, (1=2))   // Error
SELECT CONVERT(BIT, (1)=(2)) // Error
like image 939
WileCau Avatar asked Jan 06 '12 02:01

WileCau


1 Answers

I think you are misinterpreting the documentation for CONVERT. There is nothing in the documentation for CONVERT that states it will handle an expression that makes use of the comparison operators, only that it accepts an expression. It turns out that CONVERT does not handle every valid SQL expression. At the very least it cannot handle the results of an expression that uses a comparison operator.

If you check the documentation for Operators, you'll see that the comparison operators (which is what you want = to be, in this case) return a Boolean data type, and are used in WHERE clauses and control-of-flow statements. From the documentation for Operators:

The result of a comparison operator has the Boolean data type, which has three values: TRUE, FALSE, and UNKNOWN. Expressions that return a Boolean data type are known as Boolean expressions.

Unlike other SQL Server data types, a Boolean data type cannot be specified as the data type of a table column or variable, and cannot be returned in a result set.

...

Expressions with Boolean data types are used in the WHERE clause to filter the rows that qualify for the search conditions and in control-of-flow language statements such as IF and WHILE...

That helps to explain why SQL like SELECT 1=2 is invalid SQL, because it would create a result set with a Boolean data type, which the documentation says is not allowed. That also explains why the CASE WHEN construct is necessary, because it can evaluate the comparison operators and return a single value of a data type that SQL Server can return in a result set.

Furthermore, if you look at the documentation for CONVERT, you'll see that Boolean is not supported in either CAST or CONVERT (see the table towards the middle of the page, there is no Boolean data type in there).

For your purposes, I think you're stuck using CASE WHEN. If it helps you can write it all on one line:

CASE WHEN field = 'Y' THEN 1 ELSE 0 END

Alternatively, you could create a UDF to handle the CASE expression (something like dbo.func_DoCase(field, 'Y', 1, 0)), but personally I would just stick with CASE WHEN.

like image 110
rsbarro Avatar answered Sep 28 '22 08:09

rsbarro