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

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'

Related

How can I complete my current query about User Defined Table Types and getting Schema,IsIdentity,IsPrimaryKey and ...?

I have a query for getting information about User Defined Table Types.
I need to complete this query by adding the following columns :
IsIdentity
IsPrimaryKey
Schema
ColumnDefaultValue
The query:
SELECT o.name AS TableName ,
c.name AS ColumnName ,
c.isnullable AS [IsNullable] ,
t.name AS [DataType] ,
t.[length] AS [MaxLength] ,
t.prec AS [Precision]
FROM syscolumns c
INNER JOIN sysobjects o ON o.id = c.id
LEFT JOIN systypes t ON t.xtype = c.xtype
WHERE c.id IN ( SELECT type_table_object_id
FROM sys.table_types )
ORDER BY o.name ,
c.name;
And I have another question about the above query.
I have User Defined Table Types with dbo.MyType as name but in this query it shows me 'TT_MyType_37C5420D'.
How can I get the real name ?
You should use the new catalog views from the sys schema as of SQL Server 2005 and avoid the old syscolumns, sysobjects etc.
When rewriting your query to this:
SELECT
tt.name AS TableName,
c.name AS ColumnName,
c.is_nullable AS [IsNullable],
c.is_identity,
t.name AS [DataType],
t.max_length [MaxLength],
t.precision AS [Precision]
FROM
sys.table_types tt
INNER JOIN
sys.columns c ON c.object_id = tt.type_table_object_id
LEFT JOIN
sys.types t ON t.system_type_id = c.system_type_id
ORDER BY
tt.name, c.name;
you can easily tap into the more extensive information available in the sys catalog view - like the c.is_identity column on sys.columns. And also - the name from sys.table_types seems to return the more humanly readable name as you were looking for.
Check out the very extensive MSDN documentation on the sys catalog views do discover a lot more information you might be interested in

SQL grouping results

I'm trying to get the last time a table was updated by the users:
Declare #Collect Table (Name Varchar(100),last_user_update datetime)
Insert into #Collect
EXEC sp_MSForEachTable 'SELECT ''?'' as TableName,
last_user_update
FROM sys.dm_db_index_usage_stats
WHERE database_id = DB_ID(''SP3D_DB_RESEARCH_MDB'') AND OBJECT_ID = OBJECT_ID(''?'')'
SELECT * FROM #Collect ORDER BY last_user_update DESC
The problem is that in the results, some tables are appearing 3 times (please see the image bellow)
Since it appears that all tables duplicated have the same last updated time. Is there any way to group the results by the table name?
If the values are indeed the same, you can just add DISTINCT to the query, and have it return unique results
SELECT DISTINCT ''?'' as TableName, last_user_update ...
If you want to group after the fact, and only the last update interests you, you can do
SELECT TableName, max(last_user_update) as last_update
FROM #Collect
GROUP BY TableName
ORDER BY 2 DESC
Tables can have multiple indexes. The dynamic management view sys.dm_db_index_usage_stats will have separate entries for each index.
If you want to see the index name for each one, try this:
SELECT
o.name as TableName,
i.name as IndexName,
istats.last_user_update
from sys.dm_db_index_usage_stats istats
inner join sys.objects o
on o.object_id = istats.object_id
inner join sys.indexes i
on i.index_id = istats.index_id
and i.object_id = istats.object_id
order by
o.name,
i.name
Or, if you don't care about that and just want the last update time, you can group by the table name:
SELECT
o.name as TableName,
max(istats.last_user_update)
from sys.dm_db_index_usage_stats istats
inner join sys.objects o
on o.object_id = istats.object_id
group by
o.name
You can do an insert directly into your table with this query:
declare #Collect table (Name varchar(100),last_user_update datetime)
insert into #Collect
select
o.name as TableName,
istats.last_user_update
from sys.dm_db_index_usage_stats istats
inner join sys.objects o
on o.object_id = istats.object_id
inner join sys.indexes i
on i.index_id = istats.index_id
and i.object_id = istats.object_id
where database_id = db_id('SP3D_DB_RESEARCH_MDB')
Also, I'm not sure what your goal is, but please understand that this view only has entries for indexes that have activity on them. If an index is unused, it is not in this view. The first access creates a row in the view. The real interesting stuff on this view is the seek and scan information.
See this note from MSDN:
When an index is used, a row is added to sys.dm_db_index_usage_stats
if a row does not already exist for the index. When the row is added,
its counters are initially set to zero.
If your goal is to enumerate all the indexes and then show the last update date for all of them, you'll need to join to sys.indexes and then left join to sys.dm_db_index_usage_stats.

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 | :)

SQL Server meta data table and column descrption [duplicate]

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

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