MYSQL updates column with random but specific entry - mysql

MySQL update seems to update with a magic number of 2147483647 when I try to update with 0123456789.
Somewhere, MySQL seems to associate one number for another on an INT column in any schema. Where do I even look for such an association. Details of this are below.
This update does what it is suppose to and enters in 012345678 into the ContactPhone2 column for the appropriate row.
UPDATE `alacarte`.`customercontacts` SET `ContactPhone2`='012345678' WHERE `CustomerID`='cust-000004' and`ContactID`='1'
This update actually enters in 2147483647 in the ContactPhone2 column on the appropriate row; far from 0123456789.
UPDATE `alacarte`.`customercontacts` SET `ContactPhone2`='0123456789' WHERE `CustomerID`='cust-000004' and`ContactID`='1'
Datatype for the ContactPhone2 is INT(10) with a default value of NULL and NO parameters set (OK, NN, AI, etc)
This is from the MYSQL general log.
For the 012345678 update.
130101 17:51:43 89 Query set autocommit=0
130101 17:51:44 89 Prepare UPDATE `alacarte`.`customercontacts` SET `ContactPhone2`='012345678' WHERE `CustomerID`='cust-000004' and`ContactID`='1'
89 Execute UPDATE `alacarte`.`customercontacts` SET `ContactPhone2`='012345678' WHERE `CustomerID`='cust-000004' and`ContactID`='1'
89 Query commit
89 Close stmt
And the log entry for the 0123456789 update.
130101 17:51:48 89 Query set autocommit=0
130101 17:51:49 89 Prepare UPDATE `alacarte`.`customercontacts` SET `ContactPhone2`='0123456789' WHERE `CustomerID`='cust-000004' and`ContactID`='1'
89 Execute UPDATE `alacarte`.`customercontacts` SET `ContactPhone2`='0123456789' WHERE `CustomerID`='cust-000004' and`ContactID`='1'
89 Query commit
89 Close stmt
Updating with 0123456780 Works, so it is not the length of digits.
This happens on ANY column throughout the database with an INT(10+) but not on VARCHAR columns.
Even better is it does the same thing on another schema called thedesignedge that was the old schema that has since been copied and renamed, but it is still active in mysql although unused.
There are NO TRIGGERS running on the column, and only one trigger running on the table on the ContactID column. No errors are given either.
Queries have been generally made through MySQL workbench, although I tried once to directly enter in the update query through the shell in terminal and got the same results.
Somewhere, MySQL seems to associate one number for another on an INT column in any schema. Where do I even look for such an association.
We have not done anything with caching or indexing yet, aside for whatever MySQL defaults to. We are running mysql 5.5.29

A "magic" number of 2147483647 is 2^31-1, which is the upper limit for an int. it means it thinks you put in a number that was too big.
Best option is going to be to use varchar to store your phone numbers. make sure you make it big enough to handle all your expected cases, and I strongly recommend formatting the phone number using a regular expression to clean the input for you. Here's a simple way to format a phone number in php if you only need (xxx) xxx-xxxx and not extensions or anything funny (like international numbers).
$phoneNumber = '1-(235) 555.1234';
$formatted = '';
if (preg_match('/1?[^0-9]*([02-9][0-9][0-9])[^0-9]*([0-9]{3})[^0-9]*([0-9]{4})/', $phoneNumber, $matches)) {
$formatted = "($matches[1]) $matches[2]-$matches[3]";
} else {
// phone number is invalid
}
The result will be $formatted = (235) 555-1234. The regular expression includes an optional 1 prefix that gets discarded and the first actual number cannot be 1.
Obviously, you should use this same regular expression to validate the phone number before you accept it if you use it to format it.

You're probably overflowing your INT value. When MySQL overflows, by default it stores the largest value the data type supports. The largest value for a signed 32-bit integer is 231-1, which is 2147483647.
The values '012345678' and '0123456789' are okay. That is, they are within the range of an INT, and they insert fine. So I doubt those values are really causing the trouble.
I would look for some other SQL statement that's updating with a different value that exceeds the range. For example, someone may have tried to add their phone number with a phone extension.
You can enable strict mode, so that integer overflows cause an error instead of silently truncating the value. That'll tell you more clearly when it's happening.
SET SQL_MODE='STRICT_ALL_TABLES';
See http://dev.mysql.com/doc/refman/5.5/en/server-sql-mode.html
PS: You mention INT(10) as though the integer argument matters to the range of values that the data type supports. That's a common misconception, but it doesn't matter. An INT is always 32 bits. See What is the difference (when being applied to my code) between INT(10) and INT(12)?

What mysql version are you using? I can't duplicate that.
Does set ContactPhone2=round('0123456789') help? (Just changing to varchar is better, presuming you want to keep leading zeroes.)

Related

Bizarre behavior in mysql running a query

My intention was to run this query in mysql:
update my_users set isLocked=1 where categoryId=10;
But I accidentally typed a dash (-) instead of the equal sign(=). So the query looked like this:
update my_users set isLocked=1 where categoryId-10;
This produce issues because it ran for everybody instead of just that belong to the category 10
Wondering why the 2nd call do not produce any errors and prevent the execution ?
Yup . . . You have an arithmetic expression, which is interpreted as:
categoryId - 10 <> 0
So, it doesn't update all rows -- just all rows where categoryId is not 10.
Ooops. This is a consequence of MySQL helping you by treating booleans as interchangeable with integers, with 0 for false and all other values for true.
You might be able to prevent this using sql_safe_updates mode. However, I'm not sure if the mode actually checks that you make an explicit comparison on the key.

Could this simple T-SQL update fail when running on multiple processors?

Assuming that all values of MBR_DTH_DT evaluate to a Date data type other than the value '00000000', could the following UPDATE SQL fail when running on multiple processors if the CAST were performed before the filter by racing threads?
UPDATE a
SET a.[MBR_DTH_DT] = cast(a.[MBR_DTH_DT] as date)
FROM [IPDP_MEMBER_DEMOGRAPHIC_DECBR] a
WHERE a.[MBR_DTH_DT] <> '00000000'
I am trying to find the source of the following error
Error: 2014-01-30 04:42:47.67
Code: 0xC002F210
Source: Execute csp_load_ipdp_member_demographic Execute SQL Task
Description: Executing the query "exec dbo.csp_load_ipdp_member_demographic" failed with the following error: "Conversion failed when converting date and/or time from character string.". Possible failure reasons: Problems with the query, "ResultSet" property not set correctly, parameters not set correctly, or connection not established correctly.
End Error
It could be another UPDATE or INSERT query, but the otehrs in question appear to have data that is proeprly typed from what I see,, so I am left onbly with the above.
No, it simply sounds like you have bad data in the MBR_DTH_DT column, which is VARCHAR but should be a date (once you clean out the bad data).
You can identify those rows using:
SELECT MBR_DTH_DT
FROM dbo.IPDP_MEMBER_DEMOGRAPHIC_DECBR
WHERE ISDATE(MBR_DTH_DT) = 0;
Now, you may only get rows that happen to match the where clause you're using to filter (e.g. MBR_DTH_DT = '00000000').
This has nothing to do with multiple processors, race conditions, etc. It's just that SQL Server can try to perform the cast before it applies the filter.
Randy suggests adding an additional clause, but this is not enough, because the CAST can still happen before any/all filters. You usually work around this by something like this (though it makes absolutely no sense in your case, when everything is the same column):
UPDATE dbo.IPDP_MEMBER_DEMOGRAPHIC_DECBR
SET MBR_DTH_DT = CASE
WHEN ISDATE(MBR_DTH_DT) = 1 THEN CAST(MBR_DTH_DT AS DATE)
ELSE MBR_DTH_DT END
WHERE MBR_DTH_DT <> '00000000';
(I'm not sure why in the question you're using UPDATE alias FROM table AS alias syntax; with a single-table update, this only serves to make the syntax more convoluted.)
However, in this case, this does you absolutely no good; since the target column is a string, you're just trying to convert a string to a date and back to a string again.
The real solution: stop using strings to store dates, and stop using token strings like '00000000' to denote that a date isn't available. Either use a dimension table for your dates or just live with NULL already.
Not likely. Even with multiple processors, there is no guarantee the query will processed in parallel.
Why not try something like this, assuming you're using SQL Server 2012. Even if you're not, you could write a UDF to validate a date like this.
UPDATE a
SET a.[MBR_DTH_DT] = cast(a.[MBR_DTH_DT] as date)
FROM [IPDP_MEMBER_DEMOGRAPHIC_DECBR] a
WHERE a.[MBR_DTH_DT] <> '00000000' And IsDate(MBR_DTH_DT) = 1
Most likely you have bad data are are not aware of it.
Whoops, just checked. IsDate has been available since SQL 2005. So try using it.

Cassandra: Cannot parse <col_Name> as hex bytes: MarshallException

I was trying my first 'Helloworld' application in Cassandra. Whenever I try to add any data to my keyspace column family I get this error:
[default#MyKeyspace] set User['ehewitt'] ['fname']='Eben';
org.apache.cassandra.serializers.MarshalException: cannot parse 'fname' as hex bytes
This is despite the fact that I have executed
[default#MyKeyspace] assume Users keys as utf8;
So the above command does not seem to have any effect at all. How do I solve this issue?
Cassandra is assuming the columns as bytes.
Check with
help assume;
assume User keys as ascii;
assume User comparator as ascii;
assume User validator as ascii;
assume User sub_comparator as ascii;
set User['ehewitt']['fname']='Eben';
Value inserted.
Elapsed time: 216 msec(s).
I had similar problem, but the cli told me that the value is what cannot be parsed.
set game_outcome['1']['userId']='123asdasd';
cannot parse '123asdasd' as hex bytes
so I tried to use utf8 function like this :
set game_outcome['1']['userId']=utf8('123asdasd');
cannot parse '123asdasd' as hex bytes
Try
set User['ehewitt'] [utf8('fname')]='Eben'
I tried to use set some assumption like this
assume validator keys as utf8;
validator not found in current keyspace.
But as you can see it did not work as well !
I hope this answer helps.
Starting the CLI
You can start the CLI using the bin/cassandra-cli script in your Cassandra installation (bin\cassandra-cli.bat on windows). If you are evaluating a local cassandra node then be sure that it has been correctly configured and successfully started before starting the CLI.
If successful you will see output similar to this:
Welcome to cassandra CLI.
Type 'help;' or '?' for help. Type 'quit;' or 'exit;' to quit.
You must then specify a system to connect to:
connect localhost/9160;
Creating a Keyspace
We first create a keyspace to run our examples in.
create keyspace Twissandra;
Selecting the keyspace to user
We must then select our example keyspace as our new context before we can run any queries.
use Twissandra;
To Create A Column
We can then create a column to play with.
create column family User with comparator = UTF8Type;
For the later examples to work you must also update the schema using the following command. This will set the return type for the first and last name to make them human readable. It will also add and index for the age field so that you filter your gets using the Users name field.
update column family User with
column_metadata =
[
{column_name: first, validation_class: UTF8Type},
{column_name: last, validation_class: UTF8Type},
{column_name: age, validation_class: UTF8Type, index_type: KEYS}
];
To Add Data
To add data we want to into our new column we must first specify our default key type otherwise we would have to specify it for each key using the format [utf8('keyname')] this is probably advisable if you have mixed key types but makes simple cases harder to read.
So we run the command below, which will last the length of you cli session. On quitting and restarting we must run it again.
assume User keys as utf8;
and then we add our data.
set User['jsmith']['first'] = 'John';
set User['jsmith']['last'] = 'Smith';
set User['jsmith']['age'] = '38';
If you get the error like this cannot parse 'John' as hex bytes, then it likely you either haven't set your default key type or you haven't updated your schema as in the create column example.
To Update Data
If we need to update a value we simply set it again.
set User['jsmith']['first'] = 'Jack';
To Get Data
Now let's read back the jsmith row to see what it contains:
get User['jsmith'];
The get command uses API#get_slice
To Query Data
get User where age = '12';

How to get a warning when a FLOAT value is inserted into an INT column in MySQL?

I have acreated a Table containing a column of type INT:
CREATE TEMPORARY TABLE `myTab` (`int` INT, `text` TEXT, `float` FLOAT);
Now I try to add a float value into the INT column
INSERT INTO `myTab` (`int`) VALUES (13.34);
I don't get a warning:
SHOW WARNINGS;
Although the column contains only 13 afterwards:
SELECT * FROM `myTab`;
Is it somehow possible to get a warning when a float value is added to a integer column? I'm currently using mysql Ver 14.14 Distrib 5.5.31, for debian-linux-gnu (i686) using readline 6.2
Add: I'd like to avoid adding a "check for dots" for each INT-column (How do I check to see if a value is an integer in MySQL?). I'd prefer a warning when data is lost during casting to INT.
You could use a DECIMAL(n, 0) type instead of INT. Attempting to insert a non-integer number into such a column does raise a warning.
CREATE TEMPORARY TABLE t (id DECIMAL); -- equivalent to the default DECIMAL(10, 0), which covers the range of INT
INSERT INTO t VALUES (0.9); -- raises warning "1265 - Data truncated for column 'id' at row 1"
SELECT * FROM t; -- 0.9 was rounded to 1
I am aware this is only a workaround, and certainly has a negative impact on performance (albeit probably minor). But this is the only approaching solution I have been able to come up with.
EDIT: I have tested different scenarios to try an get a warning or a least an error for this but with no luck so i suspect that its either a intended behavior or its a mysql bug (although i didn't found a already known bug that describes this) so i think the best/only solution is the one posted by YaK
Use this:
TRADITIONAL
Make MySQL behave like a “traditional” SQL database system. A simple
description of this mode is “give an error instead of a warning” when
inserting an incorrect value into a column.
set global sql_mode="TRADITIONAL";
For more info read this.
UPDATE: what i purposed above is to get a error instead of a warning because with the warning the data is still inserted thus you will have corrupt data but if you still want to use warnings instead of errors then you have to use the default sql_mode:
set global sql_mode="";
EDIT: be sure that the warnings are enabled :
set global sql_warnings=1;
better yet you can add it in the config file my.cnf so that it will not be overwritten when mysql restarts .

Unique fields on mySQL table - generating promo codes

I am developing a PHP script and I have a table like this:
TABLE_CODE
code varchar 8
name varchar 30
this code column has to be a code using random letters from A to Z and characters from 0 to 9 and has to be unique. all uppercase. Something like
A4RTX33Z
I have create a method to generate this code using PHP. But this is a intensive task because I have to query the database to see if the generated code is unique before proceeding and the table may have a lot of records.
Because I know mySQL is a bag of tricks but not having advanced knowledge about it now, I wonder if there's some mechanism that could be built in a table to run a script (or something) every time a new record in created on that table to fill the code column with a unique value.
thanks
edit: What I wonder is if there's a way to created the code on-the-fly, as the record is being added to the table and that code being unique.
Better generate these codes in SQL. This is 8-character random "Promo code generator":
INSERT IGNORE INTO
TABLE_CODE(name, code)
VALUES(
UPPER(SUBSTRING(MD5(RAND()) FROM 1 FOR 8)), -- random 8 characters fixed length
'your code name'
)
Add UNIQUE on code field as #JW suggested, and some error-handling in PHP, because sometimes generated value may be not UNIQUE, and MySQL will raise error in that situation.
Adding a UNIQUE constraint on the code column is the first thing you would need to do. Then, to insert the code I would write a small loop like this:
// INSERT IGNORE will not generate an error if the code already exists
// rather, the affected rows will be 0.
$stmt = $db->prepare('INSERT IGNORE INTO table_code (code, name) VALUES (?, ?)');
$name = 'whatever name';
do {
$code = func_to_generate_code();
$stmt->execute(array($code, $name));
} while (!$stmt->rowCount()); // repeat until at least one row affected
As the table grows the number of loops may increase, so if you feel it should only try three times, you could add it as a loop condition and throw an error if that happens.
Btw, I would suggest using transactions to make sure if an error occurs after the code generation, rolling back will make sure the code is removed (can be reused).