2012-04-13 16 views
2

Ich habe ein nvarchar(50) Feld (DateHr), die das Datum und die Uhrzeit im folgenden Format enthält: yy/mm/dd hh:mm:ss (ex. 12/04/11 16:49:23, die in April 11, 2012 4:49 PM übersetzt werden soll).Berechnete Spalte Datum von Nvarchar Feld

Ich habe Schwierigkeiten, die Datumswerte in diesem Format zu verwalten.

Ich frage mich, ob ich eine Spalte als DateTime Datentyp erstellen und dieses neue Feld verwenden kann.

+0

Warum verwenden Sie nicht den richtigen Datentyp in der Spalte 'DateHr'? –

+0

Ich kann die Art, wie der Wert eingegeben wird, nicht ändern, und wenn ich zu datetime Datentyp wechsle, wird es als '12/4/2011 4:49:23 PM' interpretiert, was falsch ist. – Rick

+0

Ist es stattdessen möglich, einen Trigger zu erstellen, wenn ein neuer Datensatz erstellt wird, um ein neues Feld mit dem Datentyp datetime zu aktualisieren, und ich verwende das stattdessen? – Rick

Antwort

1

dies zu tun:

SELECT CONVERT(VARCHAR(20), cast('2012/04/11 16:49:23' as datetime), 100) 

es ist seltsam, aber beide Würfe sind notwendig

EDIT:

create table test_date 
(
DateHr varchar(50), 
DateHr2 AS (CONVERT(VARCHAR(20), cast('20'+ DateHr as datetime), 100)) 
) 

insert into test_date values ('12/04/11 16:49:23') 

select * from test_date 


12/04/11 16:49:23 Apr 11 2012 4:49PM 
+0

Ich habe eine Ansicht mit dem folgenden 'SELECT CONVERT (VARCHAR (20), CAST ('20 '+ DatumHr AS datetime), 100)' erstellt und in dem Format ausgegeben, das ich richtig wollte. Ich habe versucht, die Convert-Zeile zu der Formel unter Computed Column Specification hinzuzufügen, aber einen Fehler beim Validieren der Formel Nachricht erhalten. – Rick

+0

sehe meine edit und überprüfen Sie das Ergebnis – Diego

+0

Ich habe den Befehl 'Alter Table dbo.myTable ADD DateHr1 AS CONVERT (VARCHAR (20), CAST ('20 '+ DateHr AS datetime))' erfolgreich, aber wenn Sie in der Management Studio gehen und bearbeiten Sie etwas in der Tabelle Ich bekomme die Fehlermeldung "Fehler beim Überprüfen der Formel für die Spalte". Ich lasse mich auch nicht auf Is Persisted setzen: "Die berechnete Spalte 'test1' in der Tabelle 'Tmp_DR_Transaction' kann nicht persistiert werden, weil die Spalte nicht deterministisch ist." Die Ausgabe ist trotzdem korrekt. – Rick

1

Eine Option ist eine berechnete Spalte. Zum Beispiel

declare @t table(s nvarchar(50), dt as convert(varchar(30),case isdate(s) when 1 then cast(s as datetime) end,121)) 
insert into @t(s) values ('12/04/11 16:49:23') 
update @t set s='20'+s where ISDATE(s)=1 and LEN(s)<19 --prepend w/century 
insert into @t(s) values ('john') --demonstrate bad date string handling here 
select * from @t; 

Ergebnis:

s             dt 
-------------------------------------------------- ------------------------------ 
2012/04/11 16:49:23        2012-04-11 16:49:23.000 
john            NULL 

EDIT: Hinzufügen für schlechte Datumswerte Handhabung

EDIT: Benutzerdefinierte Datum 24h-Format - yyyy-mm-dd hh: mi: ss.mmm (24h)

EDIT: Prepend das ursprüngliche Datum mit Jahrhundert, je nach Bedarf

Alternativ können Sie prepen d das Jahrhundert in der berechneten Spalte:

declare @t table(s nvarchar(50), dt as convert(varchar(30),case isdate('20'+s) when 1 then cast('20'+s as datetime) end,121)) 
insert into @t(s) values ('12/04/11 16:49:23') 
insert into @t(s) values ('john') --demonstrate bad date string handling here 
select * from @t; 

Ergebnis:

s             dt 
-------------------------------------------------- ------------------------------ 
12/04/11 16:49:23         2012-04-11 16:49:23.000 
john            NULL 
+0

In meinem Beispiel dt sollte zurückgegeben werden 2012-04-12 16: 49: 23.000 – Rick

+0

Lösung aktualisiert, um zurückzukehren yyyy-mm-dd hh: mi: ss.mmm (24h) -Format –

+0

Das Problem, das ich habe, ist, dass Cast konvertiert Datum falsch eingegeben. '12/04/11 16: 49: 23' konvertiert zu' 2011-12-04 16: 49: 23', wenn es sein sollte '2012-04-12 16: 49: 23'. – Rick

2

Warum hat nicht nur einen Blick?

SELECT DateHr2 FROM dbo.View_MyTable 
    WHERE DateHrProper >= '20120412' 
    AND DateHrProper < '20120413'; 

Sie zu verwirren haben nicht mit dem Schema der Tabelle Auf diese Weise, und Sie können den beharrte berechneten Spalt Ansatz untersuchen nur, wenn Sie benötigen:

CREATE VIEW dbo.View_MyTable 
AS 
    SELECT 
    DateHr, 
    DateHr2 = CONVERT(VARCHAR(24), CONVERT(DATETIME, '20' + DateHr), 100)), 
    DateHrProper = CONVERT(DATETIME, '20' + DateHr) 
    FROM dbo.MyTable; 

Jetzt können Sie Ihre Abfrage sein . Wenn Sie eine berechnete Spalte hinzufügen, würde ich sie als Datetime-Spalte hinzufügen, nicht als eine andere Zeichenfolgendarstellung desselben Datums. Machen Sie es "hübsch" auf der Ausgabe, nicht im Speicher.

BEARBEITEN Wenn Sie Schreibvorgänge in die Tabelle über eine gespeicherte Prozedur steuern können (sehr empfehlenswert) und Benutzer keine Ad-hoc-Einfügungen/Aktualisierungen ausführen lassen, können Sie den Basistyp ändern und müssen sich keine Sorgen machen über den Unsinn, den sie eingehen könnten. Zum Beispiel:

UPDATE dbo.MyTable 
    SET DateHr = CONVERT(DATETIME, '20' + DateHr); 

-- assuming there are no rows left where `ISDATE(DateHr) = 0`, 
-- but you'll have to test that: 

ALTER TABLE dbo.MyTable ALTER COLUMN DateHr DATETIME; 
GO 

ALTER PROCEDURE dbo.ProcThatUpdatesMyTable 
    @key INT, 
    @DateHr NVARCHAR(50) 
AS 
BEGIN 
    SET NOCOUNT ON; 

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

    UPDATE dbo.MyTable 
    SET DateHr = CONVERT(DATETIME, '20' + @DateHr) 
    WHERE key = @key; 
END 
GO 

Jetzt ist Ihre Abfrage, wo Sie April 11, 2012 4:49 PM als Ausgabe wollen - leider gibt keine native Möglichkeit ist, einfach auf dieses Format in SQL Server zu übersetzen. Sie können es mit allen Arten von String-Manipulation, z.B.:

;WITH x AS 
(
    SELECT 
    d = DATENAME(MONTH, DateHr) + ' ' 
     + CONVERT(VARCHAR(2), DAY(DateHr)) + ', ' 
     + CONVERT(CHAR(5), YEAR(DateHr)), 
    t = CONVERT(CHAR(26), DateHr, 109) 
    FROM dbo.blab 
) 
SELECT d = d + LEFT('0' + RIGHT(t, 13), 5) + ' ' + RIGHT(t, 2) FROM x; 

Diese auf die gewünschte Ausgabe ganz in der Nähe ist:

April 11, 2012 04:49 PM 

können Sie mehr String-Manipulation tun, um die führende 0 auf der Stunde zu entfernen, wenn Sie wollen.

Viel besser, dies auf dem Client zu formatieren. Auf der positiven Seite, können Sie diese einfach in SQL Server 2012 mit der neuen FORMAT() Funktion tun:

SELECT FORMAT(DateHr, 'MMMM dd, yyyy h:mm tt') 
    FROM dbo.MyTable; 

Ergebnis:

April 11, 2012 4:49 PM 

Und natürlich werde ich erwähnen, dass wieder die ultimative Lösung ist, Lassen Sie Ihre Nutzer das Freetext-Format nicht eingeben. Ich garantiere Ihnen, dass jemand den 5. April eingibt, wenn er den 4. Mai oder Dezember 2011 meinte, als sie November 2012 bedeuteten. Lassen Sie ihn aus Drop-downs oder einem Kalender-Steuerelement wählen, wo Sie vollständige Kontrolle über die Strings haben, die an SQL Server in einem Safe übergeben werden Format statt sich auf die Stimmung der Person an diesem Tag zu verlassen, wird sicherstellen, dass Sie immer wissen, dass das Datum ist, was der Benutzer ausgewählt hat (auch wenn ihr regionales Format möglicherweise nicht das ist, was Sie erwarten).

Verwandte Themen