SQL: Create missing stored procedures using a linked server

SQL: Create missing stored procedures using a linked server

I answered an interesting question the other day on Stack Overflow. What the person who posted was after was a way to create all missing stored procedures on one database that were present on another database on another server.

Here’s an example of how to do that:

USE tempdb;
GO

-- Copying from [GREGT580] to local server

SET NOCOUNT ON;

DECLARE @MissingProcedures TABLE
(
    MissingProcedureID int IDENTITY(1,1) PRIMARY KEY,
    SchemaName sysname,
    ProcedureName sysname,
    ProcedureDefinition nvarchar(max)
);

INSERT @MissingProcedures 
(
    SchemaName, ProcedureName, ProcedureDefinition
)

SELECT s.[name], p.[name], sm.definition
FROM [GREGT580].AdventureWorks.sys.procedures AS p
INNER JOIN [GREGT580].AdventureWorks.sys.schemas AS s
ON p.schema_id = s.schema_id
INNER JOIN [GREGT580].AdventureWorks.sys.sql_modules AS sm
ON sm.object_id = p.object_id 
WHERE NOT EXISTS (SELECT 1 
                  FROM sys.procedures AS pl
                  INNER JOIN sys.schemas AS sl
                  ON sl.schema_id = pl.schema_id
                  AND sl.[name] = s.[name] COLLATE DATABASE_DEFAULT 
                  AND pl.[name] = p.[name] COLLATE DATABASE_DEFAULT);

DECLARE @SchemaName sysname;
DECLARE @ProcedureName sysname;
DECLARE @ProcedureDefinition nvarchar(max);
DECLARE @Counter int = 1;

WHILE @Counter < (SELECT MAX(MissingProcedureID) FROM @MissingProcedures AS mp)
BEGIN
    SELECT @SchemaName = mp.SchemaName,
           @ProcedureName = mp.ProcedureName,
           @ProcedureDefinition = mp.ProcedureDefinition
    FROM @MissingProcedures AS mp
    WHERE mp.MissingProcedureID = @Counter;

    EXEC SDU_Tools.ExecuteOrPrint @ProcedureDefinition; -- Change to EXEC (@ProcedureDefinition) to create

    SET @Counter += 1;
END;

I start by querying sys.procedures, sys.schemas, and sys.sql_modules on the remote database to find the ones that aren’t present on the local system. I needed sys.sql_modules to get the definition of the procedure.

This solution uses a linked server as requested by the person posting. Just change the [GREGT580] to whatever your server name is. If you are on Azure SQL DB, a similar outcome could be created using external tables. I’ve provided details on how to do that here.

Then I just looped around creating the procedures.

Note that I used SDU_Tools.ExecuteOrPrint to print out the definitions. You could use just PRINT but it barfs on long strings. (ExecuteOrPrint is just one of the useful tools you’ll find in SDU_Tools here).

To actually create, them, change the line that prints them out to just say EXEC(@ProcedureDefinition) instead.

Hope that helps someone else apart from the person who posted.

2019-10-03