복붙노트

[SQL] SQL에서 쿼리 이상한 결과를 생성

SQL

SQL에서 쿼리 이상한 결과를 생성

아래의 테이블 구조를 참조하십시오 :

CREATE TABLE Person (id int not null, PID INT NOT NULL, Name VARCHAR(50))
CREATE TABLE [Order] (OID INT NOT NULL, PID INT NOT NULL)

INSERT INTO Person VALUES (1,1,'Ian')
INSERT INTO Person VALUES (2,2,'Maria')
INSERT INTO [Order] values (1,1)

왜 다음 쿼리 반환 두 결과를 수행합니다

select * from Person WHERE id IN (SELECT ID FROM [Order])

ID 주문에 존재하지 않습니다. 왜 생산 결과 위의 쿼리를합니까? 나는 순서에 존재하지 않는 것 때문에 나는 오류를 기대.

해결법

  1. ==============================

    1.당신이 당신의 하위 쿼리에는 table.column 표기법을 사용하지 않는 것을 여기서 문제는, 테이블 주문 하위 쿼리의 열 ID와 ID가없는 정말 Person.ID하지 [주문] .ID는 것을 의미한다. 난 항상 생산 코드에서 테이블 별칭을 사용하여 주장하는 이유입니다. 이 두 쿼리 비교 :

    당신이 당신의 하위 쿼리에는 table.column 표기법을 사용하지 않는 것을 여기서 문제는, 테이블 주문 하위 쿼리의 열 ID와 ID가없는 정말 Person.ID하지 [주문] .ID는 것을 의미한다. 난 항상 생산 코드에서 테이블 별칭을 사용하여 주장하는 이유입니다. 이 두 쿼리 비교 :

    select * from Person WHERE id IN (SELECT ID FROM [Order]);
    
    select * from Person as p WHERE p.id IN (SELECT o.ID FROM [Order] as o)
    

    첫 번째 실행되지만 잘못된 결과를 반환하고, 두 번째는 에러를 발생한다. 당신이 하위 쿼리 내부에 사람 열을 사용할 수 있습니다이 경우 있도록 외부 쿼리의 열, 하위 쿼리에서 참조 될 수 있기 때문이다. 아마 당신은이 같은 쿼리를 사용하고 싶었 :

    select * from Person WHERE pid IN (SELECT PID FROM [Order])
    

    하지만 당신은 결코 알지 못할 때에서 [주문] 테이블 변경의 스키마, 그리고 누군가로부터 열 PID을 삭제하는 경우 [주문] 다음 쿼리가 테이블 사람에서 모든 행을 반환합니다. 따라서 별칭을 사용합니다 :

    select * from Person as P WHERE P.pid IN (SELECT O.PID FROM [Order] as O)
    

    다만 빠른 주 -이 SQL 서버의 특정 동작 아니라, 표준 SQL이다 :

  2. ==============================

    2.이 동작은, 직관적 동안, 아주 잘 마이크로 소프트의 기술 자료에 정의되어 있습니다 :

    이 동작은, 직관적 동안, 아주 잘 마이크로 소프트의 기술 자료에 정의되어 있습니다 :

    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)
    

    사람들은 년 동안이 문제에 대해 불평했지만, 마이크로 소프트는 그것을 해결하려고하지 않습니다. 그것은 본질적 내용의 표준을 준수, 결국입니다 :

    이것은 의도적으로 설계된 동작입니다 변경하지 않을 것을 여러 공식 확인서와 함께 다음과 같은 연결 "버그"에 대한 자세한 정보 (당신은 변경 당신해야합니다 - 그래서 즉 항상 별칭을 사용) :

    연결 # 338468 : 하위 쿼리에서 CTE 열 이름 확인이 검증되지 않습니다 연결 # 735178 : T-SQL 하위 쿼리는 어떤 경우에는 작동하지 IN 연산자를 사용하는 경우 연결 # 302281 : 비 존재 열은 하위 쿼리가 무시됩니다 연결 # 772612 : 별칭 오류가 때 IN 연산자 내에서보고되지 연결 # 265772 : 버그 사용하여 하위 선택

    귀하의 경우에는,이 "오류"아마 당신이 ID, OID 및 PID보다 더 의미있는 이름을 사용하는 경우 발생할 훨씬 덜 가능성이있을 것입니다. Person.id 또는 Person.PID에 Order.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?
    );
    
  3. ==============================

    3.주문 테이블은 id 컬럼이 없습니다

    주문 테이블은 id 컬럼이 없습니다

    대신 다음을 시도해보십시오

    select * from Person WHERE id IN (SELECT OID FROM [Order])
    

    또는

    select * from Person WHERE pid IN (SELECT PID FROM [Order])
    
  4. from https://stackoverflow.com/questions/18577622/sql-in-query-produces-strange-result by cc-by-sa and MIT license