it-swarm.com.de

Die Konvertierung ist beim Konvertieren von Datum und / oder Uhrzeit aus der Zeichenfolge fehlgeschlagen

Ich habe ein Problem, weil ich diese Abfrage ohne Probleme verwendet habe ... bis jetzt:

UPDATE T1
SET ORDINAL = DATEDIFF(DAY, T2.Opening_Date, T1.Date)
FROM FactTransactions T1
INNER JOIN DimStore T2 ON T1.cod_store = T2.cod_storeKey

Aber jetzt gab es mir einen Fehler:

Die Konvertierung ist beim Konvertieren von Datum und/oder Uhrzeit aus der Zeichenfolge fehlgeschlagen

Ich habe keine Ahnung, was los ist. Hier sind die Spalten:

Ordinal(numeric,null)
Opening_date(varchar, not null)
Date(varchar, not null)
cod_store(int,not null)
cod_storekey(PK,int, not null)
4
Miguel

Sie speichern Daten als Zeichenfolgen - warum? Opening_Date Und Date sollten date oder datetime sein, nicht varchar. Bevor Sie dies beheben können, müssen Sie die Zeilen identifizieren, die das Konvertierungsproblem verursachen:

SELECT cod_store, [Date]
FROM dbo.FactTransactions
WHERE ISDATE([Date]) = 0;

SELECT cod_storekey, Opening_Date
FROM dbo.DimStore
WHERE ISDATE(Opening_Date) = 0;

Und jetzt, da Sie die Frage behoben haben und ich weiß, dass Sie 2012 und nicht 2008 R2 verwenden, ist es möglicherweise sauberer, TRY_CONVERT() zu verwenden, zumal Sie damit alle Zeilen identifizieren können, in denen der Monat und Tag sind falsch transponiert. Angenommen, Sie erwarten, dass Datumsangaben als mm/dd/yyyy - Zeichenfolgen gespeichert werden:

SELECT cod_store, [Date]
FROM dbo.FactTransactions
WHERE TRY_CONVERT(datetime, [Date], 101) = 0;

SELECT cod_storekey, Opening_Date
FROM dbo.DimStore
WHERE TRY_CONVERT(datetime, Opening_Date, 101) = 0;

Zusätzlich zur Identifizierung von Müllzeilen, in denen Benutzer Unsinn wie floob und 9992-13-36 Als "Datumsangaben" gespeichert haben, werden hiermit auch Zeilen identifiziert, in denen Benutzer 13/07/1999 Anstelle von 07/13/1999 (Aber es gibt keine Möglichkeit zu wissen, ob 05/06/2000 Der 6. Mai oder der 5. Juni sein soll).

Jetzt müssen Sie diese Zeilen korrigieren, bevor Sie die Tabellen korrigieren können.

ALTER TABLE dbo.DimStore ALTER COLUMN Opening_Date date; -- or datetime;
ALTER TABLE dbo.FactTransactions ALTER COLUMN [Date] date; -- or datetime;

Sie können die Spalte Date auch so umbenennen, dass sie (a) weniger vage und (b) kein reserviertes Wort ist.

Wenn Sie die Tabellen nicht reparieren können, müssen Sie Ihre Abfrage ändern:

UPDATE T1
SET ORDINAL = DATEDIFF(DAY, 
  CASE WHEN ISDATE(T2.Opening_Date) = 1 THEN T2.OpeningDate END,
  CASE WHEN ISDATE(T1.[Date]) = 1 THEN T1.Date END)
FROM dbo.FactTransactions AS T1
INNER JOIN dbo.DimStore AS T2 
  ON T1.cod_store = T2.cod_storeKey
WHERE ISDATE(T2.Opening_Date) = 1
  AND ISDATE(T1.[Date]) = 1;

Und @RLF hat auch einen großartigen Punkt angesprochen; Wenn Sie die Tabelle nicht reparieren können, können die Datumsspalten Daten enthalten, die ein bestimmtes Datum darstellen (z. B. den 7. September), aber im falschen Format eingegeben werden (z. B. in einem US-englischen System, das als Zeichenfolge im britischen Format eingegeben wird.) 09.07.2015). Sie müssen also die Tabelle reparieren und aufhören, diese Dinge als Zeichenfolgen zu speichern.

Einige andere nützliche Materialien:

6
Aaron Bertrand

Sie können Konvertieren mit dem richtigen Stil verwenden, um varchar(x) in Ihrem lokalen Format in die richtigen Daten zu konvertieren:

DATEDIFF(DAY, convert(date, T2.Opening_Date, 104), convert(date, T1.Date, 104))

In diesem Beispiel habe ich angenommen, dass Sie den deutschen Stil verwenden (TT.MM.JJJJ). Deutscher Stil ist 104:

Select convert(date, '01.02.2015', 104)

Ausgabe: 2015-02-01

Sie müssen es an Ihre Einstellungen und Ihr lokales Format anpassen und 104 durch das ersetzen, was Sie verwenden. Hauptstil sind:

Style   Standard        Input/Ouput
1       U.S.            1 = mm/dd/yy
101     U.S.            101 = mm/dd/yyyy
2       ANSI            2 = yy.mm.dd
102     ANSI            102 = yyyy.mm.dd
3       British/French  3 = dd/mm/yy
103     British/French  103 = dd/mm/yyyy
4       German          4 = dd.mm.yy
104     German          104 = dd.mm.yyyy
5       Italian         5 = dd-mm-yy
105     Italian         105 = dd-mm-yyyy

Schauen Sie sich CAST und CONVERT (Transact-SQL) an

Wenn Sie Daten mit schlechten oder gemischten Formaten haben, können Sie auch TRY_CONVERT mit einer Abfrage wie der folgenden anzeigen:

Select ... 
FROM FactTransactions T1
INNER JOIN DimStore T2 ON T1.cod_store = T2.cod_storeKey
Where try_convert(date, T2.Opening_Date, 104) is null 
or try_convert(date, T1.Date, 104) is null

Sie erhalten eine Liste mit Datumsangaben mit integriertem Format für Stil 104. Passen Sie sie erneut an Ihre Einstellungen an und ersetzen Sie 104. Sie können sie verwenden, bevor Sie fehlerhafte Formate und Datumsangaben korrigieren.

Die Hauptfrage und das Hauptproblem sind jedoch: Warum verwenden Sie varchar (x)? Sie sollten Datum oder Uhrzeit 2 verwenden, wenn Sie Ihre Tabelle aktualisieren können.

5