Get object schema name from SQL Server query - sql

I have a table in SQL Server named DFDataBindingTableDefinition; it stores the database table names. Almost all the tables are under the dbo schema, but some of them are under the cus schema.
And table names are also the same under the different schema names.
Following is an example of how table names are stored in the table.
IncidentNote
cus.IncidentNote
I would like to extract the table information along with the underlying schema, so I am using the following query,
SELECT
OBJECT_SCHEMA_NAME(OBJECT_ID(DFDataBinding.TableName), DB_ID()) AS "Schema",
DFDataBinding.TableName AS "Name"
FROM sysobjects Objects
INNER JOIN sys.tables Tables on Tables.object_id = Objects.id
LEFT JOIN sys.extended_properties TableProperties on TableProperties.major_id = Objects.id
and TableProperties.name = 'MS_Description'
and TableProperties.minor_id = 0
INNER JOIN dbo.DFDataBindingTableDefinition DFDataBinding ON DFDataBinding.DBTableName = Objects.name
But it gives me result as
Schema Name
dbo IncidentNote
dbo IncidentNote
I would like it to return cus as the schema for one of the results. What is wrong with my query?

Tables cus.IndicentNote and dbo.IncidentNote are diferent objects and have diferent objectids.
If you don't pass the schema part to OBJECT_ID() it will asume the default schema which is dbo.
In your query, every row with the value IncidentNote in column DFDataBinding.TableName will execute like this: OBJECT_ID('IncidentNote') which translates to OBJECT_ID('dbo.IncidentNote'). That will give the same objectid
You can get the schema name by joining the sys.schemas with sys.tables.
SELECT
schemas.name AS "Schema",
DFDataBinding.TableName AS "Name"
FROM sysobjects Objects
INNER JOIN sys.tables Tables on Tables.object_id = Objects.id
INNER JOIN sys.schemas Schemas ON Schemas.schema_id = Tables.schema_id
LEFT JOIN sys.extended_properties TableProperties on TableProperties.major_id = Objects.id
and TableProperties.name = 'MS_Description'
and TableProperties.minor_id = 0
INNER JOIN dbo.DFDataBindingTableDefinition DFDataBinding ON DFDataBinding.DBTableName = Objects.name
Alternatively you can have the same effect with this syntax.
SELECT t.TABLE_SCHEMA AS [Schema],
t.TABLE_NAME AS [Name]
FROM INFORMATION_SCHEMA.TABLES AS t
WHERE EXISTS
(
SELECT 1
FROM DFDataBinding.DBTableName AS DFDataBinding
WHERE DFDataBinding.DBTableName = t.TABLE_NAME
);

Related

Selecting a Custom Column Type across all tables in a SQL Server 2005/2008

Currently, I have a query that uses the sys tables to return all the tables and column names where the column is a specific custom type, the query looks like this:
select
schemas.name, obj.name, col.name
from
sys.objects obj
inner join
sys.columns col on col.object_id = obj.object_id
inner join
sys.types types on types.user_type_id = col.user_type_id
inner join
sys.schemas schemas on obj.schema_id = schemas.schema_id
where
types.name = 'myCustomType'
However, the security of the SQL Server database is being changed and we can no longer query the sys tables. How else can I query for this information?

How to determine if sql table is Temporal?

With SQL Server 2016 supporting Temporal Tables I wonder if there is a way to determine if a table is currently temporal? Something like
select * from sys.objects where object_id('dbo.MyTable', 'u') = parent_object_id and type_desc = "SYSTEM_VERSIONED"
SELECT temporal_type
FROM sys.tables
WHERE object_id = OBJECT_ID('dbo.MyTable', 'u')
0 = NON_TEMPORAL_TABLE
1 = HISTORY_TABLE
2 = SYSTEM_VERSIONED_TEMPORAL_TABLE
Documentation
Another way of listing temporal tables with their history tables together is given in this SQL tutorial as List Temporal and History Tables in a SQL Server Database
select
t.object_id,
t.name,
t.temporal_type,
t.temporal_type_desc,
h.object_id,
h.name,
h.temporal_type,
h.temporal_type_desc
from sys.tables t
inner join sys.tables h on t.history_table_id = h.object_id
Here is a simple answer to the original basic question:
SELECT *
FROM sys.tables
WHERE name = 'MyTable'
AND schema_id = SCHEMA_ID('dbo')
AND temporal_type_desc = 'SYSTEM_VERSIONED_TEMPORAL_TABLE'
And here is a similar query looking for the actual system managed history table:
SELECT h.* FROM sys.tables p
INNER JOIN sys.tables h
ON p.history_table_id = h.object_id
WHERE p.name = 'MyTable'
AND p.schema_id = SCHEMA_ID('dbo')
AND p.temporal_type_desc = 'SYSTEM_VERSIONED_TEMPORAL_TABLE';
This query will give you the system versioned tables, the associated history tables, the retention policy, and whether the retention policy is enabled at the database level.
From Microsoft Docs
SELECT DB.is_temporal_history_retention_enabled,
SCHEMA_NAME(T1.schema_id) AS TemporalTableSchema,
T1.name as TemporalTableName, SCHEMA_NAME(T2.schema_id) AS HistoryTableSchema,
T2.name as HistoryTableName,T1.history_retention_period,
T1.history_retention_period_unit_desc
FROM sys.tables T1
OUTER APPLY (select is_temporal_history_retention_enabled from sys.databases
where name = DB_NAME()) AS DB
LEFT JOIN sys.tables T2
ON T1.history_table_id = T2.object_id WHERE T1.temporal_type = 2

SQL Query to get the table names which use a particular column as a foreign key

What sql query would you write to get the table names which have a particular foreign key.
Eg. Person_Table(person_id,name,address,...)
Purchases_Table(purchaseid, purchased_by_id(fkey)....)
AccountDetails_Table(AccountId,PersonID,....)
Roles_Table(PersonId,RoleID)
Now i want to find the table names where Person id is used as a foreign key.
The above schema would return me
Purchases_Table,AccountDetails_Table, Roles_Table
Database: SQL Server
select OBJECT_NAME(fkc.parent_object_id) as TableName
from sys.foreign_key_columns fkc
inner join sys.columns c
on fkc.referenced_object_id = c.object_id
and fkc.referenced_column_id = c.column_id
where fkc.referenced_object_id = OBJECT_ID('dbo.Person_Table')
and c.name = 'person_id'
For postgresql you can do something like this:
SELECT pt.tgargs, pt.tgnargs, pt.tgdeferrable, pt.tginitdeferred,
pg_proc.proname, pg_proc_1.proname FROM pg_class pc,
pg_proc pg_proc, pg_proc pg_proc_1, pg_trigger pg_trigger,
pg_trigger pg_trigger_1, pg_proc pp, pg_trigger pt
WHERE pt.tgrelid = pc.oid AND pp.oid = pt.tgfoid
AND pg_trigger.tgconstrrelid = pc.oid
AND pg_proc.oid = pg_trigger.tgfoid
AND pg_trigger_1.tgfoid = pg_proc_1.oid
AND pg_trigger_1.tgconstrrelid = pc.oid
AND ((pc.relname= '<< DB_NAME >>')
AND (pp.proname LIKE '%%ins')
AND (pg_proc.proname LIKE '%%upd')
AND (pg_proc_1.proname LIKE '%%del')
AND (pg_trigger.tgrelid=pt.tgconstrrelid)
AND (pg_trigger_1.tgrelid = pt.tgconstrrelid));
See this post (from 2000!) on the Postgresql mailing list.

How to get column metadata from a table synonym

How can I determine column metadata from a table synonym in a SQL Server 2005 database? I have a synonym called 'ProjectSyn' for a table called 'Project', but I can find no column metadata for the synonym.
My guess is to somewhere determine the 'base table' for the synonym, then query for column metadata for that table. Is this a correct approach, and if not, what would be?
This is my solution which works with synonyms of different databases:
SELECT TOP 0 * INTO #TEMP1 FROM YourTable
SELECT
[column_name] = c.name,
[data_type] = t.name,
[character_maximum_length] = c.max_length
FROM tempdb.sys.columns c
inner join tempdb.sys.types t on t.system_type_id = c.system_type_id
WHERE [object_id] = object_id('tempdb..#TEMP1');
DROP TABLE #TEMP1
Something like this? (edited)
select c.*
from
sys.columns c
inner join sys.synonyms s on c.object_id = object_id(s.base_object_name)
where
s.name = 'ProjectSyn'
Yes, I think getting the base object and then retrieve the columns, is your only option.
To get the base object name for a synonym, just query the view sys.synonyms

Query to get a Table Name based on its ID

I have a table (DB_TableInfo) in my DB like the following
TableId Type
859374678 R
579845658 B
478625849 R
741587469 E
.
.
.
this table represents all tables in my DB. What I wanna do is to write a query to select tables of Type 'R', get their Id and return the Name of the table belonging to that Id (the TableName column is not available in the specified table)
Can anybody help me out?
I wanna write a query similar to this one!
SELECT TableID = OBJECT_NAME FROM [DB_TableInfo] WHERE Type = 'R'
From the mention of sys.objects and use of square brackets I assume you are on SQL Server.
You can use the object_name function.
SELECT OBJECT_NAME(TableID) /*Might match objects that aren't tables as well though*/
FROM [DB_TableInfo]
WHERE Type = 'R'
Or join onto sys.tables
SELECT T.name
FROM [DB_TableInfo] D
join sys.tables T ON D.TableID = T.object_id
WHERE D.Type = 'R'
And to exclude empty tables
SELECT t.name
FROM DB_TableInfo d
JOIN sys.tables t ON d.TableId = t.object_id
JOIN sys.dm_db_partition_stats ps ON ps.object_id = t.object_id
WHERE d.Type = 'R' and ps.index_id <= 1
GROUP BY d.TableId, t.name
HAVING SUM(ps.row_count) > 0