How to compare two database for unique tables? - sql

I have an old SQL 2008 backup for our application. Today we encountered a case where we want to restore it as a current database in our sql-2012. I used the below query to count the tables in both database
USE YOURDBNAME
SELECT COUNT(*) from information_schema.tables
WHERE table_type = 'base table'
my current database returned total 543 tables whereas old database
showed 533 tables
How to find the unique ten tables from the current database by comparing it with the tables of my previous database. ?
Update 1
I used the below query to compare the tables but it returned no result
select 'dbtest01' as dbname, t1.table_name
from dbtest01.[INFORMATION_SCHEMA].[tables] t1
where table_name not in (select t2.table_name
from
dbtest02.[INFORMATION_SCHEMA].[tables] t2
)
union
select 'dbtest02' as dbname, t1.table_name
from dbtest02.[INFORMATION_SCHEMA].[tables] t1
where table_name not in (select t2.table_name
from
dbtest01.[INFORMATION_SCHEMA].[tables] t2
)

This query includes table_schema to make sure if the table name is repeated but in a different schema then it shows up. This shows tables that are in db_1 but not in db_2 as well as tables in db_2 but not in db_1.
SELECT
db1.dbname AS db1_name,
db1.table_schema AS db1_schema,
db1.table_name AS db1_table,
db2.dbname AS db2_name,
db2.table_schema AS db2_schema,
db2.table_name AS db2_table
FROM (
SELECT
'YOURDBNAME' AS dbname,
table_schema,
table_name
FROM YOURDBNAME.information_schema.tables
WHERE table_type = 'BASE TABLE'
) AS db1
FULL OUTER JOIN (
SELECT
'YOUROTHERDBNAME' AS dbname,
table_schema,
table_name
FROM YOUROTHERDBNAME.information_schema.tables
WHERE table_type = 'BASE TABLE'
) AS db2 ON
db1.table_schema = db2.table_schema
AND db1.table_name = db2.table_name
WHERE db1.dbname IS NULL
OR db2.dbname IS NULL

These two queries will do the work, as a quick ad-hoc query. You have to do it twice, in "both directions", to catch all possible differences.
-- All tables in dbtest01 that are not in dbtest02
SELECT schema_name(schema_id), name
from dbtest01.sys.tables
except select schema_name(schema_id), name
from dbtest02.sys.tables
order by name
-- All tables in dbtest02 that are not in dbtest01
SELECT schema_name(schema_id), name
from dbtest01.sys.tables
except select schema_name(schema_id), name
from dbtest02.sys.tables
order by name
(Updated with schemas, based on #Andrew's reply. Full outer joins work too, but they hurt my brain.)

SELECT table_name from dbtest01.information_schema.tables
WHERE table_type = 'base table'
EXCEPT
SELECT table_name from dbtest02.information_schema.tables
WHERE table_type = 'base table'

Related

Find columns that are one table and but not in the other table

I am working with two very wide tables (Table A, Table B) in Snowflake. Both tables should have exact same columns, though not necessarily in the same order. However Table B is missing a few columns. Is there a way to quickly find all the columns that are in Table A but not in Table B? I am not concerned with the Data, just the existence of columns.
Essentially, I am looking for a SQL way to find all columns in Table that are missing in Table B.
I currently use a ETL tool for this. But it is rather cumbersome. It would be nice if this can be done using SQL.
Try the following
SELECT column_name
FROM information_schema.columns
WHERE table_name = 'tableA'
AND column_name NOT IN
(
SELECT column_name
FROM information_schema.columns
WHERE table_name = 'tableB'
);
You can do this with aggregation:
SELECT column_name
FROM information_schema.columns
WHERE table_name IN ('tableA', 'tableB')
GROUP BY column_name
HAVING MIN(table_name) = MAX(table_name) AND MIN(table_name) = 'TableA';
This is a handy structure that can more easily generalize to multiple tables. It does assume that the two tables are on the same server.
Below query also gives missing columns in Table B.
SELECT column_name FROM information_schema.columns WHERE table_name = 'TableA'
MINUS
SELECT column_name FROM information_schema.columns WHERE table_name = 'TableB'

SQL Query in sap hana

I have a database and have 2 schema called DWFR and DWFR3 , what i need to do is compare 2 schmea and take the matching table name and also the table present in DWFR schema which is not available on DWFR3 and also with the below condition
SELECT schema_name, table_name
FROM tables
WHERE schema_name = 'DWFR'
AND table_name NOT LIKE 'RA%'
AND table_name NOT LIKE 'ZZ%'
AND table_name NOT LIKE 'DELETE%'
AND table_name NOT LIKE '%TEST%'
AND table_name NOT LIKE 'XX%'
AND table_name NOT LIKE 'ROB%'
AND table_name IN (
SELECT table_name
FROM tables
WHERE schema_name = 'DWFR3'
AND table_name NOT LIKE 'RA%'
AND table_name NOT LIKE 'ZZ%'
AND table_name NOT LIKE 'DELETE%'
AND table_name NOT LIKE '%TEST%'
AND table_name NOT LIKE 'XX%'
AND table_name NOT LIKE 'ROB%'
)
ORDER BY schema_name, table_name;
This will get the matched table names but i also want table name available in DWFR which is not their on DWFR3.
You can use a LEFT OUTER JOIN for selecting all data rows from a set and matchings from a second set.
I used a SQL CTE Common Table Expression in the script, you can think of it as a sub-select with additional uses
Here is how you can use for your case
with t2 as (
select table_name
from tables
where schema_name = 'DWFR3'
)
select t1.table_name, t2.table_name
from tables t1
left outer join t2
on t1.table_name = t2.table_name
where t1.schema_name = 'DWFR'
And you also need the append the additional requirements or WHERE clauses into above script
For the reason that I used CTE can be explained as follows.
In fact, the actual solution should be as simple as following.
Unfortunately, HANA seems to not supporting additional filtering criteria with ON clause on JOINs
select t1.table_name, t2.table_name
from tables t1
left outer join tables t2
on t1.table_name = t2.table_name and t2.schema_name = 'DWFR3
where t1.schema_name = 'DWFR'
Because of this reason, I had to filter the LEFT part of the JOIN earlier than applying the ON, join condition
To find matched table names in both schemas:
select
'DWFR' as schema_name,
table_name
from
(
select table_name from tables where schema_name = 'DWFR'
intersect
select table_name from tables where schema_name = 'DWFR3'
) x
where
table_name not like 'RA%' and
table_name not like 'ZZ%' and
table_name not like 'DELETE%' and
table_name not like '%TEST%' and
table_name not like 'XX%' and
table_name not like 'ROB%';
To find table names in DWFR but not in DWFR3:
select
'DWFR' as schema_name,
table_name
from
(
select table_name from tables where schema_name = 'DWFR'
except
select table_name from tables where schema_name = 'DWFR3'
) x
where
table_name not like 'RA%' and
table_name not like 'ZZ%' and
table_name not like 'DELETE%' and
table_name not like '%TEST%' and
table_name not like 'XX%' and
table_name not like 'ROB%';

Number of Tables in Database

How to count number of tables in a database ?
SELECT COUNT *
FROM SHOW TABLES AS A
SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'dbName';
Source
This one is easy
USE databasename; SHOW TABLES; SELECT FOUND_ROWS();
SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'dbName';

Column names from query

I'm trying to get make a query to return a list of the column names from a query result in postgresql
e.g.
SELECT column_name
FROM (
SELECT table1.*
FROM table1
LEFT JOIN table2
ON table1.id = table2.tbl1_id
)
is this possible
I DO NOT WANT THE COLUMNS FROM A SINGULAR TABLE!!! so please dont tell me to do
SELECT column_name
FROM information_schema.columns
WHERE table_name = 'table1'
I don't know why you would ever need to do this, but it is possible using some of the JSON functions introduced in 9.3.
SELECT json_object_keys(row_to_json(t)) FROM
(SELECT * FROM table1
LEFT JOIN table2 ON table1.id = table2.tbl1_id LIMIT 1) t;
This will give you the name of every column returned for a single row. Without the LIMIT you would get the columns repeated for every row returned. If you wanted to see the values returned as well you can get more complex:
WITH t as
(SELECT * FROM table1
LEFT JOIN table2 ON table1.id = table2.tbl1_id LIMIT 1)
SELECT json_data.key, json_data.value
FROM t, json_each_text(row_to_json(t)) AS json_data;
Both these queries will return all the columns even if they are named the same. If all you want is a list of unique column names, you can utilize hstore:
CREATE EXTENSION hstore; --Create the extension if you need it.
SELECT akeys(hstore(t)) as array_of_columns
FROM
(SELECT * FROM table1
LEFT JOIN table2 ON table1.id = table2.tbl1id LIMIT 1) t;
Maybe there is a less hacky way, but I think this should work:
create table query_column_sample from (your query where 1=2);
SELECT column_name
FROM information_schema.columns
WHERE table_name = 'query_column_sample'
Querying tables returns data. Querying the information schema returns metadata. Column names are metadata.
SELECT 'table1', column_name
FROM information_schema.columns
WHERE table_catalog = 'database_name'
AND table_schema = 'schema_name'
AND table_name = 'table1'
UNION ALL
SELECT 'table2', column_name
FROM information_schema.columns
WHERE table_catalog = 'database_name'
AND table_schema = 'schema_name'
AND table_name = 'table2';
"schema_name" is probably public. But be warned that you can have multiple tables with the same name, as long as they are in different schemas. (You could have "public.table1" and "private.table1".) You can also have multiple tables with the same name in different databases. You need to specify all three values--database name, schema name, table name--to be sure of getting the right data.
If I had to do this in production I'd probably output more data. I'd also probably include the column "ordinal_position", and sort on it. Sorting by "ordinal_position" will order column names as they appear in the current table definition.
SELECT table_catalog
, table_schema
, table_name
, column_name
, ordinal_position
FROM information_schema.columns
WHERE table_catalog = 'sandbox'
AND table_schema = 'public'
AND table_name IN ('table1', 'table2')
ORDER BY table_catalog
, table_schema
, table_name
, ordinal_position;
The only reasonable approach I can come up with is to do something like this. Schema location plays into this, but I'm just posting the basic idea. SQL doesn't have reflection at run time unless you go and hit meta data tables, which is what you seem to be trying to achieve here.
SELECT table1.*
INTO x
FROM table1
LEFT JOIN table2
ON table1.id = table2.tbl1_id LIMIT 0;
select *
from information_schema.columns
where table_Name = 'x';
Also interesting enough while traveling the Internets over lunch I ran into this. Works with PostgreSQL 8.2.0 or higher.
https://github.com/theory/colnames/tree/master/test/sql

SQL query for a database scheme

In SQL Server how do you query a database to bring back all the tables that have a field of a specific name?
The following query will bring back a unique list of tables where Column_Name is equal to the column you are looking for:
SELECT Table_Name
FROM INFORMATION_SCHEMA.COLUMNS
WHERE Column_Name = 'Desired_Column_Name'
GROUP BY Table_Name
SELECT Table_Name
FROM Information_Schema.Columns
WHERE Column_Name = 'YourFieldName'
I'm old-school:
SELECT DISTINCT object_name(id)
FROM syscolumns
WHERE name = 'FIELDNAME'