Complex insert statements - sql

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

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

Join with json column?

I need find rows in table users by joining column in table queries.
I wrote some sql but it takes 0.200s to run, when SELECT * FROM ... takes 0.80s.
How can I improve performance?
db-fiddle example
The tables are :
CREATE TABLE users (
id INT,
browser varchar
);
CREATE TABLE queries (
id INT,
settings jsonb
);
INSERT INTO users (id,browser) VALUES (1, 'yandex');
INSERT INTO users (id, browser) VALUES (2, 'google');
INSERT INTO users (id, browser) VALUES (3, 'google');
INSERT INTO queries (id, settings) VALUES (1, '{"browser":["Yandex", "TestBrowser"]}');
and the query :
select x2.id as user_id, x1.id as query_id
FROM (
SELECT id, json_array_elements_text((settings->>'browser')::JSON) browser
FROM queries) x1
JOIN users x2 ON lower(x1.browser::varchar) = lower(x2.browser::varchar)
group by 1,2;
json_array_elements_text((settings->>'browser')::JSON)
'->>' converts the result to text. Then you cast it back to JSON. Doing that on one row (if you only have one) is not really going to be a problem, but it is rather pointless.
You could instead do:
jsonb_array_elements_text(settings->'browser')
ON lower(x1.browser::varchar) = lower(x2.browser::varchar)
You can create an index that can be used for this:
create index on users (lower(browser));
It won't do much good on a table with 3 rows. But presumably you don't really have 3 rows.

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

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.

Insert into table select from table a and table b where

I want to insert data into a table by joining two tables with a where condition that each id matches.
INSERT INTO SALES(T_ID, SF)
SELECT B.T_ID, B.SF
FROM HIS B, SALES C
WHERE C.REP_ID=B.REP_ID;
I am getting an error that I cannot insert NULL into ("c.REP_ID")
I am not trying to insert anything into c.rep_id. I want to insert values into t_id, sf from HIS table where the rep_id on his table = rep id on sales table.
INSERT INTO SALES (T_ID, SF)
SELECT h.T_ID, h.SF FROM HIS h, SALES C
WHERE C.REP_ID=B.REP_ID;
Note: Make sure that the data comes from select tables is equally compare and valid with the datatypes of the columns where you inserting.
The error simply means that the column REP_ID in the SALES table has a NOT NULL constraint. Your INSERT statement doesn't insert any value into that column (you only insert T_ID and SF) and presumably there are no before-row triggers that will set that column for you.

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