Delete a row (Record) in MySQL - mysql

Here is my code to delete my first row.
But not effected!
mysql> select * from myt;
+--------+--------------+------+---------+
| Fname | Lname | age | phone |
+--------+--------------+------+---------+
| NULL | Jackson | NULL | NULL |
| stive | NULL | NULL | NULL |
| ghbfgf | rtrgf | 22 | 111 |
| zxas | zxa | 30 | 6547812 |
| wewew | uytree | 22 | 658478 |
+--------+--------------+------+---------+
5 rows in set (0.00 sec)
mysql> delete from myt
-> Where Fname = "NULL";
Query OK, 0 rows affected (0.00 sec)
Thanks!

use IS NULL.
You cannot use arithmetic comparison operators such as =, <, or <> to test for NULL.
DELETE FROM myt WHERE Fname IS NULL
Working with NULL Values

NULL is not a value.
NULL means nothing is present.
So usage of FNAME = "NULL" is wrong.
delete from myt Where Fname IS NULL;

Your first row is NULL (none) not "NULL"

NULL is not a value in RDBMS; it is a marker for a missing value. When you are using "NULL" it denotes a string value. You can simply use "IS NULL". Hope this helps.

Related

Why mysql matching rows don't update?

For some reasons it seems that the rows are not being updated. Any idea why this would happen ?
UPDATE hts SET assigned='1' AND Owner='ms' WHERE hid='217477'
Query OK, 0 rows affected (0.16 sec)
Rows matched: 1 Changed: 0 Warnings: 0
select assigned, Owner from hts where hid='217477';
+----------+-------+
| assigned | Owner |
+----------+-------+
| NULL | NULL |
+----------+-------+
Show columns from hts
+------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+-------+
| hid | varchar(25) | YES | UNI | NULL | |
| assigned | int(11) | NO | | 0 | |
| Owner | varchar(10) | YES | | NULL | |
+------------+--------------+------+-----+---------+-------+
two things you can try..
first try removing the AND from the SET.. usually you do that with a comma..
UPDATE hts SET assigned=1, Owner='ms' WHERE hid='217477'
second try removing the quotes form the hid if it is an INT and not a VARCHAR
UPDATE hts SET assigned=1, Owner='ms' WHERE hid=217477
not sure why you are storing integers as strings.. when in doubt you should ALWAYS store data by its intended datatype.
RECOMMENDATION: change the datatypes if they are varchar to int. your update would look like this.
UPDATE hts SET assigned=1, Owner='ms' WHERE hid=217477
assigned should be integer as well as hid

MySQL SELECT column FROM table WHERE column IS NULL

This is not working for me, using Toad for MySQL. I'm using MySQL 5.5 from XAMPP 1.83 on Windows.
I have a table with column InstitutionState defined as VARCHAR(20). Some rows appear to have this column "empty", meaning LENGTH(InstitutionState) = 0.
If I SELECT ... WHERE InstitutionState IS NULL, I get no rows.
If I SELECT ... WHERE InstitutionState = '', It works. Why is this?
Here's sample data.
mysql> select InstitutionState, ISNULL(InstitutionState), length(InstitutionState)
-> from institution;
+----------------------+--------------------------+--------------------------+
| InstitutionState | ISNULL(InstitutionState) | length(InstitutionState) |
+----------------------+--------------------------+--------------------------+
| NY | 0 | 2 |
| NY | 0 | 2 |
| NY | 0 | 2 |
| IL | 0 | 2 |
| NC | 0 | 2 |
| TX | 0 | 2 |
| DC | 0 | 2 |
| NY | 0 | 2 |
| CA | 0 | 2 |
| | 0 | 0 |
| KS | 0 | 2 |
| | 0 | 0 |
| NY | 0 | 2 |
| ND | 0 | 2 |
| PA | 0 | 2 |
| WI | 0 | 2 |
| PA | 0 | 2 |
| MD | 0 | 2 |
| IN | 0 | 2 |
| PA | 0 | 2 |
| NE | 0 | 2 |
| ID | 0 | 2 |
| CA | 0 | 2 |
| | 0 | 0 |
| FL | 0 | 2 |
| MO | 0 | 2 |
| | 0 | 0 |
| OH | 0 | 2 |
| IL | 0 | 2 |
| OH | 0 | 2 |
Conceptually, NULL means “a missing unknown value”
OR
NULL means no data, emptiness, nothing, unknown, missing value, etc. The value empty string means an empty string.
Confusing the NULL value and the empty string may cause data integrity problem.
What NULL means in the context of a relational database is that the pointer to the character field is set to 0x00 in the row's header, therefore no data to access.
NULL and '' take up the exact same number of bytes on the disk.
Hence, there is no space savings.
You can add an index on a column that can have NULL values. Otherwise, you must declare an indexed column NOT NULL, and you cannot insert NULL into the column.
Furthermore, allowing NULL is a less restrictive configuration than disallowing NULL. It only follows that if any entity integrity issues are to arise, it would be from FEWER checks that the data are sound. Therefore, logically, allowing NULL should always have a good, solid reason, and disallowing NULL is a good practice.
mysql> INSERT INTO ... (InstitutionState) VALUES (NULL);
mysql> INSERT INTO ... (InstitutionState) VALUES ('');
Both statements will insert a value into the InstitutionState column, but the first inserts a NULL value and the second inserts an empty string. The meaning of the first can be regarded as “InstitutionState is not known” and the meaning of the second can be regarded as “the Institution is known to have no state, and thus no InstitutionState.”
To search for column values that are NULL, you cannot use an expr = NULL test. The following statement returns no rows, because expr = NULL is never true for any expression:
mysql> SELECT ... WHERE InstitutionState = NULL;
To look for NULL values, you must use the IS NULL test. The following statements show how to find the NULL InstitutionState and the empty InstitutionState:
mysql> SELECT ... WHERE InstitutionState IS NULL;
mysql> SELECT ... WHERE InstitutionState = '';
mysql> SELECT 1 IS NULL, 1 IS NOT NULL;
+-----------+---------------+
| 1 IS NULL | 1 IS NOT NULL |
+-----------+---------------+
| 0 | 1 |
+-----------+---------------+
You cannot use arithmetic comparison operators such as =, <, or <> to test for NULL. To demonstrate this for yourself, try the following query:
mysql> SELECT 1 = NULL, 1 <> NULL, 1 < NULL, 1 > NULL;
+----------+-----------+----------+----------+
| 1 = NULL | 1 <> NULL | 1 < NULL | 1 > NULL |
+----------+-----------+----------+----------+
| NULL | NULL | NULL | NULL |
+----------+-----------+----------+----------+
In addition,
In MyISAM MYSQL you save one bit per row not using NULL.
While a NULL itself does not require any storage space, NDBCLUSTER reserves 4 bytes per row if the table definition contains any columns defined as NULL, up to 32 NULL columns. (If a MySQL Cluster table is defined with more than 32 NULL columns up to 64 NULL columns, then 8 bytes per row is reserved.)
It also makes the database work faster.
To get '' AND NULLs,
We would use:
SELECT ... WHERE IFNULL(InstitutionState , '') = '';
Which says if the field is NULL pretend that it is an empty string i.e. ''.
The NULL value isn't an actual value in SQL, but the lack of a value. One can think of it as unknown. For that reason, not even NULL is equal to another null.
Null values are actually implemented as a bitmask on the row, which indicate which columns have null values. So, these values aren't even stored on the heap table in the same way as other values, which is one of the reasons why you have to explicitly declare a column as nullable.
The string '' is actually known. It's known to be ''. This isn't null, nor is that null bit set on the tuple.
For this reason, querying for rows where a column IS NULL will not return rows with a value of '' nor will querying for rows where a column is '' return null values. They are two completely different things.
There are actually a few exceptions. For example, in Oracle, any reference to '' will be implicitly cast to NULL. This behavior was implemented back in the 80s before a real SQL standard, so Oracle has had to maintain it for backwards compatibility reasons.

Can a primary key be empty? If yes why did this alter cause this result?

I have the following table:
mysql> DESC my_contacts;
+----------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| id | varchar(20) | NO | PRI | | |
| location | varchar(20) | YES | | NULL | |
| city | varchar(20) | YES | | NULL | |
| state | varchar(2) | YES | | NULL | |
+----------+-------------+------+-----+---------+-------+
4 rows in set (0.01 sec)
If I do a select all I get:
mysql> SELECT * FROM my_contacts;
+----+--------------+------+-------+
| id | location | city | state |
+----+--------------+------+-------+
| 1 | Chester,NJ | NULL | NULL |
| 2 | Katy,TX | NULL | NULL |
| 3 | San Mateo,CA | NULL | NULL |
+----+--------------+------+-------+
3 rows in set (0.00 sec)
I run the following command:
INSERT INTO my_contacts (city,state)
VALUES
(SUBSTRING_INDEX(location,',',1),RIGHT(location,2));
My purpose was to populate the columns city and state with the part before the comma and the part after the comma from the location column.
But the following happened to my table:
mysql> INSERT INTO my_contacts (city,state)
-> VALUES
-> (SUBSTRING_INDEX(location,',',1),RIGHT(location,2));
Query OK, 1 row affected (0.02 sec)
mysql> SELECT * FROM my_contacts;
+----+--------------+------+-------+
| id | location | city | state |
+----+--------------+------+-------+
| | NULL | NULL | NULL |
| 1 | Chester,NJ | NULL | NULL |
| 2 | Katy,TX | NULL | NULL |
| 3 | San Mateo,CA | NULL | NULL |
+----+--------------+------+-------+
4 rows in set (0.00 sec)
I get a record and the id which is the primary key is empty. How is this possible?
I mean it is not NULL but a primary key is not supposed to be empty either right?
You defined your id field as a varchar, which is a dumb idea when you're using it to store integers. an empty field is NOT null. a zero-length string is still a valid string, and therefore a valid id value as far as your table is concerned. Try inserting ANOTHER blank string and you'll get a primary key violation:
INSERT INTO yourtable (id) VALUES (''); // will not work
The id field should be an int type. That'd disallow "empty" values.
primary keys are unique so if you alter the table, then the second row will attempt to add an empty value and fail. as a result, it will attempt the next possible value. If you want the first value not to be empty, you can set a default value.
It's not empty. It's probably an empty string. Note that the datatype is varchar(20).
Well, you didn't assign a value to the primary key field, so the default is NULL.
.
You want to modify the table so the primary key is auto_increment.
You can use a varchar as a foreign key related to another database table, but if you wish to use it as a numerical key, you should utilize a numerical data type such as int.
I know this doesn't answer the precise question regarding the primary key, but as your question does point out the fact you are also having issues parsing out the city and state from your location column, here's the query you would want to use (note you want an UPDATE to modify existing rows, not an INSERT which will add new rows rather than columns):
UPDATE my_contacts
SET
city = substr(location, 1, locate(',', location) - 1),
state = substr(location, locate(',', location) + 1);

Mysql, as 1 query, if row does not exist, do other query

For a preferences module I have "system defaults", and "user preferences".
If there is no personal/user preference stored, then use the system default values instead.
Here is my system preferences table:
mysql> desc rbl;
+-------------+---------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------+---------------------+------+-----+---------+-------+
| id | varchar(3) | NO | PRI | | |
| rbl_url | varchar(100) | NO | | | |
| description | varchar(100) | NO | | | |
| is_default | tinyint(1) unsigned | YES | | 1 | |
+-------------+---------------------+------+-----+---------+-------+
4 rows in set (0.00 sec)
Example data from system prefs:
mysql> select * from rbl;
+----+----------------------+------------------------------+------------+
| id | rbl_url | description | is_default |
+----+----------------------+------------------------------+------------+
| 1 | sbl-xbl.spamhaus.org | Spamhaus SBL-XBL | 1 |
| 2 | pbl.spamhaus.org | Spamhaus PBL | 1 |
| 3 | bl.spamcop.net | Spamcop Blacklist | 1 |
| 4 | rbl.example.com | Example RBL - not functional | 0 |
+----+----------------------+------------------------------+------------+
... and Query for system defaults:
mysql> SELECT rbl_url FROM rbl WHERE is_default='1';
+----------------------+
| rbl_url |
+----------------------+
| sbl-xbl.spamhaus.org |
| pbl.spamhaus.org |
| bl.spamcop.net |
+----------------------+
3 rows in set (0.01 sec)
So far so good.
OK. Now I need a user preferences table, and I came up with this:
mysql> desc rbl_pref;
+-----------+-----------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+-----------------------+------+-----+---------+----------------+
| id | mediumint(8) unsigned | NO | PRI | NULL | auto_increment |
| domain_id | mediumint(8) unsigned | NO | | NULL | |
| rbl_id | tinyint(1) unsigned | NO | | NULL | |
+-----------+-----------------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)
(FYI - A "user" is represented by "domain_id". )
Let's view the preferences of a specific user who has personalized preferences saved:
mysql> select * from rbl_pref where domain_id='2277';
+----+-----------+--------+
| id | domain_id | rbl_id |
+----+-----------+--------+
| 4 | 2277 | 1 |
| 5 | 2277 | 2 |
| 6 | 2277 | 4 |
+----+-----------+--------+
3 rows in set (0.00 sec)
... again, but in a simpler format:
mysql> SELECT rbl.rbl_url FROM rbl_pref,rbl
WHERE rbl_pref.rbl_id=rbl.id AND domain_id='2277';
+----------------------+
| rbl_url |
+----------------------+
| sbl-xbl.spamhaus.org |
| pbl.spamhaus.org |
| rbl.example.com |
+----------------------+
3 rows in set (0.00 sec)
.. so far so good. If a user has stored a preference, a result is found.
The problem example now is, user 1999 has no custom preferences.
In place of the "Empty set" result, I want the system defaults.
mysql> SELECT rbl.rbl_url FROM rbl_pref,rbl
WHERE rbl_pref.rbl_id=rbl.id AND domain_id='1999';
Empty set (0.00 sec)
I was excited to find a very similar question:
mysql if row doesn't exist, grab default value
However after a couple of days trial and error and documentation review, I could not translate that answer over to here.
Like the above question, this must be done as a single MySQL query. I am not actually making this query from PHP, but from Exim macros (and it is a very picky language... best to feed it "one liners" as variable assignments, as I try to do here.. )
UPDATE: Tried one type of a UNION query suggested by #Biff McGriff, below. The table did not display in my comment reply, so here it is again:
mysql> SELECT rbl.rbl_url FROM rbl_pref,rbl
WHERE rbl_pref.rbl_id=rbl.id AND domain_id='2277'
UNION SELECT rbl_url FROM rbl WHERE is_default='1';
+----------------------+
| rbl_url |
+----------------------+
| sbl-xbl.spamhaus.org |
| pbl.spamhaus.org |
| rbl.example.com |
| bl.spamcop.net |
+----------------------+
4 rows in set (0.00 sec)
As you can see above, user 2277 did not opt in to rbl_id 3 (bl.spamcop.net), but that's showing up anyways.
What my UNION query seems to be doing is combining the result set. So user_pref acts as "in addition to" global defaults, and I was assuming/expecting I would get a result set matching either half of the query.
So my question now is, is it better (or possible, how) to solve this as "either result set" (either subquery on either side of the UNION)? OR do I really need a new field on rbl_pref, called for example "enabled". The latter seems to be more correct - that I need something in rbl_pref to explicitly designate opt-in or opt-out (other than the implicit "that pref is not here - no rbl_id=3 - in the over ridden user result SET")
UPDATE: All set, thanks #Imre L, and everyone else. I learned something through this example.
You should be able to use a left join and then coalesce the user's field with the default field.
NOTE: you have to enter the domain_id in two places.
SELECT rbl.rbl_url FROM rbl
JOIN rbl_pref ON rbl_pref.rbl_id=rbl.id AND domain_id=2277
UNION
SELECT rbl.rbl_url FROM rbl
WHERE rbl.is_default
AND NOT EXISTS (SELECT 1 FROM rbl_pref WHERE domain_id=2277 LIMIT 1)
;
Now one or the other side of UNION will be optimized away with impossible where
You also should not use varchar(3) for rbl.id but some sort of integer
and preferable same type as rbl_pref.rbl_id for which tinyint is too tiny
and when you compare integers fields in sql code domain_id='2277' you should not use ' or " around constants integers.
You can get away whith it mostly but sometimes it may confuse mysql optimizer.
Also for optimal performance and consistency i suggest you the add the index:
ALTER TABLE rbl_pref
ADD UNIQUE INDEX ux_domain_rbl (domain_id, rbl_id);

Converting MySQL warning into an error

Is there any way to convert the warning that MySQL is issuing about an invalid datetime into a hard error? I've tried using SET sql_mode='TRADITIONAL'; which apparently is supposed to turn (some) things that are warnings into errors, but it does not have any effect here. This is MySQL 5.1.56. Something that works on a session-level would be ideal, but I'll take what I can get.
mysql> describe test_table2;
+----------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| value | int(11) | YES | | NULL | |
| name | varchar(16) | YES | | NULL | |
| sometime | datetime | YES | | NULL | |
+----------+-------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
mysql> select * from test_table2;
+-------+-------+---------------------+
| value | name | sometime |
+-------+-------+---------------------+
| 1 | one | 2002-09-01 10:00:00 |
| 2 | two | 2002-09-02 11:00:00 |
| 3 | three | 2002-09-03 12:00:00 |
| 4 | four | 2002-01-04 13:00:00 |
| 5 | five | 2002-01-05 14:00:00 |
+-------+-------+---------------------+
5 rows in set (0.00 sec)
mysql> select * from test_table2 where sometime = 'foo';
Empty set, 2 warnings (0.00 sec)
Warning (Code 1292): Incorrect datetime value: 'foo' for column 'sometime' at row 1
Warning (Code 1292): Incorrect datetime value: 'foo' for column 'sometime' at row 1
With SET sql_mode='TRADITIONAL', doing an INSERT with an invalid date causes an error, but doing a SELECT with an invalid date still causes a warning. You can trigger the error by passing the (possibly invalid) date value to this query first:
CREATE TEMPORARY TABLE IF NOT EXISTS date_guard (date DATE) SELECT 'foo' AS date;
where 'foo' is the date value you want to validate.
Who is supposed to see the error?
If this is a fixed string 'foo' just try converting 'foo' to a date and see if you can a valid result (i.e. not 00-00-000). Do a pre-query to check the validity of the date, and then continue after.
I have not been able to make MySQL give an error in this case (or even convert the invalid date to a NULL - it insists on making it 00-00-0000).