Почему этот код SQL ведет себя вот почему.Разве не должна выдаваться ошибка компиляции? - PullRequest
1 голос
/ 14 мая 2019

Изучите эту проблему SQL. Очень интересно, почему SQL компилируется. Последний оператор выбора должен выдать ошибку и ошибку, поскольку столбец client_id не существует во временной таблице. Похоже, используется область видимости первой таблицы client_orders. Но даже в этом случае после разрешения он всегда принимает значение ИСТИНА при оценке оператора IN. Ниже приведен код.

Это просто загадка. У меня есть проводник, что происходит, когда оператор в IN является нулевым или недействительным, и он просто воспринимается как ошибка компиляции. Кажется, что есть путаница с использованием client_id.

Вот пример.

IF OBJECT_ID('client_order') IS NOT NULL DROP TABLE client_order
IF OBJECT_ID('tempdb.dbo.#to_delete') IS NOT NULL DROP TABLE #to_delete
GO

CREATE TABLE client_order
(
       client_id INT NOT NULL,
       order_id INT NOT NULL,
       order_data CHAR(100) NOT NULL DEFAULT '{"amount":12}'
)
GO

INSERT INTO client_order (client_id, order_id) VALUES
(1, 1),
(1, 2),
(2, 1),
(2, 2),
(2, 3),
(3, 1)

SELECT * FROM client_order

CREATE TABLE #to_delete
(
       bobo INT NOT NULL
)

INSERT INTO #to_delete VALUES (1),(3)

SELECT * FROM client_order
WHERE client_id IN (SELECT client_id FROM #to_delete)
  • WTF? Почему все записи были возвращены?!
  • Я знаю, что выборка в #to_delete использует неправильный столбец, но почему это не было воспринято как ошибка
  • Более того, почему этот оператор выбора всегда возвращает истину при проверке, является ли client_id IN этим оператором?

Значения client_id, равные 2, должны оставаться. Почему не они?

1 Ответ

8 голосов
/ 14 мая 2019

Ваша таблица #to_delete не имеет столбца с именем client_id. Итак, вы думаете, что написали:

SELECT co.*
FROM client_order co
WHERE co.client_id IN (SELECT d.client_id FROM #to_delete d);

Но это приведет к неизвестной ошибке столбца. Итак, это интерпретируется как:

SELECT co.*
FROM client_order co
WHERE co.client_id IN (SELECT co.client_id FROM #to_delete d);

И все возвращается.

Урок: Всегда квалифицируйте все ссылки на столбцы в запросе. Если вы включите псевдоним таблицы в имя столбца, у вас никогда не возникнет этой проблемы.

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