I really don't advice to create a stored procedure in any of the system databases. In my opinion system databases should be left as-is and they should only be used by the SQL Server (=system).
Having that said, you can create the procedure in any database you want and then call it from other databases using 3-part notation.
For example create this procedure into some database
create procedure proc1 as
begin
print('I am here');
end;
and from another database call it using the following command. Just change the name of the database
execute databse_name..proc1
Of course the procedure operates in the database it's located so if you need data from the calling database, you need either to provide it to the procedure using sufficient parameters or code the 'connection' to another database inside the procedure.
Addition:
If you want to create the procedure in multiple databases (except system databases) you can use a cursor to query the databases, switch to proper database and then create the procedure in it.
Since the SQL statement containing the procedure creation must be the first statement inside a batch, the creation must be done 'dynamically' after the USE statement.
Consider the following example:
DECLARE @databasename nvarchar(200)
DECLARE @sql nvarchar(max)
DECLARE curDatabases CURSOR FOR
SELECT name
FROM sys.databases
WHERE owner_sid <> 1;
OPEN curDatabases
FETCH NEXT FROM curDatabases INTO @databasename
WHILE @@FETCH_STATUS = 0
BEGIN
PRINT @databasename
SET @sql = 'use ' + @databasename + '
exec (''create procedure dbo.proc1 as
begin
print(''''I am here'''');
end'')'
EXEC sp_executesql @stmt = @sql
FETCH NEXT FROM curDatabases INTO @databasename
END
CLOSE curDatabases;
DEALLOCATE curDatabases;
Another way would be to use
sp_msforeachdb[
^] and in the SQL statement include a condition not to run the create procedure if the database is a system database.