This is not dynamic SQL, but relies on something like deferred name resolution.
EXECUTE, see @module_name_var
parameter
DECLARE @sql varchar(300)
SELECT
[name] + '..usp_ComputeDailySales' AS Cmd
INTO #List
FROM
sys.databases d WHERE d.[name] LIKE 'branch%'
OR --Thanks Mitch
d.[name] = 'Headquarters'
WHILE EXISTS (SELECT * FROM #List)
BEGIN
SELECT TOP 1 @SQL = Cmd FROM #List
EXEC @SQL
DELETE #List WHERE Cmd = @SQL
END
Edit, after KM's comment
Yes, there is a difference but I'll clarify:
EXEC (@SQL) means @SQL could be 'SELECT * FROM foo
' OR 'DELETE User WHERE 1=1'
;.)
EXEC @SQL means @SQL is an object name. So I should have used @Obj
So, you could do this:
DECLARE @Obj varchar(200)
SELECT @Obj = 'dbo.uspCustomHook'
IF OBJECT_ID(@Obj) IS NOT NULL
EXEC @Obj @p1 = 1, @p2 = 'bob', ...
It avoids deferred name resolution errors. When the batch/proc is compiled, there is no error if dbo.uspCustomHook does not exist.
I've not used the technique since SQL 2000, and I don't know if SQL 2005 (statement level recompilation) is clever enough to work out if @Obj should be be run because it does not exist so it does not try to compile the EXEC statement...
It's also useful for cross database, same instance queries. You can configure prd-prod, dev-dev etc without relying on linked servers or hard coded databases names.