【问题标题】:How to create regtype column in postgreSQL that includes length and precision parameter如何在 postgreSQL 中创建包含长度和精度参数的 regtype 列
【发布时间】:2018-06-25 01:51:04
【问题描述】:

我想在 postgreSQL 数据库中存储一些元信息。 这需要存储列类型信息。我知道 regtype 类型,但它不存储有关长度或精度的信息。

我怎样才能做到这一点。我可以改用 TEXT 列,但是我需要处理所有的验证和参照完整性。有没有更方便的方法来实现这一点?

下面我给出示例代码。

CREATE TABLE foo
(name TEXT,
sql_type regtype);

INSERT INTO foo
VALUES('my_field_1', 'character varying'::regtype);

INSERT INTO foo
VALUES('my_field_2', 'VARCHAR(50)'::regtype);

INSERT INTO foo
VALUES('my_field_3', 'NUMERIC(32,16)'::regtype);

SELECT * from foo;

结果如下:

name             sql_type
text             regtype
-------------------------------------
my_field_1      character varying
my_field_2      character varying
my_field_3      numeric

预期结果:

name             sql_type
text             regtype
-------------------------------------
my_field_1      character varying  <-- I won't need such cases
my_field_2      character varying(50)
my_field_3      numeric(32,16)

我目前使用的是 PostgreSQL 9.6

【问题讨论】:

  • Postgres 在内部将列定义存储为 regtype 以及 typmod,它保存长度/比例/精度(请参阅docs)。您可以使用format_type() 将它们转回字符串。
  • @NickBarnes:感谢您的回复,我看到 typemod 和 format_type() 都是内部 C 实现,并且在用户代码中不可用。我正在寻找 SQL / plpgsql 中的解决方案
  • 您当然可以使用 typemod 值并在 SQL 中调用 format_type()。唯一棘手的一点是首先掌握一个 typemod(如果您从现有的表定义中提取这些类型很容易,如果您需要自己构建它们就不是那么容易了)。但这绝对是可能的;这是一个例子:rextester.com/JLK17510

标签: postgresql types create-table


【解决方案1】:

regclass 类型是一种便利类型,在内部只是该类型的数字对象标识符,因此它不包含有关比例、精度、长度和其他类型修饰符的信息。

会将类型连同其修饰符一起存储为text

但如果你愿意,你也可以这样做:

CREATE TABLE coldef (
   column_name              name     NOT NULL,
   data_type                regtype  NOT NULL,
   numeric_precision        smallint
      CHECK (numeric_precision IS NULL
             OR numeric_precision BETWEEN 1 AND 1000),
   numeric_scale            smallint
      CHECK (numeric_scale IS NULL
             OR numeric_scale BETWEEN 0 AND numeric_precision),
   character_maximum_length integer
      CHECK (character_maximum_length IS NULL
             OR character_maximum_length BETWEEN 1 AND 10485760),
   datetime_precision       smallint
      CHECK (datetime_precision IS NULL
             OR datetime_precision BETWEEN 0 AND 6),
   interval_precision       smallint
      CHECK (interval_precision IS NULL
             OR interval_precision BETWEEN 0 AND 6)
);

您可以添加更多检查约束以确保没有禁止的组合,例如具有数字精度的 character varying,或者当 numeric_scalenumeric_precision 时,NOT NULL 必须是 NOT NULL

从包含列元数据的目录表information_schema.columns 中获得灵感。

【讨论】:

  • 感谢您的回答。我想我会坚持使用包含所有类型元信息的 TEXT/VARCHAR 字段,例如“NUMERIC(32,16)”。如果出于某种原因我会选择为精度、比例等设置单独的字段,您是否知道 SQL 用户可访问的函数会产生文本输出(format_type() 等效于@NickBarnes 在他的评论中建议的)?
  • 不,但是用几个CASE 表达式构建这样一个函数就足够简单了。
猜你喜欢
  • 2021-01-14
  • 2014-10-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多