how to check same Object Name across databases on the same server - sql

I was trying to find duplicate object name across all databases on one server. Is there away to find all duplicate? I am using cursor to loop through the databases and I want to check if an object shows more than one and column called duplicates will be populated with Yes or No.

use the msforeachdb builtin function/proc, then insert those results into a temp table. Then query the temp table and do a groupby having count(1) > 1
create table #tables (db varchar(100) not null, name varchar(100) not null)
exec sp_msforeachdb 'use [?] insert into #tables select distinct db_name(), [name] from sys.objects where [type] = ''U'''
select name, count(1) from #tables group by name having count(1) > 1 order by 2 desc
drop table #tables
This isn't exact, but you get the idea. I'll keep tweaking until I know it's right.
Here's the cursor version:
set nocount on
SELECT name
into #dbs
FROM sys.databases
declare dbCursor cursor local forward_only for
select name from #dbs
declare #db varchar(100)
create table #tables (db varchar(100) not null, name varchar(100) not null)
open dbCursor
fetch next from dbCursor into #db
while (##fetch_status = 0) begin
begin try
exec ('use ' + #db + ' insert into #tables select distinct db_name(), [name] from sys.objects where [type] = ''U''')
print 'got ' + ##rowcount + ' from db ' + #db
end try
begin catch
print 'couldn''t retrieve data from database ' + #db
end catch
fetch next from dbCursor into #db
end
close dbCursor
deallocate dbCursor
select name, count(1) from #tables group by name having count(1) > 1 order by 2 desc
drop table #tables
drop table #dbs

Related

Using SELECT INTO for a multi-table query

I've been using a script that a coworker showed me to query against all of our databases. It starts with CREATE TABLE #tempTable and then I need to define all the columns. I was wondering if it was possible to not define the table and use SELECT * INTO instead.
Current Query:
CREATE TABLE #tempTable(category nvarchar(50), eventType nvarchar(50), occurtime datetime);
DECLARE #fixedname nvarchar(150);
DECLARE dbCursor CURSOR FOR
SELECT REPLACE(QUOTENAME(name),'''','''''')
FROM master.sys.databases
WHERE state_desc = 'ONLINE'
AND HAS_DBACCESS(name) = 1
AND name NOT IN ('master', 'msdb','model','tempdb');
OPEN dbCursor
FETCH NEXT FROM dbCursor INTO #fixedname;
WHILE ##FETCH_STATUS = 0
BEGIN
EXEC ('USE ' + #fixedname + ';' +
'INSERT INTO #tempTable
SELECT
DISTINCT UserChangeEvent.category [Category],
UserChangeEvent.eventType [EventType],
UserChangeEvent.occurTime[DateTime]
FROM
UserChangeEvent
WHERE
/* User Conditions */
(
(eventType LIKE ''Alarm'')
)
AND UserChangeEvent.occurtime >= ''2021-01-01''
;');
FETCH NEXT FROM dbCursor INTO #fixedname;
END;
CLOSE dbCURSOR
DEALLOCATE dbCursor
SELECT * FROM #tempTable
--The following line can be commented out if you plan to do multiple queries within the
DROP TABLE #tempTable`
What I'm hoping might work:
DECLARE #fixedname nvarchar(150);
DECLARE dbCursor CURSOR FOR
SELECT REPLACE(QUOTENAME(name),'''','''''')
FROM master.sys.databases
WHERE state_desc = 'ONLINE'
AND HAS_DBACCESS(name) = 1
AND name NOT IN ('master', 'msdb','model','tempdb');
OPEN dbCursor
FETCH NEXT FROM dbCursor INTO #fixedname;
WHILE ##FETCH_STATUS = 0
BEGIN
EXEC ('USE ' + #fixedname + ';' +
'SELECT * INTO #tempTable
;');
FETCH NEXT FROM dbCursor INTO #fixedname;
END;
CLOSE dbCURSOR
DEALLOCATE dbCursor
SELECT * FROM #tempTable
WHERE
/* User Conditions */
(
(eventType LIKE ''Alarm'')
)
AND UserChangeEvent.occurtime >= ''2021-01-01''
--The following line can be commented out if you plan to do multiple queries within the
DROP TABLE #tempTable
I also read something that suggests I might not have to drop the table at the end since it's a temp table.

SQL query to find all references of a particular column in a database?

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];

SQL get max id value from all tables in all databases

I want to get the database name, schema name, table name and max id value from all tables in all databases. Using following query I get the DBname, Schema and TableName but cannot figure out how to get the max(id) value also into the table.
DECLARE #DBName VARCHAR(256)
DECLARE #varSQL VARCHAR(256)
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'
EXEC(#varSQL)
FETCH NEXT FROM #getDBName INTO #DBName
END
CLOSE #getDBName
DEALLOCATE #getDBName
SELECT * FROM #TmpTable
DROP TABLE #TmpTable
SELECT
'#DBName' AS DBName,
IDENT_CURRENT(Name) MaxId,
SCHEMA_NAME(Schema_ID) AS SchemaName,
name AS TableName
FROM sys.Tables

Find all database tables where a common column is set to a value

All database tables have a UserId field of [uniqueidentifier] type.
I need to query the entire database and get the list of tables that have UserId set to a specific value.
Right now I achieved this by using cursor and the results are horrible and are difficult to read. How can I improve this query to retrieve back a clear list with tables and count of record that have UserId set to a specific value, instead of using this:
DECLARE #TableName VARCHAR(127);
DECLARE #Value VARCHAR(512);
DECLARE #SqlCommand varchar(1000)
--Use cursor to loop through database tables that contain UserId column
DECLARE db_cursor CURSOR FOR
SELECT t.name AS TableName
FROM sys.columns c
JOIN sys.tables t ON c.object_id = t.object_id
WHERE c.name = 'UserId';
OPEN db_cursor;
FETCH NEXT FROM db_cursor INTO #TableName;
WHILE ##FETCH_STATUS = 0
BEGIN
--Check if the next table has any UserId matching the where clause
EXEC('SELECT COUNT(UserId) , ''' + #TableName + ''' FROM ' + #TableName + ' WHERE UserId = ''FF13ACCA-022C-4296-AB3D-A35700E35BB3''');
FETCH NEXT FROM db_cursor INTO #TableName;
END;
CLOSE db_cursor;
DEALLOCATE db_cursor;
You made all the difficult part, just put the value in a temp table and select them once you've finished.
DECLARE #TableName VARCHAR(127);
DECLARE #Value VARCHAR(512);
DECLARE #SqlCommand varchar(1000)
--Creta temp table
CREATE TABLE #Results (Number int, Tablename sysname)
--Use cursor to loop through database tables that contain UserId column
DECLARE db_cursor CURSOR FOR
SELECT t.name AS TableName
FROM sys.columns c
JOIN sys.tables t ON c.object_id = t.object_id
WHERE c.name = 'UserId';
OPEN db_cursor;
FETCH NEXT FROM db_cursor INTO #TableName;
WHILE ##FETCH_STATUS = 0
BEGIN
--Check if the next table has any UserId matching the where clause
EXEC('INSERT INTO #Results (Number, ''' + #TableName + ''') SELECT COUNT(UserId) , ''' + #TableName + ''' FROM ' + #TableName + ' WHERE UserId = ''FF13ACCA-022C-4296-AB3D-A35700E35BB3''');
FETCH NEXT FROM db_cursor INTO #TableName;
END;
CLOSE db_cursor;
DEALLOCATE db_cursor;
SELECT * FROM #Results
DROP TABLE #Results
I cannot test it but this should be the way

SQL Server look for stored procedure

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