SQL Server meta data table and column descrption [duplicate] - sql

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
SQL Server: Extract Table Meta-Data (description, fields and their data types)
I just like to ask if there is a way to programmatically retrieve table and column descriptions from SQL Server 2008? These are the descriptions that you can enter when using the UI.
And if so, is there a way to programmatically update them as well?
Thanks.

If you want to retrieve the "descriptions" you set using MSSMS's UI you need to query sys.extended_properties.
Start by doing select * from sys.extended_properties and read some records in the value column to know what I mean (you'll find previously set descriptions there). You will later need to do some joins with sysobjects (I guess) in order to know which description belongs to which table and you'll be ready to go. Search in google for more info if you're confused =)
Also, try this:
select * from sys.extended_properties
inner join sysobjects on sys.extended_properties.major_id = sysobjects.id
The 'value' column and the second 'name' column (which belongs to sysobjects) are what you're looking for.
Hope that helps.

To get the description data, you need to fiddle with sysobjects/syscolumns
SELECT u.name + '.' + t.name AS [table],
td.value AS [table_desc],
c.name AS [column],
cd.value AS [column_desc]
FROM sysobjects t
INNER JOIN sysusers u
ON u.uid = t.uid
LEFT OUTER JOIN sys.extended_properties td
ON td.major_id = t.id
AND td.minor_id = 0
AND td.name = 'MS_Description'
INNER JOIN syscolumns c
ON c.id = t.id
LEFT OUTER JOIN sys.extended_properties cd
ON cd.major_id = c.id
AND cd.minor_id = c.colid
AND cd.name = 'MS_Description'
WHERE t.type = 'u'
ORDER BY t.name, c.colorder
some info can be found out at
select * from INFORMATION_SCHEMA.TABLES
select * from INFORMATION_SCHEMA.COLUMNS

Related

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

How to fetch tables and their corresponding column names used in stored procedures using t-sql?

I just want to get the tables and their corresponding columns which are written as a part of stored procedure using t-sql? How can I get a list of the same? Can anyone help me? Thanks.
If you have table names with you, use following query to get the required details as:
SELECT COLUMN_NAME,DATA_TYPE,CHARACTER_MAXIMUM_LENGTH,IS_NULLABLE,COLUMN_DEFAULT,TABLE_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME IN ('TBL1','TBL2') ORDER BY TABLE_NAME
I tried following effort to get my query resolved.
SELECT distinct sp.name as StoredProc, tbl.name AS [Table], col.name AS [Column]
FROM sysobjects sp
INNER JOIN sysdepends sd ON sp.id = sd.id
INNER JOIN sysobjects tbl ON tbl.id = sd.depid
INNER JOIN syscolumns col ON col.colid = sd.depnumber AND col.id = sd.depid
WHERE sp.name IN ( SELECT name FROM sysobjects WHERE id IN(SELECT id from syscomments
WHERE text LIKE '%passParamToGetYourSPs_%'))
--group BY sp.name
--AND sp.name = 'Search_SP_Name'
ORDER BY sp.name, tbl.name, col.name
Thanks for all your efforts. Smile | :)

Any way to retrieve SQL Field Description property with a datarows query?

I have a ProductInventory table with over 100 fields. Many need to offer user guidance to understand. I’m looking for a way to add tooltips to the form without hardcoding the text.
I want to use MS SQL table field property DESCRIPTION as the source for user tooltips during web forms data entry.
Generally, my descriptions are for other db admins, but I was wondering if with a little more thoughtful and friendly descriptions, I could make duel use of this extended SQL field property.
Is is possible to retrieve this field property WITH a datatable/dataset query?
Example:
FieldName: ProductID
Value: [string]
FieldDescription: “This is a description for the end user of what the ProductID is field used for”
I know we can get the field schema for a specific field by…
SELECT #Result = count(1)
FROM ::fn_listextendedproperty (N'MS_Description', N'Schema', 'dbo',
N'Table', '[Your Table Name]',
N'Column', '[You Field Name]')
Is this possible without a “per field” query on each field?
Perhaps run two queries. One to pull records and one to pull schema.
(i.e. retrieve entire table schema and do a loop to find matching field name.)
Any thoughts?
You can get those descriptions back via query for the whole table.
This is almost entirely lifted from Phil Factor on SQL Server Central. My modifications are only the extra join condition p.name = 'MS_Description' and the where clause.
SELECT SCHEMA_NAME(tbl.schema_id) AS [Table_Schema],
tbl.name AS [Table_Name],
clmns.name AS [Column_Name],
p.name AS [Name],
CAST(p.value AS SQL_VARIANT) AS [Value]
FROM sys.tables AS tbl
INNER JOIN sys.all_columns AS clmns ON clmns.OBJECT_ID=tbl.OBJECT_ID
INNER JOIN sys.extended_properties AS p ON p.major_id=clmns.OBJECT_ID
AND p.minor_id=clmns.column_id
AND p.class= 1
AND p.name = 'MS_Description'
WHERE tbl.name = 'Your Table Name'
ORDER BY [Table_Schema] ASC,
[Table_Name] ASC,
[Column_ID] ASC,
[Name] ASC
try
select
s.name [Schema],
ao.[name] [Table],
ac.[name] [Column],
t.[name] [Type],
p.[value] [Description]
from sys.all_columns ac
inner join sys.types t on ac.system_type_id = t.system_type_id
inner join sys.all_objects ao on ao.object_id = ac.object_id
inner join sys.schemas s on s.schema_id = ao.schema_id
LEFT OUTER JOIN sys.extended_properties p ON p.major_id = ac.object_id AND p.minor_id = ac.column_id
where ao.type = 'u'
order by s.name, ao.name, ac.name
with ao.type = 'u' (all user tables)
if you want only one table use ao.name = 'table_name'

Getting the decriptions of the tables and columns via a sql statement

I have a database and a lot of tables inside it. I wrote some information into the each table and column's decription part. And now using query i want to see all table and columns descriptions.
Note: DATABASE -> ms sql server
Can you please help me ?
You can see that using INFORMATION_SCHEMA
To get columns for each table you can do:
SELECT * FROM INFORMATION_SCHEMA.COLUMNS
To get table information you can do:
SELECT * FROM INFORMATION_SCHEMA.TABLES
Check this query:
SELECT
t.name AS TableName
, td.value AS TableDescription
, c.name AS ColumnName
, cd.value AS ColumnDescription
FROM sys.tables t
INNER JOIN sys.columns c ON t.object_id = c.object_id
LEFT JOIN sys.extended_properties td
ON td.major_id = t.object_id
AND td.minor_id = 0
AND td.name = 'MS_Description'
LEFT JOIN sys.extended_properties cd
ON cd.major_id = t.object_id
AND cd.minor_id = c.column_id
AND cd.name = 'MS_Description'
select * from INFORMATION_SCHEMA.TABLES
select * from INFORMATION_SCHEMA.COLUMNS
select * from user_col_comments;
This will display all tables's column with comments for the logged in user.
select * from user_col_comments where table_name = '<table name>';
This will display specified tables's column with comments for the logged in user.
desc table_name query is used to describe the table

How to determine if a specific set of tables in a database are empty

I have database A which contains a table (CoreTables) that stores a list of active tables within database B that the organization's users are sending data to.
I would like to be able to have a set-based query that can output a list of only those tables within CoreTables that are populated with data.
Dynamically, I normally would do something like:
For each row in CoreTables
Get the table name
If table is empty
Do nothing
Else
Print table name
Is there a way to do this without a cursor or other dynamic methods? Thanks for any assistance...
Probably the most efficient option is:
SELECT c.name
FROM dbo.CoreTables AS c
WHERE EXISTS
(
SELECT 1
FROM sys.partitions
WHERE index_id IN (0,1)
AND rows > 0
AND [object_id] = OBJECT_ID(c.name)
);
Just note that the count in sys.sysindexes, sys.partitions and sys.dm_db_partition_stats are not guaranteed to be completely in sync due to in-flight transactions.
While you could just run this query in the context of the database, you could do this for a different database as follows (again assuming that CoreTables does not include schema in the name):
SELECT c.name
FROM DatabaseA.CoreTables AS c
WHERE EXISTS
(
SELECT 1
FROM DatabaseB.sys.partitions AS p
INNER JOIN DatabaseB.sys.tables AS t
ON p.[object_id] = t.object_id
WHERE t.name = c.name
AND p.rows > 0
);
If you need to do this for multiple databases that all contain the same schema (or at least overlapping schema that you're capturing in aggregate in a central CoreTables table), you might want to construct a view, such as:
CREATE VIEW dbo.CoreTableCounts
AS
SELECT db = 'DatabaseB', t.name, MAX(p.rows)
FROM DatabaseB.sys.partitions AS p
INNER JOIN DatabaseB.sys.tables AS t
ON p.[object_id] = t.[object_id]
INNER JOIN DatabaseA.dbo.CoreTables AS ct
ON t.name = ct.name
WHERE p.index_id IN (0,1)
GROUP BY t.name
UNION ALL
SELECT db = 'DatabaseC', t.name, rows = MAX(p.rows)
FROM DatabaseC.sys.partitions AS p
INNER JOIN DatabaseC.sys.tables AS t
ON p.[object_id] = t.[object_id]
INNER JOIN DatabaseA.dbo.CoreTables AS ct
ON t.name = ct.name
WHERE p.index_id IN (0,1)
GROUP BY t.name
-- ...
GO
Now your query isn't going to be quite as efficient, but doesn't need to hard-code database names as object prefixes, instead it can be:
SELECT name
FROM dbo.CoreTableCounts
WHERE db = 'DatabaseB'
AND rows > 0;
If that is painful to execute you could create a view for each database instead.
In SQL Server, you can do something like:
SELECT o.name, st.row_count
FROM sys.dm_db_partition_stats st join
sys.objects o
on st.object_id = o.object_id
WHERE index_id < 2 and st.row_count > 0
By the way, this specifically does not use OBJECT_ID() or OBJECT_NAME() because these are evaluated in the current database. The above code continues to work for another database, using 3-part naming. This version also takes into account multiple partitions:
SELECT o.name, sum(st.row_count)
FROM <dbname>.sys.dm_db_partition_stats st join
<dbname>.sys.objects o
on st.object_id = o.object_id
WHERE index_id < 2
group by o.name
having sum(st.row_count) > 0
something like this?
//
foreach (System.Data.DataTable dt in yourDataSet.Tables)
{
if (dt.Rows.Count != 0) { PrintYourTableName(dt.TableName); }
}
//
This is a way you can do it, that relies on system tables, so be AWARE it may not always work in future versions of SQL. With that strong caveat in mind.
select distinct OBJECT_NAME(id) as tabName,rowcnt
from sys.sysindexes si
join sys.objects so on si.id=si.id
where indid=1 and so.type='U'
You would add to the where clause the tables you are interested in and rowcnt <1