将布尔值插入PostgreSQL中的字符变化字段

将布尔值插入PostgreSQL中的字符变化字段,postgresql,Postgresql,PostgreSQL 9.1将很高兴地在varchar字段中插入一个布尔值。我的期望是,这将失败,因为我插入了错误类型的数据,我希望这会在我的应用程序逻辑中引发错误。除了为每个varchar字段设置触发器或约束之外,还有什么方法可以将其设置为默认行为 CREATE TABLE foo ( text_field CHARACTER VARYING(32) ); 这两个选项都在文本_字段中插入“false”: INSERT INTO foo (text_field) VALUES (FAL

PostgreSQL 9.1将很高兴地在varchar字段中插入一个布尔值。我的期望是,这将失败,因为我插入了错误类型的数据,我希望这会在我的应用程序逻辑中引发错误。除了为每个varchar字段设置触发器或约束之外,还有什么方法可以将其设置为默认行为

CREATE TABLE
foo
(
    text_field CHARACTER VARYING(32)
);
这两个选项都在文本_字段中插入“false”:

INSERT INTO foo (text_field) VALUES (FALSE);
INSERT INTO foo (text_field) VALUES (CAST('f' AS BOOLEAN));

这是因为PostgreSQL将接受任何类型可以自动转换为该列类型的表达式(在
INSERT
语句中)(更准确地说,在这两种类型之间存在强制转换:这就是这些强制转换首先存在的原因)。例如:

好吧,我有点作弊。有一个特例。当您编写字符串文字时(如
'false'
),它有一个
未知的
类型。始终将未知值传递给实际列类型的。True
text
键入的文字看起来有点不同:
text'false'
。如果再次查看PostgreSQL提供的默认强制转换,可以看到没有从
text
boolean
的强制转换。这就是最后一句话失败的原因:

insert into foo values (text 'false', text 'false', text 'false');

编辑:因此,默认情况下,有一个
赋值
布尔值
转换为
文本
字符变化也有一个)。这就是为什么表的
text\u字段
接受布尔输入

我的期望是,这将失败,因为我插入了错误类型的数据

SQL语句通常涉及混合数据类型。SQL引擎(不仅仅是PostgreSQL)遵循内部规则,以静默方式将一种类型的值转换为另一种类型的值。PostgreSQL的规则记录在中。插入值所遵循的规则如下所示

虽然可能会改变pg_cast系统目录的内容(我不知道),但我认为这是一个非常糟糕的主意。首先,pg_的演员阵容没有pg_dump的支持。灾难恢复可能很容易使dbms处于您不期望的状态,并且很难排除故障

我认为最好的办法是停止在不应该出现的列中插入布尔值。说真的,为什么应用程序代码会像将“city”这样的列设置为False一样

下一个最佳选择是添加检查约束

alter table foo
add constraint disallow_tf_text_field
check (lower(text_field) not in ('t', 'f', 'true', 'false', 'y', 'n', 'yes', 'no', 'on', 'off', '1', '0'));

谢谢你的回答。代码的目的是在字段中存储字符串。PHP做$text=substr($text,0,32);。这在大多数情况下都能正常工作,但如果$text的长度为0,则返回false而不是“”。可能从PHP切换会有所帮助。:)那么,任何被接受到varchar(n)列中的内容都将成为字符串。但是PHP的错误处理在程序员中臭名昭著。例如,
strpos()
可以返回布尔值false,但也可以返回计算结果为false的非布尔值。您必须非常小心PHP的返回值。
alter table foo
add constraint disallow_tf_text_field
check (lower(text_field) not in ('t', 'f', 'true', 'false', 'y', 'n', 'yes', 'no', 'on', 'off', '1', '0'));