Null or empty instead of 0 - mysql

I created a new table with:
CREATE TABLE `test`.`tab1` ( `id` INT NOT NULL AUTO_INCREMENT , `name` VARCHAR(50) NULL , `age` INT NULL , PRIMARY KEY (`id`));
When I insert a new row, but want to keep age empty, I do:
INSERT INTO `tab1` (`id`, `Name`, `Age`) VALUES (NULL, 'Peter', '');
I get this entry:
| id | name | age |
|----|-------|-----|
| 1 | Peter | 0 |
Why the age column just doesn't remain empty or NULL?
How can I set a default value, so that it just remains empty, when no value is specified while inserting?

Since the column is of type int the DB tries to convert the string '' to a number. That would be 0.
Just use null instead of '' if you don't have a value. That is what null is for.

Related

MySQL INSERT INTO query column value equals another SQL SELECT query

Could anybody kindly guide me on correct direction for below query? It's not working under phpMyAdmin.
INSERT INTO `Setting`
(`id`, `type`, `name`, `value`, `parentId`, `createdAt`, `updatedAt`, `createdById`, `updatedById`)
VALUES
(NULL, 0, 'howItWorks', 'Some URL', NULL, NULL, NULL, -1, NULL),
(NULL, 0, 'howItWorksThumb', 'Some URL', (SELECT id FROM Setting WHERE name = 'howItWorks'), NULL, NULL, -1, NULL);
Same kind of query works under PostgreSQL.
Error I am getting: #1093 - You can't specify target table 'Setting' for update in FROM clause
Question is update to explained issues related to LAST_INSERT_ID() solutions:
To use LAST_INSERT_ID() solutions; child row should be inserting immediately after parent row.
I want to get the parentId for child row not immediately after I insert parent row. What will be the solution?
Also what if I want to add two children for same parent row?
MySQL doesn't allow you to SELECT in a subquery from the same table that you're inserting into in the main query. So you'll need to split this into two INSERT queries:
You can use LAST_INSERT_ID() to get the auto-increment ID that was assigned in the last INSERT, rather than using a subquery.
INSERT INTO `Setting` (`id`, `type`, `name`, `value`, `parentId`, `createdAt`, `updatedAt`, `createdById`, `updatedById`)
VALUES (NULL, 0, 'howItWorks', 'Some URL', NULL, NULL, NULL, -1, NULL);
INSERT INTO `Setting` (`id`, `type`, `name`, `value`, `parentId`, `createdAt`, `updatedAt`, `createdById`, `updatedById`)
VALUES (NULL, 0, 'howItWorksThumb', 'Some URL', LAST_INSERT_ID(), NULL, NULL, -1, NULL);
Unfortunately, using LAST_INSERT_ID() still doesn't allow you to combine them into a single query, because it calls the function before doing any inserts.
If you're doing the second insert later, you can do it with a normal INSERT ... SELECT ...:
INSERT INTO `Setting` (`id`, `type`, `name`, `value`, `parentId`, `createdAt`, `updatedAt`, `createdById`, `updatedById`)
SELECT NULL, 0, 'howItWorksThumb', 'Some URL', id, NULL, NULL, -1, NULL
FROM Setting
WHERE name = 'howItWorks'
DROP TABLE IF EXISTS my_table;
CREATE TABLE my_table
( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
, type TINYINT NOT NULL
, name VARCHAR(100) NOT NULL
, value VARCHAR(100) NOT NULL
, parentId INT NULL
, createdById INT NOT NULL
);
It would be sensible to bind the following into a transaction.
INSERT INTO my_table
( type
, name
, value
, createdById
)
VALUES
( 0
, 'howItWorks'
, 'Some URL'
, -1
);
INSERT INTO my_table
( type
, name
, value
, parentId
, createdById
)
SELECT 0
, 'howItWorksThumb'
, 'Some URL'
, LAST_INSERT_ID()
, -1
FROM my_table;
End of transaction
SELECT * FROM my_table;
+----+------+-----------------+----------+----------+-------------+
| id | type | name | value | parentId | createdById |
+----+------+-----------------+----------+----------+-------------+
| 1 | 0 | howItWorks | Some URL | NULL | -1 |
| 2 | 0 | howItWorksThumb | Some URL | 1 | -1 |
+----+------+-----------------+----------+----------+-------------+
see the data type of the table that you created. and see also DEFAULT on the field that you create. If ID is NULL should DEFAULT = auto_increment.

SQL - Setting a maximum number when incrementing a value by 1

I want increment difficulty by 1 but the value of difficulty should not go past 3. How do I do that?
This is my query
$query=mysqli_query($con,"UPDATE ticket
SET status = 'open',
difficulty = difficulty + 1
WHERE ticketid = '$_POST[ticketid]'")
Schema
create table ticket
( ticketid int auto_increment primary key,
status varchar(20) not null,
difficulty int not null
);
insert ticket(status,difficulty) values (0,0),(0,0); -- 2 rows
run this query a bunch of times:
update ticket
set status ='open',
difficulty=least(difficulty+1,3)
where ticketid=2;
Now look at data
select * from ticket;
+----------+--------+------------+
| ticketid | status | difficulty |
+----------+--------+------------+
| 1 | 0 | 0 |
| 2 | open | 3 |
+----------+--------+------------+
See Mysql Comparison functions
Try this:
$ticket_id = mysqli_real_escape_string($con, $_POST['ticketid']);
$query=mysqli_query($con,"UPDATE ticket
SET status = 'open',
difficulty = least(difficulty + 1,3)
WHERE ticketid = '$ticket_id'")
Note that I added ticket_id escaping to fix the SQL injection.
You can also use a if statement:
CREATE TABLE IF NOT EXISTS `ticket` (
`ticketid` int(11) NOT NULL AUTO_INCREMENT,
`status` varchar(20) NOT NULL,
`difficulty` int(11) NOT NULL,
PRIMARY KEY (`ticketid`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=2 ;
INSERT INTO ticket (difficulty, status) VALUES (0,0);
UPDATE
ticket
SET
`difficulty` = IF(`difficulty` < 3,`difficulty` + 1, 3)
WHERE
`ticketid`=1;
For more information have a look at https://www.ask-sheldon.com/conditions/.

How to make MySQL table primary key auto increment with some prefix

I have table like this
table
id Varchar(45) NOT NULL AUTO_INCREMENT PRIMARY KEY,
name CHAR(30) NOT NULL,
I want to increment my id field like 'LHPL001','LHPL002','LHPL003'... etc.
What should I have to do for that? Please let me know any possible way.
If you really need this you can achieve your goal with help of separate table for sequencing (if you don't mind) and a trigger.
Tables
CREATE TABLE table1_seq
(
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
);
CREATE TABLE table1
(
id VARCHAR(7) NOT NULL PRIMARY KEY DEFAULT '0', name VARCHAR(30)
);
Now the trigger
DELIMITER $$
CREATE TRIGGER tg_table1_insert
BEFORE INSERT ON table1
FOR EACH ROW
BEGIN
INSERT INTO table1_seq VALUES (NULL);
SET NEW.id = CONCAT('LHPL', LPAD(LAST_INSERT_ID(), 3, '0'));
END$$
DELIMITER ;
Then you just insert rows to table1
INSERT INTO Table1 (name)
VALUES ('Jhon'), ('Mark');
And you'll have
| ID | NAME |
------------------
| LHPL001 | Jhon |
| LHPL002 | Mark |
Here is SQLFiddle demo
Create a table with a normal numeric auto_increment ID, but either define it with ZEROFILL, or use LPAD to add zeroes when selecting. Then CONCAT the values to get your intended behavior. Example #1:
create table so (
id int(3) unsigned zerofill not null auto_increment primary key,
name varchar(30) not null
);
insert into so set name = 'John';
insert into so set name = 'Mark';
select concat('LHPL', id) as id, name from so;
+---------+------+
| id | name |
+---------+------+
| LHPL001 | John |
| LHPL002 | Mark |
+---------+------+
Example #2:
create table so (
id int unsigned not null auto_increment primary key,
name varchar(30) not null
);
insert into so set name = 'John';
insert into so set name = 'Mark';
select concat('LHPL', LPAD(id, 3, 0)) as id, name from so;
+---------+------+
| id | name |
+---------+------+
| LHPL001 | John |
| LHPL002 | Mark |
+---------+------+
I know it is late but I just want to share on what I have done for this. I'm not allowed to add another table or trigger so I need to generate it in a single query upon insert. For your case, can you try this query.
CREATE TABLE YOURTABLE(
IDNUMBER VARCHAR(7) NOT NULL PRIMARY KEY,
ENAME VARCHAR(30) not null
);
Perform a select and use this select query and save to the parameter #IDNUMBER
(SELECT IFNULL
(CONCAT('LHPL',LPAD(
(SUBSTRING_INDEX
(MAX(`IDNUMBER`), 'LHPL',-1) + 1), 5, '0')), 'LHPL001')
AS 'IDNUMBER' FROM YOURTABLE ORDER BY `IDNUMBER` ASC)
And then Insert query will be :
INSERT INTO YOURTABLE(IDNUMBER, ENAME) VALUES
(#IDNUMBER, 'EMPLOYEE NAME');
The result will be the same as the other answer but the difference is, you will not need to create another table or trigger. I hope that I can help someone that have a same case as mine.
Here is PostgreSQL example without trigger if someone need it on PostgreSQL:
CREATE SEQUENCE messages_seq;
CREATE TABLE IF NOT EXISTS messages (
id CHAR(20) NOT NULL DEFAULT ('message_' || nextval('messages_seq')),
name CHAR(30) NOT NULL,
);
ALTER SEQUENCE messages_seq OWNED BY messages.id;

data is inserting wrongly into the table

I have a table named quotation details with some columns
Field Name | Type
------------------------
Quotati_Id | bigint(20)
Fk_Rfq_Id | bigint(20)
Quotati_No | varchar(30)
Parent_Quotati_Id | bigint(20)
Fk_Client_Supplie_Id | int(11)
Is_Client_Supplie | bit(1)
and I want to insert data. The insert query is qiven below
INSERT INTO quotationdetails (
Fk_Rfq_Id,
Quotati_No,
Parent_Quotati_Id,Fk_Client_Supplie_Id,
Is_Client_Supplie
) VALUES (
'15847',
(SELECT AUTO_INCREMENT FROM information_schema.TABLES WHERE TABLE_SCHEMA='qtn' AND
TABLE_NAME='quotationdetails'),
'15640', '1',
'0')
Everything is works fine , but only one problem the column named Is_Client_Supplie is inserted wrongly. ie 1 is inserted instead of 0 in the column Is_Client_Supplie .
Whats wrong with me???
It is a bit field, not a string, so remove the apostrophes from '0'. You can do the same for Fk_Client_Supplie_Id and the other integer fields.
A bit field such as bit(3) can be assigned a binary value use the notation b'101' but if assigning 0 this notation is not necessary.
use
INSERT INTO quotationdetails (
Fk_Rfq_Id,
Quotati_No,
Parent_Quotati_Id,Fk_Client_Supplie_Id,
Is_Client_Supplie
) VALUES (
'15847',
(SELECT AUTO_INCREMENT FROM information_schema.TABLES WHERE TABLE_SCHEMA='qtn' AND
TABLE_NAME='quotationdetails'),
'15640', '1',
0)
No need of '0', use 0 instead.

How to generate a dynamic sequence table in MySQL?

I'm trying to generate a sequence table in MySQL, so that I can get unique ids from last_insert_id.
The problem is that I need multiple sequences dynamically.
At the first, I created a table:
CREATE TABLE `sequence` (
`label` char(30) CHARACTER SET latin1 NOT NULL,
`id` mediumint(9) NOT NULL DEFAULT '0',
PRIMARY KEY (`label`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8
And then tried to get the number, using example from http://dev.mysql.com/doc/refman/5.0/en/information-functions.html#function_last-insert-id
UPDATE sequence SET id = LAST_INSERT_ID(id + 1) WHERE label = 'test';
SELECT LAST_INSERT_ID();
After a while I realized that I also need to generate rows for new labels safely.
So I changed this schema into:
CREATE TABLE `sequence` (
`label` char(30) CHARACTER SET latin1 NOT NULL,
`id` mediumint(9) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`label`,`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8
And I simply gave up using WHERE clause to update its id.
INSERT INTO sequence (label) values ( ? )
SELECT LAST_INSERT_ID()
Is this a proper way? I want to know if there is a better solution.
The MyISAM engine will do it for you -
Table definition:
CREATE TABLE `sequence` (
`label` char(30) CHARACTER SET latin1 NOT NULL,
`id` mediumint(9) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`label`,`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
Populate table:
INSERT INTO sequence VALUES ('a', NULL); -- add some 'a' labels
INSERT INTO sequence VALUES ('a', NULL);
INSERT INTO sequence VALUES ('a', NULL);
INSERT INTO sequence VALUES ('b', NULL); -- add another labels 'b'
INSERT INTO sequence VALUES ('b', NULL);
INSERT INTO sequence VALUES ('a', NULL); -- add some 'a' labels
INSERT INTO sequence VALUES ('a', NULL);
Show result:
SELECT * FROM sequence;
+-------+----+
| label | id |
+-------+----+
| a | 1 |
| a | 2 |
| a | 3 |
| a | 4 |
| a | 5 |
| a | 6 |
| b | 1 |
| b | 2 |
+-------+----+