Select rows conditionally and insert into another table conditionally - tsql

How to insert into table 2 all field values of a row from table A, where all values in a column A in table 1 that satisfy a condition on column B of table 1 ,but do not exist in table 2.How to frame a query using not exists?
I tried this:
INSERT INTO Teachermast (
teacher_code,
teacher_name,
designation,
dept_code,
contact_no,
email,
address,
dob,
PASSWORD
)
SELECT
userId,
username,
designation,
dept,
contact_no,
email,
address,
dob,
PASSWORD
FROM
UserMast
WHERE NOT EXISTS
(SELECT
userId
FROM
UserMast
WHERE usertype = '3')
but this doesnt seem to work.
Kindly help.

You could do a MERGE
create table users
(
userId varchar(50),
username varchar(50),
usertype int,
password varchar(50),
contact_no varchar(50),
email varchar(50),
faxno varchar(50),
address varchar(50),
created_date date,
updated_date date,
status varchar(50),
gender varchar(50),
dob date,
lasttimelogin datetime,
login_time datetime,
logoutt_time datetime,
designation varchar(50),
dept varchar(50),
email_pass varchar(50)
)
insert into users values('T0003','Ankita',3,'12345','9858‌​585245','anki#gmail.com','201','l block noid sec 25',NULL,NULL,NULL,'Female','11/09/1990',NULL,NULL,NULL,'Teacher','EC',NULL);
insert into users values('T0004','Ribha',3,'12345','9512365423','sharma#gmail.com',NULL,'221 dwarka sec 10',NULL,NULL,NULL,'Female','12/02/1989',NULL,NULL,NULL,'Teacher','EC',NULL);
create table teachers
(
teacher_code varchar(50),
teacher_name varchar(50),
designation varchar(50),
dept_code varchar(50),
contact_no varchar(50),
email varchar(50),
address varchar(50),
dob date,
password varchar(50)
)
insert into teachers values('T0002','Tanvi','Teacher','CS','9632569856','tan123#gmai‌​l.com','298 mayur vihar ph 1','29/06/1990','12345');
insert into teachers values('T0003','Ankita','Teacher','EC','9858585245','anki#gmail‌​.com','201 l block noida sec 25','11/09/1990','12345');
merge teachers as target
using (select userid, username, designation, dept, contact_no, email, address, dob, password from users where usertype = 3)
as source(userid, username, designation, dept, contact_no, email, address, dob, password)
on target.teacher_code = source.userid
when not matched by target then
insert (teacher_code, teacher_name, designation, dept_code, contact_no, email, address, dob, password)
values (source.userid, source.username, source.designation, source.dept, source.contact_no, source.email, source.address, source.dob, source.password);
select * from teachers
However, I think there are issues with your database design. With your current model, you could have, for example, a different address (or password!) for Ankita in table1 compared to table2. And if you change any of that information you would have to change it in both places.
Could you, for example, just insert everyone into "users" and have "teachers" be a view
select {columns} from users where usertype = 3

Please try this query
SELECT
t.userId,
t.username,
t.designation,
t.dept,
t.contact_no,
t.email,
t.address,
t.dob,
t.PASSWORD
FROM Teachermast as t
LEFT join UserMast as u on t.userId = u.teacher_code
WHERE t.usertype = '3' and u.teacher_code is null

Related

I get error as "duplicate key value violates unique constraint "

I'm working on a data warehouse. I have 4 table on public schema they are customer, product, addressee and orders
Then I created this tables on my olap schema
CREATE TABLE olap.time
(
idtime SERIAL NOT NULL PRIMARY KEY,
year integer,
month integer,
week integer,
day integer
);
CREATE TABLE olap.addressees
(
idaddressee integer PRIMARY KEY NOT NULL,
name varchar(40) NOT NULL,
zip char(6) NOT NULL,
address varchar(60) NOT NULL
);
CREATE TABLE olap.customers
(
idcustomer varchar(10) PRIMARY KEY ,
name varchar(40) NOT NULL,
city varchar(40) NOT NULL,
zip char(6) NOT NULL,
address varchar(40) NOT NULL,
email varchar(40),
phone varchar(16) NOT NULL,
regon char(9)
);
CREATE TABLE olap.fact
(
idtime integer NOT NULL,
idaddressee integer NOT NULL,
idcustomer varchar(10) NOT NULL,
idfact integer NOT NULL,
price numeric(7,2),
PRIMARY KEY (idtime, idaddressee, idcustomer),
FOREIGN KEY (idaddressee) REFERENCES olap.addressees(idaddressee),
FOREIGN KEY (idcustomer) REFERENCES olap.customers(idcustomer),
FOREIGN KEY (idtime) REFERENCES olap.time(idtime)
);
After the creating tables I run these queries
INSERT INTO olap.time (year, month, week, day)
SELECT date_part('year', date), date_part('month', date), date_part('week', date), date_part('day', date)
FROM public.orders
GROUP BY public.orders.date
ORDER BY public.orders.date;
INSERT INTO olap.addressees(idaddressee, name, zip, address)
SELECT idaddressee, name, zip, address
FROM public.addressee;
INSERT INTO olap.customers (idcustomer, name, city, zip, address, email, phone, regon)
SELECT idcustomer, name, city, zip, address, email, phone, regon
FROM public.customer;
And then I try to do these set of query
INSERT INTO olap.fact (idtime, idaddressee, idcustomer, idfact, price)
SELECT olap.time.idtime, olap.addressees.idaddressee, olap.customers.idcustomer, COUNT(*), public.orders.price
FROM (((public.orders
INNER JOIN olap.time ON (date_part('year', public.orders.date) = olap.time.year AND date_part('month', public.orders.date) = olap.time.month AND date_part('week', public.orders.date) = olap.time.week) AND date_part('day', public.orders.date) = olap.time.day)
INNER JOIN olap.addressees ON public.orders.idaddressee = olap.addressees.idaddressee)
INNER JOIN olap.customers ON public.orders.idcustomer = olap.customers.idcustomer)
GROUP BY olap.time.idtime, olap.addressees.idaddressee, olap.customers.idcustomer, public.orders.price;
After running last set of queries I got error
ERROR: syntax error at or near "duplicate"
LINE 1: duplicate key value violates unique constraint"
What can the problem be? Thanks in advance

Passing UUID of one table to another table as a Foreign key value in PostgreSQL

I have table Employee in Postgres:
drop table if exists employee;
create table employee (
id uuid default uuid_generate_v4 () primary key,
first_name varchar not null,
last_name varchar not null
);
And another table salary :
drop table if exists salary;
create table salary (
check_id uuid default uuid_generate_v4 () primary key,
salary int not null,
employee_id uuid references employee (id)
);
employee_id is the foreign key to id in the Employee table, but I don't understand how to insert a value inside employee_id since UUID is unique.
I am inserting values into Employee table:
insert into employee (first_name, last_name, email, code) values ( 'jonh', 'smith', 'jonh#example.com', '1');
And then if I try insert values into salary table:
insert into salary (salary ) values ('1000');
Then select command will return employee_id value empty.
But if I make it default uuid_generate_v4 (), then result is: Key (employee_id)=(c4ccd745-02ba-4a0e-8586-32e3c6a2b84a) is not present in table "employee".
I understand that because employee_id is a foreign key it should match with uuid in employee, but since uuid is mostly unique, how can I make it work?
You have to use the uuid that was inserted into the employee table. You can do this with a CTE in a single statement:
WITH new_employee AS (
INSERT INTO employee (first_name, last_name, email, code)
VALUES ('jonh', 'smith', 'jonh#example.com', '1')
RETURNING id
)
INSERT INTO salary (salary, employee_id)
SELECT 1000, id
FROM new_employee;

Hello I'm pretty new to PostgreSQL so I trying to create a one to one relationship between the tables account and bank_account

I tried using a foreign key, but it still shows them as being separate and not connected is there something I'm missing here, my goal was to originally link the persons name to the account_balance.
CREATE TABLE accounts (
id SERIAL,
first_name VARCHAR(50),
last_name VARCHAR (50),
username VARCHAR (50),
password VARCHAR (500),
account_Type VARCHAR (10),
bday VARCHAR (50),
PRIMARY KEY(id)
);
CREATE TABLE bank_account(
id SERIAL,
account_number INTEGER PRIMARY KEY,
account_balance INTEGER,
CONSTRAINT bank_users
FOREIGN KEY (id)
REFERENCES accounts(id)
ON DELETE CASCADE
);
INSERT INTO accounts (
first_name,
last_name,
username,
password,
account_Type,
bday)
VALUES ('bob', 'john', 'bob#gmail.com', crypt('bob1',gen_salt('bf')),'Manager', '01/01/1985'),
('Tom', 'lin', 'tom#gmail.com', 'tom1', 'Manager', '5/23/1990');
INSERT INTO bank_account(
account_number,
account_balance)
VALUES ('1234', '50000'),('4332', '100000');

FROM clause with DO UPDATE in Postgres

I am writing a upsert query using CONFLICT. But I am facing issue on update part. Here is my query looks like.
INSERT INTO
customers (name, email, city)
SELECT
'jack',
'jack#io' as email,
city
FROM
customers
where
id = 1
ON CONFLICT(name) DO
update
set
email = cs.email
FROM
(
select
email
from
customers
where
id = 1
)
as cs;
following is query structure
CREATE TABLE customers (
id serial PRIMARY KEY,
name VARCHAR UNIQUE,
email VARCHAR NOT NULL,
city VARCHAR NOT NULL
);
Erro i am getting
syntax error at or near "FROM"
LINE 1: ... ON CONFLICT(name) DO update set email = cs.email FROM (sele...
Your sub-select has the wrong structure.
If you need to update multiple columns, use a tuple assignment
INSERT INTOcustomers (name, email, city)
SELECT 'jack',
'jack#io' as email,
city
FROM customers
where id = 1
ON CONFLICT(name) DO
update set (email, other_col) = (select email, c2
from customers
where id = 1)

Postgres Dynamic Query

I have scenario were I have a master table which stores db table name and column name, I need to build dynamic query based on that.
CREATE TABLE MasterTable
(
Id int primary key,
caption varchar(100),
dbcolumnname varchar(100),
dbtablename varchar(100)
);
CREATE TABLE Engineers
(
Id int primary key,
Name varchar(100),
Salary BigInt
);
CREATE TABLE Executives
(
Id int primary key,
Name varchar(100),
Salary BigInt
);
CREATE TABLE Manager
(
Id int primary key,
Name varchar(100),
Salary BigInt
);
INSERT INTO Manager(Id, Name, Salary)
VALUES(1, 'Manager 1', 6000000);
INSERT INTO Executives(Id, Name, Salary)
VALUES(1, 'Executive 1', 6000000);
INSERT INTO Engineers(Id, Name, Salary)
VALUES(1, 'Engineer 1', 6000000);
INSERT INTO MasterTable(Id, caption, dbcolumnname, dbtablename)
VALUES (1, 'Name', 'name', 'Engineers');
INSERT INTO MasterTable(Id, caption, dbcolumnname, dbtablename)
VALUES (2, 'Name', 'name', 'Manager');
INSERT INTO MasterTable(Id, caption, dbcolumnname, dbtablename)
VALUES (3, 'Name', 'name', 'Executives');
INSERT INTO MasterTable(Id, caption, dbcolumnname, dbtablename)
VALUES (4, 'Salary', 'Salary', 'Engineers');
INSERT INTO MasterTable(Id, caption, dbcolumnname, dbtablename)
VALUES (5, 'Salary', 'Salary', 'Manager');
INSERT INTO MasterTable(Id, caption, dbcolumnname, dbtablename)
VALUES (6, 'Salary', 'Salary', 'Executives');
I want to build a stored procedure which accepts caption and Id and give result back based on dbcolumnname and dbtablename. For example if I pass Salary,Name as caption and Id as 1, stored procedure should be query of dbcolumn and dbtable, something like below.
Select Id as ID, name as Value from Engineers
UNION
Select Id as ID, name as Value from Manager
UNION
Select Id as ID, name as Value from Executives
UNION
Select Id as ID, Salary as Value from Executives
UNION
Select Id as ID, Salary as Value from Engineers
UNION
Select Id as ID, Salary as Value from Manager
I have heard of dynamic sql, can that be used here?
Fiddle
EDIT :: I got one dynamic query which builds union statement to get the output, however problem is i am not able to escape double quotes. Below is the query and Error
Query :
DO
$BODY$
BEGIN
EXECUTE string_agg(
format('SELECT %I FROM %I', dbcolumnname, dbtablename),
' UNION ')
FROM MasterTable;
END;
$BODY$;
Error:
ERROR: relation "Engineers" does not exist
LINE 1: SELECT name FROM "Engineers" UNION SELECT name FROM "Manager...
I'd like to suggest an alternative way of achieving what you want. That is, using PostgreSQL inheritance mechanism.
For instance:
CREATE TABLE ParentTable (
Id int,
Name varchar(100),
Salary BigInt
);
ALTER TABLE Engineers INHERIT ParentTable;
ALTER TABLE Executives INHERIT ParentTable;
ALTER TABLE Manager INHERIT ParentTable;
SELECT Id, Salary AS value FROM ParentTable
UNION
SELECT Id, Name AS value FROM ParentTable;
Now if you want to use MasterTable in order to restrict the set of tables used, you can do it as follows:
SELECT Id, Name AS value
FROM ParentTable
INNER JOIN pg_class ON parenttable.tableoid = pg_class.oid
INNER JOIN MasterTable ON LOWER(dbtablename) = LOWER(relname)
UNION
SELECT Id, Salary AS value
FROM ParentTable
INNER JOIN pg_class ON parenttable.tableoid = pg_class.oid
INNER JOIN MasterTable ON LOWER(dbtablename) = LOWER(relname)
However, you can not arbitrarily restrict the set of columns to retrieve from one table to another with this technique.
Table names and column names are case insensitive in SQL, unless they are quoted in double quotes. Postgres does this by folding unquoted identifiers to lower case.
So, your DDL:
CREATE TABLE MasterTable
(
Id int primary key,
caption varchar(100),
dbcolumnname varchar(100),
dbtablename varchar(100)
);
Will be interpreted by Postgres as
CREATE TABLE mastertable
(
id int primary key,
caption varchar(100),
dbcolumnname varchar(100),
dbtablename varchar(100)
);
You can avoid case folding by quoting the names:
CREATE TABLE "MasterTable"
(
"Id" int primary key,
caption varchar(100),
dbcolumnname varchar(100),
dbtablename varchar(100)
);
The %I format-specifier (internally uses quote_ident()) adds quotes to its argument (when needed)
, so the query asks for "MasterTable" when only mastertable is present in the schema.
But, it is easyer to just avoid MixedCase identifiers,