11

我在 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"

我将尝试在实体框架数据模型中导入视图。

编辑 2

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

4

3 回答 3

8

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

此处 information_schema 下的系统表中的列似乎是“attrnotnull”。我在 pgsql-hackers listserv 上只看到一个线程引用“attnotnull”:编目非空约束。(但该列在早期版本中可能有不同的名称。这可能值得研究。)

您可以使用此查询查看行为。您需要使用 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,但我认为将其设置为与基表中的值匹配会更舒服。(而且更舒适,我并不是说我对在系统表中乱七八糟感到很舒服。)

于 2013-06-25T20:31:58.360 回答
1

PostgreSQL 中的可空性跟踪根本没有开发太多。在大多数地方,它会默认声明所有内容都可能为空,这在许多情况下是相关标准允许的。这里也是这种情况:不通过视图跟踪可空性。我不会依赖它来申请。

于 2013-06-26T03:11:43.480 回答
1

为什么:

可以计算视图,但引用表中的列。该计算可能会导致非空列的 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 提供程序将使用此视图并读取视图定义以确认可空性。

于 2020-09-20T14:50:41.283 回答