Insert a new record with a field containing total record in the table - sql

I wonder if it exists a function that allows me to get total rec count of a table to for new record insertion into the table?
I have this table:
CREATE TABLE "TEST"
( "NAME" VARCHAR2(20 BYTE),
"ID" NUMBER,
"FLAG" NUMBER
) ;
Insert into TEST (NAME,ID,FLAG) values ('Ahlahslfh',1,1);
Insert into TEST (NAME,ID, FLAG) values ('Buoiuop',2,1);
Insert into TEST (NAME,ID, FLAG) values ('UOIP',12,0);
My intention is to issue a statement that is equivalent to this:
INSERT INTO TEST( NAME, ID, FLAG )
VALUES( 'TST', 3,1 );
The statement I used below generated error:
INSERT INTO TEST ( NAME, ID, FLAG )
VALUES ( 'TST', SELECT COUNT(*)+1 FROM TEST WHERE FLAG=1,1 );
Below is the final result I am expecting:
Is there a way around it? Of course, I can put them in a script, count the records into a variable and insert that variable into the field. I just wonder if there is more elegant solution and do this in 1 statement.
Thanks!

This is likely to be a very bad way to set an id. In general, I think you should use sequences/identity/auto_increment and not worry about gaps.
But, you can do what you want using parentheses -- these are needed for subqueries:
INSERT INTO TEST(NAME, ID, FLAG)
VALUES ('TST',
(SELECT COUNT(*)+1 FROM TEST WHERE FLAG = 1),
1
);
Or, alternatively:
INSERT INTO TEST(NAME, ID, FLAG)
SELECT 'TST', COUNT(*) + 1, 1
FROM TEST
WHERE FLAG = 1;
I must emphasize that this seems dangerous. It is quite possible that you will get duplicate ids. You should really let the database insert a new value and not worry about gaps.

Related

Insert into 2 tables with single SQL statement instead of loop

I have to insert data in provonance of several table which itself comes from csv (COPY).
Before I used a LOOP in a function to enter the data. I want to simplify the thing for the sake of maintainability and speed.
I need to insert data into a description table, which serves as both the title and description (and multi language).
Previously my code was as follows (extract from the loop):
insert into description (label, lang_id, poi_id,date_dernier_update, date_enregistrementbdd, date_derniere_lecture) values (label, lang_id, poi_id, now(), now(), now()) RETURNING id INTO _retour_id_titre;
insert into poi_titre_poi (poi_id, titre_poi_id, titre_poi_key) values (poi_id, _retour_id_titre, label_lang);
But now I can't:
with rows as (
insert into description (label, lang_id, poi_id)
select rdfslabelfrs, '1', (select id from poi where uri_id = csv_poi_rdf_fr.poi) as toto from csv_poi_rdf_fr RETURNING id
)
insert into poi_titre_poi (poi_id, titre_poi_id, titre_poi_key)
select description.poi_id, id , 'fr'
FROM description;
In fact, I cannot insert the 'poi_id' in the 'poi_titre_poi' table which corresponds to the one which was inserted in the description table.
I get this error message:
ERROR: more than one row returned by a subquery used as an expression
État SQL : 21000
Can I make this work, or do I need to loop?
Filling in missing bits with assumptions, it could work like this:
WITH description_insert AS (
INSERT INTO description
(label , lang_id, poi_id)
SELECT c.rdfslabelfrs, 1 , p.id
FROM csv_poi_rdf_fr c
JOIN poi p ON p.uri_id = c.poi
RETURNING poi_id, id
)
INSERT INTO poi_titre_poi (poi_id, titre_poi_id, titre_poi_key)
SELECT d.poi_id, d.id , 'fr'
FROM description_insert d;
Related:
PostgreSQL multi INSERT...RETURNING with multiple columns
Insert data in 3 tables at a time using Postgres
Get Id from a conditional INSERT

Using ignore_duplicate on non primary key

I've got table:
ID (identity, PK), TaskNr, OfferNr
I want to do insert ignore statement but sadly it's not working on MSSQL, so there's a IGNORE_DUP switch. But I need to check duplicates using TaskNr column. Is there any chance to do that?
Edit:
Sample data:
ID (identity, PK), TaskNr, OfferNr
1 BP1234 XAS
2 BD123 JFRT
3 1122AH JDA33
4 22345_a MD_3
Trying to do:
insert ignore into Sample_table (TaskNr, OfferNr) values (BP1234, DFD,)
Should ignore that row and go to next value of insert statement. ID is autoincremented but unique value should be checked using TaskNr column.
SQL Server does not support insert ignore. That is MySQL functionality.
You can do what you want as:
insert ignore into Sample_table (TaskNr, OfferNr)
select x.TaskNr, x.OfferNr
from (select 'BP1234' as TaskNr, 'DFD' as OfferNr) x
where not exists (select 1
from Sample_Table st
where st.TaskNr = x.TaskNr and st.OfferNr = x.OfferNr
);
You can try two options:
insert into ... where not exists ()
t-sql merge statement (https://learn.microsoft.com/en-us/sql/t-sql/statements/merge-transact-sql)

PostgreSQL 9.3 - How to insert using json_populate_recordset but still get auto ids by sequence

This is a followup question to "Populate multiple tables from a single JSON object with json_populate_recordset".
Say my tables (table_a, table_b) have sequences for a_id and b_id,
so they look like this:
CREATE TABLE table_a (a_id serial, b_id integer, c_id integer);
CREATE TABLE table_b (b_id serial, name text, z_id integer);
...
CREATE TABLE table_z (z_id serial, some_text_entry text);
A regular insert looking like this
INSERT INTO table_a (b_id, c_id) values (1, 2);
INSERT INTO table_b (name, z_id) values ("whatever", 3);
...
INSERT INTO table_z (some_text_entry) values ("Some text");
lets PostgreSQL increment the ids for a_id (table_a), b_id(table_b), etc., so the new dataset can be created and stored.
But how could I insert data using the more complex approach following and still get automatically created ids?
WITH input AS (
SELECT '{
"tablename_a":[{"a_id":1,"b_id":2,"c_id":3},
{"a_id":2,"b_id":51,"c_id":3}],
"tablename_b":[{"b_id":2,"name":"John Doe", "z_id":123},
{"b_id":51,"name":"Mary Ann", "z_id":412}],
"tablename_z":[{"z_id":123, "some_text_entry":"Something"},
{"z_id":123, "some_text_entry":"Something else"}]
}'::json AS j
)
, a AS (
INSERT INTO tablename_a
SELECT t.*
FROM input i
, json_populate_recordset(NULL::tablename_a, i.j->'tablename_a') t
)
, b AS (
INSERT INTO table_b
SELECT t.*
FROM input i
, json_populate_recordset(NULL::tablename_b, i.j->'tablename_b') t
)
-- ... more ...
INSERT INTO tablename_z
SELECT t.*
FROM input i
, json_populate_recordset(NULL::tablename_z, i.j->'tablename_z') t
;
If I just set the id to null
"tablename_a":[{"a_id": null,"b_id":2,"c_id":3},
{"a_id": null,"b_id":51,"c_id":3}]
or leave out the respective ids like this:
"tablename_a":[{"b_id":2,"c_id":3},
{"b_id":51,"c_id":3}]
I get the error 'null value in column "a_id" violates not-null constraint'.
In addition:
Would be really great if there was a way to deal with this, without specifically listing all column names (except the serial-ones).
In MySQL if you take my table_a, I know you could do something like
INSERT INTO table_a VALUES (1,2)
meaning that MySQL would fill the a_id field with an autoincrement id and the rest with the data given by the insert command. Is there no way to accomplish that with json, too?
Usually, when you want to insert into a table that has a column of type serial or bigserial, you omit that column from the list of columns. I tried to change your original syntax as little as possible to show how this works.
-- I made no changes to the CTE, except to cut some lines.
WITH input AS (
SELECT '{
"tablename_a":[{"a_id":1,"b_id":2,"c_id":3}, {"a_id":2,"b_id":51,"c_id":3}]
}'::json AS j
)
-- Ignore a_id. It's set automatically by PostgreSQL.
-- Think about cutting it from input.
INSERT INTO table_a (b_id, c_id)
SELECT b_id, c_id
FROM input i
, json_populate_recordset(NULL::table_a, i.j->'tablename_a') t

Insert some variable columns with constants

What I'm looking to do with my code is insert some variable number of rows into test_table where 'policy' in source_table matches 'bond_ser' in policy_custsgt and 'SNL_ID' in source_table matches 'inst_key' in raw_table.
I want it to insert serial_number and ID along with some other constants. I can get it to insert serial_number and ID just fine, but how do I get it to add some constants in other fields of the table every time it inserts the variables from the other tables?
This is the code I currently have, if I remove the "'122812', '999999', 'myname'" from the first line it works fine but will only populate the serial_number and ID columns of my table with each insert.
INSERT INTO test_table(serial_number, ID, '122812', '999999', 'myname')
SELECT policy, SNL_ID
FROM source_table
WHERE (policy IN (SELECT bond_ser from policy_custsgt)) AND
(SNL_ID in (select inst_key from raw_table))
Thanks!
Of course, I over looked the simple solution. All I needed to do was move those constants I wanted down from the INSERT statement to the SELECT statment, and add the column names in the INSERT so:
INSERT INTO test_table(serial_number, ID, starting_date, ending_date, user_id)
SELECT policy, SNL_ID, '122812', '999999', 'myname'
FROM source_table
WHERE (policy IN (SELECT bond_ser from policy_custsgt)) AND
(SNL_ID in (select inst_key from raw_table))

Complex insert statements

I want to ask is it possible to insert your own value in the table as well as select other values in other table? I have tried to come out with my select and insert statement but i'm missing one statement as i want to insert my own values in rather than referencing it.
All my required tables have been created. And I wish to insert my own values like Type and rest of the insert values will be selected from other tables.
Below is my code: (Am i missing a statement?)
Insert Into Test (Test_Date, Testno, Examno, Serialno, Type, Hours)
Select S.Test_Date, E.Testno, S.Examno, S.Serialno, Type, (F.STARTED- F.ENDED) as hours
From Semester S, TIME F, TESTPAPERS e
Where S.Testno = F.Testno
And E.Testno = 1
and TYPE = 'Non-FLight'; -- this is the statement that i wish to insert own values instead and not selecting.
Is it possible to do all in one insert statement ? I don't wish to update my table so many times just to insert type value.
Thanks
Just put the value you would like for Type in your select statement:
Insert Into Test (Test_Date, Testno, Examno, Serialno, Type, Hours)
Select S.Test_Date, E.Testno, S.Examno, S.Serialno, 'Non-Flight', (F.STARTED- F.ENDED) as Hours
From Semester S, TIME F, TESTPAPERS e
Where S.Testno = F.Testno And E.Testno = 1