为什么我的视图列可以为空?

时间:2013-06-25 15:24:56

标签: postgresql view entity-framework-5

我正在Windows上运行PostgreSQL 9.2。

我有一个包含一些不可为空的列的现有表:

CREATE TABLE testtable
(
  bkid serial NOT NULL,
  bklabel character varying(128),
  lacid integer NOT NULL
}

我在这张桌子上创建了一个视图:

CREATE OR REPLACE VIEW test AS
SELECT testtable.bkid, testtable.lacid
from public.testtable;

我很惊讶视图报告的information_schema.columns对于所选列的is_nullable为YES?

select * from information_schema.columns where table_name = 'test'

报告:

"MyDatabase";"public";"test";"bkid";1;"";"YES";"integer";;;32;2;0;;"";;"";"";"";"";"";"";"";"";"";"MyDatabase";"pg_catalog";"int4";"";"";"";;"1";"NO";"NO";"";"";"";"";"";"";"NEVER";"";"NO"
"MyDatabase";"public";"test";"lacid";2;"";"YES";"integer";;;32;2;0;;"";;"";"";"";"";"";"";"";"";"";"MyDatabase";"pg_catalog";"int4";"";"";"";;"2";"NO";"NO";"";"";"";"";"";"";"NEVER";"";"NO"

这是预期的行为吗?

我的问题是我正在尝试在实体框架数据模型中导入此类视图,但它失败了,因为所有列都标记为可为空。

编辑1

以下查询:

select attrelid, attname, attnotnull, pg_class.relname
from pg_attribute
inner join pg_class on attrelid = oid
where relname = 'test'

返回:

attrelid;attname;attnotnull;relname
271543;"bkid";f;"test"
271543;"lacid";f;"test"

正如所料,attnotnull是'假'。

正如@ Mike-Sherrill-Catcall建议的那样,我可以手动将它们设置为true:

update pg_attribute
set attnotnull = 't'
where attrelid = 271543

更改反映在information_schema.columns中:

select * from information_schema.columns where table_name = 'test'

输出是:

"MyDatabase";"public";"test";"bkid";1;"";"NO";"integer";;;32;2;0;;"";;"";"";"";"";"";"";"";"";"";"MyDatabase";"pg_catalog";"int4";"";"";"";;"1";"NO";"NO";"";"";"";"";"";"";"NEVER";"";"NO"
"MyDatabase";"public";"test";"lacid";2;"";"NO";"integer";;;32;2;0;;"";;"";"";"";"";"";"";"";"";"";"MyDatabase";"pg_catalog";"int4";"";"";"";;"2";"NO";"NO";"";"";"";"";"";"";"NEVER";"";"NO"

我将尝试在Entity Framework数据模型中导入视图。

编辑2

正如猜测的那样,它可以正常运行,现在可以在实体框架数据模型中正确导入视图。 当然,我不会将所有列设置为不可为空,如上所示,只有那些在基础表中不可为空的列。

3 个答案:

答案 0 :(得分:1)

我相信这是预期的行为,但我不会假装完全理解它。基表中的列似乎具有正确的属性。

这里的information_schema底层系统表中的列似乎是“attrnotnull”。我在pgsql-hackers listserv上只看到一个引用“attnotnull”的帖子:cataloguing NOT NULL constraints。 (但是该列可能在早期版本中有不同的名称。它可能值得研究。)

您可以查看此查询的行为。您需要使用WHERE子句来准确获取需要查看的内容。

select attrelid, attname, attnotnull, pg_class.relname
from pg_attribute
inner join pg_class on attrelid = oid
where attname like 'something%'

在我的系统上,具有主键约束的列和具有NOT NULL约束的列将“attnotnull”设置为“t”。视图中的相同列将“attnotnull”设置为“f”。

如果你倾斜你的头并眯着眼睛,那那种是有道理的。视图中的列未声明为NOT NULL。只是基表中的列。

列pg_attribute.attnotnull是可更新的。您可以将其设置为TRUE,并且该更改似乎会反映在information_schema视图中。虽然您可以直接将其设置为TRUE,但我认为我更习惯将其设置为与基表中的值匹配。 (并且通过更舒服,我并不是说在系统表格中捣乱我总是很舒服。)

答案 1 :(得分:1)

PostgreSQL中的可空性跟踪根本没有得到很好的发展。在大多数地方,它将默认声称一切都可能是可空的,这在相关标准的许多情况下是允许的。这也是这种情况:通过视图不跟踪可空性。我不会依赖它来申请。

答案 2 :(得分:0)

原因:

可以计算视图,但引用表中的列。该计算可能会导致本来是非空列的NULL值。因此,基本上,他们将其放入太难的篮子中。

可以通过以下查询为自己查看潜在的空性:

select vcu.column_name, c.is_nullable, c.data_type
from information_schema.view_column_usage vcu 
join information_schema."columns" c 
    on c.column_name = vcu.column_name 
    and c.table_name  = vcu.table_name 
    and c.table_schema  = vcu.table_schema 
    and c.table_catalog = vcu.table_catalog 
where view_name = 'your_view_here'

如果您知道只投影没有功能的原始列,那么它将起作用。理想情况下,EF的Postgres提供程序将使用此视图并读取视图定义以确认可为空性。