Insert into Table by getting NextVal of Sequence in PostgreSQL - mysql

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');

Related

Add a line in between a SQL table and change following id

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');

Running a MySQL Insert when update fails

What is the fastest approach to update a row and if the parameters don't exist insert it.
My table has 2 columns for ids quote_id, order_id and those columns combined would make a unique column. I don't want 2 rows containing the same quote_id and order_id but either can have multiple rows.
id | quote_id | order_id
1 | q200 | o100
2 | q200 | o101
3 | q201 | o100
Previously I would have added a third field and combined those 2 fields with a - so I could use the ON DUPLICATE KEY UPDATE. But this is not very efficient as I seem to forget to add those fields sometimes.
My idea is to try to run the update query and if it fails the insert it as I run a lot more update queries then insert. How would I put this into a single query instead of the MySQL server having to return a error and then I rerun the insert query.
if (
UPDATE table_name SET column1=value, column2=value2 WHERE some_column=some_value === ERROR
) THEN
INSERT INTO table_name ....
I looked through some of the MySQL documentation and I couldn't find a example that showed how an error is detected in a IF statement
You should have a PRIMARY or UNIQUE constraint over the column(s) that identify rows uniquely. It's normal to use multiple columns for this, and SQL support syntax for it:
CREATE TABLE MyTable (
quote_id VARCHAR(4) NOT NULL,
order_id VARCHAR(4) NOT NULL,
other_data VARCHAR(4),
...
PRIMARY KEY(quote_id, order_id)
);
Then you can rely on the unique constraint to cause an INSERT to fail and run an UPDATE instead:
INSERT INTO MyTable (quote_id, order_id, other_data) VALUES ('q200', 'o100', 'blah blah')
ON DUPLICATE KEY UPDATE
other_data = VALUES(other_data);
Using the VALUES() clause in the UPDATE part means "use the same value for the respective column that I tried to use in the INSERT part."

insert a new record into a mysql table with one of the values incremented by 1

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

How to insert if not exists with selecting from same table?

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');

Is there a way to insert an auto-incremental primary id with a prefix in mysql database?

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.