2014-08-28 2 views
0

많은 데이터 형식을 저장하기위한 자리 표시 자로 varchar(255)을 사용하는 데이터베이스가 있습니다. 숫자 비교를 위해 decimal에이 값 중 일부를 변환하려고합니다. 일부 값이 여전히 있다면 나는 다음과 같은 기능을 사용하려고하면SQL Server : REPLACE를 사용하지 않으면 데이터 형식 varchar를 숫자로 변환하는 중 오류가 발생했습니다.

는 제목

ISNUMERIC(Value + 'e0') = 1 and CONVERT(decimal (16,4), Value) < CONVERT(decimal (16,4),11) 

에 오류가 발생합니다 나는 이것이 이상한 생각은 그래서 나는 볼 select 문에 CONVERT 이동 ISNUMERIC은 잡지 못했습니다. 존재하지 않았다. 위의 CONVERT은 오류없이 모든 단일 열을 성공적으로 변환 할 수있었습니다.

select CONVERT(decimal (16,4), Value) 

다른 선택에서 선택을 래핑하고 비교를 외부 쿼리로 이동하려고했습니다. 그 중 하나가 작동하지 않았고 또한 많은 메모리 사용량을 초래하여 그 아이디어를 폐기했습니다.

제 동료 중 한 사람이 문제의 원인이되는 데이터가 한 줄로있을 가능성이 있다고 생각합니다. 선택 항목의 CONVERT이 제대로 작동 했더니보고 싶은 가치가있었습니다. ...

ISNUMERIC(Value + 'e0') = 1 and CONVERT(decimal (16,4),REPLACE(Value, 'blah', '')) < CONVERT(decimal (16,4), 11) 

을 어떻게 든이 일을 : 우리는 아래의 CONVERT 내부 REPLACE을 시도했다. 우리가 대체하는 것을 입력해도 문제가 없습니다. 그것은 분명히 아무것도 대체하지 않습니다. REPLACE은 매우 큰 데이터 (8,000 + 바이트)를자를 것이지만, 이것은 varchar(255)이므로 잘릴 큰 데이터가 없습니다.

나는 왜이 작품이 효과가 있는지, 아니면 여기에 뭔가있을 가능성이 있고 REPLACE이 우연히 작동했는지 궁금합니다. 그것은 나에게 어떤 의미가 없습니다.

편집 : 분명히 말하면, 나는이 데이터베이스 설계에 박차 고있다. 나는 그것을 바꿀 수 없다. 나는 이것이 데이터를 저장하는 끔찍한 방법이라는 것을 알고있다. 날 믿어.

편집 # 2 : 방금 TRY_CONVERT도 작동한다는 것을 알았습니다. 내 원래의 질문은 여전히 ​​생각합니다. 두 가지 잠재적 인 해법이 있지만 왜 깨지는 지 이해할 수 없습니다.

+3

"많은 데이터 유형을 저장하기위한 자리 표시 자로 varchar (255)를 사용하는 데이터베이스가 있습니다." 이것은 데이터를 전혀 처리하는 올바른 방법이 아닙니다. 적절한 데이터 유형을 사용해야합니다. 모든 것을 varchar로 사용하면 모든 종류의 문제가 발생합니다. 이 일을 너 자신에게하지 마라. –

+0

데이터베이스를 설계하지 않았습니다. 그것을 바꿀 수 없다. 나는 그것이 얼마나 어리 석 었는지 안다. – Chase

답변

5

은 아마도, 당신의 표현은 where 절에 있습니다

where ISNUMERIC(Value + 'e0') = 1 and CONVERT(decimal (16,4), Value) < CONVERT(decimal (16,4),11) 

SQL Server는 하지 보증 식의 평가의 순서를 수행합니다. 따라서 convert()이 먼저 나올지 아니면 isnumeric()이되는지 알 수 없습니다. where 절의 이러한 표현식에 대해 모든 데이터베이스는 최적화 엔진이 원하는 모든 순서로 평가할 수있는 권한을 보유합니다.

절에있는 case을 사용하는 것이 유익한 경우입니다. case에는 평가 순서가 일부 보장되어 있습니다.다음은 작동합니다 :

where (case when ISNUMERIC(Value + 'e0') = 1 
      then CONVERT(decimal(16,4), Value) 
     end) < CONVERT(decimal(16,4), 11) 

두 번째 변환은 내 의견으로는, 불필요한 혼란입니다 : 그런데

where (case when ISNUMERIC(Value + 'e0') = 1 
      then CONVERT(decimal(16,4), Value) 
     end) < 11 

, 'e0'의 사용은 유효한, 비를 찾는 영리한 방법입니다 기하 급수적 인 숫자.

+0

내부/외부 쿼리를 사용하여 표현식 평가의 미확인 순서를 설명했으나 최소한 생각했습니다. 나는 SELECT CONVERT를 WHERE ISNUMERIC으로 한 내부 쿼리를 수행하고 그 중 하나를 선택하여 외부에서 숫자 필터를 적용했다. 이게 효과가 없어야할까요? – Chase

+0

@Steven. . . 아니. CTE 및 하위 쿼리는 평가 순서에 영향을주지 않습니다. 단일 쿼리 내에서'case '만이이를 보장합니다. –

+0

@GordonLinoff -이 문제는 잘못된 데이터에 참여하지 않는다고 생각할 때 JOIN에서 정말 못 생길 수 있습니다.하지만 평가 순서는 보장되지 않으며 다른 스레드에 최적화되어 있으므로 평가됩니다. – Hogan

관련 문제