2009-02-17 9 views
5

Mam dwie tabele w SQLite DB, INVITEM i SHOPITEM. Ich wspólnym atrybutem jest ItemId i chcę wykonać INNER JOIN. Oto zapytanie:"niejednoznaczna nazwa kolumny" w 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 nie podoba:

SQL error: ambiguous column name: ItemId 

Błąd znika, gdy piszę WHERE INVITEM.ItemId = 3, ale ponieważ WHERE warunek jest mniej lub bardziej określony przez użytkownika, wolałbym zrobić działa bez konieczności określania tabeli. NATURAL JOIN wydaje się rozwiązywać problem, ale nie jestem pewien, czy to rozwiązanie jest wystarczająco ogólne (tj. Mógłbym użyć w tym przypadku, ale nie jestem pewien, czy mogę go użyć w każdym przypadku)

Dowolny alternatywny SQL składnia, która naprawiłaby problem?

Odpowiedz

0

Zapobiegłbym temu, aby użytkownik mógł bezpośrednio pisać klauzule SQL. To jest źródło luk SQL Injection.

Jeśli chcesz, aby zapytanie było elastyczne, spróbuj przeanalizować dane wprowadzane przez użytkownika i dodać odpowiednią klauzulę where.

Oto kod C#, aby pokazać ogólną ideę

// 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)); 
} 

Oczywiście, jeśli masz do czynienia z więcej niż jednym punkcie, trzeba by zastąpić I Bo gdzie w kolejnych punktach.

+0

Skończyło się na zrobieniu czegoś takiego. Nigdy nie zezwalam użytkownikowi na bezpośrednie pisanie kodu SQL, ale klauzule WHERE są tworzone przy użyciu szablonów wyrażeń. Kwalifikacja nazw kolumn w razie potrzeby wystarczy. – ggambett

0

Po prostu zmień swój alias kolumny na coś podobnego, ale unikatowego (np. ITEM_ID).

10

chciałbym napisać tej kwerendy w ten sposób:

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

używam składni USING (ItemId) która jest po prostu kwestia gustu. Jest to odpowiednik ON (i.ItemID = s.ItemID).

Ale rozwiązałem niejednoznaczność, kwalifikując i.ItemID w klauzuli WHERE. Można by pomyśleć, że to jest niepotrzebne, ponieważ i.ItemID = s.ItemID. Obie są równe przez przemienność, więc nie ma semantycznej dwuznaczności. Ale najwyraźniej SQLite nie jest wystarczająco inteligentny, aby o tym wiedzieć.

Nie lubię używać NATURAL JOIN. Jest to odpowiednik equi-join z każdej kolumny, która istnieje w obu tabelach o tej samej nazwie. Nie lubię tego używać, ponieważ nie chcę porównywać kolumn, których nie chcę, po prostu dlatego, że mają tę samą nazwę.