how to get all the tables and structure in a database in a printed format? - sql-server-2000

how to get all the tables and structure in a database in a table format using an sql query or stored procedure?
Structure is like below:
Sl No FieldName DataType Size Description
1 UserName varchar 50

This should do the trick. There is a bit more information in here but I think you may find it useful.
Select t.Table_Schema,
t.Table_Name,
c.Column_Name,
IsNull(c.Column_Default, '') as 'Column_Default',
c.Is_Nullable,
c.Data_Type,
IsNull(c.Character_Maximum_Length, IsNull(Numeric_Precision,'') + IsNull(Numeric_Scale, IsNull(DateTime_Precision,''))) as 'Size'
From Information_Schema.Tables t
Join Information_Schema.Columns c on t.Table_Catalog = c.Table_Catalog
And t.Table_Schema = c.Table_Schema
And t.Table_Name = c.Table_Name
Where t.Table_Type = 'BASE TABLE'
Order by t.Table_Schema, t.Table_Name, c.Ordinal_Position

Related

Retrieve tables based on its contents in SQL server

I'd like to retrieve all tables and the associated column values where two of their specific columns (the column names will be passed into) that don't have the exact same content in them.
Here's a more definite break-down of the problem. Suppose, the columns that I need to look into is 'Column_1' and 'Column_2'
First identify from in INFORMATION_SCHEMA which of the tables have both of these columns present in them(possible one sub-query),
And then identify which of these tables don't have exact same content on these 2 columns meaning Column_1 != Column_2.
The following section would retrieve all the tables that has both 'Column_1' and 'Column_2'.
SELECT
TABLE_NAME
FROM
INFORMATION_SCHEMA.TABLES T
WHERE
T.TABLE_CATALOG = 'myDB' AND
T.TABLE_TYPE = 'BASE TABLE'
AND EXISTS (
SELECT T.TABLE_NAME
FROM INFORMATION_SCHEMA.COLUMNS C
WHERE
C.TABLE_CATALOG = T.TABLE_CATALOG AND
C.TABLE_SCHEMA = T.TABLE_SCHEMA AND
C.TABLE_NAME = T.TABLE_NAME AND
C.COLUMN_NAME = 'Column_1')
AND EXISTS
(
SELECT T.TABLE_NAME
FROM INFORMATION_SCHEMA.COLUMNS C
WHERE
C.TABLE_CATALOG = T.TABLE_CATALOG AND
C.TABLE_SCHEMA = T.TABLE_SCHEMA AND
C.TABLE_NAME = T.TABLE_NAME AND
C.COLUMN_NAME = 'Column_2')
As the next step, I tried to use this as a sub-query and have the following at the end but that doesn't work and sql-server returns 'Cannot call methods on sysname'. What would the next step on this? This problem assumes all columns has the exact same Data-type.
WHERE SUBQUERY.TABLE_NAME.Column_1 != SUBQUERY.TABLE_NAME.Column_2
This is what's expected :
Table_Name
Column_Name1
Column_Value_1
Column_Name2
Column_Value_2
Table_A
Column_1
abcd
Column_2
abcde
Table_A
Column_1
qwerty
Column_2
qwert
Table_A
Column_1
abcde
Column_2
eabcde
Table_B
Column_1
zxcv
Column_2
zxcde
Table_C
Column_1
asdfgh
Column_2
asdfghy
Table_C
Column_1
aaaa
Column_2
bbbb
If in fact you want to actually compare values (not length) between two columns in tables that contain those two columns, you will need to generate dynamic SQL and then execute it. This could be done semi-automatically with the following:
DECLARE #SqlTemplate VARCHAR(MAX) =
'UNION ALL'
+ ' SELECT Table_Name = <TNAME>'
+ ', Column_Name1 = <C1NAME>, Column_Value_1 = <C1>'
+ ', Column_Name2 = <C2NAME>, Column_Value_2 = <C2>'
+ ' FROM <T>'
+ ' WHERE ISNULL(<C1>, '(null)') <> ISNULL(<C2>, '(null)')'
SELECT T.TABLE_NAME
, REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(
#SqlTemplate
, '<TNAME>', QUOTENAME(T.TABLE_SCHEMA + '.' + T.TABLE_NAME, ''''))
, '<C1NAME>', QUOTENAME(C1.COLUMN_NAME, ''''))
, '<C2NAME>', QUOTENAME(C2.COLUMN_NAME, ''''))
, '<T>', QUOTENAME(T.TABLE_SCHEMA) + '.' + QUOTENAME(T.TABLE_NAME))
, '<C1>', QUOTENAME(C1.COLUMN_NAME))
, '<C2>', QUOTENAME(C2.COLUMN_NAME))
FROM INFORMATION_SCHEMA.TABLES T
JOIN INFORMATION_SCHEMA.COLUMNS C1
ON C1.TABLE_CATALOG = T.TABLE_CATALOG
AND C1.TABLE_SCHEMA = T.TABLE_SCHEMA
AND C1.TABLE_NAME = T.TABLE_NAME
AND C1.COLUMN_NAME = 'Column_1'
JOIN INFORMATION_SCHEMA.COLUMNS C2
ON C2.TABLE_CATALOG = T.TABLE_CATALOG
AND C2.TABLE_SCHEMA = T.TABLE_SCHEMA
AND C2.TABLE_NAME = T.TABLE_NAME
AND C2.COLUMN_NAME = 'Column_2'
WHERE T.TABLE_CATALOG = 'myDB'
AND T.TABLE_TYPE = 'BASE TABLE'
This would generate sql for each qualifying table of the form:
UNION ALL SELECT Table_Name = 'dbo.Z', Column_Name1 = 'X', Column_Value_1 = [X], Column_Name2 = 'Y', Column_Value_2 = [Y] FROM [dbo].[Z] WHERE ISNULL([X], '(null)') <> ISNULL([Y], '(null)')
After running the above, you would then cut & paste the generated SQL into another query window, remove the initial 'UNION ALL', and then execute the remaining SQL to get the final results.
There are ways of combining all the SQL into a single string and executing it automatically, but your problem sounds like a one-off process that doesn't warrant the extra complexity.
I believe you need to compare the CHARACTER_MAXIMUM_LENGTH or CHARACTER_OCTET_LENGTH metadata values in the INFORMATION_SCHEMA.COLUMNS table instead of using LEN(). This can be done using something like:
SELECT T.TABLE_NAME
, C1.COLUMN_NAME, C1.DATA_TYPE, C1.CHARACTER_MAXIMUM_LENGTH
, C2.COLUMN_NAME, C2.DATA_TYPE, C2.CHARACTER_MAXIMUM_LENGTH
FROM INFORMATION_SCHEMA.TABLES T
JOIN INFORMATION_SCHEMA.COLUMNS C1
ON C1.TABLE_CATALOG = T.TABLE_CATALOG
AND C1.TABLE_SCHEMA = T.TABLE_SCHEMA
AND C1.TABLE_NAME = T.TABLE_NAME
AND C1.COLUMN_NAME = 'Column_1'
JOIN INFORMATION_SCHEMA.COLUMNS C2
ON C2.TABLE_CATALOG = T.TABLE_CATALOG
AND C2.TABLE_SCHEMA = T.TABLE_SCHEMA
AND C2.TABLE_NAME = T.TABLE_NAME
AND C2.COLUMN_NAME = 'Column_2'
WHERE T.TABLE_CATALOG = 'myDB'
AND T.TABLE_TYPE = 'BASE TABLE'
AND C1.CHARACTER_MAXIMUM_LENGTH <> C2.CHARACTER_MAXIMUM_LENGTH
The inner joins both limit results to tables having both columns and retrieve the column metadata. The length compare at the end checks for a mismatch.
This assumes character types. You might also want to check DATA_TYPE consistency ("char" vs "varchar" vs "nvarchar") or some of the other precision and scale values for other non-character data types.
To query the data within the columns you need dynamic SQL. I would advise you not to use INFORMATION_SCHEMA (which is for compatibility only) and instead use sys.tables etc. You don't need to check sys.columns twice, you can use aggregation in the EXISTS subquery to check for multiple columns.
To compare the columns, you can do Column_1 <> Column_2, but that will not deal with nulls correctly. If the columns can be nullable then you should instead use the syntax shown in the code below: NOT EXISTS (SELECT Column_1 INTERSECT SELECT Column_2)
DECLARE #sql nvarchar(max);
SELECT
STRING_AGG(CAST('
SELECT
Table_Name = ' + QUOTENAME(t.name, '''') + ',
Column_1,
Column_2
FROM ' + QUOTENAME(s.name) + '.' + QUOTENAME(t.name) + '
WHERE NOT EXISTS (SELECT Column_1 INTERSECT SELECT Column_2)
' AS nvarchar(max)), '
UNION ALL
' )
FROM sys.tables t
JOIN sys.schemas s ON s.schema_id = t.schema_id
AND s.name = 'myDB'
WHERE EXISTS (SELECT 1
FROM sys.columns c
WHERE c.object_id = t.object_id
AND c.name IN ('Column_1', 'Column_2')
HAVING COUNT(*) = 2
AND COUNT(DISTINCT c.system_type_id) = 1 -- all same type
);
PRINT #sql; -- your friend
EXEC sp_executesql #sql;

AWS Athena error when running information_schema query

When running an information_schema query in Athena I am getting the following error:
Your query has the following error(s):
GENERIC_INTERNAL_ERROR: java.lang.RuntimeException: java.lang.InterruptedException: sleep interrupted
This query ran against the "default" database, unless qualified by the query. Please post the error message on our forum or contact customer support with Query Id: 277863e6-3f46-49a0-894b-e712cd49f9c0.
The error changes default to whatever database I have selected.
Script is:
SELECT t.table_schema, t.table_name, c.column_name, c.is_nullable, c.data_type
FROM information_schema.schemata s
INNER JOIN information_schema.tables t on s.schema_name = t.table_schema
INNER JOIN information_schema.columns c on c.table_name = t.table_name AND c.table_schema = t.table_schema
WHERE c.table_catalog = 'awsdatacatalog'
Can you try this?
SELECT t.table_schema, t.table_name, c.column_name, c.is_nullable,
c.data_type
FROM "information_schema"."schemata" s
INNER JOIN "information_schema"."tables" t on s.schema_name = t.table_schema
INNER JOIN "information_schema"."columns" c on c.table_name = t.table_name AND c.table_schema = t.table_schema
WHERE c.table_catalog = 'awsdatacatalog'

A script to find cells with certain values in Redshift

I have this query:
select t.table_schema,
t.table_name,
c.column_name
from information_schema.tables t
inner join information_schema.columns c
on c.table_name = t.table_name
and c.table_schema = t.table_schema
where c.column_name like '%column_name%'
and t.table_schema not in ('information_schema', 'pg_catalog')
and t.table_type = 'BASE TABLE'
order by t.table_schema;
Is there somewhere I can actually search for a specific value and see under which column & table & schema it falls under?
For example,
I would like to search for a value 'WINNER' and find out which columns contain this value (and obviously the table and schema as well)
and the column might be STATUS with value WINNER and under table CUSTOMER and schema ALL_DATA
Can anyone help please?
There is no straight forward way to do this, there is no build-in functionality in any DBMS as far as I know. One way how to do this would be to create SQL which selects all text-like columns and generates another SQL. There is an example:
select 'select '''||t.table_schema||''' as table_schema, '''||
t.table_name||''' as table_name, '''||
c.column_name||''' as column_name,'||
' count(*) as occurrences'
' from '||t.table_schema||'.'||t.table_name||
' where '||c.column_name||' like ''WINNER'''
||' union all '
from information_schema.tables t
inner join information_schema.columns c
on c.table_name = t.table_name
and c.table_schema = t.table_schema
where c.column_name like '%column_name%'
and t.table_schema not in ('information_schema', 'pg_catalog')
and t.table_type = 'BASE TABLE'
and c.data_type = 'character varying'
order by t.table_schema;
According to limitations set in query it will generate as much rows as columns you want to search. Copy this result block in your client (delete 'union all' from last row)
and execute. Try to limit rows as much as possible for better performance. Due to columnar data store Redshift will execute this quite effectively, keep in mind that on row-oriented DBMS performance for such approach will be much worse.

How to find a particular column in all tables and modify the values of that column in PostgreSQL

I am new to PostgreSQL. Actually I want to change all the email addresses in all the tables to some fake email address. Like I want that abc#gmail.com should become abc#1234gmail.com, xyz#hotmail.com should become xyz#1234hotmail.com and so on.
I found the query that gives the tables that have email column in it. Here is the query
select t.table_schema, t.table_name
from information_schema.tables t
inner join information_schema.columns c on c.table_name = t.table_name and c.table_schema = t.table_schema
where c.column_like '%email%'
and t.table_schema not in ('information_schema', 'pg_catalog')
and t.table_type = 'BASE TABLE'
order by t.table_schema;
It is giving me some records. Now one way is go to each table and alter the values of the email column. But can I modify the above query to also get the value of each email and change it to some fake address. Like if email value is abc#gmail.com then just append 12345 or any value after the # sign of each email address. So each email value becomes abc#1234gmail.com, xyz#1234hotmail.com and etc
You can build a set of update queries for each column as below -
select concat('update ', t.table_schema, '.', t.table_name, ' set ', c.column_name, ' = replace(', c.column_name, ', ''#'', ''#1234'') ')
from information_schema.tables t
inner join information_schema.columns c on c.table_name = t.table_name and c.table_schema = t.table_schema
where c.column_name like '%email%'
and t.table_schema not in ('information_schema', 'pg_catalog')
and t.table_type = 'BASE TABLE' order by t.table_schema;
This query would build one update statement per column that uses replace function to replace '#' with '#1234'. I haven't fully tested it, but hope it gives you an approach to work with.

SQL statement to print table names and their column names

SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = 'BASE TABLE'
ORDER BY TABLE_NAME ASC
I am using this code to print the table names of a db. What I want to do is print the table name and the col names in each table. Can I do this by nesting a statement.
This code is being run on a SQL Server in a query window.
I tried this
SELECT COL_NAME
FROM
(SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = 'BASE TABLE'
ORDER BY TABLE_NAME ASC)
Any ideas?
This should do it:
SELECT C.TABLE_NAME, C.COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS C
WHERE EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.TABLES T
WHERE T.TABLE_TYPE='BASE TABLE' AND C.TABLE_NAME=T.TABLE_NAME)
ORDER BY C.TABLE_NAME, C.COLUMN_NAME
In Sqlserver 2005 INFORMATION_SCHEMA views was introduced first.
These views are mainly created to get the metadata like table name,
column name, datatype of columns etc. about tables, columns, views,
domains etc.
Each and every database contains these views. If you want to check what's going on behind the scene you can check the logic of these views by doing just sp_helptext. Like
sp_helptext INFORMATION_SCHEMA.COLUMNS
By using above views you can get your desired result. Please check below query.
SELECT T.TABLE_NAME,C.COLUMN_NAME,C.DATA_TYPE
FROM INFORMATION_SCHEMA.COLUMNS C
INNER JOIN INFORMATION_SCHEMA.TABLES T ON C.TABLE_NAME = T.TABLE_NAME
AND C.TABLE_SCHEMA = T.TABLE_SCHEMA
WHERE T.TABLE_TYPE = 'BASE TABLE'
With Mssql 2008 version try the following query. This itemise column name and the tables they belong to.
SELECT c.name AS 'ColumnName', t.name AS 'TableName'
FROM sys.columns c
JOIN sys.tables t ON c.object_id = t.object_id
WHERE c.name = c.name
ORDER BY TableName, ColumnName;