Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

SQL Server:como obter um nome de banco de dados como parâmetro em um procedimento armazenado


Se você usar EXEC @Var (sem colchetes - ou seja, não EXEC (@Var) ) SQL Server procura um procedimento armazenado que corresponda ao nome passado em @Var . Você pode usar três nomes de partes para isso.

Se sys.sp_executesql é chamado com um nome de três partes, o contexto é definido para o banco de dados no qual é chamado.

Então você pode fazer isso com zero Risco de injeção de SQL conforme abaixo.
CREATE PROCEDURE dbo.test @dbname SYSNAME,
                          @col    SYSNAME
AS
    SET NOCOUNT, XACT_ABORT ON;

    DECLARE @db_sp_executesql NVARCHAR(300) = QUOTENAME(@dbname) + '.sys.sp_executesql'

    EXEC @db_sp_executesql N'
                            SELECT TOP 100 *
                            FROM sys.columns 
                            WHERE name = @col',
                           N'@col sysname',
                           @col = @col 

Mesmo que o acima não fosse possível, eu ainda argumentaria que é perfeitamente possível usar SQL dinâmico para isso de maneira segura como aqui.
CREATE PROCEDURE dbo.test
    @dbname SYSNAME, /*Use Correct Datatypes for identifiers*/
    @col SYSNAME
AS
    SET NOCOUNT ON
    SET XACT_ABORT ON

    IF DB_ID(@dbname) IS NULL  /*Validate the database name exists*/
       BEGIN
       RAISERROR('Invalid Database Name passed',16,1)
       RETURN
       END

DECLARE @dynsql nvarchar(max)  

 /*Use QUOTENAME to correctly escape any special characters*/
SET @dynsql = N'USE '+ QUOTENAME(@dbname) + N'

                         SELECT TOP 100 *
                         FROM sys.tables 
                         WHERE name = @col'

 /*Use sp_executesql to leave the WHERE clause parameterised*/
EXEC sp_executesql @dynsql, N'@col sysname', @col = @col