一些复合类型进行范式分解是没有必要的,尤其是一些统一模型的情况下
-
SET NOCOUNT ON
-
DECLARE @i TimeBalance
-
SET @i = CAST('D/2015-1-1/7' AS TimeBalance)
-
SELECT @i
-
SELECT @i.ToString()
-
SELECT @i.ToTimeString()
-
SELECT @i.Distance() AS Distance;
-
-
WITH a AS ( SELECT '100' s ,
-
'' m
-
UNION ALL
-
SELECT '281474976710693' s ,
-
'37次' m
-
UNION ALL
-
SELECT 'Y/2015-1-5/1' s ,
-
'包年' m
-
UNION ALL
-
SELECT 'M/2015-1-5/11' s ,
-
'包个月' m
-
UNION ALL
-
SELECT 'D/2015-1-1/7' s ,
-
'包天' m
-
UNION ALL
-
SELECT '1500438729850887' s ,
-
'包天' m
-
UNION ALL
-
SELECT 'H/2015-1-5 8:30/10' s ,
-
'包小时' m
-
)
-
SELECT m + ' ' + s ,
-
t.ToString() string ,
-
t.ToHex() hex ,
-
t.ToTimeString() timeString ,
-
t.ToValue() value ,
-
t.Distance() distance
-
FROM ( SELECT s ,
-
m ,
-
CAST (s AS TimeBalance) t
-
FROM A
-
) tt
相关资料:
TSql vs. SQL CLR Performance Analysis
CLR 集成的性能
操作 UDT 数据
-
using System;
-
using System.Data;
-
using System.Data.SqlClient;
-
using System.Data.SqlTypes;
-
using Microsoft.SqlServer.Server;
-
-
///
-
/// 时间钱包余额类型
-
///
-
///
-
///
-
/// 基于长整型,结构如下:
-
/// 包时类型2B,起始时间UTC秒数4B,时间总长2B(单位同类型决定)
-
///
包时类型:0不包时1秒2分3时4日5月6年
-
///
-
///
-
[Serializable]
-
[Microsoft.SqlServer.Server.SqlUserDefinedType(Format.Native)]
-
public struct TimeBalance : INullable
-
{
-
public override string ToString()
-
{
-
switch (type)
-
{
-
case 0:
-
case 1:
-
return ToValue().ToString();
-
default:
-
return string.Format("{0}/{1}/{2}", (TimeEnum)type, UTCSecondToDateTime(startSecond).ToString("yyyy-MM-dd HH:mm:ss"), value);
-
}
-
-
-
}
-
public string ToHex()
-
{
-
return type.ToString("X4") +" " + startSecond.ToString("X8") + value.ToString("X4");
-
}
-
public string ToTimeString()
-
{
-
-
switch (type)
-
{
-
case 0:
-
case 1:
-
return ToValue().ToString();
-
default:
-
TimeEnum typeEnum = (TimeEnum)type;
-
string format = "";
-
switch (typeEnum)
-
{
-
case TimeEnum.S:
-
default:
-
format = "HH:mm:ss";
-
break;
-
case TimeEnum.Mi:
-
format = "dd HH:mm";
-
break;
-
case TimeEnum.H:
-
format = "MM-dd HH";
-
break;
-
case TimeEnum.D:
-
format = "yyyy-MM-dd";
-
break;
-
case TimeEnum.M:
-
format = "yyyy-MM";
-
break;
-
case TimeEnum.Y:
-
format = "yyyy";
-
break;
-
-
-
}
-
return string.Format("{0}/{1}/{2}", (TimeEnum)type, UTCSecondToDateTime(startSecond).ToString(format), EndTime().ToString(format));
-
-
}
-
}
-
-
public long ToValue()
-
{
-
switch (type)
-
{
-
case 0:
-
case 1:
-
return value;
-
-
default:
-
return ((long)type << 48) + ((long)startSecond << 16) + value;
-
}
-
}
-
-
public static TimeBalance Parse(SqlString s)
-
{
-
if (s.IsNull)
-
return Null;
-
try
-
{
-
TimeBalance u = new TimeBalance();
-
-
if (s.Value.Contains("/"))
-
{
-
u.type = (short)(TimeEnum)Enum.Parse(typeof(TimeEnum), (s.Value.Split('/')[0]));
-
u.startSecond = DateTimeToUTCSecond(DateTime.Parse(s.Value.Split('/')[1]));
-
u.value = long.Parse(s.Value.Split('/')[2]);
-
}
-
else
-
{
-
-
byte[] bs = BitConverter.GetBytes(long.Parse(s.Value));
-
u.type = BitConverter.ToInt16(bs, 6);
-
switch (u.type)
-
{
-
case 0:
-
u.value = long.Parse(s.Value);
-
break;
-
case 1:
-
u.value = BitConverter.ToInt16(bs, 0);
-
break;
-
default:
-
-
u.startSecond = BitConverter.ToInt32(bs, 2);
-
u.value = BitConverter.ToInt16(bs, 0);
-
break;
-
}
-
}
-
-
return u;
-
}
-
catch (Exception ex)
-
{
-
throw new Exception(s.Value + "\r\n" + ex.ToString());
-
}
-
}
-
-
-
-
-
public bool IsNull
-
{
-
get
-
{
-
// 在此处放置代码
-
return _null;
-
}
-
}
-
-
public static TimeBalance Null
-
{
-
get
-
{
-
TimeBalance h = new TimeBalance();
-
h._null = true;
-
return h;
-
}
-
}
-
-
-
public long Distance()
-
{
-
return value;
-
-
}
-
-
public DateTime EndTime()
-
{
-
short v = (short)(value & 0xffff);
-
TimeEnum typeEnum = (TimeEnum)type;
-
switch (typeEnum)
-
{
-
// case TimeEnum.N:
-
-
case TimeEnum.S:
-
default:
-
return UTCSecondToDateTime(startSecond).AddSeconds(v);
-
case TimeEnum.Mi:
-
return UTCSecondToDateTime(startSecond).AddMinutes(v);
-
case TimeEnum.H:
-
return UTCSecondToDateTime(startSecond).AddHours(v);
-
case TimeEnum.D:
-
return UTCSecondToDateTime(startSecond).AddDays(v);
-
case TimeEnum.M:
-
return UTCSecondToDateTime(startSecond).AddMonths(v);
-
case TimeEnum.Y:
-
return UTCSecondToDateTime(startSecond).AddYears(v);
-
-
}
-
}
-
-
#region 获取UTC
-
-
public static int DateTimeToUTCSecond(DateTime dateTime)
-
{
-
return (int)dateTime.ToUniversalTime().Subtract(UTC).TotalSeconds;
-
}
-
-
static DateTime UTCSecondToDateTime(int second)
-
{
-
return UTC.AddSeconds(second).ToLocalTime();
-
}
-
#endregion
-
-
// 这是占位符成员字段
-
public int startSecond;
-
public short type;
-
public long value;
-
static readonly DateTime UTC = TimeZoneInfo.ConvertTimeToUtc(new DateTime(1970, 1, 1), TimeZoneInfo.Utc);
-
// 私有成员
-
private bool _null;
-
}
-
public enum TimeEnum
-
{
-
N = 0,
-
T = 1,//Times
-
S = 2,
-
Mi = 3,
-
H = 4,
-
D = 5,
-
M = 6,
-
Y = 7
-
}