2016-05-10 2 views
1

列から最大のDecimal値を取得し、次の値を取得するために1を加算しようとしています。しかし、列の値はvarchar型です。つまり、 '123a'のような値を避けながら、 '123a'のような値をキャストしようとします。10進数にキャストされた最大varcharの選択

私がこれまでに試したことは何ですか例えば100は、ID列に存在する値のような9及び値は、MAXは、私が「100

上9を優先する場合は、私は、これを実行すると、しかし

SELECT 
    (CAST(MAX(Id) AS DECIMAL(38,0)) + 1) AS 'New ID' 
FROM database 
WHERE Id NOT LIKE '%[^0-9]%' --filters out non-numeric ID values 
    AND (LEN(Id) + 1) < 39  --ensures ID is less than length 39 

:本でありますまた試みました:

SELECT 
    (CAST(MAX(CAST(Id AS DECIMAL(38,0))) AS DECIMAL(38,0)) + 1) AS 'New ID' 
FROM database 
WHERE Id NOT LIKE '%[^0-9]%' 
    AND (LEN(Id) + 1) < 39   

しかし、これは、varcharを数値に変換する際にエラーになります。なぜなら、WHERE句で数値以外のIDをフィルタリングする前に10進数としてキャストしようとしていると仮定しているからです。私はまた、最初に余分なキャストを取り除こうとしましたが、それでも同じ問題があります。

ありがとうございました!

+0

キャストが最大値の前に発生するように順序を切り替えます。 'MAX(CAST(Id AS DECIMAL(38,0))+ 1)AS 'New ID''またはそのようなもの..またはCTEを使用して最初に非数値IDを削除し、次にキャストして最大+1を取得してください – xQbert

答えて

0

あなたが欠けているものは、空の文字列です。あなたの条件:Idが空文字列の場合、Id '%[^ 0-9]%'は真です。これは動作するはずです:

SELECT 
    (MAX(CAST(Id AS DECIMAL(38,0))) + 1) AS 'New ID' 
FROM database 
WHERE Id NOT LIKE '%[^0-9]%' 
    AND Id <> '' 
    AND (LEN(Id) + 1) < 39 

外部CASTは冗長です(MAXは引数と同じ型を返します)。

PS:WHERE句はSELECT句の前に評価されるため、WHERE句の無効な値を除外すると、SELECTの変換は失敗しません。

+0

ありがとう、これは完全に機能しました! – Roug

0

あなたはtry_convert()を使用する必要があります。

SELECT MAX(TRY_CONVERT(DECIMAL(38, 0), id)) + 1 AS [New ID] 
FROM database 
WHERE Id NOT LIKE '%[^0-9]%' AND (LEN(Id) + 1) < 39 ; 

あなたの例では、バック小数に変換し、私はあなたが文字列をしたいと思う:

SELECT TRY_CONVERT(VARCHAR(38), MAX(TRY_CONVERT(DECIMAL(38, 0), id)) + 1) AS [New ID] 
FROM database 
WHERE Id NOT LIKE '%[^0-9]%' AND (LEN(Id) + 1) < 39 ; 

あなたが直面している問題は、どのようにSQLに基づいていますサーバーはクエリを処理します。 のWHERE句は、SELECTの前に処理されます。しかし、それは計算がどのように設定されるかではないかもしれません。したがって、SQL Serverは、フィルタリングされる値の変換に不必要な作業をしますが、クエリを中断するエラーが発生します。

私の意見では、これはSQL Serverの実装でのエラーです。 1つは、行が選択されていないときでも、エラーが通過するのを許容する正当な理由があることを前提としています。私たちは皆それが不便であることに同意することができます。

TRY_CONVERT()の前に、この目的のためにCASEステートメントが使用されます。

0

最初に小数点にキャストし、最大値(数値が10以上)を取得してから1を加算し、必要に応じて文字列にキャストします。

SELECT 
    CAST(MAX(CAST(Id AS DECIMAL(38,0))) + 1) AS VARCHAR(39)) AS [New ID] 
FROM database 
WHERE Id NOT LIKE '%[^0-9]%' 
    AND LEN(Id) < 39; 
関連する問題