Here's some code that I threw together a few weeks ago to build up an ordering of objects for applying to a database based on their dependencies. The first stored procedure just refreshes the metadata so that you can be sure that sql_dependencies will be accurate.
This is not fully tested code. Also, I would probably use INFORMATION_SCHEMA instead of directly going against the system tables if I did this again.
The run_level tells you when each object can be created. So, all objects with a run_level of 0 can be run first (order doesn't matter within a run_level), then all of the objects at run_level 1, etc.
IF (OBJECT_ID('dbo.RefreshSqlModuleForAllObjs') IS NOT NULL)
DROP PROCEDURE dbo.RefreshSqlModuleForAllObjs
GO
CREATE PROCEDURE dbo.RefreshSqlModuleForAllObjs
AS
BEGIN
DECLARE
@object_id INT,
@schema_name SYSNAME,
@object_name SYSNAME,
@full_name NVARCHAR(776)
DECLARE cur_objects CURSOR FOR
SELECT
object_id,
OBJECT_SCHEMA_NAME(object_id),
OBJECT_NAME(object_id)
FROM
sys.objects
WHERE
type IN ('P', 'TR', 'V', 'FN', 'TF', 'IF')
OPEN cur_objects
FETCH NEXT FROM cur_objects INTO @object_id, @schema_name, @object_name
WHILE (@@FETCH_STATUS = 0)
BEGIN
SET @full_name = QUOTENAME(@schema_name) + '.' + QUOTENAME(@object_name)
EXEC sp_refreshsqlmodule @full_name
FETCH NEXT FROM cur_objects INTO @object_id, @schema_name, @object_name
END
CLOSE cur_objects
DEALLOCATE cur_objects
END
GO
IF (OBJECT_ID('dbo.GenObjApplyOrder') IS NOT NULL)
DROP PROCEDURE dbo.GenObjApplyOrder
GO
CREATE PROCEDURE dbo.GenObjApplyOrder
AS
BEGIN
DECLARE
@i INT,
@count INT
DECLARE
@run_order TABLE (object_id INT, run_level SMALLINT)
SET @i = 0
SET @count = 1
EXEC dbo.RefreshSqlModuleForAllObjs
WHILE (@count > 0)
BEGIN
INSERT INTO @run_order (object_id, run_level)
SELECT
object_id,
@i
FROM
sys.objects o
WHERE
NOT EXISTS (SELECT * FROM sys.sql_dependencies d WHERE d.object_id = o.object_id AND d.referenced_major_id NOT IN (SELECT object_id FROM @run_order)) AND
NOT EXISTS (SELECT * FROM @run_order ro WHERE ro.object_id = o.object_id) AND
o.type IN ('U', 'P', 'V', 'TR', 'TF', 'IF', 'FN')
SELECT @count = @@ROWCOUNT
SELECT @i = @i + 1
END
INSERT INTO @run_order (object_id, run_level)
SELECT
o.object_id,
-999
FROM
sys.objects o
WHERE
NOT EXISTS (SELECT * FROM @run_order ro WHERE ro.object_id = o.object_id) AND
o.type IN ('U', 'P', 'V', 'TR', 'TF', 'IF', 'FN')
SELECT OBJECT_NAME(object_id), run_level FROM @run_order ORDER BY ABS(run_level)
END
GO