Run same query in SSMS on multiple databases in the same server - sql-server

It is possible in SSMS to run the same query on some databases?
I was thinking something like an array with database names and cycling through it, maybe with SQLCMD mode.
some pseudocode:
:setvar arr ["db1", "db2", "db3"]
foreach $db in $arr
:setvar database $db
use $(database)
go
select * from table
Thanks

-- To Achive your Desire OutpUt You Have to Use Dynamic Query
-- you can Achieve this in TSQL
-- TO Know The Database ID Run Below Query
/*
SELECT * FROM Sys.databases WHERE database_id >4
*/
USE MASTER
GO
BEGIN TRAN
DECLARE #strt INT,#End INT,#Database NVARCHAR(255)
SELECT * INTO #T FROM Sys.databases WHERE database_id IN (4,5,6)-- Here you Have to Defined the Database ID
ORDER BY 1
SELECT ROW_NUMBER ()OVER (ORDER BY database_Id)Db_Id,* INTO #TT FROM #T
SET #strt=1
SELECT #End=Max(Db_ID)FROM #tt
WHILE #strt<=#END
BEGIN
DECLARE #string NVARCHAR(MAX)
SELECT #Database=NAME FROM #TT WHERE Db_ID=#strt
Set #string=' Select * from '+#Database+'..Table_Name'
SET #strt=#strt+1
PRINT #string
EXEC(#string)
END
ROLLBACK TRAN

Here's an example using two of my databases (Staging and Warehouse) to hit the sys.columns table in each. Just change out the IN filter with the names of whichever databases you want, and the ".sys.columns" with the schema/table name you need.
DECLARE #query NVARCHAR(MAX) = ''
;
SELECT #query += CONCAT('SELECT * FROM ',[name],'.sys.columns;')
FROM sys.databases
WHERE [name] IN ('Staging','Warehouse')
;
EXEC sp_executesql #query;

You can do this with a Local Server Group as well.
View --> Registered Servers
Right-click Local Server Group and create new
Add new server registrations to the group (any databases you want to query). Be sure to specify the database in the Connection Properties tab
Now you can right-click the Local Server Group folder and execute a new query, which will run on all the databases in that folder.

Related

Declaring Databasename in sql query

I am preparing a group of sql queries for a dashboard. I want to declare the database name at the beginning so that the queries will work on the database specified on top without making any changes in the underlying code
Original query:
SELECT *
FROM Check.dbo.Dates_table
The query I want:
DECLARE #Databasename VARCHAR(200)
SET #Databasename = 'Check.dbo'
SELECT * FROM #Databasename.Dates_table
You can use "USE" operator: https://msdn.microsoft.com/en-AU/library/ms188366.aspx
use Check
SELECT * FROM dbo.Dates_table

Get the database name in which Stored Procedure exists

I am having SQL server 2008 and i am having 10 different databases in it and now i want to search one stored procedure that in which database the stored procedure is present.
Mentioned as duplicate by some ..... with out reading my question properly. My Requirement is i need to verify 'SP_Email' procedure. I which database is this procedure exists.
You can try this:
EXEC sp_msforeachdb
'if exists(select 1 from [?].sys.objects where name=''SP_Email'')
select ''?'' as FoundInDatabase from [?].sys.objects where name=''SP_Email'''
Please try this.
SELECT name DatabaseName
FROM sys.databases
WHERE OBJECT_ID(QUOTENAME(name) + '.dbo.ProcedureNameHere', 'P') IS NOT NULL;
This will return the database(s) name in which this particular object exist.
Replace ProcedureNameHere with your procedure name. In your case it would be SP_Email Keep rest of the things as it is.
you need to query sys.databases of master database to get list of databases and for each database name you get you need to query the db_name.sys.procedures to check if it exists.
try below query and give a feedback:
use master
go
declare #FullQuery varchar(max)
declare #DBName varchar(50)
set #FullQuery=''
declare cr cursor for select name from sys.databases where database_id > 4
open cr
fetch next from cr into #DBName
while(##fetch_status=0)
begin
set #FullQuery=#FullQuery+
' select name COLLATE SQL_Latin1_General_CP1_CI_AS from '+#DBName+'.sys.procedures where name like ''%proc_name%'' union'
fetch next from cr into #DBName
end
close cr
deallocate cr
set #FullQuery=substring(#FullQuery,1,len(#FullQuery)-5)
exec (#FullQuery)
SELECT OBJECT_ID('DataBase1.SchemaName.StoredProcedureName') /
OBJECT_ID('DataBase2.SchemaName.StoredProcedureName') /
OBJECT_ID('DataBase3.SchemaName.StoredProcedureName') /
...
It will return NULL if there is no such procedure. This will work if all databases are on same instance.

SQL Server Script to Iterate through servers Part 2

I am trying to create a script to obtain data from a multiple databases in a server and then I want it to continue to the next server and do the same. I already created a script to work with one server and all its databases. The script is the same for all databases, tables in all the servers.
My question, is how do I have the script recognize the linked servers that I linked to my current server and continue to obtain data from those servers? Is there a hidden stored procedure or command that someone may know? I basically want to runs the below script through all my servers. When its done iterating through all the databases in one server, I want it to continue to the next server and do the same. I'm going to be saving all the data in a table.
Here is my script below, I want to have the script run through 5 servers which I currently have linked to one of my servers:
SET NOCOUNT ON DECLARE #DBNAME NVARCHAR(MAX) DECLARE #DBNAME1 NVARCHAR(MAX) DECLARE #varSQL NVARCHAR(MAX)
DROP TABLE TEMPIMGCOUNTERSERVER3 CREATE TABLE TEMPIMGCOUNTERSERVER3 (DBname NVARCHAR(MAX), Images INT, FileSize INT, DBCreation DATETIME)
DECLARE DBNAME CURSOR FAST_FORWARD FOR select name from sys.databases where [NAME] LIKE 'Z%' AND create_date between '2011-02-06' and '2011-02-12' ORDER BY [create_date]
OPEN DBNAME
FETCH NEXT FROM DBNAME INTO #DBname WHILE (##FETCH_STATUS=0) BEGIN
Set #varSQL='INSERT INTO TEMPIMGCOUNTERSERVER3 (DBNAME, IMAGES, FileSize, DBCreation)
SELECT ''['+#DBNAME+']'', SUM(PGCOUNT), sum(filesize/1024/1024), sys.databases.CREATE_DATE
FROM SYS.DATABASES, ['+#DBNAME+'].dbo.tbldoc WHERE created between ''2011-02-06'' and ''2011-02-12''
and sys.databases.name='''+#DBNAME+'''
GROUP BY sys.databases.NAME, sys.databases.CREATE_DATE'
EXEC SP_EXECUTESQL #varSQL
FETCH NEXT FROM DBNAME
INTO #DBNAME
END
CLOSE DBNAME
DEALLOCATE DBNAME
INSERT TEMPIMGCOUNTERSERVER3 (DBNAME, IMAGES, FILESIZE)
SELECT ##SERVERNAME + ' ' +'TOTAL IMAGES AND FILE SIZE', SUM(IMAGES), SUM(FILESIZE) FROM TEMPIMGCOUNTERSERVER3
SELECT DBNAME, IMAGES, FILESIZE, convert(VARCHAR(10),
DBCREATION, 101) AS DBCREATION FROM TEMPIMGCOUNTERSERVER3
GROUP BY DBNAME, IMAGES, FILESIZE, convert(VARCHAR(10), DBCREATION, 101)
HAVING SUM(IMAGES) is not null
ORDER BY DBCREATION
Should I add another cursor? Something with this script:
select srvname from master..sysservers where srvname like 'sql%'
i would just nest your cursor in another cursor that runs on the linked servers. filter the list of servers from master..sysservers on the srvproduct field where it equals "SQL Server". if there's anything is that list you don't want put it in a not in clause. then, modify your inner cursor to add the server name to the query, giving you a four part table name.

Complex SQL Server Query between more than one database

I have Scenario and i want to convert it to a query.
My Scenario:
I have lot of dbs with same structure "Clientxxxx" i want to make loop for all these dbs to get data from one table exists in all these dbs called "EventLog" these event log recorded in this table for clients exists in another db called "Portal"
I want to get every client in "portal" db with his eventlogs from "EventLog" Table in the other dbs "Clientxxxx"
db:Client1 db:Client2 db:Client3
table:"EventLog" table:"EventLog" table:"EventLog"
each client has his db and his data in Portal db
db:portal
table:Clients
query:
Client1 data
his event logs
client2 data
his event logs
and so on
........
........
........
........
I need some help please.
thanks
I would do the following:
Create a view in your Portal db that has this in it:
vw_AggregateClients:
SELECT 'Client1' as clientName, * from Client1.dbo.EventLog
UNION
SELECT 'Client2', * from Client2.dbo.EventLog
UNION
SELECT 'Client3', * from Client3.dbo.EventLog
And then query it like this:
SELECT * from vw_AggregateClients as ac
INNER JOIN Clients as c
ON ac.clientName = c.ClientName
If you the number of client dbs will be large or you don't know how many there will be then you will probably have to use dynamic sql. If you go that route give the article i linked to a good read.
Typically, I use the dynamic SQL approach, with a cursor to loop through all the databases, insert into a consolidated table variable, and then select out of the variable:
declare #return (dbname varchar(100),
<<dataset spec for EventLog>>)
declare #db varchar(100)
declare #sql varchar(max)
declare recscan cursor for
select name from sys.databases
where database_id not in (1,2,3,4) --excludes system databases
open recscan
fetch next from recscan into #db
while ##fetch_status = 0
begin
set #sql = 'select '''+#db+''',* from '+#db+'..eventlog'
insert into #return
exec(#sql)
fetch next from recscan into #db
end
close recscan
deallocate recscan
select * from #return
Note that I create an extra field and put the database name as an explicit string value in the dynamic query so that I can break out where the data came from. I also use 3 part naming for the table object, but you could insert a dynamically constructed USE statement into your SQL variable.

Change the roles of multiple security accounts

I have many security accounts on the sql database and i want to remove/add roles to them based on a simple string comparison.
Basically i want to list all
accounts
Filter out accounts that DON'T start
with "MyDomain\"
Remove role A.
Add role B.
What i found out by now is that i use sp_helprolemember to list all the accounts and sp_addrolemember and sp_droprolemember. My problem is that i dont know how to "get" the output from sp_helprolemember and work with it.
My first attemt at a soltuion based of feedback.
DROP TABLE [dbo].[XTemp]
create table XTemp(DbRole sysname,MemberName sysname,MemberSID varbinary(85) )
insert XTemp exec sp_helprolemember
select * from XTemp
I made a permanent table to make it simpler to test and debug.
SELECT [DbRole]
,[MemberName]
,[MemberSID]
FROM [ARTICLE].[dbo].[XTemp]
WHERE MemberName like Domain\%'
exec sp_addrolemember 'OldRole MemberName
Assuming that you're using SQL 2005 or later, and executing sp_helprolemember without parameters, this is the query that sp_helprolemember runs (extracted using sp_helptext):
select DbRole = g.name, MemberName = u.name, MemberSID = u.sid
from sys.database_principals u, sys.database_principals g, sys.database_role_members m
where g.principal_id = m.role_principal_id
and u.principal_id = m.member_principal_id
order by 1, 2
This should enable you to collect the information you need into a temp table.
If you'd rather stick to documented behaviour, you can store the output of the SP into a temp table:
create table #t
(DbRole sysname,
MemberName sysname,
MemberSID varbinary(85)
)
insert #t
exec sp_helprolemember
select * from #t
EDIT
There are two ways to use this data to amend your system. One is using a cursor:
DECLARE #memberName sysname
DECLARE curMember CURSOR fast_forward FOR
SELECT MemberName
FROM #t
WHERE MemberName LIKE 'Domain\%'
OPEN curMember
FETCH NEXT FROM curMember INTO #memberName
WHILE ##FETCH_STATUS = 0
BEGIN
EXEC sp_addrolemember 'OldRole', #memberName
FETCH NEXT FROM curMember INTO #memberName
END
CLOSE curMember
DEALLOCATE curMember
The other is using dynamic SQL:
DECLARE #sql NVARCHAR(MAX),
SELECT #sql = 'EXEC sp_addrolemember ''OldRole'', ''' + MemberName + ''''
FROM #t
WHERE MemberName LIKE 'Domain\%'
EXEC sp_executesql #stmt = #sql
As you can see the dynamic SQL version is more compact but requires more effort to maintain.
Remember that after you execute either statement, the data you extracted from sp_helprolemember into a table is no longer up to date, and should probably be refreshed.
You can use Excel to generate SQL queries - I know it sounds lame but it is very simple and powerful. It is especially well-suited for tasks that have to be performed once or only from time to time.
Copy results from Management Studio to Excel.
Remove rows and columns than you don't need.
Use a formula in column B (e.g. ="EXEC sp_dropsrvrolemember '"&A1&"', 'sysadmin'") to generate queries for values stored in column A (the formula can of course reference more than one column with input data and generate really complicated queries).
Copy generated queries from Excel to Management Studio.

Resources