2016-04-09 5 views
0

の違いは何ですか、それはエラーを返しはこの文が動作するこれらのSQL文

SELECT * 
FROM artists 
WHERE SUBSTRING(DOB, 0, 5) > '1900' 
     AND CONVERT(INT, DATEPART(DAYOFYEAR, DOB)) = 
         (SELECT CONVERT(INT, datepart(DAYOFYEAR, getdate()))) 

メッセージ242、レベル16、状態3、行1
varcharデータ型をdatetimeデータ型に変換すると、範囲外の値が発生しました。

この1つは今日は年

の100回目の日であることを起こる、私はなぜ、私は、SQL Serverに2008

使用しています理解していない

SELECT * 
FROM artists 
WHERE DOB IS NOT NULL 
    AND SUBSTRING(DOB, 0, 5) > '1900' 
    AND convert(int, DATEPART(DAYOFYEAR, DOB)) = '100' 

の作品列はvarchar(10)と設定されています。私はそこのテーブルに戻って1700年の

日付形式へ行くの日付は、私は、同じデータセットに対して一度に同じウィンドウ、ハイライトと実行1で両方のクエリを置くことができる

1930-04-10 
YYYY-MM-DD 

である持っています。上記の結果を得る。

+2

'SUBSTRING(DOB、0.5)' 'DOB'は文字列ですか? – lad2025

+3

これは[XY問題](http://xyproblem.info/)です。そして、あなたは2つの日付を比較しようとします。あなたが時間の部分をスキップしたい場合/それがユーザーの誕生日かどうかを確認するには、より簡単な方法があります。サンプルデータと希望の結果を提供してください。 – lad2025

+0

これらは両方とも同じデータセット(Database.schema.table?)に対して実行されていると仮定できますか?エラーの性質は、DOBがデータベースが1日の年を解析できない文字列であることを示します。これは無効な形式であるためです。問合せが本当にその時点までIDENTICALなので、結論が出ると、別のデータセットに対して実行する必要があります。 – xQbert

答えて

0

答えは簡単ですが、まだ変です。

この文は

SELECT * FROM artists WHERE SUBSTRING(DOB, 0, 5) > '1900' 
AND CONVERT(INT, DATEPART(DAYOFYEAR, DOB)) = (SELECT CONVERT(INT, datepart(DAYOFYEAR, getdate()))) 

を動作しません。この1は、取得、現在の日付セクションから選択を除去することにより、

SELECT * FROM artists WHERE SUBSTRING(DOB, 0, 5) > '1900' 
AND CONVERT(INT, DATEPART(DAYOFYEAR, DOB)) = (CONVERT(INT, datepart(DAYOFYEAR, getdate()))) 

を行い、文は生活にスプリング、これが唯一のことを意味することができます「選択」(実際には違いはありません)の追加は、優先順位を変更します。これは複雑な意味で意味があります。しかし、私はバグだと主張します。

1

次の2つの条件をチェックしている両方のクエリでは:

SUBSTRING(DOB, 0, 5) > '1900' 

CONVERT(INT, DATEPART(DAYOFYEAR, DOB)) = some integer; 

をDBMSは最初にチェックするかを決定します。明らかに最初のクエリでは、DBMSはまず最初の式をチェックして、のうちDATEPARTで変換できなかったものを除外します。しかし、2番目のクエリは最初に2番目の条件をチェックし、何らかの値を変換しようとして失敗します。

私のアドバイス:あなたの最善の策は、あなたのテーブルを変更し、DATETIME2ではなくVARCHAR(10)として格納されたDOBを持っているだろう。

これはいくつかの理由で実行できない場合は、あなたがサブクエリ(派生テーブル)を用いて、第2の上に第1の条件の優先順位を強制することができます。

select * 
from artists 
from 
(
    select * 
    from artists 
    where substring(dob, 1, 4) > '1900' 
) after_1900 
where datepart(dayofyear, dob) = datepart(dayofyear, getdate()); 

をこれは(たぶん)動作しますが、ではありません完全に適切です。たとえば、DOBには無効な日付( '2016-XY- ??'など)が含まれている可能性があります。または単に「2016-02-30」。そして、DATEPART式では、DOBDATETIMEとして扱います。暗黙の変換が行われ、簡単に失敗する可能性があります。ここで

は、最初の右の日付形式のチェックと日付の変換を明示的に文字列を持つクエリです:

select dob, name 
from 
(
    select convert(datetime2, dob + ' 00:00:00', 120) as dob, name 
    from artists 
    from 
    (
    select dob, name 
    from artists 
    where dob like '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]' 
) valid_data_strings 
) converted 
where datepart(year, dob) > 1900 
and datepart(dayofyear, dob) = datepart(dayofyear, getdate()); 

それでも、これはしかし、2月30日の問題を解決していません。私は、有効な日付文字列を検出し、これらのレコードのみを考慮する簡単な方法はないと思います。可能ですが、確かに閏年ロジックが必要なすべてのもので動作するものもあります。

前述のように、代わりにテーブルのデザインを変更する方が簡単です。

関連する問題