복붙노트

[SQL] DECIMAL에 VARCHAR

SQL

DECIMAL에 VARCHAR

나는 진수 (10,4)에 VARCHAR (최대) 열을 변환 할.

내가 사용하는 캐스트를 시도하거나 변환 할 때 나는 산술 오버플로 예외를 얻고있다. 문제는 varchar 열 내에 저장된 데이터는 상이한 정밀도 다른 척도를 포함 할 수 있다는 것이다. 예를 들어, 123456789.1234567 ', 1.12345678 또는 123456.1234.

123456.1234 같은 값의 경우는 어떤 문제를 밖으로 변환되어 있지만 다른 값에 대한 좀 문제가 있어요.

어떤 도움을 주시면 감사하겠습니다.

해결법

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

    1.나는 그것이 문제의 원인이 된 소수의 장소가 아니다 것을 발견 테스트 후에이었다 정밀도 (10)

    나는 그것이 문제의 원인이 된 소수의 장소가 아니다 것을 발견 테스트 후에이었다 정밀도 (10)

    이것은 작동하지 않습니다 : 산술 오버플로 오류가 데이터 형식의 숫자에 VARCHAR로 변환.

    DECLARE @TestConvert VARCHAR(MAX) = '123456789.12343594'
    
    SELECT CAST(@TestConvert AS DECIMAL(10, 4))
    

    이 일

    DECLARE @TestConvert VARCHAR(MAX) = '123456789.12343594'
    
    SELECT CAST(@TestConvert AS DECIMAL(18, 4))
    
  2. ==============================

    2.내 설명은 코드입니다. :)

    내 설명은 코드입니다. :)

    DECLARE @TestConvert VARCHAR(MAX) = '123456789.1234567'
    BEGIN TRY
        SELECT CAST(@TestConvert AS DECIMAL(10, 4))
    END TRY
    BEGIN CATCH
        SELECT 'The reason you get the message "' + ERROR_MESSAGE() + '" is because DECIMAL(10, 4) only allows for 4 numbers after the decimal.'
    END CATCH
    
    -- Here's one way to truncate the string to a castable value.
    SELECT CAST(LEFT(@TestConvert, (CHARINDEX('.', @TestConvert, 1) + 4)) AS DECIMAL(14, 4))
    
    -- If you noticed, I changed it to DECIMAL(14, 4) instead of DECIMAL(10, 4) That's because this number has 14 digits, as proven below.
    -- Read this for a better explanation as to what precision, scale and length mean: http://msdn.microsoft.com/en-us/library/ms190476(v=sql.105).aspx
    SELECT LEN(LEFT(@TestConvert, (CHARINDEX('.', @TestConvert, 1) + 4)))
    
  3. ==============================

    3.당신은 6.999,50이 유효한 진수 아니라는 사실을 누락되었습니다. 쉼표 확실 진수 값의 소수점을 가질 수 없습니다? 어떤 숫자 것은이 있어야하는데?

    당신은 6.999,50이 유효한 진수 아니라는 사실을 누락되었습니다. 쉼표 확실 진수 값의 소수점을 가질 수 없습니다? 어떤 숫자 것은이 있어야하는데?

    로케일 지정 가정. 로 소수 구분 기호로, 그룹화 : 그룹화 자리를 제거하려면 :

    SELECT CONVERT (십진수 (11,2), REPLACE ( '6.999,50', '.', ''))

    소수로 6999,50을 얻을 것입니다

  4. ==============================

    4.나는 다음과 같은 해결책을했다 :

    나는 다음과 같은 해결책을했다 :

    SELECT [Str], DecimalParsed = CASE 
    WHEN ISNUMERIC([Str]) = 1 AND CHARINDEX('.', [Str])=0 AND LEN(REPLACE(REPLACE([Str], '-', ''), '+', '')) < 29 THEN CONVERT(decimal(38,10), [Str])
    WHEN ISNUMERIC([Str]) = 1 AND (CHARINDEX('.', [Str])!=0 AND CHARINDEX('.', REPLACE(REPLACE([Str], '-', ''), '+', ''))<=29) THEN 
        CONVERT(decimal(38,10), 
                CASE WHEN LEN([Str]) - LEN(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE([Str], '0', ''), '1', ''), '2', ''), '3', ''), '4', ''), '5', ''), '6', ''), '7', ''), '8', ''), '9', '')) <= 38 
                     THEN [Str] 
                     ELSE SUBSTRING([Str], 1, 38 + LEN(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE([Str], '0', ''), '1', ''), '2', ''), '3', ''), '4', ''), '5', ''), '6', ''), '7', ''), '8', ''), '9', ''))) END)
    ELSE NULL END
    FROM TestStrToDecimal
    

    나는 그것이 잔인한 것 같습니다 아마도 그것이 알고 있지만, 그것은 나를 위해 작동 (다른 정밀도와 규모 모두 긍정적, 부정적, 크고 작은 번호를 확인 - 모든 것이 진수 (38,10) 또는 NULL로 변환된다).

    당신이 다른 정밀도를 필요로하는 코드 (38, 10, 29)에 상수를 변경 그렇다면, 진수 (38,10) 유형에 하드 코딩되어있다.

    그것은 어떻게 작동 하는가? 결과는 다음과 같습니다

    각각의 경우는 위의 코드에서 언제 문 별개입니다.

    다음은 변환의 몇 가지 예입니다 :

  5. ==============================

    5.당신은 당신이 칼럼에 넣어 전에 문자열로 값을 직접 절단해야 할 것입니다.

    당신은 당신이 칼럼에 넣어 전에 문자열로 값을 직접 절단해야 할 것입니다.

    당신이 더 많은 소수 자릿수를 원하는 경우 그렇지 않으면, 당신은 소수점 열 당신의 선언을 변경해야합니다.

  6. ==============================

    6.당신은 플로트 데이터 형식을 사용할 수없는 이유 당신은 아직 설명하지 않은, 그래서 여기에 예입니다 :

    당신은 플로트 데이터 형식을 사용할 수없는 이유 당신은 아직 설명하지 않은, 그래서 여기에 예입니다 :

    DECLARE @StringVal varchar(50)
    
    SET @StringVal = '123456789.1234567'
    SELECT @StringVal, CAST(@StringVal AS FLOAT)
    
    SET @StringVal = '1.12345678'
    SELECT @StringVal, CAST(@StringVal AS FLOAT)
    
    SET @StringVal = '123456.1234'
    SELECT @StringVal, CAST(@StringVal AS FLOAT)
    
  7. ==============================

    7.귀하의 주요 문제는 소수의 오른쪽에 물건 아니라, 왼쪽으로 물건입니다. 당신의 유형 선언에서 두 값은 정밀도와 스케일입니다.

    귀하의 주요 문제는 소수의 오른쪽에 물건 아니라, 왼쪽으로 물건입니다. 당신의 유형 선언에서 두 값은 정밀도와 스케일입니다.

    당신이 (10, 4)를 지정하면, 그 수단은 당신은 단지 소수, 또는 999999.9999의 최대 숫자의 왼쪽에 6 개 자리를 저장할 수 있습니다. 보다 더 큰 아무거나는 오버 플로우가 발생합니다.

  8. ==============================

    8.사용자 정의 기능을 사용하여 구현됩니다. 문자열 값 안전하게 진수로 변환 할 수 있는지 여부를이 확인합니다

    사용자 정의 기능을 사용하여 구현됩니다. 문자열 값 안전하게 진수로 변환 할 수 있는지 여부를이 확인합니다

    CREATE FUNCTION [dbo].[TryParseAsDecimal]
    (
        @Value      NVARCHAR(4000)
        ,@Precision INT
        ,@Scale     INT
    )
    
    RETURNS BIT
    AS
    BEGIN
    
        IF(ISNUMERIC(@Value) =0) BEGIN
            RETURN CAST(0 AS BIT)
        END
        SELECT @Value = REPLACE(@Value,',','') --Removes the comma
    
        --This function validates only the first part eg '1234567.8901111111'
        --It validates only the values before the '.' ie '1234567.'
        DECLARE @Index          INT
        DECLARE @Part1Length    INT 
        DECLARE @Part1          VARCHAR(4000)   
    
        SELECT @Index = CHARINDEX('.', @Value, 0)
        IF (@Index>0) BEGIN
            --If decimal places, extract the left part only and cast it to avoid leading zeros (eg.'0000000001' => '1')
            SELECT @Part1 =LEFT(@Value, @Index-1);
            SELECT @Part1=SUBSTRING(@Part1, PATINDEX('%[^0]%', @Part1+'.'), LEN(@Part1));
            SELECT @Part1Length = LEN(@Part1);
        END
        ELSE BEGIN
            SELECT @Part1 =CAST(@Value AS DECIMAL);
            SELECT @Part1Length= LEN(@Part1)
        END 
    
        IF (@Part1Length > (@Precision-@Scale)) BEGIN
            RETURN CAST(0 AS BIT)
        END
    
        RETURN CAST(1 AS BIT)
    
    END
    
  9. ==============================

    9.나는이 오래된 질문 알아요,하지만 빌은 실제로 문제를 "설명"한 유일한 것 같다. 모두가 다른 선언의 오용 복잡한 솔루션으로 올라오고있는 것 같다.

    나는이 오래된 질문 알아요,하지만 빌은 실제로 문제를 "설명"한 유일한 것 같다. 모두가 다른 선언의 오용 복잡한 솔루션으로 올라오고있는 것 같다.

    ...

    당신이 DECIMAL (10,4)를 선언하는 경우 그래서 당신은 그들 중 4 소수점 후에 오는 10 개 숫자의 총을 가질 수 있습니다. 그래서 123456.1234 10 자리 소수점 후 4를 갖는다. 즉, 소수의 매개 변수 (10,4)에 맞는. 1234567.1234 오류가 발생합니다. 착용감이 11 진수 10 자릿수의 공간으로하고, 4 개 자리가 소수점하여 사용되어야한다. 소수의 왼쪽에 떨어져 자리를 트리밍 옵션을 선택하지 않습니다. 당신의 11 개 문자 123456.12345가 있다면, 이것은 진수 값의 끝에서 (반올림)를 트리밍으로 오류가 발생하지 않을 것은 허용됩니다.

    소수를 선언 할 때, 항상 열이 현실적으로 사용할 수있는 최대 당신이보고 싶은 소수 자릿수의 최대 수를 선언하려고합니다. 그래서 열은 오직 1 백만의 최대 값을 표시 할 경우에만 DECIMAL로, 처음 두 소수점에 대해 (9,2)를 선언 신경. 오류가 발생하기 전에 이렇게하면 9,999,999.99의 최대 수를 줄 것이다.

    당신이 그것을 해결하기 전에 문제를 이해, 당신은 당신의 상황에 맞는 수정을 선택 보장합니다, 도움 당신은 수정이 / 작품을 필요로하는 이유를 이해할 수 있습니다.

    다시 말하지만, 나는 5 년 늦게 파티에이야 알고있다. 그러나, 이것에 대한 해결책을 내 두 센트 (열이 이미 DECIMAL (10,4로 설정) 변경 될 질수 귀하의 의견에 의해 판단) 가장 쉬운 방법은 두 가지 단계가 될 것이라고 할 수 있습니다. 다음 10 자리 트림, 당신의 진수 멀리 10 점보다 더하지 있는지 확인합니다.

    CASE WHEN CHARINDEX('.',CONVERT(VARCHAR(50),[columnName]))>10 THEN 'DealWithIt'
    ELSE LEFT(CONVERT(VARCHAR(50),[columnName]),10) 
    END AS [10PointDecimalString]
    

    당신은 이상 10 자리, 소수의 왼쪽에있는 값으로 처리 할 수 ​​있도록 내가 문자열로이 왼쪽 이유입니다.

    그러나 자사의 시작.

  10. ==============================

    10.혹시 ROUND에 결과가 아니라 잘라 내기 필요, 이것을 사용할 수 있습니다 :

    혹시 ROUND에 결과가 아니라 잘라 내기 필요, 이것을 사용할 수 있습니다 :

    select convert(decimal(38,4), round(convert(decimal(38,10), '123456789.1234567'),4))
    

    이것은 다음을 반환합니다 :

    '123456789.1235' for '123456789.1234567'
    '123456789.1234' for '123456789.1234467'
    
  11. from https://stackoverflow.com/questions/11089125/varchar-to-decimal by cc-by-sa and MIT license