Table Structure
CREATE TABLE `goods` (
`id` int NOT NULL ,
`name` varchar(25) ,
`updateat` datetime
)
Now there is a piece of data like this in the table
When I want to insert a new piece of data like (1,'new','2021-12-18 12:00:00').First determine whether there is the same data in the table as the data to be inserted (except for the update time),Then compare the update time, keep the latest piece of data.
I want to know how to use sql to achieve this function.
First add primary key to your table:
CREATE TABLE goods (
id int NOT NULL ,
name varchar(25) ,
updateat datetime,
PRIMARY KEY (id, name)
)
Then use ON DUPLICATE KEY UPDATE :
insert into goods values (1, 'john', '2021-01-02');
insert into goods (id, name, updateat)
values (1, 'john', '2021-01-03')
ON DUPLICATE KEY UPDATE
updateat = greatest('2021-01-03',
(select updateat from (select * from goods as g) as g where id = 1))
Fiddle
Mysql uses INSERT ON...DUPLICATE instead of merge. This statement allows you to make modifications in your case an update based on a check when duplicate entries are identified. Duplicate entries may be identified using primary keys or unique indexes. The demo below and working db fiddle gives an example of this based on your criteria.
Using a unique index to identify duplicate entries
Using INSERT ON...DUPLICATE with the VALUES (used to identify currently inserted values) and a case expression to determine which updatedat date is more recent.
CREATE TABLE `goods` (
`id` int NOT NULL ,
`name` varchar(25) ,
`updateat` datetime
);
✓
-- use a unique index if you are interested in ensuring a subset of columns are unique and
-- these columns do not meet the criteria to be a primary/composite key based on your database design
create unique index uk_id_name on goods(id,name);
✓
insert into goods values (1,'new','2021-12-18 12:00:00');
✓
-- this should fail because of the duplicate unique index
insert into goods values (1,'new','2021-12-18 12:00:00');
Duplicate entry '1-new' for key 'uk_id_name'
select * from goods;
id | name | updateat
-: | :--- | :------------------
1 | new | 2021-12-18 12:00:00
insert into goods values (1,'new','2021-12-18 12:00:01')
on duplicate key update updateat= CASE
WHEN updateat > VALUES(updateat) THEN updateat
ELSE VALUES(updateat)
END;
✓
select * from goods;
id | name | updateat
-: | :--- | :------------------
1 | new | 2021-12-18 12:00:01
db<>fiddle here
Related
I want to write a sql script, which inserts into table some value for all the ids in some other table.
create table person
(
id int(11) not null auto_increment,
name varchar(255),
primary key (id)
);
insert into person
values (null, 'John'), (null, 'Sam');
select * from person;
id | name
----------
1 | John
2 | Sam
create table phone_details
(
id int(11) not null auto_increment,
person_id int(11),
phone int(11),
constraint person_ibfk_1 foreign key (person_id) references person (id) on delete no action,
primary key (id)
);
Now, in the phone_details table, I want the following :
id | person_id | phone
----------------------------
1 | 1 | 9999999999
2 | 2 | 9999999999
How do I do that ? Currently, I am using Java to write this one time script, but I think there must be a way of doing this in sql.
You can use INSERT INTO ... SELECT syntax:
INSERT INTO phone_details(person_id,phone)
SELECT id, 99999999
FROM person;
Consider storing phone number as VARCHAR.
SqlFiddleDemo
The given query is in mysql format. I want same query in SQL Server 2008.
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 |
This may answer your question
-- create table with 'ABCD' as prefix, combining with identity column Id
CREATE TABLE dbo.Persons
(
Id int IDENTITY (1,1) NOT NULL
,PersonId AS ('ABCD' + CONVERT(varchar(20), Id)) PERSISTED NOT NULL PRIMARY KEY
,Name varchar(100)
);
GO
-- Do not specify calculated column when insert values into the table
INSERT INTO dbo.Persons (Name)
VALUES ('Person1'), ('Person2'), ('Person3');
GO
-- Display the records from the table
SELECT PersonId, Name
FROM dbo.Persons;
GO
This approach does not require to create a separate table and trigger, therefore efficient.
Hope this helps.
I have 6 columns in my table:
Id | Name | Mail id | Gender | Contact Number | father name
while inserting a data into table i wanted to check condition like if Name,mailid,contact number already exists then insert should not happen else record should be inserted.
Can any one suggest how to check the condition while inserting a record.
IF NOT EXISTS (SELECT * FROM Table_Name WHERE Condition you are checking)
BEGIN
INSERT INTO ............. ---<----- Your Insert Statement.....
END
You can define an index on multiple columns, e.g.:
CREATE UNIQUE INDEX arbitrary_index_name ON table_name (Name, mailid, contactnumber);
I also faced similar situation, you can do this by adding unique constraint to your table and using 'insert ignore' statement to add data.
Create table statement:
CREATE TABLE Student (
Id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(50),
Mailid VARCHAR(50),
Gender CHAR,
contactnumber BIGINT,
fathername VARCHAR(50),
UNIQUE(NAME,Mailid,contactnumber));
Insert Ignore statement:
INSERT IGNORE INTO student(NAME, Mailid,Gender,contactnumber,fathername) VALUES('Shekhar', 's#s.com', 'M', 987654321, 'Joshi');
Mysql table
create table table1(
id int(3) zerofill auto_increment primary key,
username varchar(10)
)
engine=innodb;
Mysql insert query
insert into table1 (username)
select id from (select id from table1) as a where
a.id=last_insert_id();
I am trying to insert into a table by selecting the last id from the same table and the same row,the above queries give the explanation of what i want to do.The insert query gives null value in both the id and username.
The expected results is below.
id username
001 001
002 002
003 003
A possible approach
INSERT INTO table1 (username)
SELECT LPAD(COALESCE(MAX(id), 0) + 1, 3, '0')
FROM table1
Here is SQLFiddle demo
A drawback of this approach is that under heavy load different concurrent users may get the same MAX(id) and you'll end up with rows that have different ids but the same username.
Now, the more precise way to do it involves a separate sequencing table and a BEFORE INSERT triger
Proposed changed table schema
CREATE TABLE table1_seq
(
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
);
CREATE TABLE table1
(
id INT(3) ZEROFILL PRIMARY KEY DEFAULT 0,
username VARCHAR(10)
);
The trigger
DELIMITER $$
CREATE TRIGGER tg_table1_before_insert
BEFORE INSERT ON table1
FOR EACH ROW
BEGIN
INSERT INTO table1_seq VALUES(NULL);
SET NEW.id = LAST_INSERT_ID(), NEW.username = LPAD(NEW.id, 3, '0');
END$$
DELIMITER ;
Now you just insert new rows into table1 like this
INSERT INTO table1 (username)
VALUES (NULL), (NULL)
Outcome:
| ID | USERNAME |
-----------------
| 1 | 001 |
| 2 | 002 |
Here is SQLFiddle demo
Why store the value at all?
CREATE TABLE table1 (
id int(3) zerofill auto_increment PRIMARY KEY
);
CREATE VIEW oh_look_username
AS
SELECT id
, LPad(Cast(id As varchar(10)), 3, '0') As username
FROM table1
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;