Get value from multiple tables in all databases on MSSQL server - sql-server

Given a Database server on which I only have read access to the Master DB, I need to scan all databases on the server for tables that contain "SMTP Mail Setup" in their name. I also need to know the value of the field "SMTP Server" within each of those tables.
I've been able to cobble together the following which lists the Database and Table names where the data I need is stored.
EXEC sp_MSforeachdb 'USE [?] SELECT TABLE_CATALOG as DB_Name, Table_Name FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME LIKE ''%SMTP Mail Setup%'''
I'm stuck now as I can't seem to figure out how to pull the field "SMTP Server" from the given tables. Is there a better way to approach this?

You will need to generate and execute dynamic SQL based on the results of the first query.
Try the following (somewhat over-engineered) code:
DECLARE #TableNamePattern sysname = '%SMTP Mail Setup%'
DECLARE #ColumnName sysname = 'SMTP Server'
IF OBJECT_ID('TempDb..#SelectedTables') IS NOT NULL DROP TABLE #SelectedTables
CREATE TABLE #SelectedTables (DB_Name sysname, Table_Name sysname)
DECLARE #SqlTemplate1 VARCHAR(MAX) = '
USE [?]
INSERT #SelectedTables
SELECT T.TABLE_CATALOG as DB_Name, T.TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES T
JOIN INFORMATION_SCHEMA.COLUMNS C
ON C.TABLE_CATALOG = T.TABLE_CATALOG
AND C.TABLE_SCHEMA = T.TABLE_SCHEMA
AND C.TABLE_NAME = T.TABLE_NAME
WHERE T.TABLE_TYPE = ''BASE TABLE''
AND T.TABLE_NAME LIKE <TableNamePattern>
AND C.COLUMN_NAME = <ColumnName>
'
DECLARE #Sql1 VARCHAR(MAX) =
REPLACE(REPLACE(
#SqlTemplate1
, '<TableNamePattern>', QUOTENAME(#TableNamePattern, ''''))
, '<ColumnName>', QUOTENAME(#ColumnName, ''''))
EXEC sp_MSforeachdb #Sql1
SELECT * FROM #SelectedTables ORDER BY DB_Name, Table_Name
DECLARE #SqlTemplate2 VARCHAR(MAX) = 'UNION ALL
SELECT <DB_NAME_Text> AS DB_NAME, <Table_Name_Text> AS Table_Name, <Column_Name>
FROM <DB_NAME>..<Table_Name>
'
DECLARE #Sql2 VARCHAR(MAX) = STUFF((
SELECT REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(
#SqlTemplate2
, '<DB_NAME_Text>', QUOTENAME(T.DB_NAME, ''''))
, '<Table_Name_Text>', QUOTENAME(T.Table_Name, ''''))
, '<DB_NAME>', QUOTENAME(T.DB_NAME))
, '<Table_Name>', QUOTENAME(T.Table_Name))
, '<Column_Name>', QUOTENAME(#ColumnName))
FROM #SelectedTables T
ORDER BY T.DB_NAME, T.Table_Name
FOR XML PATH(''),TYPE
).value('text()[1]','nvarchar(max)')
, 1, 9, '') -- Remove initial UNION ALL
SET #Sql2 = #Sql2 + '
ORDER BY 1, 2, 3' -- Lazy way of referencing columns
PRINT #Sql2 -- Might be truncated
EXEC (#Sql2)
DROP TABLE #SelectedTables
I added checks to ensure that the column is defined in the selected table and that the table is a true table ('BASE TABLE') and not a view. The sql templates are run through a series a replace functions that insert the properly quoted and escaped object names. The first template is an expanded version of your original executed sql. The second is used to generate a series or selects for each table.
The FOR XML PATH(''),TYPE concatenates all of the generated selects into a single XML string, and the .value() at the end reliably extracts that text avoiding any XML encoding artifacts. Newer SQL Server versions support a STRING_AGG() function that can be used instead, but the code I had on hand was already using FOR XML.
Each query starts with UNION ALL so that all results display in a combined grid. The STUFF(..., 1, 11, '') strips off the leading UNION ALL.
Finally the resulting SQL is printed and executed.

Related

Create view that selects from identical tables from all databases on the server and can handle any time a new database is added to the server

I have a system that takes in Revit models and loads all the data in the model to a 2016 SQL Server. Unfortunately, the way the system works it created a new database for each model that is loaded. All the databases start with an identical schema because there is a template database that the system uses to build any new ones.
I need to build a view that can query data from all databases on the server but can automatically add new databases as they are created. The table names and associated columns will be identical across all databases, including data types.
Is there a way to pull a list of current database names using:
SELECT [name] FROM sys.databases
and then use the results to UNION the results from a basic SELECT query like this:
SELECT
[col1]
,[col2]
,[col3]
FROM [database].[dbo].[table]
Somehow replace the [database] part with the results of the sys.databases query?
The goal would be for the results to look as if I did this:
SELECT
[col1]
,[col2]
,[col3]
FROM [database1].[dbo].[table]
UNION
SELECT
[col1]
,[col2]
,[col3]
FROM [database2].[dbo].[table]
but dynamically for all databases on the server and without future management from me.
Thanks in advance for the assistance!
***Added Info: A couple suggestions using STRING_AGG have been made, but that function is not available in 2016.
Try this. It will automatically detect and include new databases with the specified table name. If a database is dropped it will automatically exclude it.
I updated the TSQL. STRING_AGG concatenates the string with each database. Without it it only returns the last database. STRING_AGG is more secure than += which also concatenates. I changed the code so it generates and executes the query. In SQL 2019 the query is all in one line using +=. I don't have SQL 2016. It may format it better in SQL 2016. You can uncomment --SELECT #SQL3 to see what the query looks like. Please mark as answer if this is what you need.
DECLARE #TblName TABLE
(
TblName VARCHAR(100)
)
Declare #SQL VARCHAR(MAX),
#SQL3 VARCHAR(MAX),
#DBName VARCHAR(50),
#Count Int,
#LoopCount Int
Declare #SQL2 VARCHAR(MAX) = ''
Select Identity(int,1,1) ID, name AS DBName into #Temp from sys.databases
Select #Count = ##RowCount
Set #LoopCount = 1
While #LoopCount <= #Count
Begin
SET #DBName = (SELECT DBName FROM #Temp Where ID = #LoopCount)
SET #SQL =
' USE ' + #DBName +
' SELECT TABLE_CATALOG FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = ''table'''
INSERT INTO #TblName (TblName)
EXEC (#SQL)
Set #LoopCount=#LoopCount + 1
End
SELECT #SQL2 +=
' SELECT ' + char(10) + 
' [col1] ' + char(10) + 
' ,[col2] ' + char(10) + 
' ,[col3] ' + char(10) + 
' FROM [' + TblName + '].[dbo].[table] ' + char(10) + 
' UNION '
FROM #TblName
DROP TABLE #Temp
SET #SQL3 = (SELECT SUBSTRING(#SQL2, 1, LEN(#SQL2) - 5))
--SELECT #SQL3
EXEC (#SQL3)

Deadlock MS-SQL when Inserting Into a Table

I am using the following query to insert in the respective historical table changes occurred to a given table. I am executing the same query simultaneously for multiple tables in python (changing the table name and database). None of the historical tables have foreign keys. But some of the executions end up in deadlock. Each table have assign a unique historical table. I am not sure how to solve the issue. Is it because I use a variable table with the same name in all the procedures?
declare #name_tab table (name_column varchar(200),
dtype varchar(200))
declare #columns varchar(max)
declare #query varchar(max)
declare #database varchar(200)
declare #table_name varchar(200)
set #database = '%s'
set #table_name = '%s'
insert into #name_tab
select c.name as name_column,
t.name as dtype
from sys.all_columns c
INNER JOIN sys.types t
ON t.system_type_id = c.system_type_id
where OBJECT_NAME(c.object_id) = #table_name
set #columns= stuff((select ','+name_column from #name_tab FOR XML PATH('')),1, 1, '')
set #query= 'insert into ' +#database+'..'+'HISTORY_'+#table_name+' select super_q.* from' +
'(select cast (GETDATE() as smalldatetime) as TIME_MODIFIED, new_info.* from '+
'(SELECT ' + #columns + ' From '+#database+'..'+#table_name +
' except ' +
'SELECT ' + #columns + ' From '+#database+'..'+'HISTORY_'+#table_name + ') new_info) as super_q'
execute(#query)
I got this sample from system_health
It appears that some concurrent process is altering or creating a table at the same time. The deadlock XML should contain additional details about what's going on.
But whatever the actual cause, the solution is simple. Use your scripting above to generate the trigger bodies in static SQL so you don't have to query the catalog for every insert.
Create a procedure in your database called, say, admin.GenerateHistoryTables and one called admin.GenerateHistoryTriggers and run those ahead of time to install the history tables and wire up the triggers.
Or stop re-inventing the wheel and use Change Data Capture or Temporal Tables.

Running one single SQL query over many databases on one single server

I have a query to check my procedures, as follows:
DECLARE #SearchTerm VARCHAR(MAX) = 'INSERT' -- Just an example
SELECT ROUTINE_NAME [Procedure]
, SPECIFIC_CATALOG [Database]
FROM INFORMATION_SCHEMA.ROUTINES
WHERE SUBSTRING(ROUTINE_DEFINITION, 54, 20) LIKE '%'+#SearchTerm+'%'
AND ROUTINE_TYPE = 'PROCEDURE'
ORDER BY [Procedure]
Example output:
Procedure Database
pGetAnimals Zoo
pGetGreens Food
pGetBeans Food
pGetChocolate Food
Trouble is, my knowledge restricts me to opening a query for each database on a server.
What I would like is to run the query over all the databases on a server, either as; a single select statement, or for the results to populate a temporary table.
I'm sure it's possible.
Does anyone know a neat trick to do this?
Please use the following code:
DECLARE #SearchTerm VARCHAR(MAX) = 'INSERT' -- Just an example
USE master
IF EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE' AND TABLE_NAME='MyProcedures') DROP TABLE MyProcedures
CREATE TABLE MyProcedures([Procedure] VARCHAR(512) NULL,[Database] VARCHAR(64) NULL)
EXEC sp_MSforeachdb 'USE ?
INSERT INTO master.dbo.MyProcedures
SELECT ROUTINE_NAME [Procedure]
, SPECIFIC_CATALOG [Database]
FROM INFORMATION_SCHEMA.ROUTINES
WHERE SUBSTRING(ROUTINE_DEFINITION, 54, 20) LIKE ''%' + #SearchTerm + '%''
AND ROUTINE_TYPE = ''PROCEDURE''
ORDER BY [Procedure]
';
SELECT * FROM MyProcedures
Note: The main SQL is populating a table on the master database, and is VARCHAR based.

In sql server, is there any way to check whether the schema change will impact on the stored procs?

In SQL Server, is there any way to check whether the changes in the schema will impact Stored Procedures (and/or Views)?
For example a change of the column name in one table, may break some Stored Procedures; how to check the impacted stored procs?
try using:
EXEC sp_depends 'YourTableName'
and/or
DECLARE #Search nvarchar(500)
SET #Search='YourTableName' --or anything else
SELECT DISTINCT
LEFT(o.name, 100) AS Object_Name,o.type_desc
FROM sys.sql_modules m
INNER JOIN sys.objects o ON m.object_id=o.object_id
WHERE m.definition Like '%'+#Search+'%'
ORDER BY 2,1
Use Visual Studio Database Edition for your T-SQL development. It will catch such problems during build, as it creates the deployment .dbschema file.
In SSMS (SQL Server Management Studio) right click on the object you are changing and click on View Dependencies. I don't think this will find references from another database.
You can also look for references in stored procedures if they are not encrypted. You would have to do this in each database you suspect might reference the object you are changing.
select objects.name
,sql_modules.definition
from sys.sql_modules sql_modules
join sys.objects objects on sql_modules.object_id = objects.object_id
where definition like '%some column name%';
I have found nothing that is 100.0000% accurate 100.000000% of the time.
Best way I can think to do this is to abstract your stored procedures from your actual tables using views, and to create those views with a "WITH SCHEMABINDING" clause which should prevent changes that will break your views...
Commercial tools such as Red Gate's SQL Refactor can do this.
I think that recent version of Visual Studio also include this kind of features, but I haven't tried.
To my knowledge, there are no built-in features of Microsoft SQL Server per-se which will do this. Correction: I just read about sp_depends in KM's answer to this post... Note that sp_depends's usage is deprecated; it is replaced by sys.dm_sql_referencing_entities and sys.dm_sql_referenced_entities
Also, if the underlying stored procedures use dynamic SQL, the task of detecting dependencies becomes more difficult and prone to "misses".
If you want to change the name of an object or column, then the Smart Rename feature of Red Gate Software's SQL Prompt 5 will generate a script that both performs the rename and updates references to the old name in other objects.
If you're just interested in what depends on a column name, then SQL Prompt 5 also has a Column Dependencies function, where hovering over the column name in a script pops up a window containing a list of objects that refer to the column.
You can download a 14-day trial for free, to see if either of these features works for you.
Paul Stephenson
SQL Prompt Project Manager
Red Gate Software
Have a look at these answers:
Refreshing metadata on user functions t-SQL
SQL Server relationships buried in stored procedures rather than schema
In SQL Server, how can I find everywhere a column is referenced?
How do I find all stored procedures that insert, update, or delete records?
Other than dynamic SQL, using SCHEMABINDING where possible and sp_refreshsqlmodule and sql_dependencies for everything else is very accurate.
If you use SQL Server
You can use this query after your change and find Stored Procedure Or View Or ...
that after your change might get error
USE <Your_DataBase_Name>;
SET NOCOUNT ON;
DECLARE #name NVARCHAR(MAX)
DECLARE #sql NVARCHAR(MAX)
DECLARE #type CHAR(2)
DECLARE #type_desc NVARCHAR(60)
DECLARE #params NVARCHAR(MAX)
DECLARE #tblInvalid TABLE
(
[type_desc] NVARCHAR(60) ,
[name] NVARCHAR(MAX) ,
[error_number] INT ,
[error_message] NVARCHAR(MAX) ,
[type] CHAR(2)
);
DECLARE testSPs CURSOR FAST_FORWARD
FOR
SELECT [name] = OBJECT_NAME(SM.[object_id]) ,
[type] = SO.[type] ,
SO.[type_desc] ,
[params] = ( SELECT (
SELECT CONVERT(XML, ( SELECT STUFF(( SELECT
', ' + [name]
+ '=NULL' AS [text()]
FROM
sys.parameters
WHERE
[object_id] = SM.[object_id]
FOR
XML
PATH('')
), 1, 1, '')
))
FOR XML RAW ,
TYPE
).value('/row[1]', 'varchar(max)')
)
FROM sys.sql_modules SM
JOIN sys.objects SO ON SO.[object_id] = SM.[object_id]
WHERE SO.[is_ms_shipped] = 0
AND SO.[type] = 'P'
OPEN testSPs
FETCH NEXT FROM testSPs INTO #name, #type, #type_desc, #params
WHILE ( ##FETCH_STATUS = 0 )
BEGIN
BEGIN TRY
SET #sql = 'SET FMTONLY ON; exec ' + #name + ' ' + #params
+ '; SET FMTONLY OFF;'
--PRINT #sql;
EXEC (#sql);
END TRY
BEGIN CATCH
PRINT #type_desc + ', ' + #name + ', Error: '
+ CAST(ERROR_NUMBER() AS VARCHAR) + ', ' + ERROR_MESSAGE();
INSERT INTO #tblInvalid
SELECT #type_desc ,
#name ,
ERROR_NUMBER() ,
ERROR_MESSAGE() ,
#type;
END CATCH
FETCH NEXT FROM testSPs INTO #name, #type, #type_desc, #params
END
CLOSE testSPs
DEALLOCATE testSPs
SELECT [type_desc] ,
[name] ,
[error_number] ,
[error_message]
FROM #tblInvalid
ORDER BY CHARINDEX([type], ' U V PK UQ F TR FN TF P SQ ') ,
[name];

How to find a text inside SQL Server procedures / triggers?

I have a linkedserver that will change. Some procedures call the linked server like this: [10.10.100.50].dbo.SPROCEDURE_EXAMPLE. We have triggers also doing this kind of work. We need to find all places that uses [10.10.100.50] to change it.
In SQL Server Management Studio Express, I didn't find a feature like "find in whole database" in Visual Studio. Can a special sys-select help me find what I need?
here is a portion of a procedure I use on my system to find text....
DECLARE #Search varchar(255)
SET #Search='[10.10.100.50]'
SELECT DISTINCT
o.name AS Object_Name,o.type_desc
FROM sys.sql_modules m
INNER JOIN sys.objects o ON m.object_id=o.object_id
WHERE m.definition Like '%'+#Search+'%'
ORDER BY 2,1
You can find it like
SELECT DISTINCT OBJECT_NAME(id) FROM syscomments WHERE [text] LIKE '%User%'
It will list distinct stored procedure names that contain text like 'User' inside stored procedure. More info
[Late answer but hopefully usefull]
Using system tables doesn't always give 100% correct results because there might be a possibility that some stored procedures and/or views are encrypted in which case you'll need to use DAC connection to get the data you need.
I'd recommend using a third party tool such as ApexSQL Search that can deal with encrypted objects easily.
Syscomments system table will give null value for text column in case object is encrypted.
-- Declare the text we want to search for
DECLARE #Text nvarchar(4000);
SET #Text = 'employee';
-- Get the schema name, table name, and table type for:
-- Table names
SELECT
TABLE_SCHEMA AS 'Object Schema'
,TABLE_NAME AS 'Object Name'
,TABLE_TYPE AS 'Object Type'
,'Table Name' AS 'TEXT Location'
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE '%'+#Text+'%'
UNION
--Column names
SELECT
TABLE_SCHEMA AS 'Object Schema'
,COLUMN_NAME AS 'Object Name'
,'COLUMN' AS 'Object Type'
,'Column Name' AS 'TEXT Location'
FROM INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME LIKE '%'+#Text+'%'
UNION
-- Function or procedure bodies
SELECT
SPECIFIC_SCHEMA AS 'Object Schema'
,ROUTINE_NAME AS 'Object Name'
,ROUTINE_TYPE AS 'Object Type'
,ROUTINE_DEFINITION AS 'TEXT Location'
FROM INFORMATION_SCHEMA.ROUTINES
WHERE ROUTINE_DEFINITION LIKE '%'+#Text+'%'
AND (ROUTINE_TYPE = 'function' OR ROUTINE_TYPE = 'procedure');
This will work for you:
use [ANALYTICS] ---> put your DB name here
GO
SELECT sm.object_id, OBJECT_NAME(sm.object_id) AS object_name, o.type, o.type_desc, sm.definition
FROM sys.sql_modules AS sm
JOIN sys.objects AS o ON sm.object_id = o.object_id
where sm.definition like '%SEARCH_WORD_HERE%' collate SQL_Latin1_General_CP1_CI_AS
ORDER BY o.type;
GO
There are much better solutions than modifying the text of your stored procedures, functions, and views each time the linked server changes. Here are some options:
Update the linked server. Instead of using a linked server named with its IP address, create a new linked server with the name of the resource such as Finance or DataLinkProd or some such. Then when you need to change which server is reached, update the linked server to point to the new server (or drop it and recreate it).
While unfortunately you cannot create synonyms for linked servers or schemas, you CAN make synonyms for objects that are located on linked servers. For example, your procedure [10.10.100.50].dbo.SPROCEDURE_EXAMPLE could by aliased. Perhaps create a schema datalinkprod, then CREATE SYNONYM datalinkprod.dbo_SPROCEDURE_EXAMPLE FOR [10.10.100.50].dbo.SPROCEDURE_EXAMPLE;. Then, write a stored procedure that accepts a linked server name, which queries all the potential objects from the remote database and (re)creates synonyms for them. All your SPs and functions get rewritten just once to use the synonym names starting with datalinkprod, and ever after that, to change from one linked server to another you just do EXEC dbo.SwitchLinkedServer '[10.10.100.51]'; and in a fraction of a second you're using a different linked server.
There may be even more options. I highly recommend using the superior techniques of pre-processing, configuration, or indirection rather than changing human-written scripts. Automatically updating machine-created scripts is fine, this is preprocessing. Doing things manually is awful.
select text
from syscomments
where text like '%your text here%'
This one i tried in SQL2008, which can search from all the db at one go.
Create table #temp1
(ServerName varchar(64), dbname varchar(64)
,spName varchar(128),ObjectType varchar(32), SearchString varchar(64))
Declare #dbid smallint, #dbname varchar(64), #longstr varchar(5000)
Declare #searhString VARCHAR(250)
set #searhString='firstweek'
declare db_cursor cursor for
select dbid, [name]
from master..sysdatabases
where [name] not in ('master', 'model', 'msdb', 'tempdb', 'northwind', 'pubs')
open db_cursor
fetch next from db_cursor into #dbid, #dbname
while (##fetch_status = 0)
begin
PRINT 'DB='+#dbname
set #longstr = 'Use ' + #dbname + char(13) +
'insert into #temp1 ' + char(13) +
'SELECT ##ServerName, ''' + #dbname + ''', Name
, case when [Type]= ''P'' Then ''Procedure''
when[Type]= ''V'' Then ''View''
when [Type]= ''TF'' Then ''Table-Valued Function''
when [Type]= ''FN'' Then ''Function''
when [Type]= ''TR'' Then ''Trigger''
else [Type]/*''Others''*/
end
, '''+ #searhString +''' FROM [SYS].[SYSCOMMEnTS]
JOIN [SYS].objects ON ID = object_id
WHERE TEXT LIKE ''%' + #searhString + '%'''
exec (#longstr)
fetch next from db_cursor into #dbid, #dbname
end
close db_cursor
deallocate db_cursor
select * from #temp1
Drop table #temp1
I use this one for work. leave off the []'s though in the #TEXT field, seems to want to return everything...
SET NOCOUNT ON
DECLARE #TEXT VARCHAR(250)
DECLARE #SQL VARCHAR(250)
SELECT #TEXT='10.10.100.50'
CREATE TABLE #results (db VARCHAR(64), objectname VARCHAR(100),xtype VARCHAR(10), definition TEXT)
SELECT #TEXT as 'Search String'
DECLARE #databases CURSOR FOR SELECT NAME FROM master..sysdatabases where dbid>4
DECLARE #c_dbname varchar(64)
OPEN #databases
FETCH #databases INTO #c_dbname
WHILE ##FETCH_STATUS -1
BEGIN
SELECT #SQL = 'INSERT INTO #results '
SELECT #SQL = #SQL + 'SELECT ''' + #c_dbname + ''' AS db, o.name,o.xtype,m.definition '
SELECT #SQL = #SQL + ' FROM '+#c_dbname+'.sys.sql_modules m '
SELECT #SQL = #SQL + ' INNER JOIN '+#c_dbname+'..sysobjects o ON m.object_id=o.id'
SELECT #SQL = #SQL + ' WHERE [definition] LIKE ''%'+#TEXT+'%'''
EXEC(#SQL)
FETCH #databases INTO #c_dbname
END
CLOSE #databases
DEALLOCATE #databases
SELECT * FROM #results order by db, xtype, objectname
DROP TABLE #results
I've used these in the past:
Searching all user stored procedures for a table name
Search and replace SQL Server data in all columns of all tables
In this particular case, where you need to replace a specific string across stored procedures, the first link is probably more relevant.
A little off-topic, the Quick Find add-in is also useful for searching object names with SQL Server Management Studio. There's a modified version available with some improvements, and another newer version also available on Codeplex with some other useful add-ins as well.
Any searching with select statement yield you only object name, where search keyword contains.
Easiest and efficient way is get script of procedure/function and then search in generated text file, I also follows this technique :) So you are exact pinpoint.
You can search within the definitions of all database objects using the following SQL:
SELECT
o.name,
o.id,
c.text,
o.type
FROM
sysobjects o
RIGHT JOIN syscomments c
ON o.id = c.id
WHERE
c.text like '%text_to_find%'
SELECT ROUTINE_TYPE, ROUTINE_NAME, ROUTINE_DEFINITION
FROM INFORMATION_SCHEMA.ROUTINES
WHERE ROUTINE_DEFINITION LIKE '%Your Text%'
Just wrote this for generic full outer cross ref
create table #XRefDBs(xtype varchar(2),SourceDB varchar(100), Object varchar(100), RefDB varchar(100))
declare #sourcedbname varchar(100),
#searchfordbname varchar(100),
#sql nvarchar(4000)
declare curs cursor for
select name
from sysdatabases
where dbid>4
open curs
fetch next from curs into #sourcedbname
while ##fetch_status=0
begin
print #sourcedbname
declare curs2 cursor for
select name
from sysdatabases
where dbid>4
and name <> #sourcedbname
open curs2
fetch next from curs2 into #searchfordbname
while ##fetch_status=0
begin
print #searchfordbname
set #sql =
'INSERT INTO #XRefDBs (xtype,SourceDB,Object, RefDB)
select DISTINCT o.xtype,'''+#sourcedbname+''', o.name,'''+#searchfordbname+'''
from '+#sourcedbname+'.dbo.syscomments c
join '+#sourcedbname+'.dbo.sysobjects o on c.id=o.id
where o.xtype in (''V'',''P'',''FN'',''TR'')
and (text like ''%'+#searchfordbname+'.%''
or text like ''%'+#searchfordbname+'].%'')'
print #sql
exec sp_executesql #sql
fetch next from curs2 into #searchfordbname
end
close curs2
deallocate curs2
fetch next from curs into #sourcedbname
end
close curs
deallocate curs
select * from #XRefDBs

Resources