如果我在没有任何函数的sqlite中选择一个日期类型的列,它会返回一个正确的.NET DateTime
对象:
// Returns .NET DateTime object
select date_column from test_table;
但是当我使用标量函数时,它总是返回string
:
// Returns string
select datetime(date_column) from test_table;
select date(date_column) from test_table;
我需要这个的原因是日期舍入
// Rounds to month
select datetime(strftime('%Y-%M-01T00:00:00', date_column)) from test_table;
// Rounds to year
select datetime(strftime('%Y-01-01T00:00:00', date_column)) from test_table;
我尝试实现自己的SQLiteFunction,但它仍然返回一个字符串:
[SQLiteFunction(Name="round_date")]
public class RoundDate : SQLiteFunction
{
/// <summary>
/// Expects 2 arguments:
/// 1: date
/// 2: rounding (Month, Quarter, Year)
/// </summary>
public override object Invoke(object[] args)
{
DateTime date = SQLiteConvert.ToDateTime(args[0].ToString());
DateTime result = date;
switch (args[1].ToString())
{
case "Month":
result = new DateTime(date.Year, date.Month, 1);
break;
case "Quarter":
int quarter = (date.Month-1)/3;
var quarterStart = quarter*3 + 1;
result = new DateTime(date.Year, quarterStart, 1);
break;
case "Year":
result = new DateTime(date.Year, 1, 1);
break;
}
// function returns a DateTime object.
// But executing the statement returns a string
return result;
}
}
// Uses custom function, but still getting String
select round_date(date_column, 'Year') from test_table;
我知道我可以手动转换/转换字符串结果。
但有没有办法强制select语句自动返回DateTime对象?
[编辑1]
据我所知,Dates和DateTimes不是sqlite中本机支持的数据类型之一。
我也知道我可以手动将格式化的字符串转换为DateTime对象。
但是,select date_column from test_table
实际上返回.NET DateTime对象。我假设System.Data.SQLite实现自动执行此转换。
var selectStmt = sqlite.CreateCommand();
selectStmt.CommandText = "select date_column from test_table";
// ==============================
// ==============================
// Returns System.DateTime object
var this_is_a_DateTime_object = selectStmt.ExecuteScalar();
// ==============================
所以当使用date(),datetime()和我自己的SQLiteFunction实现时,我期待这种行为。
答案 0 :(得分:2)
我不相信有一种方法可以强制System.Data.Sqlite在此实例中为您自动返回.NET DateTime数据类型。这是正在发生的事情。假设您的表定义如下所示:
CREATE TABLE test_table (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
date_column DATETIME NOT NULL
)
正如您已经指出的那样,SQLite中确实没有数据类型。但是,正如您所指出的那样,该库显然正在向您提供本机DateTime值。我的猜测与您的相同:它使用DATETIME的半任意措辞作为您代表您进行此有用转换的请求。
为了测试这个,我在一个DATETIME列中添加了一个明显无效的日期,并且库引发了异常“字符串未被识别为有效的DateTime”。
现在,为了回答你为什么不使用其中一个日期/时间函数获得同样好处的问题,答案在于documentation:
请注意,所有其他日期和时间函数都可以用strftime()表示:
日期(...)strftime('%Y-%m-%d',...)
时间(...)strftime('%H:%M:%S',......)
datetime(...)strftime('%Y-%m-%d%H:%M:%S',...)
julianday(...)strftime('%J',...)
提供strftime()以外的功能的唯一原因是为了方便和提高效率。
所以你不是真的调用日期/时间函数。你正在调用一个格式化函数,它的返回时间是 - 你猜对了 - 一个字符串。我尝试将函数的结果转换回日期时间时尝试了一些失败的尝试,如下所示:
select (date(...) as DATETIME), ...
但遗憾的是,您只能使用类型亲缘关系名称(NONE,TEXT,REAL,INTEGER或NUMERIC之一)对SQLite的本机存储类之一进行类型转换。
所以看起来你已经回到了事后必须自己处理转换。 (我也一样。)
答案 1 :(得分:1)
如前所述,您可以为列构建一个DATETIME类型的表,该表在.NET中返回DateTime数据类型。
使用任何内部函数或自定义SQLiteFunction后,它会将其恢复为内部(非日期)数据类型。
如果你真的想要避免String数据类型,可以使用一个有趣的hack,这似乎是我可以强制它在某种程度的日期操作后在.NET中返回DateTime数据类型的唯一方法(至今)。 我自己并不是真的热衷于 ......
如果你定义一个像这样的表......
CREATE Table test2(id bigint, name nvarchar(500), DT datetime)
第三列的查询结果是DateTime。
因此遵循以下逻辑(再次,这是丑陋的,但可能会启发有更多想法的人)将返回由内部日期时间函数修改的日期时间......
CREATE TABLE output (id bigint, name nvarchar, dt datetime)
;
INSERT INTO output
SELECT id, name, DateTime(dt,'+5 years') FROM Test2
;
SELECT * FROM output
;
DROP TABLE output
将此作为单个语句执行将填充一个数据表,其结果为第3列中预期的DateTime数据类型,移位5年。 在您的代码中,如果您可以为每个调用使用唯一的输出表名称,那么该方法可以避免与多个语句发生冲突。
答案 2 :(得分:0)
在SQLite数据库中,&#34;日期和时间&#34;没有存储数据类型。
您可以在SELECT命令之后将数据类型转换为标准.Net DateTime格式。
Query : "SELECT ID, DateModified FROM Customer"
string id = reader.GetInt64(0).ToString();
DateTime dateTime = (DateTime)reader[1];
消息来源:http://techreadme.blogspot.de/2012/11/sqlite-read-write-datetime-values-using.html
抱歉,上述信息适用于SQLite版本1&amp; 2. SQLite3确实包含数据类型,尽管它们的实现方式与标准SQL数据库不同。
答案 3 :(得分:0)
我不使用SQLite,但是从我读过的内容来看,日期和时间没有原生数据类型。如果您的原始查询正在生成SQLite ADO.NET提供程序将其解释为.NET DateTime
值的结果集,那么我只能假设它基于格式。在这种情况下,您可以使用strftime
以相同的格式输出,并自动将数据作为DateTime
值获取。似乎该格式可能是&#34; yyyy-MM-dd HH:mm:ss.fff&#34;用.NET术语。