views:

294

answers:

10

I am trying to determine that standard SQL behaviour for comparing a number to a character or string version of the same number. Does SELECT 1 = '1' (or the like) always return some sort of "truthy" value (true, 1, 't', etc.)? I have confirmed as much on PostgreSQL and MySQL, but I cannot find a resource for SQL as a whole.

Update: The purpose for the question is that I'm trying to figure out if using a number, without the quotes, will work when selecting/inserting/updating/etc. from a non-numeric field whose value is a number.

+1  A: 

1 is an Number and '1' is a CHAR array of some sort, they should never be equal. If they are that is an implementation dependent behavior

fuzzy lollipop
Remember though, that SQL does a lot of typecasting when it's necessary or convenient. It's not exactly Java.
Joey
that doesn't mean it is right, you should never do this intentionally. explict is much better than implicit
fuzzy lollipop
it does implicit otherwise you can't do thisselect 1 as aunion allselect '1'
SQLMenace
+6  A: 

SELECT 1='1' gives TRUE since '1' is a correct constructor for INT in all implementation known to me.

But SQL uses strict typing, see that:

# SELECT 1=CAST('1' AS TEXT);
ERROR:  operator does not exist: integer = text
LINE 1: SELECT 1=CAST('1' AS TEXT);
                ^
HINT:  No operator matches the given name and argument type(s). You might need to add  explicit type casts.

Regarding the standard (SQL 92, 99 & 2003) it seems to be wrong:

     <literal> ::=
            <signed numeric literal>
          | <general literal>

     <general literal> ::=
            <character string literal>
          | <national character string literal>
          | <bit string literal>
          | <hex string literal>
          | <datetime literal>
          | <interval literal>

     <signed numeric literal> ::=
          [ <sign> ] <unsigned numeric literal>

     <unsigned numeric literal> ::=
            <exact numeric literal>
          | <approximate numeric literal>

     <exact numeric literal> ::=
            <unsigned integer> [ <period> [ <unsigned integer> ] ]
          | <period> <unsigned integer>

     <unsigned integer> ::= <digit>...

     <character string literal> ::=
          [ <introducer><character set specification> ]
          <quote> [ <character representation>... ] <quote>
            [ { <separator>... <quote> [ <character representation>... ] <quote> }... ]

because <quote> is only contained in <bit string literal>, <hex string literal>, ... but not in numeric literals...

Johannes Weiß
+2  A: 

SQL Server

if 1 = '1'
print 'yes'
else
print 'no'

output: yes

This gets converted, see here for a whole list of implicit and explicit conversion possibilities: CAST and CONVERT (Transact-SQL)

SQLMenace
A: 

For an "always true" select statement simply use SELECT 1. That will always be true.

machinatus
I know; the purpose of the question is to determine if `... WHERE non_numeric_field = 1` is equivalent to `... WHERE non_numeric_field = '1'` in a query.
Daniel Vandersluis
That's not correct. 1 is not the same as true in SQL. Maybe in some implementations.
Peter Eisentraut
+1  A: 

Testing from MySQL 5.x and SQL Server 2005, they both perform implicit conversion of '1' into 1 for the evaluation to return true.

But that could also have to do with collation.

OMG Ponies
+2  A: 

First off, in SQL Server SELECT 1 = '1' isn't valid. Although, if you run the following code, you'll find that 1 does = '1'

if (1 = '1') begin
    print 'true'
end else begin
    print 'false'
end

results:

true
Gabriel McAdams
+3  A: 

"SQL in general" does not have concept of a "truthy" value.

Unlike MySQL and PostgreSQL, in Oracle and SQL Server, no internal datatypes can be used as boolean values in WHERE clauses or WHEN predicates.

You should always have some kind of a predicate to use in these clauses.

No datatype can be used in mydata to make these queries work:

SELECT  1
WHERE   @mydata

or

SELECT  1
FROM    dual
WHERE   :mydata

Also, no SQL standard prescribes the type casting order.

The datatype of the constant can be casted to that of that of the column datatype or vice versa.

This can lead to the problems similar to those described in this question.

Quassnoi
SQL has had a boolean type since 1999.
Peter Eisentraut
`@Peter Eisentraut`: and?
Quassnoi
A: 

Although it appears to work in many implementations, per SQL standard, the comparison 1 = '1' is not allowed.

Peter Eisentraut
A: 

The question (given the update text) is not if:

SELECT 1 = '1'

will work, but will:

SELECT '1'::text = 1

work. Which is of course: no. At the very least on PostgreSQL, and for a really good reason.

depesz
In version 8.2.11 at least, the second query returns 't'.
Daniel Vandersluis
A: 

From the Update:

Your update sounds like you want to do the following:

SELECT *
FROM MyTable 
WHERE StringColumn = 1

That will not work. If you have ANY values in that string column which are non-numeric, as soon as the sql engine gets to that row it will throw an error. In MS SQL Server the error is "Conversion failed when converting the varchar value 'blah' to data type int."

So, if you want to do the comparison, you would have to make sure you are comparing like data types. For example:

SELECT *
FROM MyTable 
WHERE StringColumn = '1'
Chris Lively