2013-06-25 69 views
4

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

它是一個預期的行爲?

我的問題是,我試圖在實體框架數據模型中導入這樣的視圖,並且它失敗,因爲所有列都標記爲可爲空。

EDIT 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是 '假'。

正如@麥克 - 謝里爾 - 噓聲建議,我可以手動將其設置爲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

由於猜到了,它的工作原理,該視圖現在可以正確導入實體框架數據模型。 當然,我不會將所有列設置爲非空,如上所示,只有那些不可空的在基礎表中。

回答

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,但我認爲將其設置爲與基表中的值匹配會更舒適。 (通過更加舒適,我不是故意暗示我對系統表中的所有操作感到舒服。)

+0

對@ mike-sherrill-catcall的好評:查看我的編輯,我將其設置爲true以進行測試,效果很好。現在我必須創建一個腳本來根據基表中的值來設置它。 –

0

PostgreSQL中的空性追蹤並沒有得到太多的發展。在大多數地方,它會默認聲稱一切都有可能是空的,這在很多情況下是由相關標準所允許的。這裏也是這種情況:Nullability沒有通過視圖進行跟蹤。我不會依賴它來申請。

+0

你是對的我應該謹慎依賴於無效性,因爲視圖可能會用例如COALESCE替換爲另一個值。在我的情況下,只要對象模型,視圖和information_schema保持同步,就值得冒險。 –