sql >> Base de Datos >  >> RDS >> Sqlserver

SQL Server:cómo obtener un nombre de base de datos como parámetro en un procedimiento almacenado

Si usa EXEC @Var (sin corchetes, es decir, no EXEC (@Var) ) SQL Server busca un procedimiento almacenado que coincida con el nombre pasado en @Var . Puede usar nombres de tres partes para esto.

Si sys.sp_executesql se llama con un nombre de tres partes, el contexto se establece en la base de datos en la que se llama.

Así que puedes hacer esto con cero Riesgo de inyección de SQL como se muestra a continuación.

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 

Incluso si lo anterior no fuera posible, aún diría que es perfectamente posible usar SQL dinámico para esto de una manera segura como aquí.

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