Difference between Information_schema vs sys tables in SQL Server - sql

What are the information_schema tables and sys tables in SQL Server? What are the differences between them?

Both INFORMATION_SCHEMA and sys objects are both metadata catalogs that are available in SQL Server.
The INFORMATION_SCHEMA set of views are the ANSI/ISO standard catalogs for metadata. Most RDBMSs support the majority of INFORMATION_SCHEMA views, and each view exposes essentially identical information regardless of the vendor. In SQL Server, most, if not all the INFORMATION_SCHEMA views are views that go back to the sys tables in one way or other. In SQL Server, you can see the underlying VIEW definitions by running queries like:
SELECT OBJECT_DEFINITION(OBJECT_ID('INFORMATION_SCHEMA.TABLES'))
Which returns:
CREATE VIEW INFORMATION_SCHEMA.TABLES
AS
SELECT
DB_NAME() AS TABLE_CATALOG,
s.name AS TABLE_SCHEMA,
o.name AS TABLE_NAME,
CASE o.type
WHEN 'U' THEN 'BASE TABLE'
WHEN 'V' THEN 'VIEW'
END AS TABLE_TYPE
FROM
sys.objects o LEFT JOIN sys.schemas s
ON s.schema_id = o.schema_id
WHERE
o.type IN ('U', 'V')
The sys tables and views are the original metadata catalog views and tables that were, AFAIK, created by Sybase (the vendor that Microsoft purchased SQL Server's original code base from). Most RDBMSs have an equivalent set of catalog tables, but the specific table names are all different between vendors. In SQL Server, these tables along with the later addition of the dynamic management views (DMVs) are what Microsoft created to capture a database's metadata for system and user use.
In SQL Server, since the the INFORMATION_SCHEMA views typically point back to the sys tables and due to the ISO definitions for those views, it is not uncommon for the INFORMATION_SCHEMA views do not contain all metadata or all objects that you're looking for. (Personally I think Aaron's bias in that article is a little overblown, but he's probably been bitten by the issue more than I have and he also probably works on more complexly configured databases than I do.)
That said, however:
SELECT OBJECT_DEFINITION(OBJECT_ID('sys.tables'))
Returns:
CREATE VIEW sys.tables AS
SELECT o.name, o.object_id, o.principal_id, o.schema_id, o.parent_object_id,
o.type, o.type_desc, o.create_date, o.modify_date,
o.is_ms_shipped, o.is_published, o.is_schema_published,
isnull(ds.indepid, 0) AS lob_data_space_id,
rfs.indepid AS filestream_data_space_id,
o.property AS max_column_id_used,
o.lock_on_bulk_load, o.uses_ansi_nulls, o.is_replicated, o.has_replication_filter,
o.is_merge_published, o.is_sync_tran_subscribed, o.has_unchecked_assembly_data,
lob.intprop AS text_in_row_limit,
o.large_value_types_out_of_row,
o.is_tracked_by_cdc,
o.lock_escalation_option AS lock_escalation,
ts.name AS lock_escalation_desc,
o.is_filetable,
o.is_memory_optimized,
o.durability_option as durability,
d.name as durability_desc
FROM sys.objects$ o
LEFT JOIN sys.sysidxstats lob ON lob.id = o.object_id AND lob.indid <= 1
LEFT JOIN sys.syssingleobjrefs ds ON ds.depid = o.object_id AND ds.class = 8 AND ds.depsubid <= 1 -- SRC_INDEXTOLOBDS
LEFT JOIN sys.syssingleobjrefs rfs ON rfs.depid = o.object_id AND rfs.class = 42 AND rfs.depsubid = 0 -- SRC_OBJTOFSDS
LEFT JOIN sys.syspalvalues ts ON ts.class = 'LEOP' AND ts.value = o.lock_escalation_option
LEFT JOIN sys.syspalvalues d ON d.class = 'DOPT' AND d.value = o.durability_option
WHERE o.type = 'U'
Which is clearly returning a lot more detailed information, and notice that INFORMATION_SCHEMA.TABLES returns both user tables and views, while sys.tables only returns user tables.
Personally, I find the INFORMATION_SCHEMA views much better organized and much easier to use for ad hoc queries to find tables by name or columns by name, but there are some corner cases where you have to go to the sys objects tables and there are some situations where missing objects in the INFORMATION_SCHEMA views can bite you. If I'm looking for a reliable and complete set of items then I use the sys tables (specifically sys.objects or sys.all_objects) but those require a lot more work to get readable results. The INFORMATION_SCHEMA views have done a lot of that work for you already.

INFORMATION_SCHEMA.TABLES view allows you to get information about all tables and views within a database. By default it will show you this information for every single table and view that is in the database.
Kindly visit this: https://www.mssqltips.com/sqlservertutorial/196/informationschematables/
Sys tables contain the all-important meta data, the data about your data. This data includes information about table names, column names, and data types, so that SQL Server can properly process queries and return result sets. System tables contain information about valid users and their permissions, so data can be secure, and information about your SQL Server configuration, so you can predict and control the system's behavior.

Related

How can I get the list of all tables used in all the stored procedures of a particular schema?

I'd like to find all the tables used in all the stored procedures of a particular schema. I've tried to use the following code for checking the tables used in one Stored Procedure, however, I received an empty table though there are many tables used in the stored procedure.
SELECT SD.DEPID
FROM SYSOBJECTS SO,
SYSDEPENDS SD
WHERE SO.NAME = '<name of stored procedure>
AND SD.ID = SO.ID
I'm new to SSMS and SQL. Hope you can help. Thank you!
I have created few tables, procedure and after that wrote(copy - paste) a query and all by following the article I have found on internet: https://www.c-sharpcorner.com/blogs/find-list-of-tables-used-in-stored-procedure-using-types-of-joins
Here is the query that will get you the list of tables:
SELECT
NAME as 'List Of Tables'
FROM SYSOBJECTS
WHERE ID IN ( SELECT SD.DEPID
FROM SYSOBJECTS SO
join SYSDEPENDS SD on SD.ID = SO.ID
)
And here is the demo :
DEMO
I would suggest not to use sysdepends table, as it is deprecated and will be removed in future versions. Sysdepends on MSDN
This SQL Server 2000 system table is included as a view for backward
compatibility. We recommend that you use the current SQL Server system
views instead. To find the equivalent system view or views, see
Mapping System Tables to System Views (Transact-SQL). This feature
will be removed in a future version of Microsoft SQL Server. Avoid
using this feature in new development work, and plan to modify
applications that currently use this feature.
You can use sql_expression_dependencies to get that.
More Information on SQL_Expression_Dependencies usage scenarios
The advantage of expression dependencies is that, it can also tell CROSS DATABASE dependencies
SELECT
referenced_server_name AS [Referenced Server],
referenced_database_name AS [Referenced DB],
referenced_schema_name AS [Referenced Schema],
referenced_entity_name AS [Referenced Entity],
referenced_class_desc AS [Referenced Entity Class]
FROM sys.sql_expression_dependencies as ep
INNER JOIN sys.procedures as p
on ep.referencing_id = p.object_id -- Referencing Stored Procedure Object Id
where p.schema_id = SCHEMA_ID('dbo') -- dbo schema

Get column differences between 2 databases (SQL Server)

I've got 2 databases almost identical to one another. However, it seems that for some tables in the new database, they are missing columns that are in the old database.
What would be the best way to see the differences between columns in tables between 2 databases? Specifically, I need to see what columns AREN'T in the new database that ARE in the old one.
I've tried looking this up but most things I found were either not what I needed or looking at "records".
You can query the columns from your db using the sys tables and compare the result sets. This script assumes your old db has all the columns you want.
;WITH old_db_columns AS (
SELECT c.object_id, c.column_id, c.name AS column_name, t.name AS table_name
FROM old_db.sys.tables t
INNER JOIN old_db.sys.columns c
ON t.object_id = c.object_id
)
, new_db_columns AS (
SELECT c.object_id, c.column_id, c.name AS column_name, t.name AS table_name
FROM new_db.sys.tables t
INNER JOIN new_db.sys.columns c
ON t.object_id = c.object_id
)
SELECT *
FROM old_db_columns o
WHERE NOT EXISTS (
SELECT 1
FROM new_db_columns n
WHERE n.table_name = o.table_name
AND n.column_name= o.column_name)
You may use SQL Compare and SQL Data Compare, tools by Red Gate, to compare and sync databases schema and data.
You can generate the create statement of the tables and you can compare them with using any diff tool.
Check out that video: VS Comparision
Visual Studio has built in functionality that you are able to do data compares, schema compares and it will generate the differences for you in a script if you need to recitfy the variances.

Translating query from Firebird to PostgreSQL

I have a Firebird query which I should rewrite into PostgreSQL code.
SELECT TRIM(RL.RDB$RELATION_NAME), TRIM(FR.RDB$FIELD_NAME), FS.RDB$FIELD_TYPE
FROM RDB$RELATIONS RL
LEFT OUTER JOIN RDB$RELATION_FIELDS FR ON FR.RDB$RELATION_NAME = RL.RDB$RELATION_NAME
LEFT OUTER JOIN RDB$FIELDS FS ON FS.RDB$FIELD_NAME = FR.RDB$FIELD_SOURCE
WHERE (RL.RDB$VIEW_BLR IS NULL)
ORDER BY RL.RDB$RELATION_NAME, FR.RDB$FIELD_NAME
I understand SQL, but have no idea, how to work with this system tables like RDB$RELATIONS etc. It would be really great if someone helped me with this, but even some links with this tables explanation will be OK.
This piece of query is in C++ code, and when I'm trying to do this :
pqxx::connection conn(serverAddress.str());
pqxx::work trans(conn);
pqxx::result res(trans.exec(/*there is this SQL query*/));//and there is a mistake
it writes that:
RDB$RELATIONS doesn't exist.
Postgres has another way of storing information about system content. This is called System Catalogs.
In Firebird your query basically returns a row for every column of a table in every schema with an additional Integer column that maps to a field datatype.
In Postgres using system tables in pg_catalog schema something similar can be achieved using this query:
SELECT
TRIM(c.relname) AS table_name, TRIM(a.attname) AS column_name, a.atttypid AS field_type
FROM pg_class c
LEFT JOIN pg_attribute a ON
c.oid = a.attrelid
AND a.attnum > 0 -- only ordinary columns, without system ones
WHERE c.relkind = 'r' -- only tables
ORDER BY 1,2
Above query does return system catalogs as well. If you'd like to exclude them you need to add another JOIN to pg_namespace and a where clause with pg_namespace.nspname <> 'pg_catalog', because this is the schema where system catalogs are stored.
If you'd also like to see datatype names instead of their representative numbers add a JOIN to pg_type.
Information schema consists of collection of views. In most cases you don't need the entire SQL query that stands behind the view, so using system tables will give you better performance. You can inspect views definition though, just to get you started on the tables and conditions used to form an output.
I think you are looking for the information_schema.
The tables are listed here: https://www.postgresql.org/docs/current/static/information-schema.html
So for example you can use:
select * from information_schema.tables;
select * from information_schema.columns;

Programmatically get all tables of a database owned by a user

I created the following query:
select
is_tables.table_name
from information_schema.tables is_tables
join pg_tables
on is_tables.table_name=pg_tables.tablename
where
is_tables.table_catalog='<mydatabase>'
and is_tables.table_schema<>'information_schema'
and is_tables.table_schema<>'pg_catalog'
and pg_tables.tableowner='<myuser>';
I assume there is no database vendor independent way of querying this. Is this the easiest/shortest SQL query to achieve what I want in PostgreSQL?
I think you're pretty close. Object owners don't seem to appear in the information_schema views, although I might have overlooked it.
select is_tables.table_schema,
is_tables.table_name
from information_schema.tables is_tables
inner join pg_tables
on is_tables.table_name = pg_tables.tablename
and is_tables.table_schema = pg_tables.schemaname
where is_tables.table_catalog = '<mydatabase>'
and is_tables.table_schema <> 'information_schema'
and is_tables.table_schema <> 'pg_catalog'
and pg_tables.tableowner = '<myuser>';
You need to join on both the table name and the schema name. Table names are unique within a schema; they're not unique within a database.

Given a column name how can I find which tables in database contain that column?

Given a column name how can I find
which tables in database contain that
column ?
or alternatively
How can I find that particular column
exists for all tables in Database ?
Note: Kindly explain answers with Examples as that I get most knowledge from the answer.
Edit: I am using MySQL Database.
SELECT * FROM information_schema.columns WHERE COLUMN_NAME = 'mycolumn'
Depends on the database you are using. Many database systems expose a set of tables of views that contain details of the schema. For example, you can get schema information from the SYSTABLE and SYSCOLUMN views in Sybase ASA.
in SQL Server:
select distinct t.name
from sys.Columns c
inner join sys.tables t on c.object_id = t.object_id
where c.name = 'YOUR_COLUMNNAME'