简体   繁体   中英

Loop Through All SSMS Databases without Recreating Stored Procedure

Background Information:

In Python, I might write something like this if I want to apply the same logic to different values in a list.

database_list = ["db_1", "db_2", "db_3"]

for x in range(0,len(database_list),1):
     
     print("the database name is " + database_list[x])

What I am trying to do:

What I am trying to do in SSMS, is pull a list of DB objects for each database. I created a stored procedure to pull exactly what I want, but I have to run it against each database, so 10 databases mean running it 10 times.

My goal is to do this with a T-SQL query instead of Python.

I tried doing something like this:

 exec sp_MSforeachdb 'USE ?; EXEC [dbo].[my_stored_procedure]';

The problem with this is, [dbo].[my_stored_procedure] has to exist in every database I want to do this in.

How can I create the stored procedure in 1 database, but execute it for all databases or a list of databases that I choose?

I know what you are trying to do and if it's what I think (you seem reluctant to actually say:) you can do the following:

In the master database, create your procedure. Normally you wouldn't do this, but in this case you must prefix it sp_

use master
go
create procedure sp_testproc as

select top 10 * from sys.tables
go

Now if you run this, it will return tables from the master database.

If you switch context to another database and exec master.dbo.sp_testproc , it will still return tables from the master database.

In master , run

sys.sp_MS_marksystemobject sp_testproc

Now switch context to a different database and exec master.dbo.sp_testproc

It will return tables from the database you are using.

Try creating your sproc in master and naming it with an sp_ prefix:

USE master
GO

CREATE PROCEDURE sp_sproc_name
AS
 BEGIN
 ...
 END
GO

-- You *may* need to mark it as a system object
EXEC sys.sp_MS_marksystemobject sp_sprocname

See: https://nickstips.wordpress.com/2010/10/18/sql-making-a-stored-procedure-available-to-all-databases/

It should then be available in all dbs

Create the stored procedure in the Master database with the sp_ prefix, and use dynamic SQL in the stored procedure so it resolves object names relative to the current database, rather than the database which contains the stored procedure.

EG

use master 
go
CREATE OR ALTER  PROCEDURE [dbo].[sp_getobjects]
AS
exec ('
     select *
     from [sys].[objects]
     where is_ms_shipped = 0
     order by type, name
     ')
go

use AdventureWorks2017
exec sp_getobjects 

@LunchBox - it's your single stored procedure (that you create in one database) that is actually going to need to contain the "exec sp_MSforeach...." command, and instead of the command to be executed being "EXEC ", it will need to be the actual SQL that you were going to put into the stored proc.

Eg. (inside your single stored procedure)

EXEC sp_MSforeachdb 'USE ?; SELECT * FROM <table>; UPDATE <another table> SET ...';

Think of the stored procedure (that you put into one database) as being no different than your Python code file - if you had actually wanted to achieve the same thing in Python, you would have either needed to create the stored proc in each database, or build the SQL statement string in Python and execute it against each database.

I understand what you thought you might be able to achieve with SQL, but stored procedures really don't work the way you were expecting. Even when you're in the context of a different database, but you run EXEC <different_db>.stored_proc, that stored proc ends up running in the context of the database in which it exists (not your context database).

Now, the only one issue you may come up against is that the standard sp_MSforeachdb stored proc has a limit of 2000 characters for the command that can be executed (although, it does have multiple "command" parameters, this may not be practical if you were planning on running a very large code block, perhaps with variables that carry all the way through). If this is something that might impact what you're intending to do, you could do a search online for "sp_MSforeachdb alternatives" - there seem to be a handful that people have created where the command parameter can contain a larger string.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM