2011-07-08 29 views
4

SQL Serverの:リターン以下SQL Serverの:機能評価時間2005

クエリデータなし((0行(複数可)の影響を受ける))、OK。

ただし、行番号3関数呼び出しが有効な場合、クエリは失敗します。
"文字列からdatetimeを変換するときに変換に失敗しました。" Oracleのバックグラウンドから来

- これはちょうど考えられません!
何が起こっているのか教えてください - 間違っているのですか?
SSは最後のステップでSELECTリストの関数呼び出しを評価しません(Oracleのように、または分かりやすいプログラマが行うように)?

 
select 
    1 as one 
    --,DATEPART(yyyy,cast(inception_date27 as datetime)) as inception_yr 
from [DBO].[H5_PREMIUM_DETAIL] dtl, 
     [DBO].[H5_POLICY_MASTER] polmst 
    where polmst.policy_no2 = cast(dtl.arch_master_policy_no41 as numeric)  
    and len(inception_date27) != 8 

Here is a small clip I recorded

おかげ


注:私はSSはおよそここで文句こと(一部の行が "0" の代わりに "20110704" を持っている)不良データのルートソースを知っています - なぜJOINからデータが見つからない場合にこの障害が発生するのですか。

+0

ちょうどいいですが、文字列からdatetimeに変換するときに変換が失敗したと言えます。これは、** inception_date27 **列がおそらくdatetimeデータ型に正しく変換できない形式であることを示しています。 – Flimzy

+2

私は質問のポイントは、ゼロ行が返されているので、なぜSql Serverは任意の値をキャストしようとしていると思いますか? –

+0

ここで何か他のことが起こっているかどうかを確認するために、クエリプランを確認すると便利です。 Sql Serverが実際に関数の評価を延期していることを示す簡単な例: 'SELECT CAST( 'xxxx' AS DATETIME)WHERE 1 = 0' –

答えて

2

たぶん、あなたは8

に異なるlenのない8にLENが等しいている必要があります別の方法は、とき、日付のケースを使用することです

len(inception_date27) = 8 

len(inception_date27) != 8 

を交換してください有効でない場合NULLを返します

例:あなたのクエリを見て

DECLARE @mydate VARCHAR(8) 

SET @mydate = '20100708' 

SELECT CASE WHEN LEN(@mydate) = 8 THEN DATEPART(yyyy,CAST(@mydate AS datetime)) ELSE NULL END 
--WHERE LEN(@mydate) <> 8 
+0

はい2番目の提案は良いので、述語len(inception_date27)= 8を追加する必要はありません。(私はしたくありません)FORCEにデータを返さないように "len(inception_date27)!= 8"を追加しました。 – Ralph

1

あなたは積極的にlen(inception_date27)!=8を言っているので、あなたはおそらく何の結果が現れないことを期待しています。

しかし、そこに値が「0」であることがわかっていると指定します。返されているのは0!=8です。したがって、結果は返されます。

はその後何が起こるかを見るために(0=1)len(inception_date27)!=8を交換してみてください。それは間違いなく結果を返さないはずです。

+0

ここに書式設定された返信:http://paste.pocoo.org/show/433536/ – Ralph

6

SSは最後のステップでSELECTリストの関数呼び出しを評価していません(オラクルのように - または分かりやすいプログラマが行います)?

(および - いいえ)。

SQLの一般的なルールは、クエリの部分が処理されるように見えるように定義された「順序」があることです。ただし、異なるデータベースシステムでは、その結果を自由に並べ替えることができます同じ。

しかし、あまりにもあいまいさがあります.SQL Serverは、他の方法で予想よりも早くコンバージョンをプッシュする可能性が高いと思われます。操作のIOオーバーヘッドを考慮すると、結合操作を実行する費用(テーブルの大きさ、オプティマイザが選択した結合の種類)、結合が発生する前に変換操作を実行することは実質的に自由であるため、オプティマイザが選択したものです。

SQL Serverが処理中に行内でこのような変換エラーをマークでき、結果セットにまだ変換に失敗した行が含まれている場合は、最後にレポートするだけでいいです働くSELECT句のCASE表現にそれのすべてをプッシュ

はおそらく、(同様の答えをniktrsするために)十分だろう:

SELECT 
    /* Other columns */ 
    CASE 
     WHEN inception_date27 LIKE '[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]' 
      THEN DATEPART(year,CONVERT(datetime,inception_date27)) 
    END 
+0

いいです! WHEREで使用することもできます。私はあなたのように改善することができると思う:LIKE '[12] [0-9] [0-9] [0-9] [01] [0-9] [0-3] [0-9]'。また、これはpropably記載された@ypercubeとしてインデックスを使用します。 +1 – niktrs

0

SQL-Serverがクエリを実行するために内部でどのように機能するかをどのように正確な詳細を知らなくてもそのような動作のための私の推測では、それを実行するために並列プロセスまたはスレッドを使用するということです。

メイン処理結果を収集、変換DATEPART(yyyy,cast(inception_date27 as datetime))を行っている第3のプロセスに一致する行を送信している間そこで、3つのスレッド、polmst.policy_no2 = cast(dtl.arch_master_policy_no41 as numeric)をチェック一つ別のチェックlen(inception_date27) != 8があってもよいです。

これにより、上記のエラーは発生しません。しかし、上記の条件でのCAST()LEN()の出現は、関連分野における索引の使用を禁じている。だからおそらく(それは私の野生の推測です)、1番目のプロセスは2番目のプロセスよりも遅く、2番目のスレッドの結果を3番目のプロセスに送信します。

データベースがクエリを実行する通常の方法である可能性があります。あなたはそれを以前に見たことがない。 Oracleも同様に動作する可能性があります。

inception_date27フィールドは[H5_PREMIUM_DETAIL] (dtl)テーブルにあります。

以下のようにクエリを記述し、同じエラーが発生していることを確認できますか?サブクエリは実行順序を強制しないため、まだ実行されている可能性があります。

select 
    1 as one 
    ,DATEPART(yyyy,cast(inception_date27 as datetime)) as inception_yr 
from 
    (select 
     cast(arch_master_policy_no41 as numeric) as arch_master_policy_no41 
     ,inception_date27 
     from [DBO].[H5_PREMIUM_DETAIL] 
     where len(inception_date27) != 8 
    ) dtl, 
    [DBO].[H5_POLICY_MASTER] polmst 
    where polmst.policy_no2 = dtl.arch_master_policy_no41  
+0

@Damienには、適切にインデックスを使用する良い選択肢があります。 – niktrs

+0

@niktrs:あなたの選択肢(と@Damien's)は、サーバーに不正なデータで 'DATEPART()'関数を使わないようにする良い方法です。私はインデックスについてはわかりません(おそらくそれらを使用していません)が、それは無関係です。 –

+0

@ DemianのコードLIKE '[0-9] [0-9] [0-9] [0-9] [0-9] [0-9] [0-9] [0-9]'はSQLサーバがWHEREに置かれている場合はインデックスを使用します。つまり、LENを使用する代わりに – niktrs

0

WHERE句にISDATE関数を使用して、有効な日付文字列があることを確認してください。