Sql server 如何从MSSQL表中动态选择包含多个列的列表,而无需关联字符串?

Sql server 如何从MSSQL表中动态选择包含多个列的列表,而无需关联字符串?,sql-server,stored-procedures,sql-injection,dynamic-sql,Sql Server,Stored Procedures,Sql Injection,Dynamic Sql,我进行了一些搜索,但示例仅使用一个参数/列名,或者只是将字符串添加到一起 我有一张描述项目的桌子。有一些不可更改的列,如id、projectnumber等,还有一些“动态”列,用户/管理员可以通过应用程序中的界面添加这些列 之后,用户应该看到所有“动态”列的列表,并可以决定通过复选框显示它们 所以我现在需要的是这样一个查询 SELECT id, projectname, <LIST_OF_COLUM_NAMES> FROM project 然后显示它 我发现了几种解决方案,其中qu

我进行了一些搜索,但示例仅使用一个参数/列名,或者只是将字符串添加到一起

我有一张描述项目的桌子。有一些不可更改的列,如id、projectnumber等,还有一些“动态”列,用户/管理员可以通过应用程序中的界面添加这些列

之后,用户应该看到所有“动态”列的列表,并可以决定通过复选框显示它们

所以我现在需要的是这样一个查询

SELECT id, projectname, <LIST_OF_COLUM_NAMES> FROM project
然后显示它

我发现了几种解决方案,其中querystring只是在程序端或存储过程内部连接起来

我找到了几个存储过程的示例,这些存储过程获取一个列名称并从中创建查询语句

我找到了这篇文章 我必须承认,我不确定这是否适用于我的问题


有没有一种方法可以在不通过SQL注入造成安全风险的情况下实现这一点?

有几种简单的方法可以在不存在SQL注入风险的情况下解决这一问题

  • 写入
    SELECT*FROM
    查询并限制在应用程序上看到的列数,这样所有列都将返回,由应用程序决定显示哪些列
  • 不需要将列字符串传递给存储过程,而是让用户传递列索引列表,并且基于整数值,您可以使用动态sql,只生成包含用户想要返回的列的
    SELECT
    语句
  • 如果您只想向用户显示表中存在的列列表,您应该从中选择列列表,这样您就可以确定数据库中存在哪个列
  • 在SQL Server中,您可以指定参数datatype,其中的datatype是所有系统对象名称的存储方式,这可以为您提供额外的数据验证

无论您决定做什么,都不应该在应用程序或存储过程中连接字符串。

我尝试使用信息架构视图,但无法避免将字符串全部连接在一起。这就是我想到的:

当用户想要添加列时,他可以输入显示名称,并从一系列数据类型中进行选择。然后我创建一个内部唯一的内部列名(如DATETIME_67)

然后,我创建如下查询:

String querystring = "ALTER TABLE projects ADD " + internalname + " " + typestring;
请注意,字符串internalname和typestring都是在我的代码中生成的,没有来自用户的输入(因此,我想这应该可以防止注入)

然后将内部名称和显示名称写入查找表:

String querystring = "INSERT INTO lookup (tablename, displayname) " +
"VALUES (@tablename, @displayname)";
using (SQLCommand command = new SQLCommand(querystring, con)) { //con is a SQLConnection object
  command.Parameters.AddWithValue("@tablename", internalname);
  command.Parameters.AddWithValue("@displayname", displayname);
}
这里插入了来自用户的实际输入,但它是参数化的,因此也应该是安全的

在检索要显示的列时,我也使用(希望是)安全的内部名称:

 List<String> selectedColumns; //the list of internal col names   
 String query = "SELECT id, projectnumber, projectname {0} FROM projects"; //projectnumer and name a mandatory fields 
                if (selectedColumns.Count > 0)
                {
                    fieldstring  = String.Join(",", selectedColumns);
                    fieldstring = ", " + fieldstring;
                }
                query = String.Format(query, fieldstring);
列出所选列//内部列名称的列表
String query=“从项目中选择id、项目编号、项目名称{0}”//projectnumer和name是必填字段
如果(selectedColumns.Count>0)
{
fieldstring=String.Join(“,”,selectedColumns);
fieldstring=“,”+fieldstring;
}
query=String.Format(查询,字段字符串);

请对此发表评论。它正按照我的需要工作。用户可以向datatabe添加(和删除)自定义字段,并为其提供显示名称。他还可以定义要显示的当前自定义字段,并可以为创建的字段输入数据。我只是不确定这是否可以防止恶意注射。

千万不要说“永不:)。某些应用程序需要它。感谢您的评论。我把我的方法作为自己的回答,我想听听你们的意见,这是否是解决这个问题的安全方法。
 List<String> selectedColumns; //the list of internal col names   
 String query = "SELECT id, projectnumber, projectname {0} FROM projects"; //projectnumer and name a mandatory fields 
                if (selectedColumns.Count > 0)
                {
                    fieldstring  = String.Join(",", selectedColumns);
                    fieldstring = ", " + fieldstring;
                }
                query = String.Format(query, fieldstring);