2009-02-17 45 views
5

我在SQLite數據庫中有兩個表,INVITEM和SHOPITEM。他們的共享屬性是ItemId,我想執行一個INNER JOIN。這裏的查詢:SQLite INNER JOIN中的「模棱兩可的列名」

SELECT INVITEM.CharId AS CharId, 
      INVITEM.ItemId AS ItemId 
     FROM (INVITEM as INVITEM 
INNER JOIN SHOPITEM AS SHOPITEM 
     ON SHOPITEM.ItemId = INVITEM.ItemId) 
    WHERE ItemId = 3; 

SQLite不喜歡它:

SQL error: ambiguous column name: ItemId 

錯誤消失,如果我寫WHERE INVITEM.ItemId = 3,但由於WHERE條件或多或少用戶指定的,我寧願做它工作時無需指定表格。 NATURAL JOIN似乎解決了這個問題,但我不確定解決方案是否足夠普遍(即我可以在這種情況下使用,但我不確定是否可以在任何情況下使用)

任何備用SQL將解決問題的語法?

回答

0

我會避免讓用戶直接編寫SQL子句。這是SQL注入漏洞的來源。

如果您需要查詢是靈活的,請嘗試解析用戶的輸入並添加適當的where子句。

下面是一些C#代碼顯示的總體思路

// from user input 
string user_column = "ItemID"; 
string user_value = "3"; 

string sql = "SELECT INVITEM.CharId AS CharId, INVITEM.ItemId AS ItemId FROM (INVITEM as INVITEM INNER JOIN SHOPITEM AS SHOPITEM ON SHOPITEM.ItemId = INVITEM.ItemId) "; 

if (user_column == "ItemID") 
{ 
    // using Int32.Parse here to prevent rubbish like "0 OR 1=1; --" being entered. 
    sql += string.Format("WHERE INVITEM.ItemID={0}",Int32.Parse(user_value)); 
} 

顯然,如果你正在處理一個以上的條款,你需要替換和WHERE在後續子句。

+0

我最終做了這樣的事情。我從不允許用戶直接編寫SQL,但WHERE子句是使用表達式模板構建的。在需要的地方限定列名就夠了。 – ggambett 2009-02-18 12:21:54

0

只要將您的列別名更改爲類似但唯一的(如ITEM_ID)。

SELECT i.CharId AS CharId, i.ItemId AS ItemId 
FROM INVITEM as i INNER JOIN SHOPITEM AS s USING (ItemId) 
WHERE i.ItemId = 3; 

我使用USING (ItemId)語法這僅僅是一個品味的問題:

10

我會這樣寫這個查詢。這相當於ON (i.ItemID = s.ItemID)

但我通過在WHERE條款中限定i.ItemID來解決含糊不清的問題。你會認爲這是不必要的,因爲i.ItemID = s.ItemID。它們通過交換性都是相等的,所以不存在語義歧義。但顯然SQLite不夠聰明,不知道這一點。我不喜歡使用NATURAL JOIN。這相當於的每個列的同等連接,這兩列存在於具有相同名稱的兩個表中。我不喜歡使用它,因爲我不希望它比較我不想要的列,只是因爲它們具有相同的名稱。