Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

SQL IN заявката дава странен резултат

Това поведение, макар и неинтуитивно, е много добре дефинирано в базата знания на Microsoft:

KB #298674:PRB:Подзаявка преобразува имена на колони към външни таблици

От тази статия:

CREATE TABLE X1 (ColA INT, ColB INT)
CREATE TABLE X2 (ColC INT, ColD INT)
SELECT ColA FROM X1 WHERE ColA IN (Select ColB FROM X2)
SELECT ColA FROM X1 WHERE ColA in (Select X2.ColB FROM X2)

Хората се оплакват от този проблем от години, но Microsoft няма да го поправи. В края на краищата той отговаря на стандарта, който по същество гласи:

Повече информация в следните "бъгове" на Connect заедно с множество официални потвърждения, че това поведение е проектирано и няма да се промени (така че ще трябва да промените своя - т.е. винаги използвайте псевдоними ):

Свързване #338468:Резолюцията на име на колона CTE в подзаявка не е валидирана
Connect #735178 :T-SQL подзаявката не работи в някои случаи, когато се използва оператор IN
Connect #302281 :Несъществуваща колона кара подзаявката да бъде игнорирана
Connect #772612 :Грешка с псевдоним не се съобщава, когато сте в оператор IN
Connect #265772:Грешка при използване на sub изберете

Във вашия случай тази "грешка" вероятно ще бъде много по-малка, ако използвате по-смислени имена от ID, OID и PID. Прави Order.PID посочете Person.id или Person.PID ? Проектирайте таблиците си така, че хората да могат да разберат връзките, без да се налага да ви питат. PersonID винаги трябва да бъде PersonID , без значение къде в схемата е; същото с OrderID . Спестяването на няколко знака от въвеждане не е добра цена за напълно двусмислена схема.

Можете да напишете EXISTS клауза вместо това:

... FROM dbo.Person AS p WHERE EXISTS 
(
  SELECT 1 FROM dbo.[Order] AS o
  WHERE o.PID = p.id -- or is it PID? See why it pays to be explicit?
);


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как да намерите полета, съдържащи знака TAB в SQL Server

  2. MSSQL2008 - Pyodbc - Предишният SQL не беше заявка

  3. VB6 ADODB.Recordset Свойството RecordCount винаги връща -1

  4. UDT като параметър в EF4 заявка

  5. Изпълнете съхранена процедура от функция