我创建了一个表格如下:
CREATE TABLE case_status(data_entry_timestamp DATETIME DEFAULT (datetime('now','localtime')) NOT NULL,
case_number TEXT PRIMARY KEY NOT NULL,
case_name TEXT DEFAULT MISSING,
death_reportdate DATE CONSTRAINT death_reportdate_chk CHECK (death_reportdate==strftime('%Y-%m-%d',death_reportdate)),
);
列death_reportdate
需要具有预定义格式的日期(例如2000-12-31)。我创建了表,插入了一些数据行,然后尝试修改death_reportdate
中的数据,当我输入一些随机字符串时,检查规则似乎被绕过了。
我做错了什么?
答案 0 :(得分:3)
最后你有一个额外的逗号。正确的代码:
CREATE TABLE case_status(data_entry_timestamp DATETIME DEFAULT (datetime('now','localtime')) NOT NULL,
case_number TEXT PRIMARY KEY NOT NULL,
case_name TEXT DEFAULT MISSING,
death_reportdate DATE CONSTRAINT death_reportdate_chk CHECK (death_reportdate==strftime('%Y-%m-%d',death_reportdate))
)
答案 1 :(得分:2)
这是一个旧主题,但我遇到了同样的问题。如果strftime方法无法格式化字符串(输入错误)它返回null,所以你必须检查最后不是null
答案 2 :(得分:0)
这是另一种效果像魅力的解决方案:
`date` DATE CHECK(date IS strftime('%Y-%m-%d', date))
这也适用于time
:
`time` TIME CHECK(time IS strftime('%H:%M:%S', time))
使用此定义您的列。我认为这是比检查null
值更优雅的解决方案。
答案 3 :(得分:0)
首先,两个小笔记。
TEXT
类型,因为SQLite没有“真实类型”。 It has 5 column "affinities",INTEGER
,TEXT
,BLOB
,REAL
和NUMERIC
。如果您说DATE
,那么它使用NUMERIC
的行为在我看来可能有点怪异。我发现最好明确使用5种相似性之一。date(...)
而不是strftime('%Y-%m-%d', ...)
,因为they are the same thing。让我们解释为什么原始问题不起作用。
DROP TABLE IF EXISTS TEMP.example;
CREATE TEMPORARY TABLE example (
deathdate TEXT CHECK (deathdate == date(deathdate))
);
INSERT INTO TEMP.example (deathdate) VALUES ('2020-01-01');
INSERT INTO TEMP.example (deathdate) VALUES ('a');
INSERT INTO TEMP.example (deathdate) VALUES (NULL);
SELECT * FROM TEMP.example;
运行此命令可使所有三个值进入数据库。为什么?让我们检查一下CHECK
constraints的文档。
如果结果为零(整数值0或实数值0.0),则发生约束冲突。如果CHECK表达式的计算结果为NULL或任何其他非零值,则不是约束冲突。
如果您运行SELECT 'a' == date('a');
,则会看到它是NULL
。为什么?选中SELECT date('a');
,您还会看到它也是NULL
。呵呵,也许documentation for ==
可以帮上忙吗?
请注意,等于和不等于运算符有两种变体。等于可以是=或==。 [...]
IS和IS NOT运算符的工作方式类似于=和!=,但当一个或两个操作数为NULL时除外。在这种情况下,如果两个操作数均为NULL,则IS运算符的计算结果为1(true),而IS NOT运算符的计算结果为0(false)。如果一个操作数为NULL而另一个操作数为NULL,则IS运算符的计算结果为0(假),而IS NOT运算符的计算结果为1(真)。 IS或IS NOT表达式无法计算为NULL。
我们需要使用IS
,而不是==
,并尝试使'a'
不再进入。
DROP TABLE IF EXISTS TEMP.example;
CREATE TEMPORARY TABLE example (
deathdate TEXT CHECK (deathdate IS date(deathdate))
);
INSERT INTO TEMP.example (deathdate) VALUES ('2020-01-01');
INSERT INTO TEMP.example (deathdate) VALUES ('a');
INSERT INTO TEMP.example (deathdate) VALUES (NULL);
SELECT * FROM TEMP.example;
如果您不希望NULL
进入,只需将其更改为deathdate TEXT NOT NULL CHECK (deathdate IS date(deathdate))