sql >> データベース >  >> RDS >> Sqlserver

有効な日付が含まれている場合にのみvarcharを日付に変換するにはどうすればよいですか?

    典型的な答えは、WHERE句を追加することです:

    WHERE ISDATE(a.valor) = 1
    

    ただし、これはいくつかの理由で状況に問題があります。

    1. ISDATE() サーバーの地域設定、ユーザーの言語または日付形式のオプションなどによっては、必ずしも希望どおりに一致するとは限りません。例:

      SET DATEFORMAT dmy;
      SELECT ISDATE('13/01/2012'); -- 1
      
      SET DATEFORMAT mdy;
      SELECT ISDATE('13/01/2012'); -- 0
      
    2. SQLServerがCONVERTを実行しようとすることを実際に制御することはできません。 フィルターの後。

    SQLServerはできるため、サブクエリやCTEを使用してフィルターをCONVERTから分離することもできません。 クエリの操作を、より効率的と思われる順序で最適化します。

    たとえば、限られたサンプルでは、​​これで問題がないことがわかるでしょう:

    SET DATEFORMAT dmy;
    
    SELECT valor, valor_date FROM (
      SELECT valor, valor_date = CONVERT(DATE, 
        CASE WHEN ISDATE(valor) = 1 THEN valor ELSE NULL END, 103)
      FROM dbo.mytable
      WHERE ISDATE(valor) = 1
    ) AS sub WHERE valor_date BETWEEN '01/01/2012' AND '01/03/2012';
    

    しかし、SQL Serverが最初にフィルターを評価しようとして、現在発生しているのと同じエラーが発生する、この構成のケースも見ました。

    より安全な回避策がいくつかあります:

    計算列を追加します。例:

    ALTER TABLE dbo.mytable ADD valor_date
      AS CONVERT(DATE, CASE WHEN ISDATE(valor) = 1 THEN valor 
        ELSE NULL END, 103);
    

    実行時に起こりうる誤解から身を守るために、計算列を参照するクエリを発行する前に、dateformatを指定する必要があります。例:

    SET DATEFORMAT dmy;
    SELECT valor, valor_date FROM dbo.mytable WHERE ...;
    

    ビューを作成する:

    CREATE VIEW dbo.myview
    AS
      SELECT valor, valor_date = CONVERT(DATE, 
        CASE WHEN ISDATE(valor) = 1 THEN valor ELSE NULL END, 103)
      FROM dbo.mytable
      WHERE ISDATE(valor) = 1;
    

    繰り返しになりますが、SET DATEFORMATを発行する必要があります ビューをクエリするとき。

    一時テーブルを使用する:

    SELECT <cols>
    INTO #foo
    FROM dbo.mytable
    WHERE ISDATE(valor) = 1;
    
    SELECT <cols>, CONVERT(DATE, valor) FROM #foo WHERE ...;
    

    それでもDATEFORMATを使用することをお勧めします ISDATE間の競合から身を守るため およびユーザー設定。

    いいえ、すべきではありません 別の(現在は削除されている)回答で提案されているように、文字列パターンマッチングを使用して、文字列を日付として検証してみてください:

    like '%__/%' or like '%/%'
    

    うるう年を含むすべての有効な日付を処理するには、かなり複雑で手間のかかる検証が必要になります。



    1. オラクルで最新の従業員レコードを取得するにはどうすればよいですか?

    2. #temptableと##TempTableの違いは?

    3. MySQLテーブルを2番目のドライブに移動できますか?

    4. PostgreSQL SHOW TABLES Equivalent(psql)