Insert multiple rows with one column from another table - sql

I have two tables
CREATE TABLE table1 (
id bigint NOT NULL,
name character varying(255),
CONSTRAINT table1_pkey PRIMARY KEY (id)
);
CREATE TABLE table2 (
id bigint NOT NULL,
name character varying(255),
table1_id bigint,
CONSTRAINT table2_pkey PRIMARY KEY (id),
CONSTRAINT fk_table1_table2 FOREIGN KEY (table1_id)
REFERENCES table1 (id) MATCH SIMPLE
);
now what i want to do is for each entry in table1 add entry in table2
ie if my table 1 has entries
|id | name |
|1 | First |
|2 | Second |
|3 | Third |
I need to create three entries in table2
insert into table2 (id,name,table2_id) values (nextval('table2_seq'),'new entry', 1);
insert into table2 (id,name,table2_id) values (nextval('table2_seq'),'new entry', 2);
insert into table2 (id,name,table2_id) values (nextval('table2_seq'),'new entry', 3);
and as only foreign key is changed for each new entry, i was wonder is it any possibility to automate this process.
Is it possible to achieve with query, or should i look at procedures?

Use an insert based on a select:
insert into table2 (id,name,table1_id)
select nextval('table2_seq'), 'new entry', t1.id
from table1;

I struggled to get a "SELECT ... WHERE" in the subquery, likely not enough coffee, but finalised on the below syntax:
insert into table (col1, col2 ...)
select 'staticval1',
r.variable1 from reftable r where r.variable2 = 'Some search term'
...;

Related

Create new records in one table-A and add as foreign key to table-B if the foreign key field in table-B is null -PostgresSQL

Table A and Table B look like shown below. The intention is to write an SQL script to run and update the tables. Table B has a foreign key to Table-A. If the field is null in Table B, then create a new record in Table-A and update Table B with that foreign key
It is expected to add two new records in Table A and add those foreign key in the Table B as per the above example. Thanks in advance
I wrote for you sample for do it.
But I don't know your business logic detail. You can change some solutions.
CREATE TABLE tablea (
id serial4 NOT NULL,
"name" varchar NULL,
CONSTRAINT tablea_pk PRIMARY KEY (id)
);
CREATE TABLE tableb (
id serial4 NOT NULL,
a_id int4 NULL,
"name" varchar NULL,
CONSTRAINT tableb_pk PRIMARY KEY (id)
);
INSERT INTO tableb (id, a_id, "name") VALUES(1, 100, 'b1');
INSERT INTO tableb (id, a_id, "name") VALUES(2, NULL, 'b2');
INSERT INTO tableb (id, a_id, "name") VALUES(3, NULL, 'b3');
INSERT INTO tableb (id, a_id, "name") VALUES(4, NULL, 'b4');
-- create function for inserting data into tablea and returning these id
CREATE OR REPLACE FUNCTION tablea_inserting()
RETURNS integer
LANGUAGE plpgsql
AS $function$
declare
ret int4;
begin
insert into tablea ("name") values ('test')
returning id into ret;
return ret;
end
$function$
;
-- After then you can update your tableb
update tableb set
a_id = tablea_inserting()
where a_id is null
select * from tableb;
Result:
id a_id name
1 100 b1
2 1 b2
3 2 b3
4 3 b4

Compare between columns on different tables

I need to write T-SQL code that will compare between T1.PercentComplete that need to be between T2.StageFrom and T2.StageTo. and than get the T2.Bonus_Prec and join T1
T1:
T2:
The desired result for T2.Bonus_Prec is 0.02 since T1.Percent_Complete is .27, which is between 0 and 1.
The thing is that each Key can have a different T2.StageID between 1-6.
If Key have just one T2.StageID it'll be 0. (fast way for me to know that there is only 1 bonus option)
If it have more than 1 it's will start with 1. (This can be changed if needed)
T1:
DROP TABLE T1;
CREATE TABLE T1(
Key VARCHAR(10) NOT NULL PRIMARY KEY
,Percent_Complete_ NUMBER(16,2) NOT NULL
);
INSERT INTO T1(Key,Percent_Complete_) VALUES ('Key Vendor',Percent_Complete);
INSERT INTO T1(Key,Percent_Complete_) VALUES ('***',0.27);
T2:
DROP TABLE T2;
CREATE TABLE T2(
Key VARCHAR(50) NOT NULL
,StageID INT NOT NULL
,Stage_From NUMERIC(10,2) NOT NULL
,Stage_To NUMERIC(8,2) NOT NULL
,Stage_Bonus_Prec NUMERIC(16,2) NOT NULL
);
INSERT INTO T2(Key,StageID,Stage_From,Stage_To,Stage_Bonus_Prec) VALUES ('Key',Stage_Id,Stage_From,Stage_To,Stage_Bonus_Prec);
INSERT INTO T2(Key,StageID,Stage_From,Stage_To,Stage_Bonus_Prec) VALUES ('***',1,0,0.8,0.02);
INSERT INTO T2(Key,StageID,Stage_From,Stage_To,Stage_Bonus_Prec) VALUES ('***',2,0.8,1,0.035);
INSERT INTO T2(Key,StageID,Stage_From,Stage_To,Stage_Bonus_Prec) VALUES ('***',3,1,-1,0.05);
OUTPUT:
+-----+-------------------+--------------------+
| Key | Percent_Complete | [Stage_Bonus_Prec] |
+-----+-------------------+--------------------+
| *** | 0.27 | 0.02 |
+-----+-------------------+--------------------+
Here is a SQLFiddle with these values
It is still not clear what you are trying to do but I made an attempt. Please notice I also corrected a number of issues with ddl and sample data you posted.
if OBJECT_ID('T1') is not null
drop table T1
CREATE TABLE T1(
KeyVendor VARCHAR(10) NOT NULL PRIMARY KEY
,PercentComplete VARCHAR(16) NOT NULL
);
INSERT INTO T1(KeyVendor,PercentComplete) VALUES ('***','0.27');
if OBJECT_ID('T2') is not null
drop table T2
CREATE TABLE T2(
MyKey VARCHAR(50) NOT NULL
,StageID INT NOT NULL
,Stage_From NUMERIC(10,0) NOT NULL
,Stage_To NUMERIC(8,0) NOT NULL
,Stage_Bonus_Prec NUMERIC(16,3) NOT NULL
);
INSERT INTO T2(MyKey,StageID,Stage_From,Stage_To,Stage_Bonus_Prec) VALUES ('***',1,0,0.8,0.02);
INSERT INTO T2(MyKey,StageID,Stage_From,Stage_To,Stage_Bonus_Prec) VALUES ('***',2,0.8,1,0.035);
INSERT INTO T2(MyKey,StageID,Stage_From,Stage_To,Stage_Bonus_Prec) VALUES ('***',3,1,-1,0.05);
select *
from T1
cross apply
(
select top 1 Stage_Bonus_Prec
from T2
where t1.PercentComplete >= t2.Stage_Bonus_Prec
and t1.KeyVendor = t2.MyKey
order by Stage_Bonus_Prec
) x
Taking a shot at this as well, since it's still a bit unclear:
SELECT t1.percent_complete, t2.Stage_Bonus_Prec
FROM T1 INNER JOIN T2
ON T1.[key vendor] = T2.[Key] AND
T1.[percent_complete] BETWEEN T2.Stage_From AND T2.Stage_To
Joining T1 and T2 on [Key Vendor] and [Key] and using the BETWEEN operator to find the percent_complete value that is between Stage_From and Stage_To.
I think I'm still missing something since I'm still confused about where Key value of *** comes from in your desired results.
SQLFiddle of this in action, based on a slightly fixed up version of your DDL (you put your field names in their own data record, I've removed them since they don't belong there).

Is there a way to set AUTO_INCREMENT property on existing table column in Vertica?

Suppose I have a simple table:
CREATE TABLE user(
id INT NOT NULL PRIMARY KEY,
name VARCHAR(32) NOT NULL,
)
Is there a way to alter this table so id will become AUTO_INCREMENT field?
I tried the following with no luck:
ALTER TABLE (no such syntax)
Creating another table with auto increment ID, and copying the data from the original one (didn't work because of the error: Cannot insert into or update IDENTITY/AUTO_INCREMENT column "id")
Thanks!
I would try to just rank the rows, and use the sequence for future inserts.
\set AUTOCOMMIT 'on'
CREATE TABLE t1 (
val char(1)
);
INSERT INTO t1 VALUES ('a');
INSERT INTO t1 VALUES ('b');
INSERT INTO t1 VALUES ('c');
INSERT INTO t1 VALUES ('d');
CREATE TABLE t2 (
id int,
val char(1)
);
INSERT INTO t2 (val, id)
SELECT val, RANK() OVER (ORDER BY val) as id
FROM t1;
SELECT * FROM t2;
We get:
id | val
----+-----
1 | a
3 | c
2 | b
4 | d
Success!
Let's prepare the table for future inserts:
-- get the value to start sequence at
SELECT MAX(id) FROM t2;
-- create the sequence
CREATE SEQUENCE seq1 START 5;
-- syntax as of 6.1
-- modify the column to add next value for future rows
ALTER TABLE t2 ALTER COLUMN id SET DEFAULT NEXTVAL('seq1');
Quick test:
INSERT INTO t2 (val) VALUES ('e');
INSERT INTO t2 (val) VALUES ('f');
SELECT * FROM t2;
We get:
id | val
----+-----
4 | d
2 | b
3 | c
6 | f
1 | a
5 | e
Hope this helps.

How to insert a record into a table with a column declared with the SERIAL function

My database is using PostgreSQL. One table is using the serial auto-increment macro. If I want to insert a record into the table, do I still need to specify that value, or it is be automatically assigned for me?
CREATE TABLE dataset
(
id serial NOT NULL,
age integer NOT NULL,
name character varying(32) NOT NULL,
description text NOT NULL DEFAULT ''::text
CONSTRAINT dataset_pkey PRIMARY KEY (id)
);
Using the DEFAULT keyword or by omitting the column from the INSERT list:
INSERT INTO dataset (id, age, name, description)
VALUES (DEFAULT, 42, 'fred', 'desc');
INSERT INTO dataset (age, name, description)
VALUES (42, 'fred', 'desc');
If you create a table with a serial column then if you omit the serial column when you insert data into the table PostgreSQL will use the sequence automatically and will keep the order.
Example:
skytf=> create table test_2 (id serial,name varchar(32));
NOTICE: CREATE TABLE will create implicit sequence "test_2_id_seq" for serial column "test_2.id"
CREATE TABLE
skytf=> insert into test_2 (name) values ('a');
INSERT 0 1
skytf=> insert into test_2 (name) values ('b');
INSERT 0 1
skytf=> insert into test_2 (name) values ('c');
INSERT 0 1
skytf=> select * From test_2;
id | name
----+------
1 | a
2 | b
3 | c
(3 rows)
These query work for me:
insert into <table_name> (all columns without id serial)
select (all columns without id serial)
FROM <source> Where <anything>;
Inserting multiple rows wasn't working for me in this scenario:
create table test (
id bigint primary key default gen_id(),
msg text not null
)
insert into test (msg)
select gs
from generate_series(1,10) gs;
because I had mistakenly marked my gen_id function IMMUTABLE.
The insert query was being optimized to only call that function once rather than 10 times. Oops...
For example, you create "person" table with "id" of serial and "name" as shown below:
CREATE TABLE person (
id serial PRIMARY KEY,
name VARCHAR(50)
)
Then, you can use DEFAULT for "id" of serial and insert rows without column(field) names as shown below:
INSERT INTO person VALUES (DEFAULT, 'John'), (DEFAULT, 'Tom');
postgres=# SELECT * FROM person;
id | name
----+------
1 | John
2 | Tom

How can I make a copy of a table with a PK?

In an Oracle 10g database, I would like to make a copy of an existing table. I would like it to have the same data and rows as the original table. The original table uses a PK though, so I'm not sure how to copy it and keep them unique.
oracle maintains the pk as a column constraint. you have to copy the table and subsequently create this constraint for the new table.
the following code illustrates how to get your job done.
-- setting up table t1 - this is just for the sake of demonstration
create table t1 (
t_id integer
, t_data varchar2(40)
);
alter table t1 modify ( t_id constraint t1_pk primary key );
insert into t1 values ( 1, 'test');
insert into t1 values ( 2, 'another test');
insert into t1 values ( 3, 'final test');
commit;
-- copying table t1 (definition + contents) and defining the pk
create table t2 as ( select * from t1 );
alter table t2 modify ( t_id constraint t2_pk primary key );
hope this helps,
best regards,
carsten
You can make the copy using
CREATE TABLE dummy_copy as SELECT * FROM dummy//Structure and data
Also you could use dbms_metadata.get_ddl to get the associated constraints of the table
and create it with all the checks
SELECT dbms_metadata.get_ddl( 'TABLE', 'dummy' ) FROM DUAL;
Or you can just do it all in one statement:
create table mike_temp_1 (
col1,
col2,
col3,
col4,
col5,
constraint xpk_mike_temp_1 primary key (col1)
)
as select *
from OLD_POLICY_TERM;
I think the format of specifying column names when using create table as select is a bit fiddly in that I don't believe that you can specify data types (sort of obvious really) but you can specify constraints such as not null, primary key and foreign key.