SQL Server: how to get a database name as a parameter in a stored procedure

后端 未结 4 1407
一向
一向 2020-12-05 15:16

I\'m trying to create a simple stored procedure which queries a sys.tables table.

CREATE PROCEDURE dbo.test
    @dbname NVARCHAR(255),
    @col NVARCHAR(255         


        
4条回答
  •  时光说笑
    2020-12-05 15:32

    If you use EXEC @Var (without brackets - i.e. not EXEC (@Var)) SQL Server looks for a stored procedure matching the name passed in @Var. You can use three part naming for this.

    If sys.sp_executesql is called with a three part name the context is set to the database in which it is called.

    So you can do this with zero SQL injection risk as below.

    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 
    

    Even if the above wasn't possible I'd still argue that it is perfectly possible to use dynamic SQL for this in a safe manner as here.

    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
    

提交回复
热议问题