2017-05-26 6 views
0

残念ながら、浮動小数点データ型を比較す​​る2つのテーブルがあります。私はキャスト、変換者、小さな違いを使用して試してみて、それらを試してみました。ストアドプロシージャ内のSQL Serverの浮動小数点比較

奇妙な部分は、これはストアドプロシージャを実行しているときにのみ失敗します。ストアドプロシージャの本体をSSMSウィンドウに切り取って貼り付けると、うまく動作します。

サンプルSQL:

set @newEnvRiskLevel = -1 

select 
    @newEnvRiskLevel = rl.RiskLevelId 
from 
    LookupTypes lt 
inner join 
    RiskLevels rl on lt.LookupTypeId = rl.RiskLevelTypeFk 
where 
    lt.Code = 'RISK_LEVEL_ENVIRONMENTAL' 
    and convert(numeric(1, 0), rl.RiskFactor) = @newEnvScore 

set @errorCode = @@ERROR 

if (@newEnvRiskLevel = -1 or @errorCode != 0) 
begin 
    print 'newEnvScore = ' + cast(@newEnvScore as varchar) + ' and risk level = ' + cast(isnull(@newEnvRiskLevel, -1) as varchar) 
    print 'ERROR finding environmental risk level for code ' + @itemCode + ', skipping record' 
    set @recordsErrored = @recordsErrored + 1 
    goto NEXTREC 
end 

マイ@newEnvScore変数もnumeric(1, 0)に変換floatです。私はRiskFactor列に値0,1,2、および3しかないことを確認しました(デバッグを介して)@newEnvScoreの値は2です。私のクエリにはコード= 「RISK_LEVEL_ENVIRONMENTAL」とRiskFactor = 2

私は障害がで-1滞在@newEnvRiskLevelに起因して、デバッグを経由して検証してきましたし、その@errorCodeは私も両方の10進数のキャストを試してみた0

で、 int、intに変換し、 "rl.RiskFactor - @newEnvScore < 1"を私のwhere節に置き換えます。いずれもnewEnvRiskLevelを設定しません。

私が言うように、これはしか実行されませんが、実際には理解できない部分です。私は、SQLがストアドプロシージャの本体を実行しているのか、まったく同じSQLをSSMSタブに実行しているのかにかかわらず、SQL Serverが決定論的であることを期待しています。

+3

何が問題なのですか?間違いはありますか?正しい情報は返されませんか? –

+0

テーブルのコンテキストを提供することも役に立ちます。うん、私は値が何であるか教えてくれたことは知っていますが、今のところペーストするための具体的なデータはありません。 –

+0

また、変換(数値(1、0)、rl.RiskFactor)= @newEnvScoreなどのキャストを実行する際に問題が見つかりました。変換してみましたか(数値(1、0)、rl.RiskFactor)=変換(数値(1、0)、@newEnvScore)?おそらく奇妙なことが鋳造時に起こる可能性がある冗長... –

答えて

0

ストアドプロシージャも完全なスクリプトも投稿しないことは残念です。有用なデモンストレーションがなければ問題を診断することは困難です。しかし、私は多くの点で関連している "goto"の使用を見ます。また、ローカル変数を割り当てるためにselectステートメントを使用することもあります。これは、開発者が代入が常に発生すると仮定していることが多いため、しばしば問題になります。証明するために - ボーナスで終わり

set nocount on; 
declare @risk smallint; 
declare @risklevels table (risklevel float primary key, code varchar(10)); 
insert @risklevels(risklevel, code) values (1, 'test'), (2, 'test'), (-5, 'test'); 

-- here is your assignment logic. Notice that @risk is 
-- never changed because there are no matching rows. 
set @risk = 0; 
select @risk = risklevel from @risklevels where code = 'zork'; 
select @risk; 

-- here is a better IMO way to make the assignment. Note that 
-- @risk is set to NULL when there are no matching rows. 
set @risk = -1; 
set @risk = (select risklevel from @risklevels where code = 'zork'); 
select @risk; 

-- and a last misconception. What value is @risk set to? and why? 
set @risk = -1; 
select @risk = risklevel from @risklevels where code = 'test'; 
select @risk; 

で、これが問題の原因である(またはそれに貢献する)かどうか私が言うことはできません。しかし、それは可能性です。浮動小数点データ型に整数を格納することは一般的に問題に過ぎません。テーブルを変更できない場合でも、ローカル変数を変更して、より適切なデータ型の使用を強制することができます。それはおそらくあなたが考慮すべきもう一つの変化です。

+0

アイデアありがとう。 sprocはかなり大きいです、私は皆を圧倒したくありませんでした。 nullを使用する場合は、最初に-1の代わりにその値を使用し、if文で 'is null'をチェックしました。どんなものでも、ヌルか-1は、私がマッチしなかったことを伝えるダミーの値です。私が上で述べたように、これは一度限りの大量更新であり、手動で実行することに害はありません。 SSMSのタブでSQLを実行するのが、CREATE PROCEDUREステートメントでラップされた正確なSQLとは異なる動作をしてから、そのプロシージャを実行する理由が不思議です。 –

関連する問題