日付と時刻を次の形式で保持するnvarchar(50)
フィールド (DateHr) があります: yy/mm/dd hh:mm:ss
(例:12/04/11 16:49:23
に変換する必要がありApril 11, 2012 4:49 PM
ます)。
この形式で日付の値を管理しようとして苦労しています。
DateTime
列をデータ型として作成し、この新しいフィールドを使用できるかどうか疑問に思っていました。
日付と時刻を次の形式で保持するnvarchar(50)
フィールド (DateHr) があります: yy/mm/dd hh:mm:ss
(例:12/04/11 16:49:23
に変換する必要がありApril 11, 2012 4:49 PM
ます)。
この形式で日付の値を管理しようとして苦労しています。
DateTime
列をデータ型として作成し、この新しいフィールドを使用できるかどうか疑問に思っていました。
ただ眺めを持ってみませんか?
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;
これで、クエリは次のようになります。
SELECT DateHr2 FROM dbo.View_MyTable
WHERE DateHrProper >= '20120412'
AND DateHrProper < '20120413';
このように、テーブルのスキーマをいじる必要はなく、必要な場合にのみ、永続化された計算列アプローチを調査できます。計算列を追加する場合は、同じ日付の別の文字列表現としてではなく、日時列として追加します。ストレージではなく、出力で「きれいにする」ことを行います。
ストアドプロシージャを介してテーブルへの書き込みを制御でき(強く推奨)、ユーザーにアドホックな挿入/更新を実行させない場合は、基本タイプを変更でき、ナンセンスを心配する必要はありません。入力。例えば:
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
ここでApril 11, 2012 4:49 PM
、出力として必要なクエリを作成します。残念ながら、SQLServer内でその形式に簡単に変換するネイティブな方法はありません。あらゆる種類の文字列操作でそれを行うことができます。例:
;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;
これは、目的の出力に非常に近いものです。
April 11, 2012 04:49 PM
必要に応じて、より多くの文字列操作を実行して、時間の先頭の0を削除できます。
これをクライアントでフォーマットする方がはるかに優れています。FORMAT()
プラス面として、SQL Server 2012では、次の新機能を使用してこれを簡単に行うことができます。
SELECT FORMAT(DateHr, 'MMMM dd, yyyy h:mm tt')
FROM dbo.MyTable;
結果:
April 11, 2012 4:49 PM
そしてもちろん、究極の解決策は、ユーザーに最初からフリーテキストの日付形式を入力させないことです。誰かが2011年5月4日を意味する4月5日または2012年11月を意味する12月に入ると保証します。ドロップダウンまたはカレンダーコントロールから選択してもらうと、安全な場所でSQLServerに渡される文字列を完全に監視できます。その日の気分に頼るのではなく、フォーマットを使用すると、ユーザーが選択した日付が日付であることが常にわかります(地域のフォーマットが期待どおりでない場合でも)。
1つのオプションは、計算列です。例えば、
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;
結果:
s dt
-------------------------------------------------- ------------------------------
2012/04/11 16:49:23 2012-04-11 16:49:23.000
john NULL
編集:悪い日付値の処理を追加
編集:カスタム日付24時間形式-yyyy-mm-dd hh:mi:ss.mmm(24h)
編集:必要に応じて、元の日付の前に世紀を付けます
または、計算列の前に世紀を追加することもできます。
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;
結果:
s dt
-------------------------------------------------- ------------------------------
12/04/11 16:49:23 2012-04-11 16:49:23.000
john NULL
これを行う:
SELECT CONVERT(VARCHAR(20), cast('2012/04/11 16:49:23' as datetime), 100)
奇妙ですが、両方のキャストが必要です
編集:
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