我正在开发一个新的WPF项目,用户可以在其中填写字段以提交到C#中的SQLite数据库。在用户选择一个跨越9月至10月以及12月至1月的日期范围之前,从数据库提交和检索信息的工作都很好。即使该日期范围内有记录,也不会返回任何记录。日期范围可以从一月到九月,十月到十二月,但是如果您从一位数月份到两位数月份相交,则不会返回任何内容。
我知道SQLite显然没有“日期”作为数据类型,但是当我创建数据库时,它是使用“ DATE”创建的,没有任何问题。我也用“ TEXT”做到了,但是两者都有相同的日期范围问题。我正在使用“ System.Data.SQLite”创建和查询数据库。
我的查询命令字符串包括:
string cmdString = "SELECT * FROM " + table + " WHERE DATE >= '" + dateFrom + "' AND DATE <= '" + dateTo + "'";
dateFrom和dateTo字符串格式分别为“ 9/30/2019”和“ 10/31/2019”
我尝试将两个日期都格式化为“ MM / DD / YYYY”,但这无济于事。
我尝试使用“ BETWEEN”,但没有帮助。
我已经尝试在SQLite中使用“日期”功能,但我猜它在C#中不起作用。
我的连接字符串是:
"data source=" + database + ";datetimeformat=CurrentCulture"
我无法粘贴整个代码,因为它与我的工作有关。
更新: 感谢您的答复和回答。在更改日期格式以适合SQLite之后,我可以正常工作。我错过的另一件事是,当从WPF中的日期选择器小部件中获取日期文本时,显然是给我一个单一的数字来表示“ 9/1/2019”之类的日期,这导致并在我添加逻辑后向SQLite转换器函数中添加0日期范围可以成功找到。
答案 0 :(得分:0)
我知道SQLite显然没有“日期”作为数据类型,但是当我创建数据库时,它是使用“ DATE”创建的,没有任何问题。
与其他数据库不同,SQLite中的列类型非常灵活,并且与基础数据的存储方式无关。简而言之,您几乎可以使用任何类型,甚至根本可以不使用任何类型。
基于一组规则DATE,MY_DATE,A_DATE甚至RUMPLESTILTSKIN的列类型结尾都具有派生的列类型(类型相似性),最后都具有所有NUMERIC类型的相似性。
但是,类型相似性并没有那么重要。实际上,在SQLite中,您可以在任何列中存储任何类型的数据(bar 1例外,它是rowid或rowid列的别名)。
但是,SQLite确实具有非常强大的date and time functions。
我尝试在SQLite中使用“日期”功能,但我猜它在C#中不起作用。
它们是SQLite的一部分,无论使用哪种语言来调用SQLite命令,它们都可以与SQLite一起使用。
如果日期/时间以公认的格式存储,则日期和时间功能很有用:-
时间字符串
A time string can be in any of the following formats: YYYY-MM-DD YYYY-MM-DD HH:MM YYYY-MM-DD HH:MM:SS YYYY-MM-DD HH:MM:SS.SSS YYYY-MM-DDTHH:MM YYYY-MM-DDTHH:MM:SS YYYY-MM-DDTHH:MM:SS.SSS HH:MM HH:MM:SS HH:MM:SS.SSS now DDDDDDDDDD
因此,最好使用这种格式。
假设您使用2019-09-30(而不是2019年9月30日),则此类日期可以直接比较,即WHERE DATE BEWTEEN 2019-09-30 AND 2019-10-31
会像
string cmdString = "SELECT * FROM " + table + " WHERE DATE >= '" + dateFrom + "' AND DATE <= '" + dateTo + "'";
(假设dateFrom和dateTo的格式如此)。
9/30/2019大于10/31/2019的原因是因为比较是文本的,因此字符 9 大于字符 1 (比较结束)。同样,2/1/1700比11/12/2099大。
替代方法是包括一些相对复杂的操作,例如:-
-- An example that would handle dd/mm/yyyy where dd and mm could be either 1 or 2 characters
WITH
-- First CTE gets the day and the rest of the date
ctedaypart AS (
SELECT
rowid AS daypartid,
substr(DATE,1,instr(DATE,'/')-1) AS day_part,
substr(DATE,instr(DATE,'/')+1) AS rest_after_day
FROM mytable
),
-- Second CTE gets the month and the rest of the date
ctemonthpart AS (
SELECT
daypartid AS monthpartid,
substr(rest_after_day,1,instr(rest_after_day,'/')-1) AS month_part,
substr(rest_after_day,instr(rest_after_day,'/')+1) AS year
FROM ctedaypart
),
-- Third CTE expands the day and month the have a leading 0 id less than 10 and joins the parts to form YYYY-MM-DD
expandedparts AS (
SELECT
*,
mytable.rowid AS expandedpartsid,
year||'-'||
CASE WHEN length(month_part) = 1 THEN '0'||month_part ELSE month_part END ||'-'||
CASE WHEN length(day_part) = 1 THEN '0'||day_part ELSE day_part END AS date_in_sqlite_format
FROM mytable JOIN ctedaypart ON mytable.rowid = daypartid JOIN ctemonthpart ON daypartid = monthpartid)
SELECT mytable.* FROM mytable JOIN expandedparts ON mytable.rowid = expandedpartsid WHERE (date_in_sqlite_format) BETWEEN ('2019-01-01') AND ('2019-03-31');