Postgresql 为什么我的观点是';哪些列可以为空?

Postgresql 为什么我的观点是';哪些列可以为空?,postgresql,view,entity-framework-5,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

我正在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;
我很惊讶视图报告的信息\u schema.columns对于所选列可以为“是”

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为“false”

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

update pg_attribute
set attnotnull = 't'
where attrelid = 271543
更改反映在信息_schema.columns中:

CREATE TABLE testtable
(
  bkid serial NOT NULL,
  bklabel character varying(128),
  lacid integer NOT NULL
}
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"
我将尝试导入实体框架数据模型中的视图

编辑2

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

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

此处信息模式下的系统表中的列似乎是“attrnotnull”。我在pgsql listserv上只看到一个线程引用“attnotnull:”。(但该专栏在早期版本中可能有不同的名称。它可能值得研究。)

您可以看到此查询的行为。您将需要使用WHERE子句来获得所需的内容

select attrelid, attname, attnotnull, pg_class.relname
from pg_attribute
inner join pg_class on attrelid = oid
where attname like 'something%'
在我的系统中,具有主键约束的列和具有NOTNULL约束的列的“attnotnull”设置为“t”。视图中的相同列将“attnotnull”设置为“f”

如果你歪着头,眯着眼睛看得恰到好处,那是有道理的。视图中的列未声明为NOT NULL。只有基表中的列


列pg_attribute.attnotnull是可更新的。您可以将其设置为TRUE,并且该更改似乎反映在信息\u架构视图中。虽然您可以直接将其设置为TRUE,但我认为将其设置为与基表中的值相匹配会更舒服。(我所说的更舒适,并不是说我对在系统表中乱搞感到很舒服。)

PostgreSQL中的可空性跟踪没有得到太多开发。在大多数情况下,它默认声明所有内容都可能为空,这在许多情况下是相关标准允许的。这里的情况也是如此:不通过视图跟踪可空性。我不会把它作为应用程序使用。

原因:

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'
可以计算视图,但引用了表中的列。该计算可能会导致非空列上的空值。所以基本上,他们把它放进了太硬的篮子里

有一种方法可以通过以下查询查看基本的可空性:

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提供商将使用此视图,并读取视图定义以确认可为空。

感谢@mike sherrill catcall:查看我的编辑,为了测试的目的,我将其设置为true,并且效果良好。现在,我必须创建一个脚本来根据基表中的值进行设置。在适当的时候手动将视图列设置为不为null是否存在任何已知问题(除了非常令人讨厌之外)?@ChristopherLewis:Define known。“是关系数据库管理系统存储架构元数据的地方,如表和列的信息以及内部簿记信息。PostgreSQL的系统目录是常规表。您可以删除和重新创建表、添加列、插入和更新值,并以这种方式严重破坏您的系统。”也就是说,我还没有测试过手动更新pg_attribute.attnotnull。你说得对,我应该小心不要依赖于null性,因为视图可能会用另一个值替换null,例如使用COALESCE。在我的上下文中,只要对象模型、视图和信息模式保持同步,就值得冒险。这是在Postgres v12.4Hasura上。用户看到以下问题: