Auslesen FB-System-Tabellen "zugeordnete Domain"

Themen rund um den praktischen Einsatz von Firebird. Fragen zu SQL, Performance, Datenbankstrukturen, etc.

Moderator: thorben.braun

Antworten
Hamburgo
Beiträge: 126
Registriert: Di 28. Mai 2019, 17:28

Hallo zusammen,

kann mir jemand folgenden SELECT dahingehend ergänzen, dass dieser mir auch den
Namen der einem Feld zugeordneten Domain mitliefert ?

Code: Alles auswählen

                 $Select = "SELECT r.RDB\$FIELD_NAME AS field_name,
                                  r.RDB\$DESCRIPTION AS field_description,
                                  r.RDB\$DEFAULT_VALUE AS field_default_value,
                                  r.RDB\$NULL_FLAG AS field_not_null_constraint,
                                  f.RDB\$FIELD_LENGTH AS field_length,
                                  f.RDB\$FIELD_PRECISION AS field_precision,
                                  f.RDB\$FIELD_SCALE AS field_scale,
                                  CASE f.RDB\$FIELD_TYPE
                                  WHEN 261 THEN 'BLOB'
                                  WHEN 14 THEN 'CHAR'
                                  WHEN 40 THEN 'CSTRING'
                                  WHEN 11 THEN 'D_FLOAT'
                                  WHEN 27 THEN 'DOUBLE'
                                  WHEN 10 THEN 'FLOAT'
                                  WHEN 16 THEN 'INT64'
                                  WHEN 8 THEN 'INTEGER'
                                  WHEN 9 THEN 'QUAD'
                                  WHEN 7 THEN 'SMALLINT'
                                  WHEN 12 THEN 'DATE'
                                  WHEN 13 THEN 'TIME'
                                  WHEN 35 THEN 'TIMESTAMP'
                                  WHEN 37 THEN 'VARCHAR'
                                  ELSE 'UNKNOWN'
                                  END AS field_type,
                                  f.RDB\$FIELD_SUB_TYPE AS field_subtype,
                                  coll.RDB\$COLLATION_NAME AS field_collation,
                                  cset.RDB\$CHARACTER_SET_NAME AS field_charset
                                  FROM RDB\$RELATION_FIELDS r
                                  LEFT JOIN RDB\$FIELDS f ON r.RDB\$FIELD_SOURCE = f.RDB\$FIELD_NAME
                                  LEFT JOIN RDB\$COLLATIONS coll ON f.RDB\$COLLATION_ID = coll.RDB\$COLLATION_ID
                                  LEFT JOIN RDB\$CHARACTER_SETS cset ON f.RDB\$CHARACTER_SET_ID = cset.RDB\$CHARACTER_SET_ID
                                  WHERE r.RDB\$RELATION_NAME='".$Name."' 
                                  ORDER BY r.RDB\$FIELD_POSITION
                          ";
Herzlichen Dank
Benutzeravatar
martin.koeditz
Beiträge: 500
Registriert: Sa 31. Mär 2018, 14:35

Hi,

die Domain-Namen stehen im Feld RDB$FIELD_NAME.

Code: Alles auswählen

SELECT r.RDB$FIELD_NAME AS field_name,
                                  r.RDB$DESCRIPTION AS field_description,
                                  r.RDB$DEFAULT_VALUE AS field_default_value,
                                  r.RDB$NULL_FLAG AS field_not_null_constraint,
                                  f.RDB$FIELD_LENGTH AS field_length,
                                  f.RDB$FIELD_PRECISION AS field_precision,
                                  f.RDB$FIELD_SCALE AS field_scale,       
                                  f.RDB$FIELD_NAME as domain_name,
                                  CASE f.RDB$FIELD_TYPE
                                  WHEN 261 THEN 'BLOB'
                                  WHEN 14 THEN 'CHAR'
                                  WHEN 40 THEN 'CSTRING'
                                  WHEN 11 THEN 'D_FLOAT'
                                  WHEN 27 THEN 'DOUBLE'
                                  WHEN 10 THEN 'FLOAT'
                                  WHEN 16 THEN 'INT64'
                                  WHEN 8 THEN 'INTEGER'
                                  WHEN 9 THEN 'QUAD'
                                  WHEN 7 THEN 'SMALLINT'
                                  WHEN 12 THEN 'DATE'
                                  WHEN 13 THEN 'TIME'
                                  WHEN 35 THEN 'TIMESTAMP'
                                  WHEN 37 THEN 'VARCHAR'
                                  ELSE 'UNKNOWN'
                                  END AS field_type,
                                  f.RDB$FIELD_SUB_TYPE AS field_subtype,
                                  coll.RDB$COLLATION_NAME AS field_collation,
                                  cset.RDB$CHARACTER_SET_NAME AS field_charset
                                  FROM RDB$RELATION_FIELDS r
                                  LEFT JOIN RDB$FIELDS f ON r.RDB$FIELD_SOURCE = f.RDB$FIELD_NAME
                                  LEFT JOIN RDB$COLLATIONS coll ON f.RDB$COLLATION_ID = coll.RDB$COLLATION_ID
                                  LEFT JOIN RDB$CHARACTER_SETS cset ON f.RDB$CHARACTER_SET_ID = cset.RDB$CHARACTER_SET_ID
                                  --WHERE r.RDB$RELATION_NAME='".$Name."' 
                                  ORDER BY r.RDB$FIELD_POSITION
Gruß
Martin
Martin Köditz
SynDesk SW GmbH
Hamburgo
Beiträge: 126
Registriert: Di 28. Mai 2019, 17:28

Hallo Martin,

vielen Dank für den Tipp, aber ich glaube, dass Du mich falsch verstanden hast.

Den obigen Select habe ich mal aus einem Forum geholt und ich habe keine Ahnung
warum so aufgebaut ist, weil hierfür meine Kenntnisse einfach zu mangelhaft sind.

Er liefert mir alle Informationen zu meinen Tabellen, die bisher brauchte, mit Ausnahme
des Namens einer evtl. zugeordneten Domain.

Mein Know-How reicht ebenfalls nicht dafür aus, in diesem Select irgend etwas zu ändern.

Meine Hoffnung ist, dass irgendeiner von Eurch Spezialisten diesen Select so ergänzen
kann, dass er mir zusätzlich auch den Domain-Namen liefert, wenn eine einem Feld zugeordnet ist.

Eine solche Änderung habe ich in Deiner Antwort nicht ausfindig machen können.

Oder habe ich da etwas übersehen ?
bfuerchau
Beiträge: 574
Registriert: Mo 7. Mai 2018, 18:09
Kontaktdaten:

FIELD_NAME = Feldname
DOMAIN_NAME = Domain

In o.a. Beispiel kannst du die Where-Klausel mit deinem Tabellennamen verwenden.
Übrigens:
Die kostenlose PE-Version von IBExpert funktioniert immer noch sehr gut und liefert viele Erkenntnisse, auch mit FB3.0.

https://www.ibexpert.net/ibe_de/pmwiki. ... nalEdition

Wenn man sich damit die Feldliste einer Tabelle ansieht, sieht man auch die Domainnamen (die gibts nämlich grundsätzlich) und kann sie da auch in gewissem Rahmen anppassen, z.B. CHAR(5) => CHAR(10), VARCHAR(N) => VARCHAR(N+100).
Durch die Satzkomprimierung bedarfs da noch nicht mal ein Umkopieren.
Hamburgo
Beiträge: 126
Registriert: Di 28. Mai 2019, 17:28

Hallo zusammen,

weil ich eine Info suchte, bin ich heute mal wieder meine eigenen Beiträge durchgegangen
und dabei nochmals auf diesen Thread gestoßen.

Im März 2022 bin ich nochmals dieses Thema angegangen und habe mein Problem lösen können.

Folgender Select liefert alle aus meiner Sicht wichtigen Infos zu Tabellen und ihren
Spalten / Feldern, auch halt die zugeordnete Domain (auch RDB$-Domains):

FIELD_NAME_LONG,
FIELD_TYPE,
FIELD_TYPE_NO,
FIELD_NULL,
FIELD_CHARSET,
FIELD_COLLATION,
FIELD_DEFAULT,
FIELD_CHECK,
FIELD_LENGTH,
FIELD_PRECISION,
FIELD_SCALE,
FIELD_SUBTYPE,
FIELD_POS,
FIELD_DESCRIPTION,
FIELD_DOMAIN,
FIELD_FLAG

Code: Alles auswählen

SELECT
  RF.RDB\$FIELD_NAME FIELD_NAME_LONG,
  CASE F.RDB\$FIELD_TYPE
    WHEN 7 THEN
      CASE F.RDB\$FIELD_SUB_TYPE
        WHEN 0 THEN 'SMALLINT'
        WHEN 1 THEN 'NUMERIC(' || F.RDB\$FIELD_PRECISION || ', ' || (-F.RDB\$FIELD_SCALE) || ')'
        WHEN 2 THEN 'DECIMAL(' || F.RDB\$FIELD_PRECISION || ', ' || (-F.RDB\$FIELD_SCALE) || ')'
      END
    WHEN 8 THEN
      CASE F.RDB\$FIELD_SUB_TYPE
        WHEN 0 THEN 'INTEGER'
        WHEN 1 THEN 'NUMERIC(' || F.RDB\$FIELD_PRECISION || ', ' || (-F.RDB\$FIELD_SCALE) || ')'
        WHEN 2 THEN 'DECIMAL(' || F.RDB\$FIELD_PRECISION || ', ' || (-F.RDB\$FIELD_SCALE) || ')'
      END
    WHEN 9 THEN 'QUAD'
    WHEN 10 THEN 'FLOAT'
    WHEN 12 THEN 'DATE'
    WHEN 13 THEN 'TIME'
    WHEN 14 THEN 'CHAR(' || (TRUNC(F.RDB\$FIELD_LENGTH / CH.RDB\$BYTES_PER_CHARACTER)) || ') '
    WHEN 16 THEN
      CASE F.RDB\$FIELD_SUB_TYPE
        WHEN 0 THEN 'BIGINT'
        WHEN 1 THEN 'NUMERIC(' || F.RDB\$FIELD_PRECISION || ', ' || (-F.RDB\$FIELD_SCALE) || ')'
        WHEN 2 THEN 'DECIMAL(' || F.RDB\$FIELD_PRECISION || ', ' || (-F.RDB\$FIELD_SCALE) || ')'
      END
    WHEN 27 THEN 'DOUBLE'
    WHEN 35 THEN 'TIMESTAMP'
    WHEN 37 THEN 'VARCHAR(' || (TRUNC(F.RDB\$FIELD_LENGTH / CH.RDB\$BYTES_PER_CHARACTER)) || ')'
    WHEN 40 THEN 'CSTRING' || (TRUNC(F.RDB\$FIELD_LENGTH / CH.RDB\$BYTES_PER_CHARACTER)) || ')'
    WHEN 45 THEN 'BLOB_ID'
    WHEN 261 THEN 'BLOB SUB_TYPE ' || F.RDB\$FIELD_SUB_TYPE
    ELSE 'RDB\$FIELD_TYPE: ' || F.RDB\$FIELD_TYPE || '?'
  END FIELD_TYPE,
  TRIM(RF.RDB\$FIELD_NAME) AS FIELD_NAME,
  IIF(COALESCE(RF.RDB\$NULL_FLAG, 0) = 0, NULL, 'NOT NULL') FIELD_NULL,
  TRIM(CH.RDB\$CHARACTER_SET_NAME) FIELD_CHARSET,
  TRIM(DCO.RDB\$COLLATION_NAME) FIELD_COLLATION,
  COALESCE(RF.RDB\$DEFAULT_SOURCE, F.RDB\$DEFAULT_SOURCE) FIELD_DEFAULT,
  F.RDB\$VALIDATION_SOURCE AS FIELD_CHECK,
  F.RDB\$FIELD_TYPE AS FIELD_TYPE_NO,
  F.RDB\$FIELD_LENGTH AS FIELD_LENGTH,
  F.RDB\$FIELD_PRECISION AS FIELD_PRECISION,
  F.RDB\$FIELD_SCALE AS FIELD_SCALE,
  F.RDB\$FIELD_SUB_TYPE AS FIELD_SUBTYPE,
  MIN(i.RDB\$INDEX_NAME) AS FIELD_IDX,
  RF.RDB\$FIELD_POSITION AS FIELD_POS,
  RF.RDB\$DESCRIPTION AS FIELD_DESCRIPTION,
  TRIM(RF.RDB\$FIELD_SOURCE) AS FIELD_DOMAIN,
  RF.RDB\$SYSTEM_FLAG AS FIELD_FLAG

 FROM RDB\$RELATION_FIELDS RF

LEFT JOIN RDB\$INDEX_SEGMENTS s ON s.RDB\$FIELD_NAME=RF.RDB\$FIELD_NAME

LEFT JOIN RDB\$INDICES i ON i.RDB\$INDEX_NAME = s.RDB\$INDEX_NAME 
      AND i.RDB\$RELATION_NAME=RF.RDB\$RELATION_NAME

LEFT JOIN RDB\$RELATION_CONSTRAINTS rc ON rc.RDB\$INDEX_NAME = s.RDB\$INDEX_NAME
      AND rc.RDB\$INDEX_NAME = i.RDB\$INDEX_NAME
      AND rc.RDB\$RELATION_NAME = i.RDB\$RELATION_NAME

 JOIN RDB\$FIELDS F ON (F.RDB\$FIELD_NAME = RF.RDB\$FIELD_SOURCE)
 LEFT OUTER JOIN RDB\$CHARACTER_SETS CH ON (CH.RDB\$CHARACTER_SET_ID = F.RDB\$CHARACTER_SET_ID)
 LEFT OUTER JOIN RDB\$COLLATIONS DCO ON ((DCO.RDB\$COLLATION_ID = F.RDB\$COLLATION_ID) AND (DCO.RDB\$CHARACTER_SET_ID = F.RDB\$CHARACTER_SET_ID))

 WHERE ";
         if ($Field == "#No#Field#"){
             $Select .= "
(RF.RDB\$RELATION_NAME = '".strtoupper($Table)."')";
         } else {
             $Select .= "
(RF.RDB\$RELATION_NAME = '".strtoupper($Table)."' AND RF.RDB\$FIELD_NAME = '".strtoupper($Field)."')";
         }
         $Select .= " AND (COALESCE(RF.RDB\$SYSTEM_FLAG, 0) = 0)
 GROUP BY 
        FIELD_NAME_LONG,
        FIELD_TYPE,
        FIELD_TYPE_NO,
        FIELD_NULL,
        FIELD_CHARSET,
        FIELD_COLLATION,
        FIELD_DEFAULT,
        FIELD_CHECK,
        FIELD_LENGTH,
        FIELD_PRECISION,
        FIELD_SCALE,
        FIELD_SUBTYPE,
        FIELD_POS,
        FIELD_DESCRIPTION,
        FIELD_DOMAIN,
        FIELD_FLAG

 ORDER BY RF.RDB\$FIELD_POSITION ASC;
Das war dann die Basis mir einen eigenen, web-basierten FireBird-DB-Manager zu bauen,
der Einiges mehr kann, als IbExpert und Konsorten.

Vielleicht ist das für Andere auch ganz nützlich, die auf meinem, eher bescheidenen Niveau kicken.
Benutzeravatar
martin.koeditz
Beiträge: 500
Registriert: Sa 31. Mär 2018, 14:35

Danke, dass du dein Ergebnis nochmals mit uns geteilt hast.
Martin Köditz
SynDesk SW GmbH
Antworten