如何在SQL Server存储过程中传递模式名称作为参数?

时间:2018-05-06 11:41:48

标签: sql-server stored-procedures

正如我到目前为止所见,人们建议使用动态SQL。

例如:

How to pass schema as parameter to a stored procedure in sql server?

How to pass schema name as parameter in stored procedure

但是,动态SQL存在SQL注入的风险。因此,我想知道是否还有其他安全的选择?

基本上,我创建的这个存储过程将在运行时调用。将传递2个可能的模式。表名也将被传入。

如下所示:(它不起作用)

CREATE PROCEDURE [EFM].[usp_readApexTable] 
    @SCHEMANAME VARCHAR(20) = NULL,
    @TABLENAME VARCHAR(100) = NULL
AS
BEGIN 
    SET NOCOUNT ON;

    SELECT *  
    FROM [@SCHEMANAME].[@TABLENAME];
END
GO

这只是READ操作的一个示例。我的计划是为CRUD创建,这需要4个不同的存储过程。

2 个答案:

答案 0 :(得分:1)

您可以使用QUOTENAME来避免任何SQL注入,并构建动态查询,如下所示:

CREATE PROCEDURE [EFM].[usp_readApexTable] 
    @SCHEMANAME VARCHAR(20) = NULL,
    @TABLENAME VARCHAR(100) = NULL
AS
BEGIN 
    SET NOCOUNT ON;

    DECLARE @SQL VARCHAR(MAX)=N'SELECT *  FROM '
          + QUOTENAME(@SCHEMANAME) + '.' + QUOTENAME(@TABLENAME)
    EXEC (@SQL)
END
GO

注意:如果您有任何计划为WHERE子句添加参数,那么QUOTENAME也无济于事,我建议使用{{ 1}}通过传递sp_executesql子句中使用的适当参数。

您仍然需要将WHERE用于架构和表名称QUOTENAME,除了它只是文字,您不能使用表和架构的变量名称。

例如。

SQL

您可以找到更多详情here

答案 1 :(得分:0)

您需要使用dynamic sql来执行此操作

CREATE PROCEDURE [EFM].[usp_readApexTable] 
@SCHEMANAME VARCHAR(20) = NULL,
@TABLENAME VARCHAR(100) = NULL
AS
BEGIN 
    SET NOCOUNT ON;
    DECLARE @sqlCommand nvarchar(MAX)
    SET @sqlCommand='SELECT *  FROM ['+@SCHEMANAME+'].['+@TABLENAME+'];'
    --Create Your Temp Table where you can set the records after executing the dynamic query
    CREATE TABLE #tmpTbl(
        Column1 [datatype]
        Column2 [datatype]
        .
        .
        ColumnN
    )
    INSERT INTO #tmpTbl EXEC sp_executesql  @sqlCommand --Copy data to #tmpTbl table
    SELECT * FROM #tmpTbl
    DROP TABLE #tmpTbl
END
GO