2011-04-07 39 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(); 
      } 
     }