2008-12-22 103 views
2

我最近已經增加了一個國際化的公司,它被命名爲「BLA‘BLAHBLAH’有限責任公司(雙引號是名稱的一部分。)逃生在SQL雙引號2005/2008

每當用戶嘗試搜索這家公司,通過輸入「Blah」或其他影響,搜索失敗,並在SQL Server中出現語法錯誤。

我該如何逃避這個搜索不會失敗?

樣品SQL:

SELECT c.companyID, c.companyName, c.dateAdded, count(cm.maxID) as NumDirect 
    FROM RussoundGeneral.dbo.Company c 
     LEFT JOIN RussoundGeneral.dbo.CompanyMax cm 
       ON (cm.companyId = c.companyId and cm.maxID is not null) 
    WHERE CONTAINS (companyName, '"BLAH*') 
    GROUP BY c.companyID, c.companyName, c.dateAdded 
    ORDER BY c.companyName ASC 
+0

請示例SQL代碼? – 2008-12-22 20:09:09

回答

6

不幸的是,雙引號在FTI內部有特殊的含義,所以即使你參數化了它,FTI引擎也會將它視爲短語分隔符。我不確定是否有簡單的方法在FTI搜索中加入雙引號。括號也是一種特殊字符,但可以用引號括起來作爲查詢詞 - 但不包括AFAIK雙引號。

更新

搜索的一點建議,加倍報價爲「」可以解決這個問題 - 值得一試。就個人而言,我會在數據庫中執行此操作,因爲這是TSQL實現細節。

同樣地,「需要翻番才能‘(完全獨立於TSQL逃逸)之前傳遞給FTI’,

+2

T-SQL中的字符串操作速度令人難以置信。如果查詢被調用了很多,最好在調用之前修改數據庫外部的引號。 – 2008-12-24 21:24:29

3

我強烈懷疑你是動態生成SQL - 例如

// Bad code, do not use! 
string sql = "SELECT * FROM Foo WHERE X LIKE '" + input + "%'"; 

這是有很多原因一個非常,非常糟糕的主意 - 尤其是SQL injection attacks。改爲使用參數化的SQL語句,而不是單獨指定參數。

請看sql-injection tag問題的各種答案,以瞭解如何正確執行此操作的示例。

+1

對不起,但沒有。 concatinated數據庫會讓你在這裏被俗語毆打.....被我。我不會強迫他們。 – Russ 2008-12-22 20:14:57

7

使用參數化查詢,所有引用的問題都將消失。

編輯:如果您不讓他們在CONTAINS中輸入多個單詞,請刪除引號以清除參數。無論多字搜索如何,通過刪除引號來消除輸入可能無論如何都有效。

0

你試圖取代它的ASCII碼字符?

0

嘗試使用ESCAPE關鍵字:

SELECT c.companyID, c.companyName, c.dateAdded, count(cm.maxID) as NumDirect 
FROM RussoundGeneral.dbo.Company c   
LEFT JOIN RussoundGeneral.dbo.CompanyMax cm 
ON (cm.companyId = c.companyId and cm.maxID is not null) 
WHERE CONTAINS (companyName, '\"BLAH*') escape '\' 
group by c.companyID, c.companyName, c.dateAdded ORDER BY c.companyName ASC 
0

應該像

string sqlCommand = "SELECT c.companyID, c.companyName, c.dateAdded, count(cm.maxID) as NumDirect FROM RussoundGeneral.dbo.Company c LEFT JOIN RussoundGeneral.dbo.CompanyMax cm ON (cm.companyId = c.companyId and cm.maxID is not null) WHERE CONTAINS (companyName, '@strVal') group by c.companyID, c.companyName, c.dateAdded ORDER BY c.companyName ASC" 
SqlCommand command = new SqlCommand(strSQLCommand, conn); 
SqlCommand.Parameters.AddWithValue("@strval", SearchTextBox.Text);
1

這是一個有點理論的答案,但也許會有所幫助。簡短版本是「在查詢中使用參數」,但它有助於理解全部細節。

在標準SQL中,字符串單引號括起來,而嵌入的單引號由兩個單引號在一行表示:

SELECT * FROM SomeWhere 
    WHERE SomeThing = 'He said, "Don''t do it!"'; 

在一些SQL方言,可以改爲接近串在雙引號;那麼你需要加倍的雙引號中嵌入雙引號的單個實例:

SELECT * FROM SomeWhere 
    WHERE SomeThing = "He said, ""Don't do it!""'; 

它不是從問題的公司名稱是否包括外雙引號,以及中間的一個,或明確如果它只包含中間的一個。但是,原則上,規則是一樣的。假設所有的三個雙引號是必需的,而在SQL中使用單引號 - 在這方面要容易得多:

SELECT c.companyID, c.companyName, c.dateAdded, count(cm.maxID) as NumDirect 
    FROM RussoundGeneral.dbo.Company c 
     LEFT JOIN RussoundGeneral.dbo.CompanyMax cm 
       ON (cm.companyId = c.companyId and cm.maxID is not null) 
    WHERE CONTAINS (companyName, '"BLAH "BLAHBLAH" Ltd.') 
    GROUP BY c.companyID, c.companyName, c.dateAdded 
    ORDER BY c.companyName ASC; 

使用雙引號:

SELECT c.companyID, c.companyName, c.dateAdded, count(cm.maxID) as NumDirect 
    FROM RussoundGeneral.dbo.Company c 
     LEFT JOIN RussoundGeneral.dbo.CompanyMax cm 
       ON (cm.companyId = c.companyId and cm.maxID is not null) 
    WHERE CONTAINS (companyName, """BLAH ""BLAHBLAH"" Ltd.") 
    GROUP BY c.companyID, c.companyName, c.dateAdded 
    ORDER BY c.companyName ASC; 

如果你是在一個編程語言創建的字符串,那麼你不得不擔心你的編程語言中的任何評估字符串都會被引用。例如,如果您構建了一個字符串在C,你必須用反斜槓轉義雙引號:

static const char sql_stmt[] = 
"SELECT c.companyID, c.companyName, c.dateAdded,\n" 
"  COUNT(cm.maxID) AS NumDirect\n" 
" FROM RussoundGeneral.dbo.Company c\n" 
"   LEFT JOIN RussoundGeneral.dbo.CompanyMax cm\n" 
"    ON (cm.companyId = c.companyId AND cm.maxID IS NOT NULL)\n" 
" WHERE CONTAINS(companyName, \"\"\"BLAH \"\"BLAHBLAH\"\" Ltd.\")\n" 
" GROUP BY c.companyID, c.companyName, c.dateAdded\n" 
" ORDER BY c.companyName ASC"; 

在另一方面,如果你看過來自用戶的數據 - 比如公司名稱,那麼您只需確保讀取的內容正確引用。

那些誰說:「使用參數」是正確的 - 這是更簡單,更可靠,更不容易受到SQL注入式攻擊(見XKCD如果你還沒有看到它)。但是,如果你瞭解基礎知識,就可以適應系統的實際需求。

最後說明:在標準SQL中,雙引號括起'分隔標識符'。也就是說,雙引號包圍一個名稱,該名稱必須被視爲數據庫中的某個名稱,而不是字符串文字。在MS SQL Server中,[方括號]用於相同的目的;括號之間是什麼是列或數據庫內的任何內容的名稱。許多系統比這更靈活;並不是所有的系統在偏離標準方面都是一樣的。

0

您最終必須從數據庫中提取數據,並將其顯示在屏幕上或打印在報告中。操縱雙引號或任何額外字符可能會變得非常混亂。

通過轉換你的字符串插入或更新,你是避免全掛報價管理混亂之前爲HTML。在SELECT時間,從HTML轉換回來很容易。在報告時間(因爲報表工具(如Crystal Reports)提出了一種HTML格式選項),您甚至不必採取任何措施以正確的方式顯示數據。

順便說一下,不要忘記掛上發明這個公司名稱的傢伙。