Transfer existing data after database model changes (PostgreSQL) - postgresql

I'm trying to remove an association table from my database. It contains two columns (a_id and b_id) referencing the tables a and b.
This table is unnecessary because in fact it's an OneToMany relation. So I added column a_id in table b.
My problem: How can I transfer the existing entrys from assoc_a_b to b.a_id?
SELECT DISTINCT b.id, a.id FROM table_a AS a
JOIN assoc_a_b AS assoc ON a.id = assoc.a_id
JOIN table_b AS b ON b.id = assoc.b_id;
This select statement works. Can it be combined with an UPDATE statement? The UPDATE statement would look someway like:
UPDATE b SET a_id = a.id WHERE id = b.id;
using a.id and b.id from the select statement above.

update b set a_id = (SELECT assoc_a_b.a_id from assoc_a_b where assoc_a_b.b_id = b.id)

Related

Conditional delete and insert in postgres

I have two tables Table_A and Table_B. How can I write a conditional SQL that does the following logic
If table A records match table B records on id
then
delete records from table A and Insert records into Table B
How can I do this with SQL most likely using with
delete from Table_A where Exists (select a.id from TABLE_A
join TABLE_B as b on a.id = b.id)
The Insert is:Insert into Table_A (id) select id from TABLE_B
Use a CTE to catch the ids of the deleted records, and re-join these with the b records:
WITH del AS (
DELETE FROM a
WHERE EXISTS ( SELECT *
FROM b
WHERE b.id = a.id
)
returning *
)
INSERT INTO a (id, x, y, z)
SELECT id, x, y, z
FROM b
WHERE EXISTS (
SELECT *
FROM del
WHERE del.id = b.id
);
BTW: you should have very good reasons (such as wanting to activate the triggers) to prefer delete+insert to a update.

How to change update statements into insert statements while maintaining SET command from UPDATE command?

As the title suggests, I need to change my update and join statements into insert statements. How I would do this while incorporating SET from the UPDATE statements?
Update statement:
UPDATE tableA
SET A = tableB.A
FROM tableB
JOIN tableC ON tableB.C = tableC.C
WHERE tableC.D = tableA.D
Your tables are empty, thus tableC.D = tableA.D wouldn't provide anything.
May it be you are looking for something like this?:
INSERT INTO tableA (A)
SELECT DISTINCT tb.A
FROM tableB tb
JOIN tableC tc ON tb.C = tc.C
Or perhaps including the D column:
INSERT INTO tableA (A, D)
SELECT DISTINCT tb.A, tc.D
FROM tableB tb
JOIN tableC tc ON tb.C = tc.C
Note the use of DISTINCT here to dispense duplicate records.
Generally, it is good practice to include all the column names in the INSERT statement. And you can remove WHERE clause by JOINing tableA to tableC. But just the simple answer for your question would be:
INSERT INTO tableA (<col name you want to update>)
VALUES (SELECT <one value> FROM tableB JOIN tableC ON tableB.C = tableC.C JOIN tableA ON tableC.D = tableA.D
);

Postgresql how to select values in the column from one table that are only available in another table?

I am using Postgresql and need to query two tables like this:
Table1
ID Bill
A 1
B 2
B 3
C 4
Table2
ID
A
B
I want a table with all the columns in Table1 but keeping only the records with IDs that are available in Table2 (A and B in this case). Also, Table2's ID is unique.
ID Bill
A 1
B 2
B 3
Which join I should use or if I can use WHERE statement?
Thanks!
SELECT Table1.*
FROM Table1
INNER JOIN Table2 USING (ID);
or
SELECT *
FROM Table1
WHERE ID IN (SELECT ID FROM Table2);
but the first one is better for performance reason.
SELECT *
FROM Table1
WHERE EXISTS (
SELECT 1 FROM Table2 WHERE Table2.ID = Table1.ID LIMIT 1
)

Comparing data between tables in same database

My requirement is i have to compare data between two different tables with same schema in same database ,
For the moment I am making comparison in different fields in same table and if some validation fails error will be stored in one table like :
IF (NEW.vision IS NULL and new.vispres IS NOT NULL)
THEN INSERT INTO exception_detail( noces,exception) VALUES
(new.no,'please check the values if vision is null then vispres should also be null');
END IF;
The same kind of comparison i want to do with two tables for same element (no) eg
IF (TABLE1.NEW.vispres IS NULL and TABLE2.new.vispres IS NOT NULL)
THEN INSERT INTO exception_detail( noces,exception) VALUES
(new.no,'please check the values if vispres is null for number 5 in table 1 then vispres should also be null for number 5 in Table 2 ');
END IF;
Please help
Thank you in advance
Can I do something like :
SELECT q1.* FROM TABLE1 q1
INNER JOIN TABLE2 q2 ON (q1.noces = q2.noces);
I think it will give all the records from both tables where noces is same
In continuation now i want to compare each row of the output, and if data is not same it must throw exception, IS there a possibility like :
foreach row of above output{
if (q1.name != q2.name)
Do something ;
if (q2.address < q1.address)
Do something ;
}
but it all must be in one query or trigger
I would look at essentially three cases.
ID's the same, but data differs
ID in table_a not found in table_b
ID in table_b not found in table_a
SQL might look like this:
SELECT (r).* FROM ( -- Wrapper query
SELECT a as r
FROM table_a a
JOIN table_b b ON a.id = b.id AND a <> b
UNION ALL
SELECT a as r
FROM table_a a
LEFT JOIN table_b b ON a.id = b.id
WHERE b.id IS NULL
UNION ALL
SELECT b AS r
FROM table_b b
LEFT JOIN table_a a ON a.id = b.id
WHERE a.id IS NULL
) t;
It might be possible to fold this into a case and a full outer join but this should give you the basic idea.

How do I look at column metadata in Sybase?

I have a list of columns a co-worker has given to me, but these columns reside in different tables in the DB. Is there some kind of tool in Sybase where I can query the table a column belongs to?
(I've tried Google-ing for this kind of tool, but no luck so far)
syscolumns holds column metadata.
select * from syscolumns where name = ;
The id column in syscolumns is the id of the column's table, in sysobjects;
select b.name as tablename, a.name as columnname
from syscolumns a join systables b on (a.id = b.id)
where b.type='U' and b.name = 'foo';
gets all columns for the table named 'foo'. The type = 'U' limits it to user tables.
select b.name as tablename, a.name as columnname
from syscolumns a join systables b on (a.id = b.id)
where b.type='U' and a.name = 'foo';
gets all columns named 'foo'.
Most current version of ASE will use sysbojects instead of systables
I had to make a few small change for it to work:
select b.name as tablename,
a.name as columnname
from dbo.syscolumns a
join sysobjects b on a.id = b.id
where b.type='U'
and upper(a.name) like '%FOO%' -- wildcard search for column name
and b.name = 'bar' -- exclude tables
order by b.name
You can find the information for any column in:
SELECT *
FROM sys.syscolumns
If you want to know to what table a column belongs:
SELECT cname, tname
FROM sys.syscolumns
WHERE tname IN ('col_1', 'col_2')
NOTE: I test this in Sybase ASA 9.