I want to have an empty field on a MySQL Numeric field. If I define the field to allow a NULL value it defaults to 0.00. Sometimes for this row item I prefer no value. I could probably create a different table to track these few items, but at this point I prefer a one table solution.
Because you did this with DEFAULT. Don't do that:
create table t1
( id int auto_increment primary key,
thing varchar(100) not null,
anInt NUMERIC(5,2) NULL DEFAULT 0
);
insert t1(thing) values ('fish');
select * from t1;
+----+-------+-------+
| id | thing | anInt |
+----+-------+-------+
| 1 | fish | 0.00 |
+----+-------+-------+
Works for me on mysql 5.7.12:
mysql> create table X (a double null);
Query OK, 0 rows affected (0.01 sec)
mysql> desc X;
+-------+--------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------+------+-----+---------+-------+
| a | double | YES | | NULL | |
+-------+--------+------+-----+---------+-------+
1 row in set (0.00 sec)
mysql> alter table X add column b int;
Query OK, 0 rows affected (0.01 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> desc X;
+-------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| a | double | YES | | NULL | |
| b | int(11) | YES | | NULL | |
+-------+---------+------+-----+---------+-------+
2 rows in set (0.00 sec)
mysql> insert into X (a) values (1.3);
Query OK, 1 row affected (0.00 sec)
mysql> insert into X (b) values (1);
Query OK, 1 row affected (0.00 sec)
mysql> select * from X;
+------+------+
| a | b |
+------+------+
| 1.3 | NULL |
| NULL | 1 |
+------+------+
2 rows in set (0.00 sec)
Related
I used the code below to change VARCHAR from (20) to (40) but no change happened in my table:
mysql> ALTER TABLE create_user modify email VARCHAR(40);
Query OK, 0 rows affected (0.02 sec)
Records: 0 Duplicates: 0 Warnings: 0
But i use your code can accomplish.
mysql> desc create_user;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| email | varchar(40) | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+
1 row in set (0.00 sec)
mysql> Alter table create_user modify email varchar(20);
Query OK, 0 rows affected (0.04 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> desc create_user;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| email | varchar(20) | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+
1 row in set (0.00 sec)
As per my comment you should run commit but that also means your auto commit settings are different from the default. you may want to look into that further to prevent future headaches
https://dev.mysql.com/doc/refman/5.7/en/commit.html
Here is my table:
// table
+----+--------+
| id | number |
+----+--------+
| 1 | 123 |
| 2 | 123. |
| 3 | 12.3 |
+----+--------+
I want this:
// newtable
+----+--------+
| id | number |
+----+--------+
| 1 | 123 |
| 2 | 123 |
| 3 | 12.3 |
+----+--------+
How can I do that?
I can do that like this: (But I'm searching for faster and better approach)
// Not tested, But I think this works!
SELECT
id,
IF(RIGHT(number,1) == '.', REPLACE(number, '.', ''), number)
FROM table
// also I can use CAST(number as unsigned) instead of REPLACE(number, '.', '')
Well, is there any better solution? (without IF-statement)
SELECT id, CONVERT(number, DECIMAL(10,6)) FROM test
remove last corresponding characters if exist
SELECT id, TRIM(TRAILING '.' FROM number) FROM test
use this if you want to change the data in the table
mysql> CREATE TABLE test(
-> id INT(1),
-> number VARCHAR(5)
-> );
Query OK, 0 rows affected (0.02 sec)
mysql> INSERT INTO test
-> VALUES(1, '123'),
-> (2, '123.'),
-> (3, '12.3');
Query OK, 3 rows affected (0.00 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> SELECT * FROM test;
+------+--------+
| id | number |
+------+--------+
| 1 | 123 |
| 2 | 123. |
| 3 | 12.3 |
+------+--------+
3 rows in set (0.00 sec)
mysql> UPDATE test
-> SET number=REPLACE(number, '.', '')
-> WHERE RIGHT(number,1) = '.';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> SELECT * FROM test;
+------+--------+
| id | number |
+------+--------+
| 1 | 123 |
| 2 | 123 |
| 3 | 12.3 |
+------+--------+
3 rows in set (0.00 sec)
and use this if you want just to get the data in this form
mysql> DROP TABLE IF EXISTS test;
Query OK, 0 rows affected (0.01 sec)
mysql> CREATE TABLE test(
-> id INT(1),
-> number VARCHAR(5)
-> );
Query OK, 0 rows affected (0.02 sec)
mysql> INSERT INTO test VALUES
-> (1, '123'),
-> (2, '123.'),
-> (3, '12.3')
-> ;
Query OK, 3 rows affected (0.01 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> SELECT * FROM test;
+------+--------+
| id | number |
+------+--------+
| 1 | 123 |
| 2 | 123. |
| 3 | 12.3 |
+------+--------+
3 rows in set (0.00 sec)
mysql> SELECT
-> id,
-> CASE
-> WHEN RIGHT(number,1) = '.' THEN floor(number)
-> ELSE number
-> END AS number
-> from test;
+------+--------+
| id | number |
+------+--------+
| 1 | 123 |
| 2 | 123 |
| 3 | 12.3 |
+------+--------+
3 rows in set (0.00 sec)
I am having issues inserting Id fields from two tables into a single record in a third table.
mysql> describe ing_titles;
+----------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+------------------+------+-----+---------+----------------+
| ID_Title | int(10) unsigned | NO | PRI | NULL | auto_increment |
| title | varchar(64) | NO | UNI | NULL | |
+----------+------------------+------+-----+---------+----------------+
2 rows in set (0.22 sec)
mysql> describe ing_categories;
+-------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+------------------+------+-----+---------+----------------+
| ID_Category | int(10) unsigned | NO | PRI | NULL | auto_increment |
| category | varchar(64) | NO | UNI | NULL | |
+-------------+------------------+------+-----+---------+----------------+
2 rows in set (0.02 sec)
mysql> describe ing_title_categories;
+-------------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------------+------------------+------+-----+---------+----------------+
| ID_Title_Category | int(10) unsigned | NO | PRI | NULL | auto_increment |
| ID_Title | int(10) unsigned | NO | MUL | NULL | |
| ID_Category | int(10) unsigned | NO | MUL | NULL | |
+-------------------+------------------+------+-----+---------+----------------+
3 rows in set (0.04 sec)
Let's say the data from the tables is:
mysql> select * from ing_titles;
+----------+-------------------+
| ID_Title | title |
+----------+-------------------+
| 3 | Chicken |
| 2 | corn |
| 1 | Fettucini Alfredo |
+----------+-------------------+
3 rows in set (0.00 sec)
mysql> select * from ing_categories;
+-------------+----------+
| ID_Category | category |
+-------------+----------+
| 1 | Dinner |
| 3 | Meat |
| 2 | Veggie |
+-------------+----------+
3 rows in set (0.00 sec)
I want to insert into ing_title_categories the record "corn, Veggie" or where ID_Title = 2 and ID_Category = 2.
Here's what I tried:
INSERT INTO ing_title_categories (ID_Title, ID_Category)
SELECT ing_titles.ID_Title, ing_categories.ID_Category
FROM ing_title_categories
LEFT JOIN ing_titles ON ing_title_categories.ID_Title=ing_titles.ID_Title
LEFT JOIN ing_categories ON ing_title_categories.ID_Category=ing_categories.ID_Category
WHERE (ing_titles.ID_Title=2) AND (ing_categories.ID_Category = 2);
There is no data inserted into the table ing_title_categories, and here is the reply from MySQL:
Query OK, 0 rows affected (0.00 sec)
Records: 0 Duplicates: 0 Warnings: 0
What is the correct syntax for inserting the ing_titles.ID_Title and ing_categories.ID_Category into the table ing_titles_categories?
Please, no PHP or Python examples. Use SQL that I can copy and paste into the MySQL prompt. I will be adding this to a C++ program, not PHP, JavaScript or Python.
Edit 1:
The ing_title_categories.ID_Title and ing_title_categories.ID_Category are foreign keys into the other tables.
INSERT INTO
ing_title_categories (ID_Title, ID_Category)
SELECT
ing_titles.ID_Title, ing_categories.ID_Category
FROM
ing_titles, ing_categories
WHERE
ing_titles.ID_Title = ing_categories.ID_Category AND
ing_titles.ID_Title = 2 AND ing_categories.ID_Category = 2;
SQL Fiddle demo
After taking advice from #DrewPierce and #KaiserM11, here is the MySQL sequence:
mysql> INSERT INTO ing_title_categories (ID_Title, ID_Category)
-> SELECT
-> ing_titles.ID_Title,
-> ing_categories.ID_Category
-> FROM ing_titles, ing_categories
-> where (ing_titles.ID_Title = 2) AND (ing_categories.ID_Category = 2)
-> ;
Query OK, 1 row affected (0.07 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> select * from ing_title_categories;
+-------------------+----------+-------------+
| ID_Title_Category | ID_Title | ID_Category |
+-------------------+----------+-------------+
| 17 | 2 | 2 |
+-------------------+----------+-------------+
1 row in set (0.00 sec)
In this case, only possible way I see is using a UNION query like
INSERT INTO ing_title_categories (ID_Title, ID_Category)
SELECT Title, NULL
FROM ing_title WHERE ID_Title = 2
UNION
SELECT NULL, category
FROM ing_categories
WHERE ID_Category = 2
(OR)
You can change your table design and use an AFTER INSERT trigger to perform the same in one go.
EDIT:
If you can change your table design to something like below (No need of that extra chaining table)
ing_titles(ID_Title int not null auto_increment PK, title varchar(64) not null);
ing_categories( ID_Category int not null auto_increment PK,
category varchar(64) not null,
ing_titles_ID_Title int not null,
FOREIGN KEY (ing_titles_ID_Title)
REFERENCES ing_titles(ID_Title));
Then you can use a AFTER INSERT trigger and do the insertion like
DELIMITER //
CREATE TRIGGER ing_titles_after_insert
AFTER INSERT
ON ing_titles FOR EACH ROW
BEGIN
-- Insert record into ing_categories table
INSERT INTO ing_categories
( category,
ing_titles_ID_Title)
VALUES
('Meat' NEW.ID_Title);
END; //
DELIMITER ;
Table looks like:
mysql> DESC text;
+-----------------+--------------+------+-----+-------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+--------------+------+-----+-------------------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| text | varchar(255) | YES | | NULL | |
+-----------------+--------------+------+-----+-------------------+----------------+
2 rows in set (0.00 sec)
and AUTO_INCREMENT is 1:
mysql> ALTER TABLE text AUTO_INCREMENT = 1;
Query OK, 1 row affected (0.36 sec)
Records: 1 Duplicates: 0 Warnings: 0
but I get strange id like:
mysql> SELECT id FROM text;
+------------+
| id |
+------------+
| 2147483647 |
+------------+
1 row in set (0.00 sec)
What is the problem?
When you change the auto increment it is set to greatest(your_value,max(column)+ 1)
though I cant find the part in the docs which mention it, it is in the comments
http://dev.mysql.com/doc/refman/5.0/en/example-auto-increment.html
ALTER TABLE text AUTO_INCREMENT = 1;
then check the result of
SELECT `AUTO_INCREMENT`
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'DatabaseName'
AND TABLE_NAME = 'text';
to confirm that its not actually 1
MySQL provides 2 ways to check truth value of boolean columns, those are column_variable = true and column_variable is true. I created a table, inserted few values & tried a few select statements. Here are the results:
First I created this table:
mysql> create table bool_test (
-> id int unsigned not null auto_increment primary key,
-> flag boolean );
Query OK, 0 rows affected (0.13 sec)
Then I inserted 4 rows:
mysql> insert into bool_test(flag) values (true),(false),(9),(null);
mysql> select * from bool_test;
+----+------+
| id | flag |
+----+------+
| 1 | 1 |
| 2 | 0 |
| 3 | 9 |
| 4 | NULL |
Here are all the select queries I fired on this table:
mysql> select * from bool_test where flag;
+----+------+
| id | flag |
+----+------+
| 1 | 1 |
| 3 | 9 |
+----+------+
2 rows in set (0.49 sec)
mysql> select * from bool_test where flag = true;
+----+------+
| id | flag |
+----+------+
| 1 | 1 |
+----+------+
1 row in set (0.02 sec)
mysql> select * from bool_test where flag is true;
+----+------+
| id | flag |
+----+------+
| 1 | 1 |
| 3 | 9 |
+----+------+
2 rows in set (0.04 sec)
mysql> select * from bool_test where flag = false;
+----+------+
| id | flag |
+----+------+
| 2 | 0 |
+----+------+
1 row in set (0.01 sec)
mysql> select * from bool_test where flag is false;
+----+------+
| id | flag |
+----+------+
| 2 | 0 |
+----+------+
1 row in set (0.00 sec)
mysql> select * from bool_test where !flag;
+----+------+
| id | flag |
+----+------+
| 2 | 0 |
+----+------+
1 row in set (0.00 sec)
mysql> select * from bool_test where not flag;
+----+------+
| id | flag |
+----+------+
| 2 | 0 |
+----+------+
1 row in set (0.00 sec)
mysql> select * from bool_test where flag != true;
+----+------+
| id | flag |
+----+------+
| 2 | 0 |
| 3 | 9 |
+----+------+
2 rows in set (0.00 sec)
mysql> select * from bool_test where flag is not true;
+----+------+
| id | flag |
+----+------+
| 2 | 0 |
| 4 | NULL |
+----+------+
2 rows in set (0.00 sec)
mysql> select * from bool_test where flag != false;
+----+------+
| id | flag |
+----+------+
| 1 | 1 |
| 3 | 9 |
+----+------+
2 rows in set (0.04 sec)
mysql> select * from bool_test where flag is not false;
+----+------+
| id | flag |
+----+------+
| 1 | 1 |
| 3 | 9 |
| 4 | NULL |
+----+------+
3 rows in set (0.00 sec)
My Question is: when is it advisable to use is/is not and when is it advisable to use =/!= with true/false ? Which one is vendor independent?
MySQL is actually fooling you. It doesn't have a boolean column type at all:
BOOL, BOOLEAN
These types are synonyms for TINYINT(1). A value of zero is considered
false. Nonzero values are considered true:
Also, the boolean literals are not such:
The constants TRUE and FALSE evaluate to 1 and 0, respectively.
Considering that:
Many database systems do not have booleans either (not at least in standard SQL and column types)
MySQL doesn't have an easy way to enforce 0 or 1 in BOOLEAN
My conclusion would be:
You'll have to use WHERE IS flag or just WHERE flag because = simply doesn't work correctly. Which one, is possibly a matter of preference.
Whatever you choose, no option will be vendor independent. For instance, Oracle won't even run either of them.
Edit: if cross-platform is a must, I'd go for this:
WHERE flag=0
WHERE flag<>0
I'm sure we've all done it lots of times.
If the flag column is indexed and all values are either 0 or 1, where flag = true is much faster than where flag is true.
During our testing, is true resulted in a “full table scan” and took 1.121 seconds, while = true was executed with “key lookup” and only took 0.167 seconds. The table had about 3 million rows.