Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

SQL Server :comment obtenir un nom de base de données en tant que paramètre dans une procédure stockée

Si vous utilisez EXEC @Var (sans crochets - c'est-à-dire pas EXEC (@Var) ) SQL Server recherche une procédure stockée correspondant au nom passé dans @Var . Vous pouvez utiliser un nom en trois parties pour cela.

Si sys.sp_executesql est appelé avec un nom en trois parties, le contexte est défini sur la base de données dans laquelle il est appelé.

Vous pouvez donc le faire avec zéro Risque d'injection SQL comme ci-dessous.

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 

Même si ce qui précède n'était pas possible, je dirais toujours qu'il est parfaitement possible d'utiliser SQL dynamique pour cela de manière sûre comme ici.

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