【问题标题】:Firebird list domains and data typesFirebird 列出域和数据类型
【发布时间】:2018-07-05 11:46:15
【问题描述】:

我想列出所有域、它们的数据类型和大小。

背景

我已经设法根据this SO answer 进行查询。

基本代码取所有字段:

SELECT
  *
FROM
  rdb$fields

我发现我可以从rdb$fields获取字段:

  1. 通过RDB$FIELD_NAME过滤来自该请求的字段
  2. RDB$FIELD_TYPE获取字段类型代码
  3. RDB$FIELD_LENGTH获取字段长度

参考:

https://firebirdsql.org/file/documentation/reference_manuals/fblangref25-en/html/fblangref-appx04-fields.html


问题

如何结合所有这些来列出所有域、它们的数据类型和大小?

我只想获取用户创建的域,而不是自动创建的域。

【问题讨论】:

  • 问题中的“参考”超链接下方有表格,请阅读有关“RDB$SYSTEM_FLAG”的评论
  • 你也错过了 - RDB$NULL_FLAG, RDB$DEFAULT_SOURCE, RDB$COMPUTED_SOURCE, RDB$FIELD_SCALE, RDB$SEGMENT_LENGTH, RDB$COLLATION_ID, RDB$FIELD_PRECISION, RDB$CHARACTER_SET_ID, RDB$COLLATION_ID >

标签: firebird ibexpert


【解决方案1】:

代码:

select
    t.RDB$FIELD_NAME                     Name,
    case t.RDB$FIELD_TYPE
        when 7 then 'SMALLINT'
        when 8 then 'INTEGER'
        when 10 then 'FLOAT'
        when 12 then 'DATE'
        when 13 then 'TIME'
        when 14 then 'CHAR'
        when 16 then 'BIGINT'
        when 27 then 'DOUBLE PRECISION'
        when 35 then 'TIMESTAMP'
        when 37 then 'VARCHAR'
        when 261 then 'BLOB'
    end                                  Type_Name,
    t.RDB$CHARACTER_LENGTH               Chr_Length


from RDB$FIELDS t

     where coalesce( rdb$system_flag, 0) = 0 
       and not ( rdb$field_name starting with 'RDB$')

另外有趣的是,我找不到具有数据类型的系统表。必须从reference 对它们进行硬编码。

感谢cmets的帮助:

@MarkRotteveel

RDB$TYPE 包含类型,但名称不同:

您可以在RDB$TYPE 中找到 RDB$FIELD_NAME = 的所有数据类型 'RDB$FIELD_TYPE' (虽然你需要映射一些类型,因为它列出 SMALLINT 为 SHORT,INTEGER 为 LONG,BIGINT 为 INT64,VARCHAR 为 变化)

需要使用字段RDB$CHARACTER_LENGTH 而不是RDB$FIELD_LENGTH

请注意,RDB$FIELD_LENGTH 是 char/varchar 的错误列 列,因为它是以字节为单位的长度(取决于字符 设置),你需要使用RDB$CHARACTER_LENGTH作为长度 字符,对于数字字段,您更可能需要 RDB$FIELD_PRECISION (+ RDB$FIELD_SCALE),你也忽略了 sub 输入信息。

我只需要 varchars 的长度,但出现 RDB$FIELD_LENGTH = RDB$CHARACTER_LENGTH, 1 byte = 1 char for 1 byte character set

如果您使用 1 字节字符集 [1 字节 = 1 字符],但例如 UTF-8 是 (最大)每个字符 4 个字节,因此 field_length = 4 x 字符长度

@Arioch

获取用户域最可靠的方法:

在某种程度上可以使用select * from rdb$fields where coalesce( rdb$system_flag, 0) = 0 and not ( rdb$field_name starting with 'RDB$') 但是没有人禁止用户手动/显式创建列 命名为“RDB$1234567”。

【讨论】:

  • but it assumes all manually created domains have one pattern 不需要它,“手动创建” - 或者更好的是“显式创建”域有一个特殊的列来告诉他们自动创建 - RDB$SYSTEM_FLAG(以及一些程度较小,因为可以有伪自动手动创建的 - RDB$FIELD_NAME)
  • 您可以在RDB$TYPE 中找到RDB$FIELD_NAME = 'RDB$FIELD_TYPE' 的所有数据类型(尽管您需要映射某些类型,因为它将SMALLINT 列为SHORTINTEGER 列为LONG , BIGINTINT64VARCHARVARYING)。
  • 另请注意,RDB$FIELD_LENGTH 是 char/varchar 列的错误列,因为它是以字节为单位的长度(取决于字符集),您需要使用 RDB$CHARACTER_LENGTH 作为长度字符,对于数字字段,您更可能需要 RDB$FIELD_PRECISION (+ RDB$FIELD_SCALE),您也忽略了子类型信息。
  • 确实...在一定程度上可以使用select * from rdb$fields where coalesce( rdb$system_flag, 0) = 0 and not ( rdb$field_name starting with 'RDB$'),但是没有人禁止用户手动/显式创建名为“RDB$1234567”的列。也许没有可靠的方法来区分彼此,因为服务器显然不需要这种区分。您还可以检查是否有多个表列使用这些域,但这也不是万无一失的。我会提醒 Rus Manual 维护者,但我不太希望更新英文手册
  • @MaxMakhrov 仅当您使用 1 字节字符集时才会出现这种情况,但例如 UTF-8 是(最大)每个字符 4 字节,因此 field_length = 4 x character_length。跨度>
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-21
  • 1970-01-01
  • 2020-04-30
  • 2014-03-05
相关资源
最近更新 更多