I'm using SQL Server Management Studio and I have multiple server connections and I need to know where a specific stored procedure exists in every server which contains multiple databases!
Looking for a query to run on each server
Here is a little script that you could run on each server.
I know that it uses a while loop, which is generally not preferred, someone might be able to improve on it.
Run the script from the master database.
SQL Query:
set nocount on
declare #procname varchar(150) = '<SPROCNAME_TO_FIND>' -- SET THIS TO THE STORED PROCEDURE NAME YOU ARE LOOKING FOR
declare #alldbonserver table
( databasename varchar(150),
doneflag bit )
declare #foundtbl table
( countcol int,
dbname varchar(150) )
declare #errortbl table
( dbname varchar(150) )
insert #alldbonserver
( databasename,
doneflag )
select sdb.name,
0
from sys.databases sdb
declare #curdbname varchar(150),
#sqlcmd varchar(max)
while exists (select 1
from #alldbonserver
where doneflag = 0)
begin
select top 1
#curdbname = databasename
from #alldbonserver
where doneflag = 0
select #sqlcmd = 'select distinct 1, ''' + #curdbname + ''' as dbname from ' + #curdbname + '.sys.objects where type = ''P'' and name = ''' + #procname + ''''
begin try
insert #foundtbl
( countcol, dbname )
exec(#sqlcmd)
end try
begin catch
insert #errortbl
values ( #curdbname )
end catch
update #alldbonserver
set doneflag = 1
where databasename = #curdbname
end
select dbname as 'Databases with stored procedure'
from #foundtbl
select dbname as 'Unable to access databases'
from #errortbl
set nocount off
Sample output:
Databases with stored procedure
-----------------------------------------
MainDatabase
SomeOtherDatabase
Unable to access databases
-----------------------------------------
model
ReportServer$SQLTemp
VeryPrivateDatabase
If you are using SSMS, you could create a server registration group that contains all of the servers you connect to, right click on the group and run this query against the group: exec sp_MSforeachdb 'select * from [?].sys.procedures where name=''<your_name_here>'''
This query will enumerate each of the databases on each of the servers in the group (note: the single quotes are like that for a reason...)
I just put this together on SQL2012. It should return all Stored Procs on a Server for a given name. If you leave #SPName blank, you will get all of them.
The Query utilizes sys.all_objects so you could easily change it to work the same for tables, functions, any or all db objects.
DECLARE #SPName VARCHAR(256)
SET #SPName = 'My_SP_Name'
DECLARE #DBName VARCHAR(256)
DECLARE #varSQL VARCHAR(512)
DECLARE #getDBName CURSOR
SET #getDBName = CURSOR FOR
SELECT name
FROM sys.databases
CREATE TABLE #TmpTable (DBName VARCHAR(256),
SchemaName VARCHAR(256),
SPName VARCHAR(256))
OPEN #getDBName
FETCH NEXT
FROM #getDBName INTO #DBName
WHILE ##FETCH_STATUS = 0
BEGIN
SET #varSQL = 'USE [' + #DBName + '];
INSERT INTO #TmpTable
SELECT '''+ #DBName + ''' AS DBName,
SCHEMA_NAME(schema_id) AS SchemaName,
name AS SPName
FROM sys.all_objects
WHERE [type] = ''P'' AND name LIKE ''%' + #SPName + '%'''
EXEC (#varSQL)
FETCH NEXT
FROM #getDBName INTO #DBName
END
CLOSE #getDBName
DEALLOCATE #getDBName
SELECT *
FROM #TmpTable
DROP TABLE #TmpTable
Related
I need to write some SQL to find all references of a particular column in a database. The column that I'm trying to find references to exists in a different databases. I've found a few examples of finding references of a column that exist in the same database:
In SQL Server, how can I find everywhere a column is referenced?
But I'm having problems figuring out how to do this for a column that exists in a different database. Can you provide the SQL for this? For example purposes, let's refer to the external column I'm trying to find as:
MyExternalDB.MyExternalSchema.MyExternalTable.MyExternalColumn
Ok, just run this and make sure you set your ColumnName variable
USE [master];
GO
IF OBJECT_ID('tempdb..#columns') IS NOT NULL
DROP TABLE #columns;
GO
CREATE TABLE #columns
( databaseName nvarchar(MAX),
columnid int,
columnName nvarchar(MAX),
objectid int,
objectName nvarchar(MAX));
DECLARE #databaseName sysname;
DECLARE #columnName nvarchar(MAX) = 'ColumnName';
DECLARE cur CURSOR LOCAL FORWARD_ONLY STATIC FOR
SELECT [name]
FROM [sys].[databases]
WHERE [state] = 0
AND [name] NOT IN ( 'tempdb', 'master', 'msdb', 'model' );
OPEN cur;
FETCH NEXT FROM cur
INTO #databaseName;
WHILE ( ##FETCH_STATUS != -1 )
BEGIN;
IF ( ##FETCH_STATUS != -2 )
BEGIN;
DECLARE #statement nvarchar(MAX);
SET #statement =N'Use '+ #databaseName +
N';
if EXISTS (SELECT name FROM sys.[columns] WHERE name = ''' + #columnName + ''')
BEGIN;
INSERT [#columns] ( [databaseName], [columnid], [columnName], [objectid], [objectName] )
SELECT ''' + #databaseName + N''',
c.[column_id],
c.[name],
o.[object_id],
o.[name]
FROM sys.[columns] c
INNER JOIN sys.[objects] o
ON [o].[object_id] = [c].[object_id]
WHERE c.[name] = ''' + #columnName + ''';
END;';
EXEC [sys].[sp_executesql] #stmt = #statement;
END;
FETCH NEXT FROM cur
INTO #databaseName;
END;
CLOSE cur;
DEALLOCATE cur;
SELECT * FROM [#columns];
I have many databases in my SQL Server.
I have to just search for database names containg particular table name Heartbitmaster
I have many databases such as Gotgold, DVD, etc and I just want to find database names from query that contain this table Heartbitmaster.
I searched I tried for query:
SELECT
TABLE_NAME
FROM
INFORMATION_SCHEMA.TABLES
WHERE
TABLE_TYPE = 'base table'
AND table_schema = 'Heartbitmaster'
but it didn't work.
I searched further and came across:
SELECT name, database_id, create_date
FROM sys.databases
but dont know how to arrange further where condition for search of table name
Please help me.
I got it done through following query:
SELECT name
FROM sys.databases
WHERE CASE WHEN state_desc = 'ONLINE'
THEN OBJECT_ID(QUOTENAME(name) + '.[dbo].[heartbit]', 'U')
END IS NOT NULL
sp_MSforeachdb 'SELECT "?" AS DB, * FROM [?].sys.tables WHERE name like ''%tablename%'''
try this one
I needed something slightly different.
This will return all tables and their corresponding DBs with names containing the supplied string:
SELECT TABLE_NAME, TABLE_SCHEMA
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME like '%_<insert_name_here>';
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??
As for the INFORMATION_SCHEMA or the SQL Server specific catalog views: as far as I know, those are always constrained to the current database you're in - so you cannot search across all databases on your server. SQL Search does this for you - by searching into every single database on the server.
Create Procedure as bellow
CREATE PROCEDURE usp_FindTableNameInAllDatabase
#TableName VARCHAR(256)
AS
DECLARE #DBName VARCHAR(256)
DECLARE #varSQL VARCHAR(512)
DECLARE #getDBName CURSOR
SET #getDBName = CURSOR FOR
SELECT name
FROM sys.databases
CREATE TABLE #TmpTable (DBName VARCHAR(256),
SchemaName VARCHAR(256),
TableName VARCHAR(256))
OPEN #getDBName
FETCH NEXT
FROM #getDBName INTO #DBName
WHILE ##FETCH_STATUS = 0
BEGIN
SET #varSQL = 'USE ' + #DBName + ';
INSERT INTO #TmpTable
SELECT '''+ #DBName + ''' AS DBName,
SCHEMA_NAME(schema_id) AS SchemaName,
name AS TableName
FROM sys.tables
WHERE name LIKE ''%' + #TableName + '%'''
EXEC (#varSQL)
FETCH NEXT
FROM #getDBName INTO #DBName
END
CLOSE #getDBName
DEALLOCATE #getDBName
SELECT *
FROM #TmpTable
DROP TABLE #TmpTable
GO
EXEC usp_FindTableNameInAllDatabase 'Address'
GO
exec usp_FindTableNameInAllDatabase 'user'
It Works!!!!!!!
Run this query for finding database name for a particular table
The paste table name in #tablename
Drop table #tempo for next time run
declare #tablename varchar(max) = 'patient'
declare #count int = (select max(database_id) FROM sys.databases)
declare #n int = 1
declare #dbname varchar(max)
declare #query nvarchar(max)
create table #tempo(Databasename varchar(max), tablename varchar(max))
while #n <= #count
begin
select #dbname = name from sys.databases where database_id = #n and service_broker_guid <> '00000000-0000-0000-0000-000000000000'
set #query = 'insert into #tempo(Databasename,tablename) select '''+#dbname+''' [Database],name from '+#dbname+'.sys.tables where name like ''%'+#tablename+'%'''
exec(#query)
set #n=#n+1;
end
select * from #tempo
At the last giving error like
Database 'databasename' cannot be opened because it is offline.
then run this query separately
select * from #tempo
I Complete sp_MSforeachdb and create a procedure like this :
create PROCEDURE findTableName
#tablename nvarchar(max)
AS
BEGIN
declare #sqlCommand nvarchar(max)
CREATE TABLE #t (DBName VARCHAR(256),SchemaName VARCHAR(256),TableName VARCHAR(256))
set #sqlCommand='insert into #t (DBName,SchemaName,TableName) exec sp_MSforeachdb ''SELECT "?" AS DB, SCHEMA_NAME(schema_id) AS SchemaName ,name FROM [?].sys.tables WHERE name like ''''%'+#tablename+'%'''''''
--print #sqlCommand
exec ( #sqlCommand)
select * from #t
END
I have several databases in my SQL Server 2008. And I forgot where some tables from, so I need to ask if there's a such query that finds the database location of a certain table?
I need something goes like this:
SELECT DATABASE_NAME FROM SQLSERVER WHERE TABLE= "TBL_PRODUCTS"
Addition:
Now, i need to know the database location of certain Views and Stored Procedures
Something like this:
SELECT DATABASE_NAME FROM SQLSERVER WHERE VIEW= "VW_PRODUCTS"
SELECT DATABASE_NAME FROM SQLSERVER WHERE StoredProcedure= "SP_PRODUCTS"
Thanks!
The following procedure will do the job:
CREATE PROCEDURE usp_FindTableNameInAllDatabase
#TableName VARCHAR(256)
AS
DECLARE #DBName VARCHAR(256)
DECLARE #varSQL VARCHAR(512)
DECLARE #getDBName CURSOR
SET #getDBName = CURSOR FOR
SELECT name
FROM sys.databases
CREATE TABLE #TmpTable (DBName VARCHAR(256),
SchemaName VARCHAR(256),
TableName VARCHAR(256))
OPEN #getDBName
FETCH NEXT
FROM #getDBName INTO #DBName
WHILE ##FETCH_STATUS = 0
BEGIN
SET #varSQL = 'USE ' + #DBName + ';
INSERT INTO #TmpTable
SELECT '''+ #DBName + ''' AS DBName,
SCHEMA_NAME(schema_id) AS SchemaName,
name AS TableName
FROM sys.tables
WHERE name LIKE ''%' + #TableName + '%'''
EXEC (#varSQL)
FETCH NEXT
FROM #getDBName INTO #DBName
END
CLOSE #getDBName
DEALLOCATE #getDBName
SELECT *
FROM #TmpTable
DROP TABLE #TmpTable
GO
EXEC usp_FindTableNameInAllDatabase 'Address'
GO
The result would look like that:
Source
Do this
Use Master
Go
select
'select '''+CAST(name as varchar(200))+''' from '+CAST(name as varchar(200))+'.sys.tables where name = yourTableName'
from sysdatabases
replacing yourTableName with the name of your table, with ' '
You will get selects; then run those and will get the results.
If there are more than 100 databases, use results to text, because to grid, you will only get 100 selects maximum
I have several databases in a Sql Server 2008 R2 instance. Some of those databases have a full-text enabled table. The name of the full-text table is equal for all databases, but the databases have different names and they are created on demand (I never know what databases exists and what does not).
The thing is: I need to query all catalogs in all databases to check if a population is done, but I have no idea how many databases I have (of course I know, but they are created on demand as I said). The script must query all databases and check if a population is done in a table (which the name I know because it never changes besides the name of the database that does change)
I have seen many people using things like:
sys.fulltext_catalogs
But it does not work if i am using the master database for example.
Any ideas?
Edit: Here is more complete code with a cursor, a full list of databases (even those without catalogs), and the right catalog view name:
SET NOCOUNT ON;
DECLARE #sql NVARCHAR(MAX) = N'';
SELECT #sql += ' UNION ALL
SELECT [name] = ''' + QUOTENAME(name) + ''',
catalog_name = name COLLATE Latin1_General_CI_AI,
is_importing
FROM ' + QUOTENAME(name) + '.sys.fulltext_catalogs'
FROM sys.databases WHERE database_id > 4;
SET #sql = 'SELECT [database] = d.name,
s.catalog_name,
s.is_importing
FROM sys.databases AS d
LEFT OUTER JOIN (' + STUFF(#sql, 1, 10, '') + ') AS s
ON QUOTENAME(d.name) = s.name
WHERE d.database_id > 4;';
CREATE TABLE #temp(db SYSNAME, catalog_name NVARCHAR(255), is_importing BIT);
INSERT #temp EXEC sp_executesql #sql;
DECLARE #db SYSNAME, #catalog_name NVARCHAR(255), #is_importing BIT;
DECLARE c CURSOR LOCAL STATIC FORWARD_ONLY READ_ONLY
FOR SELECT db, catalog_name, is_importing FROM #temp;
OPEN c;
FETCH NEXT FROM c INTO #db, #catalog_name, #is_importing;
WHILE ##FETCH_STATUS = 0
BEGIN
IF #catalog_name IS NULL
BEGIN
PRINT 'No catalogs for ' + #db;
END
ELSE
BEGIN
IF #is_importing = 1
BEGIN
PRINT 'Do something to ' + #db
+ '(importing)';
END
ELSE
BEGIN
PRINT #db + ' is not importing.';
END
END
FETCH NEXT FROM c INTO #db, #catalog_name, #is_importing;
END
CLOSE c;
DEALLOCATE c;
DROP TABLE #temp;
This gives you a complete list of used catalogs.
CREATE TABLE #info (
databasename VARCHAR(128)
, [Fulltext Catalog Name] VARCHAR(128));
SET NOCOUNT ON;
INSERT INTO #info
EXEC sp_MSforeachdb 'use ?
SELECT ''?''
, name
FROM sys.fulltext_catalogs;'
SELECT * FROM #info
-- get rid of temp table
DROP TABLE #info;
After performing a database restore, I want to run a dynamic script to fix ophaned users. My script below loops through all users that are displayed after executing sp_change_users_login 'report' and applys an "alter user [username] with login = [username]" statement to fix SID conflicts. I'm getting an "incorrect syntax error on line 15" and can't figure out why...help..
DECLARE #Username varchar(100), #cmd varchar(100)
DECLARE userLogin_cursor CURSOR FAST_FORWARD
FOR
SELECT UserName = name FROM sysusers
WHERE issqluser = 1 and (sid IS NOT NULL AND sid <> 0×0)
AND suser_sname(sid) IS NULL
ORDER BY name
FOR READ ONLY
OPEN userLogin_cursor
FETCH NEXT FROM userLogin_cursor INTO #Username
WHILE ##fetch_status = 0
BEGIN
SET #cmd = ‘ALTER USER ‘+#username+‘ WITH LOGIN ‘+#username
EXECUTE(#cmd)
FETCH NEXT FROM userLogin_cursor INTO #Username
END
CLOSE userLogin_cursor
DEALLOCATE userLogin_cursor
Orphaned users can be fixed by using the [dbo].[sp_change_users_login] stored procedure.
Loop through all your users and execute the procedure
Good Luck
DECLARE #UserCount INT
DECLARE #UserCurr INT
DECLARE #userName VARCHAR(100)
DECLARE #vsql NVARCHAR(4000)
DECLARE #Users TABLE(
id INT IDENTITY(1,1) PRIMARY KEY NOT NULL,
userName VARCHAR(100))
INSERT INTO #Users(UserName)
SELECT [name] FROM
--
master.[dbo].sysUsers -- SQL 2008 & SQL 2005
--master.dbo.sysxlogins -- SQL 2000
SELECT #UserCount = max([id]) FROM #Users
SET #UserCurr = 1
WHILE (#UserCurr <= #UserCount)
BEGIN
SELECT #userName=userName FROM #Users WHERE [id] =#UserCurr
SET #vsql = '[dbo].[sp_change_users_login] ''AUTO_FIX'',''' + #userName + ''''
-- EXEC(#vsql)
PRINT #vsql
SET #UserCurr = #UserCurr + 1
END
DECLARE #Username VARCHAR(100),
#cmd VARCHAR(100)
DECLARE userlogin_cursor CURSOR FAST_FORWARD FOR
SELECT username = name
FROM sysusers
WHERE issqluser = 1
AND (sid IS NOT NULL
AND sid <> 0x01)
AND Suser_sname(sid) IS NULL
ORDER BY name
FOR READ ONLY
OPEN userlogin_cursor
FETCH NEXT FROM userlogin_cursor INTO #Username
WHILE ##FETCH_STATUS = 0
BEGIN
SET #cmd = 'ALTER USER [' + #username + '] WITH LOGIN = [' + #username + ']'
EXECUTE(#cmd)
FETCH NEXT FROM userlogin_cursor INTO #Username
END
CLOSE userlogin_cursor
DEALLOCATE userlogin_cursor
I've used a similar approach, wrapping the code in a stored procedure:
USE [master]
GO
CREATE PROCEDURE [sp_AutoFixAllUsers]
AS
BEGIN
DECLARE #AutoFixCommand NVARCHAR(MAX)
SET #AutoFixCommand = ''
SELECT --dp.[name], dp.[sid] AS [DatabaseSID], sp.[sid] AS [ServerSID],
#AutoFixCommand = #AutoFixCommand + ' '
+ 'EXEC sp_change_users_login ''Auto_Fix'', ''' + dp.[name] + ''';'-- AS [AutoFixCommand]
FROM sys.database_principals dp
INNER JOIN sys.server_principals sp
ON dp.[name] = sp.[name] COLLATE DATABASE_DEFAULT
WHERE dp.[type_desc] IN ('SQL_USER', 'WINDOWS_USER', 'WINDOWS_GROUP')
AND sp.[type_desc] IN ('SQL_LOGIN', 'WINDOWS_LOGIN', 'WINDOWS_GROUP')
AND dp.[sid] <> sp.[sid]
IF (#AutoFixCommand <> '')
BEGIN
PRINT 'Fixing users in database: ' + DB_NAME()
PRINT #AutoFixCommand
EXEC(#AutoFixCommand)
PRINT ''
END
END
GO
I then used the sys.sp_MS_marksystemobject stored procedure to make my stored procedure available in all user databases (allowing it to operate on local objects)
EXEC sys.sp_MS_marksystemobject 'sp_AutoFixAllUsers'
You can then run it as follows:
EXEC [MyDB].[dbo].[sp_AutoFixAllUsers]
Or for every database using sp_msforeachdb:
EXEC sp_msforeachdb '[?].[dbo].[sp_AutoFixAllUsers]'