2012-03-20 14 views
0

こんにちは私はいくつかのサードパーティのソフトウェアに対して報告されたアプリケーションを持っています。残念ながら、それはnvarchar型としてすべての値を格納したときにNVARCHARフィールドの日付値を検証

"Conversion failed when converting date and/or time from character string" 
System.Data.SqlClient.SqlException was unhandled by user code 

か、私は次のエラーを取得していた結果として、私はSSMSでコードを実行しようとした場合、クライアント側でのデータ入力を検証しません。

Msg 241, Level 16, State 1, Procedure settlement_list, Line 10 
Conversion failed when converting date and/or time from character string. 

私はこれは誰かが私は不正な値を見つけるために、このISDATEコードを試してみたデータフィールドにテキスト値を入力した結果であると仮定します。

SELECT mat3_02_01, CONVERT(datetime, mat3_04_02), mat3_04_02 FROM lntmu11.matter3 
    WHERE ISDATE(mat3_04_02) <> 1 
    AND Coalesce(mat3_04_02, '') <> '' 
    order by mat3_04_02 desc 

を、私はゼロの行が返された...私を取得また、手動でデータを篩い分けしました。

誰にも提案はありますか?

EDIT ---ここ

は、ストアドプロシージャ(句は醜いです、私が知っている)あなたが順序を強制することはできません

SELECT mat_no, 'index'=matter.mat1_01_06, 
    'insurance'=Replace(Replace(matter.mat1_03_01, 'INSURANCE COMPANY', ' '), 'COMPANY', ''), 
    matter.[status], 'casestage'=mat1_04_01, 'injured'=matter.MAT1_01_07, matter.client, 
'terms'=mat3_04_06, 'ClmAmt'=matter.mat1_07_01, 
    'ClmBal'=matter.mat1_07_03, 'SetTot'=matter3.MAT3_04_09, 'By'=mat3_03_02, 
    'DtSttld'=mat3_04_02, 'SettlStg'=(MAT3_06_08 + '/' + MAT3_06_05) 
FROM [lntmu11].matter3 inner join 
[lntmu11].matter ON [lntmu11].matter.sysid = [lntmu11].matter3.sysid 
WHERE 
(DateDiff(month, convert(datetime, MAT3_04_02, 101), GETDATE()) = @range 
    and mat3_03_02 like @by) 
or 
(mat3_04_06 like @by2 
    and DateDiff(month, convert(datetime, MAT3_04_02, 101), GETDATE()) = @range) 
ORDER BY MAT3_03_02 
+0

を見つける変身しましたタイトルに "MSSQL"などを付ける。それがタグのためのものです。 –

+0

は ISDATE(mat3_04_02)= 1 と 合体(mat3_04_02、 '')= '' が合体しません(mat3_04_02を、 '')= '' が唯一のヌルと一致するクエリを調べますか? 日付とnullの両方にすることはできません。 – Paparazzi

+0

@Blamそれは良い点です...自分の投稿を編集していたとき、私はもともと、「これはIS NOT NULLではないはずですか? –

答えて

2

クエリエンジンが最初せずに文を処理しようとしています#テンポテーブルにISDATE() = 1の行をダンプします。不正な行を最初にフィルタリングするためにCTEまたはサブクエリを使用することを推奨する場合でも、処理順序または短絡を保証することはできません。したがって、いくつかの提案があります:

;WITH x AS 
(
    SELECT mat3_02_01, mat3_04_02 
    FROM Intmu11.matter3 
    WHERE ISDATE(mat3_04_02) = 1 
    AND mat3_04_02 IS NOT NULL -- edited! 
) 
SELECT mat3_02_01, CONVERT(DATETIME, mat3_04_02), mat3_04_02 
FROM x 
ORDER BY mat3_04_02 DESC; 

これは今日でも機能するようです。しかし、長期的には、本当にこの処理順序を保証する唯一の方法 - SQL Serverの現在のバージョンでは - です:

SELECT mat3_02_01, mat3_04_02 
    INTO #x 
    FROM Intmu11.matter3 
    WHERE ISDATE(mat3_04_02) = 1 
    AND mat3_04_02 IS NOT NULL; -- edited! 

SELECT mat3_02_01, CONVERT(DATETIME, mat3_04_02), mat3_04_02 
    FROM #x 
    ORDER BY mat3_04_02 DESC; 

あなたは入力に値を検証し考えたことはありますか?たとえば、悪いデータを選択した人を処罰するのではなく、無効な日付を入力したときに手首に適用することによって、このエラーがアプリケーションに表示される場所を変更できます。あなたが更新を制御している場合は/ストアドプロシージャを経由して挿入し、あなたが言うことができます。

IF ISDATE(@mat3_04_02) = 0 
BEGIN 
    RAISERROR('Please enter a valid date.', 11, 1); 
    RETURN; 
END 

ストアドプロシージャ(複数可)を介してデータ操作を制御されていない場合、あなたがテーブルにチェック制約を追加することができます(既存の不良データをクリーンアップした後)。

UPDATE Intmu11.matter3 SET mat3_04_02 = NULL 
    WHERE ISDATE(mat3_04_02) = 0; 

ALTER TABLE Intmu11 WITH NOCHECK 
    ADD CONSTRAINT mat3_04_02_valid_date CHECK (ISDATE(mat3_04_02)=1); 

エラーメッセージは、それらが制約名が表示され、うまくいけば、失敗したフロントエンドのデータ・エントリ・ポイントにそれをマッピングすることができるようになりますユーザーまで泡立てます。この方法:

メッセージレベル547、レベル16、状態0、行1
INSERTステートメントがCHECK制約 "mat3_04_02_valid_date"を使用して と競合しました。データベース "your_db"、テーブル "Intmu11.matter3"、列 "mat3_04_02"で競合が発生しました。
ステートメントが終了しました。

さらに、正しいデータ型を最初に使用してください。ここでも、NULLように、既存の不正なデータを更新した後、あなたが言うことができます。

ALTER TABLE Intmu11.matter3 ALTER COLUMN mat3_04_02 DATETIME; 

誰かが非日付を入力しようとすると今、彼らは、彼らがしようとすると、ユーザーは、現在取得しているのと同じエラーが発生します文字列から日付/時刻を変換する際に
変換が失敗した

メッセージ241、レベル16、状態1、行1:不正なデータを選択します。

SQL Server 2012では、TRY_CONVERT()でこれを回避できますが、最初からデータ型を取得しようとしている必要があります。

+0

"を使用してください。入力値の検証について考えましたか?残念ながら、私はソースコードへのアクセス権がありません。サードパーティ製のソフトウェアです...私が問題を理解することができれば、悪い価値を取り除くという仕事を考えていました。私はこれらの変更の両方を試み、まだ行がありませんか?私はここで何が欠けているのですか? –

+0

p.s.あなたはSQLの獣私の友人です –

+0

あなたはゼロの行を持っている場合は、誰も有効な日付を入力したように聞こえる。これはさらに、データ型を修正する必要がある理由をさらに証明するはずです。あなたが持っている 'WHERE'句は、(すべての行のようです)、無効な日付を除外、しかし非常に気をつけている - 別のプランのSQL Serverとフィルター*前に' CONVERT' *を処理しようとするかもしれません。 –

1

ISDATE(mat3_04_02) = 1 
    AND 
    Coalesce(mat3_04_02, '') = '' 

クエリは、それが値を持たなければならない日であるために調べます。 ただし、値が設定されていない場合は、2番目の条件に一致します。 これら2つの条件の交差点(および)は常にfalseです。

あなたはヌルを探しているなら、「mat3_04_02がnullである」しかし、それはまだ0の行を返します。

私はあなたが日付ソートしていない文字列をしたいと思う

SELECT mat3_02_01, CONVERT(datetime, mat3_04_02), mat3_04_02 
    FROM lntmu11.matter3 
    WHERE ISDATE(mat3_04_02) = 1 
    order by CONVERT(datetime, mat3_04_02) desc 

を試してみては

をソート質問は、有効な日付を見つけて開始し、それはドンしてください無効な日付

SELECT mat3_02_01, mat3_04_02 
    FROM lntmu11.matter3 
    WHERE ISDATE(mat3_04_02) = 0 
    AND mat3_04_02 is not null 
    order by mat3_04_02) desc 
+0

試してみました:私はこれを試して、それは私に有効な日付の行を返しますか? ISDATE(..)= 0を試してみると、100,000個の空の行がありますが、悪いテキストデータはありませんか? –

+2

元の質問は有効な日付を見つけることでした。どのようなことが起こっているのかを理解するために、この質問に従った誰かを期待してください。どのようにCONVERT(datetime、mat3_04_02)が無効な日付で成功すると思いますか? – Paparazzi

+0

私はちょっとイライラしていることに同意します:( –