【问题标题】:SQL Server 2012 dynamic SQL - stored procedure - getting syntax errorSQL Server 2012 动态 SQL - 存储过程 - 出现语法错误
【发布时间】:2016-12-29 17:42:35
【问题描述】:

我正在编写脚本以在当前模式表示法未知的数据库中生成存储过程(想想共享主机)。

我决定在存储过程中使用动态 SQL,以便 Web 应用程序可以根据用户定义的设置将数据库架构传递给 SQL Server,以便它正确触发。

当我开始编写存储过程时,我注意到动态 SQL 引发了一个我通常不会遇到的整个 SQL 注入问题,因此我重新编写了该过程来解决这个问题。然而,尽管 SQL 允许我运行脚本来生成存储过程,但每次我尝试运行测试存储过程时,都会出现语法错误

关键字“WHERE”附近的语法不正确

我相信这与架构的参数有关,但我不知道为什么这不起作用?我正在为架构输入值 dbo

/* 
    Name            : usp_GetTestTicker

    Description     : returns test ticker

*/

if not exists (select * from dbo.sysobjects 
               where id = object_id(N'usp_GetTestTicker') 
   and OBJECTPROPERTY(id, N'IsProcedure') = 1)
BEGIN
    DECLARE @sql as nvarchar(150)
    SET @sql = 'CREATE procedure usp_GetTestTicker AS'

    EXEC(@sql)
END
GO

ALTER PROCEDURE usp_GetTestTicker
    @schema VARCHAR(25),
    @TickerItemId INT
AS
    SET NOCOUNT ON
BEGIN
    DECLARE @sql_cmd NVARCHAR(MAX)
    DECLARE @sql_params NVARCHAR(MAX)

    SET @sql_cmd = N'SELECT * FROM @schema.TickerItem WHERE TickerItemId = @TickerItemId'

    SET @sql_params = N'@schema VARCHAR(25), @TickerItemId INT'

    EXEC sp_executesql @sql_cmd, @sql_params, @schema, @TickerItemId
END
GO

【问题讨论】:

  • 如果你把你的EXEC命令改成这个EXEC sp_executesql @stmt = @sql_cmd, @params = @sql_params, @schema = @schema, @TickerItemId = @TickerItemId;
  • 您不能将架构作为参数传递。您必须构建字符串。
  • 杰里米有原因。考虑一下如果您直接编写像SELECT * From @schema.MyTable 这样的SELECT 语句会发生什么。它不起作用,因为您不能将变量作为架构标识符。

标签: sql-server stored-procedures sql-server-2012


【解决方案1】:

为防止 SQL 注入,您需要根据 sys.schemas 表验证架构,例如

ALTER PROCEDURE usp_GetTestTicker
    @schema NVARCHAR(25),
    @TickerItemId INT
AS
BEGIN
    SET NOCOUNT ON

    IF NOT EXISTS (SELECT * FROM sys.schemas WHERE name = @schema)
    BEGIN
        -- throw an error here. Your web code will have to handle the error and report an invalid schema

    END
    ELSE
    BEGIN
        DECLARE @sql_cmd NVARCHAR(MAX), @sql_params NVARCHAR(MAX)

        SET @sql_cmd = N'SELECT * FROM ' + @schema + '.TickerItem WHERE TickerItemId = @TickerItemId'

        SET @sql_params = N'@TickerItemId INT'

        EXEC sp_executesql @sql_cmd, @sql_params, @TickerItemId
    END
END

【讨论】:

    猜你喜欢
    • 2019-10-17
    • 2013-11-11
    • 1970-01-01
    • 2018-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-10
    • 1970-01-01
    相关资源
    最近更新 更多