테이블에서 PK가 걸린 컬럼이 있었습니다. 그 컬럼을 id라 하겠습니다. 수천개의 데이터를 insert를 해야 하는데, 해당 id값이 있는 데이터를 insert를 해야 하는 경우에, 오류가 발생합니다. 저는, 이러한 상황이 발생하는 데이터를 모두 뽑고 싶었습니다. 어떻게 하면 좋을까요?
제가 말한 문제를 해결하기 위해서, exists 구문을 사용하는 것을 고려해 볼 만 합니다. 이것은, 하위 질의의 결과가 빈 릴레이션을 반환하는 경우에 False를, 아니라면 True를 리턴합니다. 예제를 하나 들어보겠습니다.
먼저, t2에 있는 데이터들을 보겠습니다.
2개의 레코드가 있습니다. (1, 'cho')하고, (3,'gahui')가 있습니다.
먼저 exists 안에, select * from t2를 넣어보겠습니다. 괄호 안에 들어가 있는 것을, 저는 서브 쿼리라고 부르겠습니다. 보시면, t2에는 2개의 레코드가 있습니다. id가 1인 것과 3인 것 2개입니다. result가 2개 존재하기 때문에, 결과는 true입니다.
1이 찍히는군요. 그러면 아래 쿼리는 어떨까요?
서브 쿼리가 select * from t2 where id = 1입니다. 해당 조건을 만족하는 레코드가 있나요?
있습니다. (1, 'cho')입니다. 결과가 있기 때문에, 해당 쿼리의 결과는 참이 나올 겁니다.
결과는 예상 대로입니다. 그러면 아래의 질의는 어떨까요?
이번에는, t2에서 id가 5인 결과가 exists 하느냐고 물어보았습니다. 있나요?
아무리 찾아도 없어 보입니다. 따라서, 질의의 결과는 거짓이 될 겁니다.
0이 출력되는 것을 알 수 있습니다. 다시 정리하면 exists 안에 들어가는 쿼리의 결과가 하나라도 나온다면 참이고, 그렇지 않으면 거짓입니다. 참과 거짓으로 나타내는 무언가. where 절하고 어울릴 수 있습니다.
저는 보통 db의 엑셀 데이터가 저장이 되어 있는 것을 받으면, 이것을 먼저 select ~ union 문으로 변환합니다.
위와 같이요. 이것은 보시다시피, 'cho', 'ga', 'hui', 'gahui' 라는 결과 4개를 출력하라는 질의입니다.
당연하게도, 파일로부터 insert를 할 데이터를 읽어서, union으로 변환하면 쿼리가 길어지겠지만, 구조 자체는 같을 겁니다. 여기서, 저는, temp의 str 값이 테이블 t2의 str 필드에 이미 있는지 찾고 싶습니다. 이건 어떻게 하면 좋을까요? 고려해 볼만한 옵션 중 하나는 sql의 exists 구문을 쓰는 것입니다.
왼쪽에 있는 테이블은 union 문으로 생성한 temp라는 view이고, 오른쪽에 있는 것은 t2 테이블입니다. 그러면, 우리는 어떤 걸 확인하면 될까요? t2.str에 대해서 where 조건을 걸면 되는데요. temp.str이 t2.str과 같은 경우가 존재하는지만 찾으면 됩니다. 예를 들어서, 'cho'라는 게 t2에 존재하냐. 그러면 exists 안에 서브쿼리로, t2에서 str 필드가 'cho'인 걸 질의하는 것을 넣으면 됩니다. 단지, 우리는 str 필드가 'cho'이냐 라는 것을 질의하는 대신에, str 필드가 temp.str인 레코드를 모두 찾으라고 물어본다 정도로 보시면 됩니다.
그러면 쿼리는 위와 같이 작성할 수 있습니다.
실행 결과는 위와 같습니다. 만약에 exists를 쓰지 말라고 하면 어떻게 하면 될까요?
outer join을 이용하시면 됩니다. left outer join은 왼쪽 릴레이션에 있는 결과들을 모두 보존합니다. 예를 들어서, 위 질의의 경우에는, 'cho'와 'ga', 'hui', 'gahui' 라는 temp의 결과는 모두 보존할 겁니다. 대신에 'ga'와 'hui'는 t2에 나타나지 않았는데요.
이들의 t2.id와 t2.str 필드는 null로 채워집니다. 제가 요구한 것은 temp.str이 t2 테이블의 str 필드로 존재하는 경우가 있느냐인데요. 만약에 있다면, t2.str이 null은 아닐 겁니다. 따라서 t2.str이 not null인지 체크하기만 하면 됩니다. 이에 대한 처리는 9번째 줄에 있습니다.
'코딩 > Sql' 카테고리의 다른 글
sql update 문 : 레코드를 변경할 때 쓴다. (0) | 2020.07.27 |
---|---|
sql insert 문 : 레코드를 테이블에 넣는다. (1) | 2020.07.05 |
mysql inet_ntoa inet_aton 함수 : ipv4 주소를 어떻게 다룰까요? (0) | 2020.06.22 |
sql union 연산자 : 결과를 합친다. (2) | 2020.06.09 |
sql injection과 jdbc PreparedStatement (2) | 2020.06.02 |
최근댓글