Getting Objects information - sql

I am trying to get the table and column information. So I wrote two queries like this:
SELECT * FROM Chag.sys.columns c
WHERE OBJECT_NAME(c.object_id)='Aduser'
SELECT * FROM Chag.sys.tables so
WHERE so.name = 'Aduser' AND SCHEMA_NAME(so.schema_id) = 'Tref'
These two work fine when I execute them in Chag Database but when I execute this in different databse they return nothig.
I want to execute them in different database so how do i do that?

The OBJECT_NAME() function accepts an additional parameter of database ID. As for SCHEMA_NAME(), you should probably replace it with OBJECT_SCHEMA_NAME(), which is equivalent to SCHEMA_NAME(), only it uses the object ID instead of schema ID and accepts the database ID too as the second (optional) parameter.
You can use DB_ID() to get the ID of the specified database.
Here are modified versions of your statements:
SELECT *
FROM Chag.sys.columns c
WHERE OBJECT_NAME(c.object_id, DB_ID('Chag'))='Aduser'
SELECT *
FROM Chag.sys.tables so
WHERE so.name = 'Aduser'
AND OBJECT_SCHEMA_NAME(so.object_id, DB_ID('Chag')) = 'Tref'

If the reason is in functions OBJECT_NAME, SCHEMA_NAME like Shark pointed out, then getting data from corresponding views instead of calling those functions may help:
select c.* from chag.sys.columns c
join chag.sys.objects o on
c.object_id = o.object_id
where o.name = 'Aduser'
select t.* from chag.sys.tables t
join chag.sys.schemas s on
t.schema_id = s.schema_id
where t.name = 'Aduser' and s.name = 'Tref'

Because you are using a Database.Schema.Object reference. Try running this against other databases:
SELECT * FROM sys.columns c
WHERE OBJECT_NAME(c.object_id)='Aduser'
SELECT * FROM sys.tables so
WHERE so.name = 'Aduser' AND SCHEMA_NAME(so.schema_id) = 'Tref'
Notice, though, that if there is no 'Aduser' or 'Tref' objects then you will not get results.

Related

T-SQL: Show stored procedures related to tables, cyclically

I'm using the following t-sql code:
USE [my_database]
SELECT DISTINCT so.name
FROM syscomments sc
INNER JOIN sysobjects so ON sc.id=so.id
WHERE sc.TEXT LIKE '%table_name%'
in order to show all the Stored Procedures that use the table table_name.
I want do this work for all tables in my database.
How can I perform this task and organize the output?
This uses information schema for both tables, and stored procedures. You can change or get rid of ROUTINE_TYPE condition to add functions, and you can change table type to return views.
This answer produces its results by checking what tables a stored procedure depends on. I think this will be a much more accurate result then checking if a name is in the query text. If the procedure refers to a table in a comment section, then this result will not be returned in the first query, but will be in the second and other answers given.
SELECT t.TABLE_NAME, s.ROUTINE_NAME
FROM INFORMATION_SCHEMA.TABLES t
INNER JOIN INFORMATION_SCHEMA.ROUTINES s ON
s.ROUTINE_NAME IN (SELECT referencing_entity_name
FROM sys.dm_sql_referencing_entities(TABLE_SCHEMA + '.' + TABLE_NAME, 'OBJECT'))
AND s.ROUTINE_TYPE = 'PROCEDURE'
WHERE t.TABLE_TYPE = 'BASE TABLE'
edit: Here's how to get the dependencies without the function. (I like this method the best)
SELECT DISTINCT t.name [TableName], p.name [ProcedureName]
FROM sys.objects t
LEFT JOIN sys.sql_dependencies d ON
d.referenced_major_id = t.object_id
LEFT JOIN sys.objects p ON
p.object_id = d.object_id
AND p.type = 'p'
WHERE t.type = 'u'
If your specific use is to just find any string that matches a table name, below will work:
SELECT t.TABLE_NAME, s.ROUTINE_NAME
FROM INFORMATION_SCHEMA.TABLES t
INNER JOIN INFORMATION_SCHEMA.ROUTINES s
ON CHARINDEX(t.TABLE_NAME, s.ROUTINE_DEFINITION) > 0
AND s.ROUTINE_TYPE = 'PROCEDURE'
WHERE t.TABLE_TYPE = 'BASE TABLE'
You could do a JOIN on LIKE:
select * from INFORMATION_SCHEMA.TABLES t
join
(
SELECT DISTINCT so.name
FROM syscomments sc
INNER JOIN sysobjects so ON sc.id=so.id
) x on x.name like '%' + t.TABLE_NAME + '%'
Note that your query doesn't restrict to procs - you'll also get views, defaults, and other objects too. If you just want procs, you can add where so.xtype = 'P' to your inner query.
Another version that uses sys tables only:
select t.name as TableName, p.name as SPName
from sys.objects t
join sys.syscomments c
on c.text like '%' + t.name + '%'
join sys.objects p
on p.object_id = c.id
where t.type = 'U' -- user table
and p.type = 'P' -- procedure
You can also use the built in function that's been around at least since SQL 2005 and works for tables, views, and stored procedures. I get the same number of results as Daniel's answer above when checking dependencies on a table in a fairly enterprisy database.
sp_depends [TableName]
sp_depends [TableName.Column]
sp_depends [StoredProcedureName]
http://msdn.microsoft.com/en-us/library/ms189487(v=sql.90).aspx

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

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

A query to determine if a column is computed [duplicate]

Would any of you know how to get the list of computed columns in a SQL Server database table?
I found sys.sp_help tablename does return this information, but only in the second result-set.
I am trying to find out if there is a better way of doing this. Something which only returns a single result set.
Check the sys.columns system catalog view:
SELECT *
FROM sys.columns
WHERE is_computed = 1
This gives you all computed columns in this database.
If you want those for just a single table, use this query:
SELECT *
FROM sys.columns
WHERE is_computed = 1
AND object_id = OBJECT_ID('YourTableName')
This works on SQL Server 2005 and up.
UPDATE: There's even a sys.computed_columns system catalog view which also contains the definition (expression) of the computed column - just in case that might be needed some time.
SELECT *
FROM sys.computed_columns
WHERE object_id = OBJECT_ID('YourTableName')
If you want to use the INFORMATION_SCHEMA views, then try
SELECT
COLUMNPROPERTY(OBJECT_ID(TABLE_SCHEMA+'.'+TABLE_NAME),COLUMN_NAME,'IsComputed')
AS IS_COMPUTED,
*
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME='<Insert Your Table Name Here>'
For SQL Server 2000 the syntax is:
SELECT * FROM sys.columns
WHERE is_computed = 1
And the slightly more useful:
SELECT
sysobjects.name AS TableName,
syscolumns.name AS ColumnName
FROM syscolumns
INNER JOIN sysobjects
ON syscolumns.id = sysobjects.id
AND sysobjects.xtype = 'U' --User Tables
WHERE syscolumns.iscomputed = 1
sample output:
TableName ColumnName
===================== ==========
BrinksShipmentDetails Total
AdjustmentDetails Total
SoftCountDropDetails Total
CloserDetails Total
OpenerDetails Total
TransferDetails Total
(6 row(s) affected)
If you have many tables with computed columns and want to see the table names as well:
SELECT sys.objects.name, sys.computed_columns.name
from sys.computed_columns
inner join sys.objects on sys.objects.object_id = sys.computed_columns.object_id
order by sys.objects.name

Sql Query to list all views in an SQL Server 2005 database

I need an sql query to enumerate all views (I only need the view names) of a specific database in SQL Server 2005.
To finish the set off (with what has already been suggested):
SELECT * FROM sys.views
This gives extra properties on each view, not available from sys.objects (which contains properties common to all types of object) or INFORMATION_SCHEMA.VIEWS. Though INFORMATION_SCHEMA approach does provide the view definition out-of-the-box.
SELECT SCHEMA_NAME(schema_id) AS schema_name
,name AS view_name
,OBJECTPROPERTYEX(OBJECT_ID,'IsIndexed') AS IsIndexed
,OBJECTPROPERTYEX(OBJECT_ID,'IsIndexable') AS IsIndexable
FROM sys.views
SELECT *
FROM sys.objects
WHERE type = 'V'
Run this adding DatabaseName in where condition.
SELECT TABLE_NAME, ROW_NUMBER() OVER(ORDER BY TABLE_NAME) AS 'RowNumber'
FROM INFORMATION_SCHEMA.VIEWS
WHERE TABLE_CATALOG = 'DatabaseName'
or remove where condition adding use.
use DataBaseName
SELECT TABLE_NAME, ROW_NUMBER() OVER(ORDER BY TABLE_NAME) AS 'RowNumber'
FROM INFORMATION_SCHEMA.VIEWS
select v.name
from INFORMATION_SCHEMA.VIEWS iv
join sys.views v on v.name = iv.Table_Name
where iv.Table_Catalog = 'Your database name'
Some time you need to access with schema name,as an example you are using AdventureWorks Database you need to access with schemas.
SELECT s.name +'.'+v.name FROM sys.views v inner join sys.schemas s on s.schema_id = v.schema_id
Necromancing.
Since you said ALL views, technically, all answers to date are WRONG.
Here is how to get ALL views:
SELECT
sch.name AS view_schema
,sysv.name AS view_name
,ISNULL(sysm.definition, syssm.definition) AS view_definition
,create_date
,modify_date
FROM sys.all_views AS sysv
INNER JOIN sys.schemas AS sch
ON sch.schema_id = sysv.schema_id
LEFT JOIN sys.sql_modules AS sysm
ON sysm.object_id = sysv.object_id
LEFT JOIN sys.system_sql_modules AS syssm
ON syssm.object_id = sysv.object_id
-- INNER JOIN sys.objects AS syso ON syso.object_id = sysv.object_id
WHERE (1=1)
AND (sysv.type = 'V') -- seems unnecessary, but who knows
-- AND sch.name = 'INFORMATION_SCHEMA'
/*
AND sysv.is_ms_shipped = 0
AND NOT EXISTS
(
SELECT * FROM sys.extended_properties AS syscrap
WHERE syscrap.major_id = sysv.object_id
AND syscrap.minor_id = 0
AND syscrap.class = 1
AND syscrap.name = N'microsoft_database_tools_support'
)
*/
ORDER BY
view_schema
,view_name
This is old, but I thought I'd put this out anyway since I couldn't find a query that would give me ALL the SQL code from EVERY view I had out there. So here it is:
SELECT SM.definition
FROM sys.sql_modules SM
INNER JOIN sys.Objects SO ON SM.Object_id = SO.Object_id
WHERE SO.type = 'v'