2010-12-31 2 views
3

방금 ​​where 절을 잊어 버린 소프트웨어 중 하나에서 버그를 발견했습니다. 코드가 성공적으로 테스트를 통해 갔다select에서 변수 할당이 여러 값을 반환하면 오류를 발생시킬 수 있습니까?

declare @foo bigint 
declare @bar bigint 
select @foo = foo, @bar=bar from tbFooBar 
where (....a long list of condition goes there) 
    (... and an extra condition should have went there but I forgot it) 

불행하게도, 내가 잊고 where 절은 매우 특정 코너의 경우에 유용과 : 코드는 그런 일이었다.

결국 쿼리는 하나가 아닌 두 개의 값을 반환하고 결과 버그는 추적하기 어려운 악몽이었습니다 (재현하기가 매우 어려웠으므로이 특정 저장 프로 시저가 우리가 발견 한 문제)

@ foo = foo가 여러 행 중에서 첫 번째 값을 자동으로 지정하는 대신 예외를 발생시킨 경우 디버깅이 훨씬 쉬워졌습니다.

왜 이렇게됩니까? 나는 실수를 제기하지 않고 실제로 그것을하고 싶어하는 상황을 생각할 수 없다. (이유를 들어 '별개'와 '정상'을 염두에 두라.)

이 상황이 발생하면 SQL Server 2008에서 오류가 발생합니까?

+1

오라클에만 적용되는 plsql에 태그를 지정하는 이유는 무엇입니까? 당신은 여기에 tsql을 사용할 수 있습니다 –

+0

당신은 물론입니다, 그냥 태그를 업데이트했습니다. 알았어 고마워! – Brann

답변

1

이 같은 쿼리를 공식화 할 수 있으며, 오류를 얻을 것보다, 여러 결과가있는 경우 :

declare @foo bigint 
select @foo = (
    Select foo 
    from tbFoo 
    where (....a long list of condition goes there) 
     (... and an extra condition should have went there but I forgot it) 
) 

이 다른 구문은 설계 오류를 던져하지.

편집 : 당신이 1 개 이상의 열을 필요로 할 때, 당신은 테이블 변수를 사용할 수 있습니다

, 그것은 그 결과를 할당하고 해당 행의 수를 확인하고 그에 따라 작동합니다.

+0

음, 내 쿼리가 지나치게 단순화 된 것 같습니다. 실생활 시나리오에서는 두 가지 이상의 과제가 있었기 때문에 제안을 구현할 수 없습니다. 내 질문에 따라 업데이 트했습니다 – Brann

6

이 시도 :

declare @d datetime 
select @d = arrived from attendance; 
if @@ROWCOUNT > 1 begin 
    RAISERROR('Was more than expected 1 row.', 16, 1) 
end 
2

왜이 방법이다? 사람들은 변수 이 각 행에 할당 된이라는 사실을 기반으로 상당히 많은 작업을 수행 할 수 있습니다. 예를 들어, 일부는 string concatenation을 수행하는 데 사용합니다.

@bernd_k는 단일 변수에만 할당한다고 가정 할 때 오류를 유발하는 한 가지 방법을 보여줍니다. 지금이 순간, 당신은 여러 변수를 지정해야하는 경우 그 기술을 일반화 할 수있는 방법이 없다 - 당신은 여전히 ​​당신의 쿼리는 특정 쿼리가 큰 것을 하나 개의 행이 염려되는 경우


를 반환하도록해야/단지/나중에 편집 할 수도 있고, 누군가가 실수로 새 변수를 소개하고이 같이 당신의 선택 모양의 시작을 만들 수 있습니다, 그것은 추가 행을 반환 할 수 있습니다

declare @dummy bit 
select @dummy = CASE WHEN @dummy is null then 1 ELSE 10/0 END 

이 다음 오류 경우가 발생합니다 여러 행이 리턴됩니다.

+0

같은 1 위로 명시 적으로 얻을 수 있을까? btw, 나는 당신의 @dummy 트릭을 아주 좋아한다. – Brann

+0

@Brann - top 1은 추가 행을 무시합니다 (* 선택했을지라도) –

0

나는 테이블 변수에 값을 할당하고 할당 후에 테이블에 여러 레코드가 있는지 확인합니다. 사실 나는 근시안적인 것처럼 하나의 레코드를 반환하는 쿼리에 거의 의존하지 않습니다. 그것은 시험에서 볼 수 있지만 실제 데이터가 도착하면 자주하지 않으며 어쩌면하지 않아도됩니다. 하나의 레코드 대신 세트의 관점에서 생각한다면, 당신은 더 신뢰할 수있는 코드를 갖게 될 것입니다.

관련 문제