web-dev-qa-db-ja.com

範囲外の値に関するヘルプ

エラーが発生しているこのクエリがあります

Varcharデータ型からdatetimeデータ型への変換により、範囲外の値が発生しました。

クエリ:

select 
    COUNT(*) 
from 
    dbo.patient
INNER JOIN 
    dbo.study on dbo.patient.pk = dbo.study.patient_fk
              and dbo.study.study_datetime IS NOT NULL
              and dbo.patient.pat_birthdate IS NOT NULL
              and dbo.study.study_datetime <= DATEADD(D, -2192, GETDATE())
              and dbo.patient.pat_birthdate <= DATEADD(D, -7670, GETDATE());

これを「DATETIME2」に変換するのに役立つ可能性がある場所を読みましたが、「s.study_datetime」列を正しく変換する方法がわかりません。この列には、エントリとして不適切な値が含まれている可能性が高いためです。

2
Docjay

Varchar列には不正なデータが含まれており、SQL Serverがそれらを評価しようとするタイミング(フィルタリングが行われる前または後)を実際に制御することはできません。したがって、それらが含まれないようにするwhere句を追加できます(値が日付である行のみをチェックすることによって)が、where句が評価される順序の保証はありません(つまり、エラー)。したがって、これらのフィルター(NOT NULLフィルターを論理的に置き換えることができる)に加えて、述部が実際に有効な日付である場合にのみ述部が評価されるようにすることもできます。

SELECT COUNT(*) 
FROM dbo.patient AS p
INNER JOIN dbo.study AS s
  ON s.patient_fk = p.pk
WHERE ISDATE(p.pat_birthdate) = 1
AND ISDATE(s.study_datetime) = 1
AND CASE WHEN ISDATE(s.study_datetime) = 1 THEN s.study_datetime END 
  <= DATEADD(DAY, -2192, GETDATE())
AND CASE WHEN ISDATE(p.pat_birthdate) = 1 THEN p.pat_birthdate END 
  <= DATEADD(DAY, -7670, GETDATE());

次に、ランダムな迷惑メールがこれらの列に届かないようにテーブルを修正してください。最初に以下を使用して不良データを特定します。

SELECT * FROM dbo.study 
  WHERE ISDATE(study_datetime) = 0;

SELECT * FROM dbo.patient
  WHERE ISDATE(pat_birthdate) = 0;

次に、それに応じて修正します(すべて同じパターンの「日付」である場合もあれば、実際にはランダムなジャンクの束であり、NULLに設定する必要があるだけの場合もあります)。そこに悪い値がなくなったら、最初からデータ型をDATEまたはDATETIMEに変更できます。

次の投稿をご覧ください。

5
Aaron Bertrand