Check for usage of an XML Schema Collection? - sql-server

As part of a script, in which execution is halted and changes are rolled back if there are any errors, I use the following statements to drop an xml schema collection if it exists
IF EXISTS (SELECT * FROM sys.xml_schema_collections WHERE name = 'MyXMLSchemaCollection')
BEGIN
PRINT 'Drop MyXMLSchemaCollection';
DROP XML SCHEMA COLLECTION MyXMLSchemaCollection;
END
GO
This works nicely except for when the schema collection is in use, the result of which is an error like the following:
Specified collection 'MyXMLSchemaCollection' cannot be dropped because it is used by object 'MyObject'.
How would I go about only dropping the schema collection if it is not used by any objects in the database? The xml schema collection does not need to be dropped if it's being used.

Using the example XML Schema Collection from MSDN documentation ALTER XML SCHEMA COLLECTION (Transact-SQL) I found that you can determine if an XML Schema Collection is being referenced by a table using:
select distinct t.name from sys.tables t
left join sys.columns c ON c.object_id = t.object_id
left join sys.xml_schema_collections x ON x.xml_collection_id = c.xml_collection_id
where x.name = 'MyXMLSchemaCollection'
Also for stored procedures and I imagine other object types sys.sql_expression_dependencies table will be of use to you.
select
*
from sys.sql_expression_dependencies sed
left join sys.objects o ON o.object_id = sed.referencing_id
where referenced_entity_name = 'MyXMLSchemaCollection'
Have a look at these questions for more information on exploring object catalogs:
List of Stored Procedure from Table
Find all references to an object in an SQL Server database

Related

How to find all tables depends to stored procedure

I want to find all tables used in stored procedures but it only gives me the tables that are in the database that I'm just using. Is there a solution to find all tables used in stored procedures, which are in other databases (in the same server)?
I try this:
SELECT DISTINCT p.name AS proc_name, t.name AS table_name
FROM sys.sql_dependencies d
INNER JOIN sys.procedures p ON p.object_id = d.object_id
INNER JOIN sys.tables t ON t.object_id = d.referenced_major_id
WHERE p.name like '%sp_example%'
ORDER BY proc_name, table_name
The procedures I need to analyze contain tables from different databases, but the code above gives me only results from one database.
First of all, sys.sql_dependencies is deprecated. Instead, you should use sys.sql_expression_dependencies. In it, you will find 4-part names of referenced objects (this includes objects referenced via linked server, for example).
Second, any object_id in SQL Server only makes sense within its database. If you are looking for anything outside of your current DB, don't join tables by these identifiers - use object names instead.

Identify bad table or view references in stored procedures

I am looking for a way to identify stored procedures that refer to tables or views that are no longer available (i.e. that have been deleted), in order to help resolve these conflicts by editing the procedures. I would also like to be able to find and display the table or view names that do not exist. I am using SQL Server 2014.
You can use the following query to list missing dependencies:
select
object_name(referencing_id) as 'object making reference',
referenced_class_desc,
referenced_schema_name,
referenced_entity_name as 'object name referenced',
(select object_id from sys.objects where name = [referenced_entity_name]) as 'Object Found?'
from sys.sql_expression_dependencies e
left join sys.tables t
on e.referenced_entity_name = t.name
Source

auto pick schema change of underlying table for view

I know that the sql server doesnt pick the schema change of underlying table. for example, if we execute the following,
CREATE TABLE tbl (id INT)
CREATE VIEW viewa
AS
SELECT *
FROM tbl
ALTER TABLE tbl ADD NAME INT
and execute a select on view, only ID column is returned
SELECT *
FROM viewa
Is there any property I can set by which the sql engine autopicks the schema changes
use sp_refreshview for this,
exec sp_refreshview N'dbo.viewa'
There's no out of the box functionality for this. But you could roll your own. The system tables detail all the columns currently attached to each view and table.
-- Returns every column for the given table/view.
SELECT
c.*
FROM
sys.objects AS o
INNER JOIN sys.schemas AS s ON s.schema_id = o.schema_id
INNER JOIN sys.columns AS c ON c.object_id = o.object_id
WHERE
s.name = 'MySchema'
AND o.name = 'MyTable'
;
You would need to create a control table that maps your tables to views. You would also need to schedule the process.
You can create view with "SCHEMABINDING" option. That way base table definition cannot be modified in a way that could affect view definition.
CREATE VIEW viewa
AS
SELECT *
FROM tbl SCHEMABINDING

How can i join sys.columns of view to sys.columns of the table it is referencing in T-SQL?

I am trying to join records in sys.columns for a view, to the records in sys.columns for the table it is referencing, because i need the values of is_nullable, is_computed and default_object_id columns for the columns that are selected in the view.
The sys.columns records for the view have "incorrect" values, which you can observe by running the example queries below:
CREATE TABLE TestTable (
FieldA int NOT NULL,
FieldB int DEFAULT (1),
FieldC as CONVERT(INT, FieldA + FieldB),
FieldD int NOT NULL
)
GO
CREATE VIEW TestView WITH SCHEMABINDING AS
SELECT FieldA, FieldC as TestC, FieldB + FieldC as TestD
FROM dbo.TestTable WHERE FieldD = 1
GO
SELECT OBJECT_NAME(c.object_id) as ViewName, c.name as ColumnName,
c.is_nullable as Nullable, c.is_computed as Computed,
cast(CASE WHEN c.default_object_id > 0 THEN 1 ELSE 0 END as bit) as HasDefault
FROM sys.columns c
WHERE object_id = OBJECT_ID('TestTable')
GO
SELECT OBJECT_NAME(c.object_id) as ViewName, c.name as ColumnName,
c.is_nullable as Nullable, c.is_computed as Computed,
cast(CASE WHEN c.default_object_id > 0 THEN 1 ELSE 0 END as bit) as HasDefault
FROM sys.columns c
WHERE object_id = OBJECT_ID('TestView')
GO
I have tried using system views to join on dependencies, but they do not give us information about which column in the view refers to which column in the table:
-- dm_sql_referenced_entities gives us all columns referenced, but all records
-- have referencing_minor_id 0, so we do not know which column refers to what
SELECT * FROM sys.dm_sql_referenced_entities('dbo.TestView', 'OBJECT')
GO
-- sql_dependencies gives us all columns referenced, but all records has
-- column_id 0 so we can not use this either of joining the columns
SELECT * FROM sys.sql_dependencies WHERE object_id = OBJECT_ID('TestView')
GO
-- sql_expression_dependencies just tells us what table we are referencing
-- if view is not created WITH SCHEMABINDING. If it is, it will return columns,
-- but with referencing_minor_id 0 for all records, so not able use this either
SELECT * FROM sys.sql_expression_dependencies
WHERE referencing_id = OBJECT_ID('TestView')
GO
This unanswered post on social.msdn submitted by someone seems to be the same issue:
http://social.msdn.microsoft.com/Forums/en-US/transactsql/thread/4ae5869f-bf64-4eef-a952-9ac40c932cd4
You said "i need to know that TestView TestC refers to a computed column". This is not supported by SQL Server 2008 R2 (not sure for 2012 though, but i doubt it).
First you can query sys.columns or INFORMATION_SCHEMA.COLUMNS and you won't find what you want.
If you dig deeper, you will most probably try sys.sql_expression_dependencies and sys.dm_sql_referenced_entities (N'dbo.TestView', N'OBJECT'), but you can find table-column mapping there, not column-column. SQL server stores dependency information by 'high level' object (table, trigger...), not by its details (column). You will find same in sys.sysdepends. As a matter of fact dependency information is in SQL server unreliable.
At last, your only possibility would be to parse the view body by yourself. It can be found in sys.sql_modules:
SELECT m.definition
FROM
sys.objects o
JOIN sys.sql_modules m
ON m.object_id = o.object_id
WHERE
o.object_id = object_id('dbo.TestView')
and o.type = 'V'
Parsing T-SQL is VERY hard, it could really push you to the limit of your efforts. For instance, it should be more or less easy to grab table references from the view, and then table columns, especially if your view is schema-bound. But if it's not, well... just think of asterisks that reference OUTER APPLY, which references recursive CTE...
Anyway, good luck!
Currently, when views are created there are two operations that happen at a high level - parsing & binding. Parsing is basically checking for syntax of the statement, keywords & such. Binding is the process of mapping the identifiers (object names, column names) in the statement to the corresponding objects (tables, views, functions, columns etc.) & derivation of types. Additionally, in case of view similar to SELECT statements you can optionally alias column references and expressions in the SELECT list or after the view name (ex: create view v1(a) as select i from t).
After binding, we persist only the column aliases & the derived types in the metadata since a view is logically a table derived from a query expression. So there is currently no way to determine the expression that the column aliases map to or what it contains (columns or functions or literals etc.)
Only way to obtain the information you are looking for is to parse the view definition & perform your own binding. I believe we already have a bug that tracks the feature request to expose more richer dependency information regarding the mapping of aliases to column expressions in view definitions.
Lastly, SQL Server Developer Studio or Visual Studio Database Project uses the managed T-SQL parser to track such references so you can do refactoring or renaming for example using the project.
Hope this helps clarify the problem/current implementation.
It seems like the misunderstanding is the assumption that object_id is a primary key in sys.columns. It is not. The object_id in sys.columns relates to the object_id in sys.objects.
So:
SELECT C.*
FROM sys.objects T
INNER JOIN sys.columns C
ON T.object_id = C.object_id
WHERE T.type in ('S','U') -- System Tables and User Tables
AND T.name = 'Address' -- Table Name
order by C.Column_ID
will return the columns in the "Address" table in AdventureWorks.

list of views referencing a table

Is there any way to know if a particular table is being referenced by any Views or not.I used the below code which gives only SP's and function names:
select * from sys.objects p inner join sys.sql_modules m
on p.object_id = m.object_id
where m.definition like '%abc%'
Please help!!!
select *
from INFORMATION_SCHEMA.VIEWS
where VIEW_DEFINITION like '%abc%'
First, your query gives views in the result set (I tried it on AdentureWorks2012 -> Production.Product table):
If you're using SQL Server 2008 or above, you can use the sys.sql_expression_dependencies catalog view. For example:
SELECT
referencing_object_name = o.name,
referencing_object_type_desc = o.type_desc,
referenced_object_name = referenced_entity_name,
referenced_object_type_desc = o1.type_desc
FROM sys.sql_expression_dependencies sed
INNER JOIN sys.objects o
ON sed.referencing_id = o.[object_id]
LEFT OUTER JOIN sys.objects o1
ON sed.referenced_id = o1.[object_id]
WHERE referenced_entity_name = 'YourTable'
It will give you nice look on each by-name dependency on a user-defined entity
For column level dependencies you can use the sys.dm_sql_referenced_entities function
Hope this helps
If you need to find database objects (e.g. tables, columns, triggers) by name - have a look at the FREE Red-Gate tool called SQL Search which does this - it searches your entire database for any kind of string(s).
It's a great must-have tool for any DBA or database developer - did I already mention it's absolutely FREE to use for any kind of use??
If that doesn't fit your bill - you could also check out the sysdepends catalog view in SQL Server - it lists what objects depend on what (see details in the MSDN docs).
To find out what objects depend on a given table, you could use something like:
SELECT
id,
OBJECT_NAME(ID)
FROM sys.sysdepends
WHERE depid = OBJECT_ID('YourTable')
That should give you a list of all objects depending on that table (or view or whatever you're checking)

Resources