Bes*_*ska 14 sql sql-server parameterized
我只是遇到了一个奇怪的事情...我们网站上有一些代码正在处理一个巨大的SQL语句,通过执行一些搜索来修改代码并根据某些用户值进行替换,然后将其传递给SQL Server一个问题.
我认为这将作为存储过程的参数化查询更清晰,用户值作为参数,但当我仔细观察时,我明白为什么他们可能会这样做...他们从中选择的表是可变地依赖于那些用户值.
例如,在一种情况下,如果值为("FOO","BAR"),则查询最终会变为"SELECT*FROM FOO_BAR"
有一个简单明了的方法吗?我正在尝试的一切似乎都不优雅.
编辑:当然,我可以动态生成存储过程中的sql,并执行(bleh),但那时我想知道我是否获得了任何东西.
EDIT2:以一种聪明的方式重构表名,比如将它们全部放在一个表中,不同的名称作为新列将是一个很好的方法来解决所有这些,这是几个人直接指出或暗示的.可悲的是,在这种情况下,它不是一种选择.
RBa*_*ung 41
首先,你应该永远不会做这样的客户端应用程序SQL命令组成,这是 SQL注入是什么.(对于没有自己的私有的管理工具,它可以,但不适用于共享使用应用程序).
其次,是的,对存储过程的参数化调用既更清晰又更安全.
但是,由于您需要使用动态SQL来执行此操作,因此您仍然不希望在执行的查询的文本中包含传递的字符串.相反,您希望使用传递的字符串来查找应该允许用户查询的实际表的名称.
这是一个简单的天真例子:
CREATE PROC spCountAnyTableRows( @PassedTableName as NVarchar(255) ) AS
-- Counts the number of rows from any non-system Table, *SAFELY*
BEGIN
DECLARE @ActualTableName AS NVarchar(255)
SELECT @ActualTableName = QUOTENAME( TABLE_NAME )
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = @PassedTableName
DECLARE @sql AS NVARCHAR(MAX)
SELECT @sql = 'SELECT COUNT(*) FROM ' + @ActualTableName + ';'
EXEC(@SQL)
END
Run Code Online (Sandbox Code Playgroud)
有些人公平地问为什么这样更安全.希望小Bobby Tables可以让这个更清晰:

更多问题的答案:
单独的QUOTENAME不保证是安全的.MS鼓励我们使用它,但是它们没有保证它不会被黑客搞砸.仅供参考,真正的安全就是保证.使用QUOTENAME查找表格是另一个故事,它是牢不可破的.
对于此示例,QUOTENAME不是严格必需的,仅Info_SCHEMA上的Lookup转换通常就足够了.QUOTENAME就在这里,因为它包含一个完整而正确的解决方案,是安全的好形式.这里的QUOTENAME实际上是针对潜在注射的独特但类似的潜在问题进行保护.
(联合国)幸运的是没有办法做到这一点 - 除了动态sql生成之外,你不能将表名作为参数传递给存储代码.在决定在哪里生成sql代码时,我更喜欢应用程序代码而不是存储代码.应用程序代码通常更快,更易于维护.
如果您不喜欢您正在使用的解决方案,我建议进行更深入的重新设计(即更改架构/应用程序逻辑,以便您不再需要将表名作为参数传递到任何地方).