Eva*_*oll 10 postgresql null domain
PostgreSQL 允许NULL
在标记为 的域中使用s NOT NULL
。这是为什么,文档是这么说的,
尽管存在这样的约束,但名义上属于域类型的列仍有可能读取为空。例如,如果域列位于外连接的可为空一侧,则这可能发生在外连接查询中。
这能更好地解释吗?
Eva*_*oll 13
嗯,首先看看这个,
CREATE DOMAIN mydomain AS int;
CREATE TABLE foo(bar) AS SELECT 42::mydomain;
SELECT f1.bar AS f1, f2.bar AS f2, pg_typeof(f1.bar), pg_typeof(f2.bar)
FROM foo AS f1
LEFT JOIN foo AS f2
ON false;
Run Code Online (Sandbox Code Playgroud)
目前返回,
f1 | f2 | pg_typeof | pg_typeof
----+----+-----------+-----------
42 | | mydomain | mydomain
Run Code Online (Sandbox Code Playgroud)
但它应该返回什么?您正在连接两个表,该表中唯一的类型是mydomain
允许NULL
s。从逻辑上讲,返回的两列都应该是类型mydomain
。现在如果你回去运行这个,
CREATE DOMAIN mydomain AS int NOT NULL;
Run Code Online (Sandbox Code Playgroud)
考虑到上述命令,它是否应该返回不同的东西?答案是否定的——出于同样的原因。结果集由来自表的两列组成。如果要返回与源表相同的类型,如上面的查询,那么它必须返回一个带有NULL
. 请注意,这不是关于INSERT
它只是向您展示无论 SQL 的类型是什么都可以使其 return NULL
。这就是你如何得到NULL
s转换为DOMAIN
当域本身不支持NULL
。
你怎么能以正确的方式解决这个问题?您可以从Three-valued_logic (3vl)(真/假/空)升级到 4vl(类似于真/假/空/未知)。这将使SQL原始未提供给用户的是一切将在参数。它看起来像,
// Definitions // Value Constructors on
// Two-value
type Bool = True | False; // True | False
// Three-value
type NonNullable<T> = T; // True | False
type Nullable<T> = Null | NonNullablle<T>; // Null | True | False
// Four-value!
type Option<T> = Unknown | Nullable<T>; // So over every column
type Option<T> = Unknown | NonNullable<T>; // you can store Unknown
Run Code Online (Sandbox Code Playgroud)
然后,SQL 作为 a 的结果返回的每一列SELECT
都可以是Unknown
用户无法选择的值,并且每种类型都必须允许。这样就可以解决这个问题了。它还会使 SQL 更难教和理解。想象一个四值真值表。
SELECT
来自Paul White 的另一种解决方案是,SELECT
如果值不能被域强制或表示,则使语句抛出致命错误。一些SELECT
语句已经抛出错误,例如SELECT 1/0
或SELECT CAST('foo' AS int);
归档时间: |
|
查看次数: |
686 次 |
最近记录: |