sql >> Databáze >  >> RDS >> Sqlserver

SQL IN dotaz vytváří podivný výsledek

Toto chování, i když je neintuitivní, je velmi dobře definováno ve znalostní bázi Microsoft:

KB #298674 :PRB:Poddotaz řeší názvy sloupců na vnější tabulky

Z toho článku:

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)

Lidé si na tento problém stěžují roky, ale Microsoft to nehodlá opravit. Je to přece v souladu s normou, která v podstatě říká:

Další informace naleznete v následujících „chybách“ Connect spolu s několika oficiálními potvrzeními, že toto chování je záměrné a nezmění se (takže budete muset změnit své – tj. vždy používejte aliasy ):

Připojení #338468 :Rozlišení názvu sloupce CTE v dílčím dotazu není ověřeno
Connect #735178 :Poddotaz T-SQL nefunguje v některých případech, když je použit operátor IN
Připojení #302281 :Neexistující sloupec způsobí, že bude poddotaz ignorován
Connect #772612 :Chyba aliasu není hlášena, když je operátor IN
Připojení #265772 :Chyba při použití sub vybrat

Ve vašem případě bude tato „chyba“ pravděpodobně mnohem méně pravděpodobná, pokud použijete smysluplnější názvy než ID, OID a PID. Má Order.PID přejděte na Person.id nebo Person.PID ? Navrhněte své tabulky tak, aby lidé mohli zjistit vztahy, aniž by se vás museli ptát. PersonID by mělo být vždy PersonID , bez ohledu na to, kde ve schématu je; totéž s OrderID . Ušetřit pár znaků psaní není dobrá cena za zcela nejednoznačné schéma.

Můžete napsat EXISTS místo toho klauzule:

... 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. Dotaz poskytující duplicitní výsledek?

  2. MAX. DÉLKA CONCAT MYSQL

  3. Distribuovaná transakce na propojeném serveru mezi serverem SQL a serverem mysql

  4. MySQL převádí datový typ sloupce z VARCHAR na INT