Null entering as 0 in the below query - mysql

In the below query I am saving into data base an array from multiple select2 options.
Here i have a database table participants with event_id(int, not null), user_id(int, null), p_mail(varchar, null).
When I pass proper id which is in users the data gets saved properly and null will be displayed in p_email column.
But when i pass some varchar values through array, the user_id is saved as 0 which should be NULL and Null is stored in p_email which should store the values.
foreach($resources as $r) {
global $response;
$sql = "INSERT INTO participants(event_id, user_id, p_email)
SELECT $response,
CASE
WHEN EXISTS (SELECT * from users where id = '$r') THEN
'$r'
ELSE NULL
END,
CASE
WHEN EXISTS (SELECT * from users where id = '$r') THEN
NULL
ELSE '$r'
END
FROM users WHERE id = 1;";
$query_result = $conn->query($sql) or die("Failed".$sql);
this is expected where it int is passed it should be stored in user_id column if id exists otherwise if its varchar it should be stored in p_email.
Present if I store a varchar which is not in users after checking instead of storing it in p_email. it stores null in p_email and 0 in user_id.

I think the issue here is that the id column is numeric. In the first test, you are presumably passing some legitimate numerical string id, such as '123'. MySQL has no issue internally converting between '123', the string, and 123, the number. However, in your second test, you are passing something like abc. In this case, MySQL appears to be converting that to a numeric value of 0. Also, assuming the id zero does exist, you would see NULL in your email column as well.
So, I think the correction here is to just bind numbers to your insert query, assuming the id column is really numeric.
And, you should read about using prepared statements in MySQL.

I cleared this issue by using LIKE instead of '=' in the code.

Related

Why MySQL "WHERE" clause approximation: retrieves values even the condition is not met

I have a table which primary key is numeric and auto-incremented.
When I run a query such as:
SELECT * FROM my_table where id = '1a';
The query returns the row with the primary key set to "1".
I was not aware of this behavior, is it possible to prevent it?
I was expecting this WHERE clause to retrieve nothing since the id is "1" and not "1a". It is behaving like it was a LIKE clause.
MySQL implicitly converts a String literal to int while comparing with an int column.
You should really fix your application code (eg: PHP), and properly typecast to (int) before using them in a query. Ideally, your application should not have been inputting string values to compare against an integer field.
Now still, if you don't have control over input value, an approach can be to check if the value is numeric or not, and use it accordingly for comparison. Adapting a sargable approach from https://dba.stackexchange.com/q/89760/160363
SELECT * FROM my_table
WHERE id = CASE WHEN CONCAT('','1a'*1) = '1a' THEN '1a' ELSE NULL END;
mysql automatically converts strings to numbers, and just takes the leading characters that are digits. You could instead explicitly cast the ID to a string:
SELECT * FROM my_table where CAST(id AS CHAR) = '1a';

Unexpected result using SELECT ... WHERE id = 0 on VARCHAR id in MySQL

I'm using MySQL 8 with InnoDB with a node server with mysql2 driver.
My table looks like:
CREATE TABLE IF NOT EXISTS users(
id VARCHAR(36) NOT NULL,
name VARCHAR(32) NOT NULL,
email VARCHAR(255) NOT NULL,
...
PRIMARY KEY (id)
)
I use no auto increment and as VARCHAR ids, I use time based UUIDs.
If I now do my SELECT query:
SELECT * FROM users where id = 'some valid id';
I get my expected result.
If I do:
SELECT * FROM users where id = '0';
I get nothing, because no id in my table has the value '0'.
BUT, if i do:
SELECT * FROM users where id = 0;
I get the last inserted row, which has, of course, a valid VARCHAR id different from 0.
This behavior occured on my node server by accident, because JS sometimes interpretes undefined as 0 in http querys.
In consequence I can easyly avoid inserting 0 in my querys (what I do now), but I would like to understand why this happens.
Your id is varchar(), so this comparison:
WHERE id = 0
requires type conversion.
According to the conversion rules in SQL, the id is turned into a string. Now, in many databases, you would get an error if any values of id could not be converted into numbers.
However, MySQL supports implicit conversion with no errors. (You can read about such conversion in the documentation.) This converts all leading digits to a number -- ignoring the rest. If there are no leading digits, then the value is zero. So, all these are true in MySQL:
'a' = 0
'0a' = 0'
'anything but 0!' = 0
There are two morals to this story.
If you really want id to be a number, then use a number data type (int, bigint, decimal).
Don't mix types in comparisons.

Making a field empty in mysql for one row

Assume I have the following in my users table:
id name email
'1', 'foo', 'foo#bar.com'
'2', 'foo2', 'foo2#bar.com'
'3', 'foo3', 'foo3#bar.com'
'4', 'foo4', 'foo4#bar.com'
Question 1)
If I want to delete a column data for one of the fields. Is it safe if I set it to NULL (Please see the following update query in my example); in other words is it safe for all data types in mysql (int, varchar, bit,...) to assign NULL to make it empty?
UPDATE users
SET email = NULL
WHERE id = 3;
The above update query empties email field for user with id 3, but please confim this is the valid solutoin for all datatypes...
Question2)
After making the email field empty for user with id of 3 the following query is returning nothing:
select * from users where email is NULL
Am I doing something wronmg here?
Please let me know if you need more clarification if the question is vague...
Thanks
If NULL is allowed for the column in the table definition, then you can set NULL to any data type. Your code should work. What happens when you run "select * from users" in a command line or use a database manager?
UPDATE users
SET email = ''
WHERE id = 3;

Conversion error with NULL column and SELECT INTO

I'm experimenting with temporary tables and running into a problem.
Here's some super-simplified code of what I'm trying to accomplish:
IF(Object_ID('tempdb..#TempTroubleTable') IS NOT NULL) DROP TABLE #TempTroubleTable
select 'Hello' as Greeting,
NULL as Name
into #TempTroubleTable
update #TempTroubleTable
set Name = 'Monkey'
WHERE Greeting = 'Hello'
select * from #TempTroubleTable
Upon attempting the update statement, I get the error:
Conversion failed when converting the varchar value 'Monkey' to data type int.
I can understand why the temp table might not expect me to fill that column with varchars, but why does it assume int? Is there a way I can prime the column to expect varchar(max) but still initialize it with NULLs?
You need to cast null to the datatype because by default its an int
Select 'hello' as greeting,
Cast (null as varchar (32)) as name
Into #temp

getting data directly from insert query after running it

i have a database i insert item into using php. i want to get the ID which is auto increment column, i read the manual and it says that the mysql_query returns a resource variable rather than boolean, is there any way to retreive data from that resouce?
echo $query_ins = "INSERT INTO `house` VALUES ('' , '$city', '$street', 'num');
$res = mysql_query($query_ins);
the first field is the ID field i am interested in.
i tried mysql_fetch_assoc and mysql_result function to convert the $res into array or retrieve data directly like i would do with SELECT query but no succes.
any suggestions?
See the manual: mysql_insert_id — Get the ID generated in the last query
This is really something you should have been able to find on your own easily, without posting to StackOverflow. It's to your advantage to review the documentation of any API you're using.
Re your comment:
SELECT * FROM house WHERE id = LAST_INSERT_ID()
This supposes you have an auto-incrementing primary key.
If you generate a nondeterministic primary key value on insert, for example using RAND() or UUID(), then there is effectively no way to retrieve the value generated. You should generate the value before doing the INSERT, so you have a literal value you can use to look up the row.
SET #r := RAND();
INSERT INTO house (id, ...) VALUES (#r, ...);
SELECT * FROM house WHERE id = #r;
MD5 is deterministic, so supposing you have an original key string that you hash, you should be able to retrieve the row using that MD5 expression and the original string.
INSERT INTO house (id, ...) VALUES (MD5('xyzzy'), ...);
SELECT * FROM house WHERE id = MD5('xyzzy');