Bizarre behavior in mysql running a query - mysql

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.

Related

Is there an equivalent way to do MySQL's JSONOBJECTAGG() in MariaDB?

The server I was working on for a data project crashed and I am now recreating the database. I used to be working on a MySQL database, and now I'm using MariaDB. I have never used MariaDB before.
Previously, I used the following command to insert some data into one table from another:
CREATE TABLE collaborators_list
SELECT awards.id, awards.researcher_name, awards.organization_id,
JSON_OBJECTAGG(awards.fiscal_year, coapplicants.coapplicant_name,
coapplicants.organization_number)
AS 'coapplicants_list' FROM awards
INNER JOIN coapplicants
ON awards.id=coapplicants.id
GROUP BY awards.researcher_name, awards.organization_id;
Basically, I want to do the same thing in MariaDB. I tried looking here:
https://mariadb.com/kb/en/library/json-functions/
but unless I am misreading something, none of these is what I really want...
Help!
No, MariaDB still does not support JSON_ARRAYAGG and JSON_OBJECTAGG functions. A JIRA ticket has been raised for requesting this feature: https://jira.mariadb.org/browse/MDEV-16620
Now, from the docs of JSON_OBJECTAGG():
It takes only two column names or expressions as arguments, the
first of these being used as a key and the second as a value.
An error occurs if any key name is NULL or the number of arguments is
not equal to 2.
However, you are specifying three arguments in JSON_OBJECTAGG(awards.fiscal_year, coapplicants.coapplicant_name, coapplicants.organization_number); so your attempted query will not work as well.
Now, in the absence of the required functions, we can utilize Group_Concat() with Concat(). I am assuming that you need only first two arguments (as explained in previous para).
GROUP_CONCAT( DISTINCT CONCAT('"', awards.fiscal_year, '": "',
coapplicants.coapplicant_name, '"')
SEPARATOR ', ')
Note that, in case of string getting very very long, Group_Concat() may truncate it. So, you can increase the allowed length, by executing the following query, before the above query:
SET SESSION group_concat_max_len = ##max_allowed_packet;

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.

MYSQL updates column with random but specific entry

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.)

count(*) on mysql giving me value 0

select count(*) FROM antecedente_delito WHERE rut_polichile = NEW.rut_polichile
this statement is giving de value 0, when it should give me 18 :/ ive been trying a lot to find any bug in it.
Here's the working solution that I mocked up using/changing your code in SqlFiddle. http://sqlfiddle.com/#!2/ac2e9/1
To trouble shoot this, I would view your actual values and verify that NEW. is returning what you think it should. Sometimes it may be doing some trims or removal of special characters, especially the _ and % signs are likely to stripped in subprocedures.
I would start with the query:
select top 50 rut_polichile, NEW.rut_plichile FROM antecedente_delito
If the issue is not obvious from that add in a varbinary check:
select top 50 cast( rut_polichile as varbinary), cast(NEW.rut_plichile as varbinary) from antecedente_delito
If the table only has 18 records, then you should be good to go with the above troubleshooting, but if there is more data, I would suggest limiting your results from the above by the rowid or other identifier in a where statement.
It's not the answer, but I hope it helps you find the answer.
The SELECT privilege for the subject table if references to table columns occur via OLD.col_name or NEW.col_name in the trigger definition.
but in your trigger i can't see any trigger definition. so try without NEW.
for more info: http://www.sqlinfo.net/mysqldocs/v51/triggers.html or
http://bugs.mysql.com/bug.php?id=31068

SQL query execution - different outcomes on Windows and Linux

The following is generated query from Hibernate (except I replaced the list of fields with *):
select *
from
resource resource0_,
resourceOrganization resourceor1_
where
resource0_.active=1
and resource0_.published=1
and (
resource0_.resourcePublic=1
or resourceor1_.resource_id=resource0_.id
and resourceor1_.organization_id=2
and (
resourceor1_.resource_id=resource0_.id
and resourceor1_.forever=1
or resourceor1_.resource_id=resource0_.id
and (
current_date between resourceor1_.startDate and resourceor1_.endDate
)
)
)
Currently I have 200+ records in both the Windows and Linux databases and currently for each record, the following happens to be true:
active = 1
published = 1
resourcePublic = 1
When I run this directly in a SQL client, this SQL query gets me all the matching records on Windows but none on Linux. I've MySQL 5.1 on both Windows and Linux.
If I apply the Boolean logic, (true and true and (true or whatever)), I expect the outcome to be true. It indeed is true on Windows but false on Linux!!!
If I modify the query as the following, it works on both Windows and Linux:
select *
from
resource resource0_
where
resource0_.active=1
and resource0_.published=1
and (
resource0_.resourcePublic=1
)
So, just the presence of conditions related to resourceOrganization is making the query bring 0 results on Linux and I expected that since it is the second part of an 'or' condition whose first part is true, the outcome should be true.
Any idea why this difference in behavior between the 2 OSs and why what should obviously work on Linux doesn't!
Thanks in advance!
Check the case sensitivity and collation sets (Collation issues)
Check the table case sensitivity. In particular note that on windows the table names are case-insensitive and on Linux they are case-sensitive.
Have you tried a simple test case on both system?
Check that current_date() returns the same format in both plataforms
I notice that the second test query only consults the resource table not the resourceOrganisation table.
I suspect that the table resourceOrganisation is populated differently on the two machines, and the corresponding rows may not exist in your Linux MySQL.
What does this query return?
select *
from
resource resource0_,
resourceOrganization resourceor1_
where
resource0_.active=1
and resource0_.published=1
and (
resource0_.resourcePublic=1
or resourceor1_.resource_id=resource0_.id
and resourceor1_.organization_id=2
)
Also don't forget to check the collation and case sensitivity, if one server uses a different collation to the other then you will have this same issue.