2010-01-15 109 views
2

我正在使用MySQL連接器/網絡,我想寫一個名稱將在運行時指定的表的查詢。什麼是在運行時動態選擇表名的最佳方式?

這個例子是把我的頭(未測試)的頂部:

public class DataAccess 
{ 
    public enum LookupTable 
    { 
     Table1, 
     Table2, 
     Table3 
    } 

    public int GetLookupTableRowCount(LookupTable table) 
    { 
     string tableName = string.Empty; 

     switch (table) 
     { 
      case LookupTable.Table1: 
       tableName = "table_1"; 
       break; 
      case LookupTable.Table2: 
       tableName = "table_2"; 
       break; 
      case LookupTable.Table3: 
       tableName = "table_3"; 
       break; 
      default: 
       throw new ApplicationException("Invalid lookup table specified."); 
     } 

     string commandText = string.Concat("SELECT COUNT(*) FROM ", tableName); 

    // Query gets executed and function returns a value here... 
    } 
} 

因爲我不認爲你可以在查詢參數表名,我用了一個枚舉,而不是一個字符串功能參數限制SQL injection的可能性。

這似乎是一個很好的方法嗎?有沒有更好的辦法?

+0

.net是否不支持向枚舉類型添加額外屬性? – Jherico 2010-01-15 19:16:02

+0

你的意思是像Table1 =「table_1」等,如果是這樣,那麼你只能使用像int和long這樣的整型。 – 2010-01-15 19:19:18

回答

4

您不能在MySQL中提出identifier(表名或字段名)的參數,但是您可以使用反引號將它們轉義。

下面的查詢將安全地運行,但因爲表不存在產生錯誤(除非一些奇怪的機會,你實際上有一個名爲像這樣的表):

SELECT * FROM `users; DROP TABLE users;`; 

基本上,你可以使用動態名稱或字段,只要它們用反引號括起來即可。爲了防止SQL注入這樣,所有你需要做的是首先去掉任何反引號:

tableName = tableName.Replace("`", ""); 
string commandText = "SELECT COUNT(*) FROM `" + tableName + "`"; 
+0

我明白你在說什麼,但我認爲我更安全地將查詢文本與任何自由形式的輸入隔離。這就是爲什麼我不想在我的數據訪問方法中使用字符串參數的原因。 – 2010-01-15 19:29:16

+0

嗯,我不能讓你相信語言的語義。你要麼信任MySQL的反向和退出方法,要麼你不信任。另一種方法是像其他人所建議的那樣通過某種查找表將數據庫結構耦合到您的代碼中,我個人覺得這很令人厭惡。 – zombat 2010-01-15 19:37:41

+0

我實際上建議你仔細閱讀標識符頁面,因爲它列出了一個有效的標識符。如果你想要額外的保護,你可以只使用字母數字字符,或者甚至查詢預先存在的表是否存在。但是,MySQL會通過在查詢中拋出錯誤來處理標識符中的任何無效字符。 – zombat 2010-01-15 19:45:19

1

對,你不能使用表名,列名,SQL關鍵字或表達式等的查詢參數。你可以使用查詢參數僅用於單個值。

我同意做一些從輸入到文字表名的映射是防止SQL注入的好方法。

我不用.NET編程,我通常使用PHP,Python或Perl等動態語言。所以我使用了一個哈希數組。如果您可以簡單地使用枚舉變量來索引散列數組,則可以跳過switch()

$tableName = $tableNameHash[ $table ]; 

.NET是否支持哈希映射類型的數據結構?這就是我想要的。


看起來像標準C++庫中有一個hash_map類。

+0

是的,在.NET中有哈希表和字典以及很多其他集合式類。我喜歡你的建議。 – 2010-01-15 19:23:09

2

動態表名是不是一個好辦法(除非你正在開發一個類似PHPMyAdmin或東西)。

如果你的表名是有限的,你爲什麼不製作一個存儲過程並用參數調用它?

DECLARE _which INT 
BEGIN 
     SELECT COUNT(*) 
     FROM table_1 
     WHERE _which = 1 
     UNION ALL 
     SELECT COUNT(*) 
     FROM table_2 
     WHERE _which = 2 
     UNION ALL 
     SELECT COUNT(*) 
     FROM table_3 
     WHERE _which = 3 
END 
+3

我不同意「從來不是一個好方法」。大型企業應用程序幾乎肯定會使用某種動態命名機制將數據分解爲可管理的集合。數據庫分片技術甚至會使用動態*數據庫*名稱,而不僅僅是表格。 – zombat 2010-01-15 19:26:28

相關問題