Joh*_*zer 6 postgresql datatypes type-conversion
我刚刚发现我可以将任何类型的值插入到 PostgreSQL (9.6) 类型的列中text
:
drop table if exists d cascade;
create table d ( a text );
insert into d values ( 42 );
insert into d values ( true );
select a, pg_typeof( a ) from d;
a | pg_typeof
------+-----------
42 | text
true | text
(2 rows)
Run Code Online (Sandbox Code Playgroud)
这是故意的功能吗?我做错了什么吗?有没有设置可以避免这种情况?这是否违反了 RDBMS 应该是类型安全的假设?
我知道这text
在 PostgreSQL 中就像一个包罗万象的东西,这通常很方便,因为您可以编写任意类型的字符串表示。但是有时您肯定希望确保只有字符串被插入到给定的列中,以排除隐式转换值。
我能做些什么来避免“随意”类型转换?
这是故意的功能吗?
是的,隐式类型转换是一个有意的特性。无论哪种方式都有优点和缺点,但这就是 postgres的设计方式:
在很多情况下,用户不需要了解类型转换机制的细节。但是,PostgreSQL 进行的隐式转换会影响查询的结果。必要时,可以使用显式类型转换来定制这些结果
这是否违反了 RDBMS 应该是类型安全的假设?
不,一切仍然是类型安全的,并且“SQL 是一种强类型语言”。隐式转换不会改变这一点。
我能做些什么来避免“随意”类型转换?
除了弄乱系统目录,这通常是一个非常糟糕的主意(在某些情况下是不可能的),您可以做很多事情来完全避免隐式转换。即使您在任何地方都包含显式转换,隐式转换仍可能会错误地发生:
Run Code Online (Sandbox Code Playgroud)create table t(foo text); insert into t(foo) values(11::integer);
Run Code Online (Sandbox Code Playgroud)select * from t;
| 富| | :-- | | 11 |
dbfiddle在这里
@Jack 说的话。
另外,准确地说,你的演员表在INSERT
常识上是“隐式的”:
Run Code Online (Sandbox Code Playgroud)insert into d values ( 42 );
但它是一个赋值转换,而不是Postgres 术语中的隐式转换。这是一个重要的区别,隐式强制转换有更多的应用。看:
分配或隐式强制转换仅基于...
pg_cast
与castcontext = 'a'
或castcontext = 'i'
分别。
当前安装的完整列表:
SELECT casttarget::regtype AS target_type
, castsource::regtype AS source_type
, castcontext
FROM pg_cast
WHERE castcontext IN ('i', 'a')
ORDER BY 1, 2;
Run Code Online (Sandbox Code Playgroud)
需要注意的是
pg_cast
,并不代表系统知道如何执行的每一种类型转换;只有那些不能从某些通用规则中推导出来的。例如,域与其基类型之间的转换在pg_cast
. 另一个重要的例外是“自动 I/O 转换强制转换”,即使用数据类型自己的 I/O 函数在text
或其他字符串类型之间进行转换而执行的转换,在pg_cast
.
大胆强调我的。
从理论上讲,您可以通过更改或更改为(“显式”)来弄乱pg_cast
( 1. ) 中的 条目- 这可能会产生深远的影响并且是一个坏主意,除非您确切地知道自己在做什么;但不是与其余的(2.)。'i'
'a'
'e'
有关的:
unknown
再次引用有关“常量”的手册:
PostgreSQL 中有三种隐式类型的常量:字符串、位字符串和数字。常量也可以用显式类型指定,这可以使系统更准确地表示和更有效地处理。
在那一章中有更多细节。
unknown
-type 文字是字符串,可以使用上面提到的“自动 I/O 转换转换”进行转换。但是 Postgres 需要在确定合适的类型转换之前确定目标类型。在普通赋值中,目标类型是显而易见的。在其他情况下,确定目标类型可能很棘手。在以下方面有广泛的规则体系:
归档时间: |
|
查看次数: |
6161 次 |
最近记录: |