Writing to a MySQL ENUM column by index using ODBC - mysql

From the MySQL reference manual:
If you store a number into an ENUM column, the number is treated as the index into the possible values, and the value stored is the enumeration member with that index.
But when I try to write an SQL_SMALLINT value to that ENUM column using ODBC I get the error HY000:1:1265 (Data truncated for column ...).
So how can I write a number into a MySQL ENUM column using ODBC, such that this number is interpreted as the enum index?
Edit: Some more information
The column is defined as:
`TrackState` ENUM('NEWE','NEWN','VALID','INVISIBLE','CLOSED','DIED') NULL
and the statement used with ODBC is:
INSERT INTO test (TrackState) VALUES (?)
and in my C code I use SQLBindParameter with SQL_C_USHORT and SQL_SMALLINT to bind an unsigned short variable.
When I change my TrackState column to an ordinary INT column, the numeric value (which I want to be interpreted as the index of an enum) is successfully written.

Related

Mysql enum field problems

in a mysql table I have a field of type Enum ('S', 'N') with default value = S. Now I have checked this table and I find many records that have no value in this field. How is it possible? I wanted to force the values of this field to be only S and N. Where did I go wrong?
Mysql version 5.0.92
my field definition:
`conteggia` enum('S','N') NOT NULL default 'S'
From the Empty or NULL Enumeration Values documentation:
If you insert an invalid value into an ENUM (that is, a string not present in the list of permitted values), the empty string is inserted instead as a special error value. ...
If strict SQL mode is enabled, attempts to insert invalid ENUM values result in an error.
So you must not have strict mode enabled, and due to some error in your code it assigned invalid values to the column.

MYSQL inserting UNC time into a column, yet getting errors

I am trying to insert a UTC timestamp into a row in mysql by using MySQLWorkBench. I have set the column type as TIMESTAMP, BIGINT, INT and TIME. No matter what I set it as I receive the same error - "incorrect (Type Here) value".
I am using this code to test this:
INSERT INTO mytablenamehere (`Time`) VALUES ('UNIX_TIMESTAMP(NOW(3))')
Should add I am on MYSQL 8.0. What am I doing wrong?
You're trying to insert a string. Your query should be VALUES (UNIX_TIMESTAMP(NOW(3))) (without the single quotes). Also note that (from the docs):
The return value is an integer if no argument is given or the argument does not include a fractional seconds part, or DECIMAL if an argument is given that includes a fractional seconds part.
So your column must be either an INT or a DOUBLE, depending on the precision you want.

Strange answer behavior with SELECT

I have a simple table using a non auto inc INT as primary key.
When querying the table with condition e.g. WHERE id='2,5,6' (unintentionally!) it returns a result set!
Ok, it works, but why?
id is an integer and you compare it with a string '2,5,6'. MySQL converts the string to a number in order to compare the two.
Well, '2,5,6' isn't a number and other DBMS would throw an error. But MySQL uses another approach: it converts character per character until the string is ended or the character is not numeric. So it sees the 2 then the comma. Depending on your settings the comma is the dicimal separater or not. So MySQL either converts to 2 or to 2.5.
Here is the documentation on implicit conversions in MySQL: https://dev.mysql.com/doc/refman/5.5/en/type-conversion.html.
The algorithm on how to convert a string to a number is not explicitly described there, but they say for instance
there are many different strings that may convert to the value 1, such as '1', ' 1', or '1a'.
They also point out in that document that implicit conversion is dangerous, because strings are not converted to DECIMAL (as I would have thought), but to the approximate datatype DOUBLE. So in MySQL we should always avoid implicit conversion from string to number.

Select with join outputs not exact match [MySQL]

Can anyone explain why query:
select rma.id, history_transactions.reference
from history_transactions
join rma on history_transactions.reference = rma.id
Returns:
id | reference
100144 | 100144
102299 | 102299a
100316 | 100316AFEN1
Can't get it to show only 100% matched, so only first row. If someone can explain why it happens it would be great.
Evidently rma.id column is numeric (integer), while the reference field is textual, since it contains text as well.
As MySQL documentation on Type Conversion in Expression Evaluation describes, if you compare text with number, the comparison is one as floating point numbers, meaning that the reference field is converted to a number.
MySQL converts a string to number by evaluating its characters left to right, as long as the charters can be interpreted as a number. If it encounters a character that cannot be evaluated as a number, then MySQL stops the evaluation and returns the previous characters as the numeric value.
In case of the 2nd record, the letter a is the 1st character that cannot be evaluated as number, therefore the numeric value of '102299a' string is 102299. The same logic applies to the 3rd record.
To force MySQL to return exact matches only, explicitly convert rma.id to string using cast() or convert() functions in the query. This way the comparison would be done as strings, not as floating point numbers.
The reason is most probably implicit type conversion. My guess is that id field is of integer type, whereas reference field is of varchar type. Hence, when comparing MySQL converts varchar to a number. So, e.g. value '10299a' is converted to 10299 and is then compared to the corresponding value of id field.
Live demo of the issue
Implicit datatype conversion.
I suspect the id column is declared as numeric datatype. Most likely INT.
The reference column is declared as character type. Most likely VARCHAR.
To do the equality comparison, MySQL can't compare a "string" with a "number".
So MySQL is implicitly doing a conversion of the string value into a number, and then doing the comparison of the numeric values.
Other databases would throw an error given a string that isn't a valid number.
But MySQL allows the conversion (without error or warning.)
As a demonstration, these expressions cause MySQL to do implicit conversion of a string to a number:
SELECT '123ABC' + 0
, '4D5E6F' + 0
, 'G7H8I9' + 0
Given your values, for example
SELECT '100316AFEN1' + 0
We see that MySQL returns a numeric value of 100316 which it uses to compare.

Is a non-nullable, MySQL enum column guaranteed to only contain those values?

If I have a column in a MySQL database that is:
Non-nullable
Is an ENUM with 5 possible values
Has a default value of 1 of those ENUM's
Can it be guaranteed that there can never be a value in that column apart from one of those ENUM's?
Not by default - there is one more value your column can have in addition to the values of the enum, an empty string in the column.
You have to enable strict SQL mode in MySQL to have the guarantee that only the enum values (or NULL if the column is nullable ) can occur.
Taken from here
If you insert an invalid value into an ENUM (that is, a string not
present in the list of permitted values), the empty string is inserted
instead as a special error value. This string can be distinguished
from a “normal” empty string by the fact that this string has the
numeric value 0. See Section 11.4.4, “ Index Values for Enumeration
Literals ” for details about the numeric indexes for the enumeration
values.
If strict SQL mode is enabled, attempts to insert invalid ENUM values
result in an error.
If strict SQL mode is enabled, attempts to insert invalid ENUM values result in an error.
Source