I would like to insert a row in the middle of my SQL table. Similar to Excel, the existing rows should then be automatically increased by ID+1. Is there such a function?
Example:
Current state:
After insert inbetween:
Please never do it in production.
Setup
create table tbl(
id int NOT NULL AUTO_INCREMENT primary key,
val varchar(20)
);
insert into tbl (val)
values
('a'),('b'),('c'),('d');
The script to add 'x' between 'b' and 'c' when ordered by id
update tbl
set id=id+1
where id > 2
order by id desc;
insert tbl(id, val)
values (3,'x');
Related
I've got the following table:
productId price
1 price_value1
2 price_value2
3 price_value3
I would like to insert a new product into the table and assign it a new productId. In this case its value equals to 4.
So I want my new table to look like so:
productId price
1 price_value1
2 price_value2
3 price_value3
4 price_value4
So as far as I understand, in order to do that I have to somehow retrieve the max value of productId and insert it using INSERT INTO mytable VALUES (productId + 1, price_value4).
But how do I find out the maximum value of productId?
I tried INSERT INTO mytable VALUES (SELECT MAX(productId) + 1 FROM mytable, price_value4) but it didn't work.
This should Work:
Select the max(productID) and price_value4 as a columns from mytable and insert the result.
INSERT INTO mytable (SELECT MAX(productId) + 1, 'price_value4' FROM mytable);
However, if you are not going to jump some number you can just add an auto increment id key to product_id and then you will have only to insert the price, the product ID will be incremented automatically..
This will do so :
ALTER TABLE mytable
MODIFY COLUMN `productId` INT(10) UNSIGNED PRIMARY KEY AUTO_INCREMENT;
you can change INT(10) with the INT(5) for example depanding on the size you want to give to your productId column
EDIT :
In return to the OP question in comments why his solution wouldn't work
Some suggetions says you have to make the SELECT statment in insert always between parenthesis
INSERT INTO mytable VALUES ( (SELECT MAX(ID)+1 FROM mytable) , price_value4)
.. In my Case it Return
(1093): You can't specify target table
'mytable' for update in FROM clause
AND HERE IS WHY (Quoting From the documentation)
When selecting from and inserting into the same table, MySQL creates
an internal temporary table to hold the rows from the SELECT and then
inserts those rows into the target table. However, you cannot use
INSERT INTO t ... SELECT ... FROM t when t is a TEMPORARY table,
because TEMPORARY tables cannot be referred to twice in the same
statement
BUT there is away to overcome by using a query instead of the table itself in the FROM, which has the effect of copying the requested table values instead of referencing the one that you are updating..
INSERT INTO mytable VALUES (
(SELECT MAX(ID)+1 FROM (SELECT * FROM mytable ) as mytmp ),
'price_value4');
OR (Quoting From the documentation)
To avoid ambiguous column reference problems when the SELECT and the
INSERT refer to the same table, provide a unique alias for each table
used in the SELECT part, and qualify column names in that part with
the appropriate alias.
INSERT INTO mytable Values ( (SELECT MAX(ID)+1 FROM mytable as mytmp) , 'price_value4')
This is a duplicate question. In order to take advantage of the auto-incrementing capability of the column, do not supply a value for that column when inserting rows.
A simple syntax to create table
CREATE TABLE Product (
productId MEDIUMINT NOT NULL AUTO_INCREMENT,
price INT NOT NULL,
PRIMARY KEY (productid)
);
While inserting supplied default or leave column as blank or supplied value as NULL. Take a look at below code snippet.
INSERT INTO Product (price) VALUES
('10'),('20'),('4'),
('30');
refer this link
I have my table schema in H2 db as follows:
create table if not exists Test ( id bigint not null,name varchar(255), primary key (id) );
alter table Test add constraint if not exists Test_NAME UNIQUE (name);
I want to insert a value for the name attribute as 'Default' if it does not exist in the table by selecting the latest id value from the table and increment it by one.
Example:
Do not insert if an entry for name = Default already exists.
ID | Name
1 | Default
Insert if an entry for name = Default does not exists.
ID | Name
1 | ABC
2 | XYZ
For the id column, find the max id and increment it by one. In this case, insert id=3 and name=Default.
My query is as follows:
INSERT INTO Test (id , name)
SELECT max(id) + 1, 'Default' from Test
WHERE NOT EXISTS (SELECT * FROM Test where name='Default');
However, it gives me an error saying:
NULL not allowed for column "ID"; SQL statement
as it applies the where condition on the inner select statement.
I also tried:
MERGE INTO Test KEY(name) VALUES (SELECT MAX(id) + 1 from Test, 'Default');
It gives an error because, merge tries to update with the new values.
If it finds 'Default', it will update the row with new id causing primary key violation.
Is there a better way to do this? How can I make the query work?
You are massively overcomplicating this. Define the id field as auto increment and place a unique index on the name field. The unique index prevents duplicate names to be inserted, while the auto increment increases the value of the id field by 1 (by default) if the insert is successful.
I updated id to auto increment and the following query work flawlessly
INSERT INTO Test (name) select * from (select 'Default') as tmp WHERE NOT EXISTS (SELECT name from Test where name='Default');
when you run your query first time, no record found in table so, it give error 'null' there, so if you add IFNULL() function there as below
INSERT INTO Test (id , name)
SELECT **IFNULL**(max(id),0) + 1, 'Default'
FROM Test
WHERE NOT EXISTS (SELECT * FROM Test where name='Default');
I have a table called SEQ_TABLE which has two columns, SEQ_NAME and ID
SEQ_NAME | ID
----------------------
SEQ_TABLE_10 | 1
SEQ_TABLE_20 | 5
Where ID is the Max of COLUMN_1 of TABLE_10 and TABLE_20
Now, I have to Insert new records into TABLE_10 by obtaining nextvalue of sequence from SEQ_TABLE.
I have written PostgreSQL query as follows:
INSERT INTO TABLE_10 (COLUMN_1, COLUMN_2, COLUMN_3) VALUES ((SELECT nextval(SEQ_TABLE)), 'Bangalore' ,NULL);
When I execute above Query, It is giving below error:
********** Error **********
ERROR: column "SEQ_TABLE_10" does not exist
SQL state: 42703
Character: 99
But, following Query works fine in MySQL Database:
INSERT INTO TABLE_TABLE(COLUMN_1, COLUMN_2, COLUMN_3) VALUES ((SELECT nextval('TABLE_172_SEQ','true')), 'Bangalore' ,NULL);
What is the Exact Postgres Query to achieve it in PostgreSQL DB?
You want to create a sequence, not a table(SEQ_TABLE)
Kindly refer this link
https://www.postgresql.org/docs/8.1/static/sql-createsequence.html
Eg.
CREATE SEQUENCE serial START 101;
SELECT nextval('serial');
create table MyTable(col1 int,col2 varchar(20));
INSERT INTO MyTable VALUES (nextval('serial'), 'nothing');
In current PostgreSQL versions you would use identity columns:
CREATE TABLE table_10 (
id integer GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
other text NOT NULL
);
That will implicitly generate a sequence. You are not allowed to insert numbers into into id, but you have to
INSERT INTO table_10 (other) VALUES ('new');
or
INSERT INTO table_10 (id, other) VALUES (DEFAULT, 'new');
and id is automatically filled with the next value from the sequence.
On older PostgreSQL versions, you would use serial or bigserial:
CREATE TABLE table_10 (id serial PRIMARY KEY, other text NOT NULL);
Then id is of type integer, a sequence table_10_id_seq is created and a nextval call is added to the DEFAULT clause of the id column.
You can examine this with \d in psql:
\d table_10
Table "laurenz.table_10"
Column | Type | Modifiers
--------+---------+-------------------------------------------------------
id | integer | not null default nextval('table_10_id_seq'::regclass)
other | text | not null
Indexes:
"table_10_pkey" PRIMARY KEY, btree (id)
Moreover, the sequence belongs to the table and will be dropped automatically when the table is dropped.
You insert rows omitting the id column like this:
INSERT INTO table_10 (other) VALUES ('something');
Then the DEFAULT values will be used.
If you want to do the same thing “on foot”, for example to use a different name or different starting values for the sequence, that would work like this:
CREATE TABLE table_10 (id integer PRIMARY KEY, other text NOT NULL);
CREATE SEQUENCE table_10_id_seq OWNED BY table_10.id;
ALTER TABLE table_10 ALTER id SET DEFAULT nextval('table_10_id_seq');
I'm trying to insert a data as a primary ID that has one alphanumerical value and two numerical value in MySQL database. This data will auto incrementally generate number, but the alphanumerical value will be fixed. Like, D1, D2....D54, D55, D56 etc. Here, 'D' is always the same, but the number will be automatically incremented. Is there any way to do this?
First of all it's unadvisable to do so, like others commented, you can have this id value generated on the fly.
But if nonetheless you want it your way there're at least two ways to do so:
More or less reliable way involves using a separate table for sequencing and a trigger
Schema:
CREATE TABLE Table1_seq
(
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
);
CREATE TABLE Table1
(
`id` VARCHAR(10) NOT NULL PRIMARY KEY DEFAULT '',
...
);
Trigger:
DELIMITER $$
CREATE TRIGGER tg_bi_table1
BEFORE INSERT ON table1
FOR EACH ROW
BEGIN
INSERT INTO table1_seq() VALUES();
SET NEW.id = CONCAT('D', LPAD(LAST_INSERT_ID(), 4,'0'));
END$$
DELIMITER ;
Then you just insert your rows to table1
INSERT INTO Table1 () VALUES (),(),();
And you'll get
| ID |
---------
| D0001 |
| D0002 |
| D0003 |
Here is SQLFiddle demo
Unreliable way is to generate your new id on the fly in INSERT statement itself
INSERT INTO Table1 (id, ...)
SELECT CONCAT('D', LPAD(COALESCE(SUBSTR(MAX(id), 2), 0) + 1, 4, '0')),
...
FROM table1
Here is SQLFiddle demo
The problems with this approach:
Under heavy load two concurrent sessions can grab the same MAX(id) value and therefore generate the same new id leading to the failure of insert.
You can't use multi-insert statements
We can't set auto-increment for alphanumeric. In your case if D is always same then no need to add it to your pk field. Keep your constant in a separate field and add it when you select.
Is there a possibility in MySQL to fill specific number of columns in record by random values, except of ID (which should be auto-incremented)?
Something like that:
INSERT INTO 'table_name' ('ID', column1, column2, ...)
VALUES (<auto-increment> , random-value1, random-value2, ...);
I am testing something with database by removing few records, and after that i have to manually create few again. I'd like creating new records to be more automatic.
Yes. The ID has to be declared as auto_increment and not listed in the insert statment. Rand() returns a float between 0 and 1.
create table my_table(
id int primary key auto_increment,
val1 float,
val2 float
);
insert into my_table(
val1,
val2
) values (
rand(),
rand()
);
select * from my_table;
SQL Fiddle
MySQL 5.7 rand() function documentation