2011-04-07 38 views
7

我有一个过滤器对象来查询表具有很多列,而非写覆盖所有列(允许可选的过滤)这样的条件:如何动态查询列名使用的是Postgres/Npgsql的

WHERE ((:value0 IS NULL) OR (column_name0 = :value0)) AND ((:value1 IS NULL) OR (column_name1 = :value1)) AND... etc 
每列为

。相反,我想最好我想能够在字段名作为参数传递:

WHERE :column_name0 = :value0 AND column_name1 = :value1 AND... etc 

为列在分析时需要这是不可能的(类似于此答案given here) 。

你如何克服这一点? - 当新列被添加或删除时(我必须在第一个示例中),我并不想维护SQL,我认为将列名构造到命令字符串中会很危险直接,因为这可能会允许SQL注入。

请注意,此代码位于Web服务的后面。

+0

为什么你经常需要添加或删除列?这样的需求有什么好的理由? – 2011-04-07 17:02:55

+0

@ypercube,我不需要经常这样做。我只是不想为我的数据库中的每个更改维护过滤器对象中的sql,同时提供用于过滤数据的灵活对象。 – 2011-04-07 17:08:21

回答

23

只要确保最终用户不能直接提供列名称,并且在手动构建查询时应该是安全的。如果你需要找出列名是有效的运行时,您可以使用下面的查询:

SELECT column_name 
FROM information_schema.columns 
WHERE table_schema='public' AND table_name='yourtablename' 
+1

对于获取有效列名的想法+1。请注意 - 由于这是一项Web服务,客户端软件提供了过滤信息,尽管实施了安全/身份验证,但仍可以使用非客户端数据调用Web服务。 – 2011-04-07 17:49:09

+0

我打算用你的想法在服务启动时将(允许的)列名称服务器端存储在列名字典(在表名字典中)。客户端可以引用键,而不是过滤器对象中要使用的表或列的实际名称。 – 2011-04-07 18:00:25

1

我认为最简单的解决方案是建立在运行的SQL语句。

如果您使用用户提供的数据参数,SQL注入是不可能的。

+0

是的,在飞行中是一个简单的解决方案,但是这是一个Web服务,客户端通过过滤标准,包括列信息,它仍然可能被攻击。 – 2011-04-07 17:50:36

+1

你说得对,如果列名是由用户提供的,那就很危险。一种解决方案(不完美)是只允许字符(A-Z,a-z)和下划线(_)。可能还有数字(0-9),但不在开头。 – 2011-04-07 19:13:51

+0

客户端是客户端应用程序。 + 1的正确答案,尽管@Eelke提供了最好的想法来回答我的问题。 – 2011-04-07 23:05:41

0

例如:

NpgsqlCommand command = new NpgsqlCommand(SQL, Connection); 
     Npgsql.NpgsqlDataReader Resource = command.ExecuteReader(); 

     while (this.Resource.Read()) 
     { 
      for (int i = 0; i < this.Resource.FieldCount; i++) 
      { 
       string field = this.Resource.GetName(i).ToString(); 
      } 
     }