Problema:
- você quer/precisa usar SQL dinâmico para criar procedimento/função/view/trigger em outros bancos de dados que não o atual
- você não pode especificar o nome do banco de dados na instrução,
CREATE VIEW tempdb.dbo.v_test AS SELECT 1
; falhará com o Erro 166: 'CREATE/ALTER VIEW' não permite especificar o nome do banco de dados como um prefixo para o nome do objeto. - a instrução
CREATE
(ouALTER
) precisa ser a primeira no lote, caso contrário, você obterá o erro 111: 'CREATE ...' deve ser a primeira instrução em um lote de consulta. . Por esta razão, você não pode simplesmente escreverUSE <database>
antes deCREATE
:
DECLARE @create_sql NVARCHAR(max);
SET @create_sql = CONCAT('USE tempdb', CHAR(13) + CHAR(10),
'CREATE VIEW dbo.v_test AS SELECT 1 AS n;'
);
EXEC (@create_sql) -- fails
-- or
EXEC sys.sp_executesql @create_sql -- fails too
- você não pode usar
GO
dentro de uma instruçãoEXEC()
orEXEC sys.sp_executesql
, porque não está no padrão SQL (apenas uma palavra fictícia configurável usada dentro do SSMS e várias outras ferramentas SQL), então você não pode simplesmente adicioná-lo entre o USE e o comando CREATE em o script acima como você faria no SSMS ao criar um script de implantação "normal" - o procedimento interno
sys.sp_executesql
existe em cada banco de dados e executa o comando fornecido em seu próprio banco de dados, mas pode haver muitos (por exemplo, centenas) bancos de dados, de modo que você não pode realmente usar váriasIF
instruções para "codificar" onde deseja executá-lo