«неоднозначное имя столбца» в SQLite INNER JOIN - PullRequest
5 голосов
/ 17 февраля 2009

У меня есть две таблицы в БД SQLite, INVITEM и SHOPITEM. Их общий атрибут ItemId, и я хочу выполнить 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 более или менее задано пользователем, я скорее заставляю его работать без указания таблицы. Кажется, что ЕСТЕСТВЕННОЕ СОЕДИНЕНИЕ решает проблему, но я не уверен, является ли решение достаточно общим (то есть я мог бы использовать в этом случае, но я не уверен, что смогу использовать в каждом случае)

Какой-нибудь альтернативный синтаксис SQL, который решит проблему?

Ответы [ 3 ]

10 голосов
/ 17 февраля 2009

Я бы написал этот запрос следующим образом:

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), который является делом вкуса. Это эквивалентно ON (i.ItemID = s.ItemID).

Но я решил эту двусмысленность, квалифицировав i.ItemID в предложении WHERE. Вы можете подумать, что в этом нет необходимости, поскольку i.ItemID = s.ItemID. Они оба равны по коммутативности, поэтому нет никакой смысловой двусмысленности. Но, очевидно, SQLite недостаточно умен, чтобы это понимать.

Я не люблю использовать NATURAL JOIN. Это эквивалентно равному объединению каждого столбца , который существует в обеих таблицах с одинаковыми именами. Мне не нравится использовать это, потому что я не хочу, чтобы он сравнивал столбцы, с которыми я этого не хочу, просто потому, что они имеют одинаковые имена.

0 голосов
/ 17 февраля 2009

Просто измените псевдоним столбца на нечто похожее, но уникальное (например, ITEM_ID).

0 голосов
/ 17 февраля 2009

Я бы не стал позволять пользователю писать предложения 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 в последующих предложениях AND.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...