2

SQL Server から奇妙な動作が発生しています。金額フィールドを返す基本ビューがあります。その金額フィールドは VARCHAR(50) から FLOAT にキャストされています。

次のクエリを正常に実行できます。

SELECT AMOUNT
FROM vReturnDetails

次のクエリも正常に実行できます。

SELECT AMOUNT
FROM vReturnDetails v 
    INNER JOIN MyTable t 
        ON t.LicenceNumber = v.LicenceNumber
        AND t.ReturnYear = v.ReturnYear 
WHERE t.ReturnYear = 2012

同様に、次のクエリを実行できます。

SELECT AMOUNT
FROM vReturnDetails v 
    INNER JOIN MyTable t 
        ON t.LicenceNumber = v.LicenceNumber
        AND t.ReturnYear = v.ReturnYear 
WHERE t.ReturnYear <> 2012

ここが奇妙になりますが、次のいずれも実行できません。

SELECT AMOUNT
FROM vReturnDetails v 
    INNER JOIN MyTable t 
        ON t.LicenceNumber = v.LicenceNumber
        AND t.ReturnYear = v.ReturnYear 
WHERE t.ReturnYear = 2012 OR t.ReturnYear <> 2012

SELECT AMOUNT
FROM vReturnDetails v 
    INNER JOIN MyTable t 
        ON t.LicenceNumber = v.LicenceNumber
        AND t.ReturnYear = v.ReturnYear 

ただし、このクエリを正常に実行できます。

SELECT AMOUNT
FROM vReturnDetails v 
    INNER JOIN MyTable t 
        ON t.LicenceNumber = v.LicenceNumber
        AND t.ReturnYear = v.ReturnYear 
WHERE t.ReturnYear <> 2013 --2013 is a dummy value that doesn't exist

ここのカバーの下で何が起こっているのか、誰かに光を当てることができますか. 私にはまったく意味がないので、問題を解決するためにどこから始めればよいかわかりません。

私が受け取っているエラーは

データ型 varchar を float に変換中にエラーが発生しました。

これはSql Server 2008 SP2にあります

4

3 に答える 3

2

SQL Server は複雑です。SQL エンジンでの処理の順序は、クエリでの順序と必ずしも同じではありません。たとえば、WHERE 句のフィルターは、データの読み取り時、またはデータの処理後に適用できます。

明らかに、AMOUNT フィールドに有効な float ではない値がいくつかあります。最も簡単な説明は、実行したときです。

SELECT AMOUNT
FROM vReturnDetails

すべての行が返されませんでした。. . 不良データの行は後でした。

あるいは、vReturnDetails は基礎となるデータに基づくビューであり、その一部は不適切です。クエリがコンパイルされると、フィルタリングが発生する場所に影響を与える可能性があります。場合によっては、エンジンがすべてのデータを読み取り、変換を実行してから続行することを決定することがありますが、変換中にエラーが発生し、プロセスが中断されます。

ビューを次のように変更することで、これを修正できます。

select (case when isnumeric(amountstr) = 1 then cast(amountstr as float) end) as Amount

SQL Server、case ステートメントでの評価の順序を保証します。したがって、これはエラーを返すべきではありません。

ISNUMERIC() と CONVERT to FLOAT は完全には一致していません。ISNUMERIC がコンマとドル記号 (およびその他の文字) を受け入れることはわかっています。これを試すこともできます (数値に米国スタイルの形式を使用していると仮定します):

select (case when isnumeric(amountstr) = 1
             then cast(replace(replace(amountstr, ',', ''), '$', '') as float) end) as Amount
于 2012-08-21T02:01:18.617 に答える
0

クエリで CONVERT が呼び出されている場所がわかりにくいです。上記のコメントから、AMOUNT が VARCHAR(50) であることを理解しています。どこでFLOATに変換していますか?

于 2012-08-21T01:44:45.503 に答える