Firebird Documentation IndexFirebird 1.5.6 Release NotesSQL Language Enhancements → Data Definition Language (DDL)
Firebird Home Firebird Home Prev: SQL Language EnhancementsFirebird Documentation IndexUp: SQL Language EnhancementsNext: Data Manipulation Language (DML)

Data Definition Language (DDL)

New Data Types
(1.5) Enhancements to named constraints
(1.5) Multi-action triggers
(1.5) RECREATE VIEW
(1.5) CREATE OR ALTER {TRIGGER | PROCEDURE }
(1.5) (1.0) Alter Trigger no longer increments the change count on tables
(1.5) NULLs in unique constraints and indices
(1.0) DROP GENERATOR
From Firebird v.1.0.x

DDL is the language subset that is used for creating, altering and dropping metadata. The following changes have been implemented:

New Data Types

(1.5) BIGINT

BIGINT is the new SQL99-compliant name for the 64-bit signed, exact numeric type, with a scale of zero. Available in Dialect 3 only.

Examples

i)

  DECLARE VARIABLE VAR1 BIGINT;
        

ii)

  CREATE TABLE TABLE1 (FIELD1 BIGINT);
        

(1.5) Enhancements to named constraints

Dmitry Yemanov

Indexes that enforce named constraints may now be named with user-defined identifiers.

Previously, although it was possible to created named PRIMARY, FOREIGN KEY and UNIQUE constraints, the identifier of the automatically-generated enforcing index was calculated by the system, e.g., RDB$FOREIGN13, and could not be altered. This remains the default behaviour when named constraints are not used.

However, language extensions have been added to enable

  1. a system-generated index to receive automatically the same identifier as the named constraint it enforces

  2. an index which enforces a named or unnamed constraint to be explicitly assigned a custom identifier and to be optionally constructed in DESCENDING order.

Note

It is not currently possible to use a pre-existing index.

Syntax Pattern

  ...
  [ADD] CONSTRAINT [<constraint-identifier>]
  <constraint-type> <constraint-definition>
  [USING [ASC[ENDING] | DESC[ENDING]] INDEX <index_name>]
      

Caution

Make sure that foreign key and primary key indexes use the same sort order (DESC | ASC ).

Examples

i) Named constraint and explicitly-named index:

  CREATE TABLE ATEST (
    ID BIGINT NOT NULL,
    DATA VARCHAR(10));
  COMMIT;
      

The following statement will create a primary key constraint named PK_ATEST and an enforcing, descending index named IDX_PK_ATEST:

  ALTER TABLE ATEST
  ADD CONSTRAINT PK_ATEST PRIMARY KEY(ID)
  USING DESC INDEX IDX_PK_ATEST;
  COMMIT;
      

ii) Alternative to i) above:

  CREATE TABLE ATEST (
    ID BIGINT NOT NULL,
    DATA VARCHAR(10),
    CONSTRAINT PK_ATEST PRIMARY KEY(ID)
    USING DESC INDEX IDX_PK_ATEST;
      

iii) This statement creates the table ATEST with the primary key PK_ATEST. The enforcing index is also named PK_ATEST.:

  CREATE TABLE ATEST (
    ID BIGINT NOT NULL,
    DATA VARCHAR(10),
    CONSTRAINT PK_ATEST PRIMARY KEY(ID));
      

(1.5) Multi-action triggers

Dmitry Yemanov

Triggers are enhanced to enable them to handle multiple row-level operations conditionally.

Syntax Pattern

  CREATE TRIGGER name FOR table
    [ACTIVE | INACTIVE]
    {BEFORE | AFTER} <multiple_action>
    [POSITION number]
  AS trigger_body

  <multiple_action> ::= <single_action> [OR <single_action> [OR <single_action>]]
  <single_action> ::= {INSERT | UPDATE | DELETE}
      

Examples

i)

  CREATE TRIGGER TRIGGER1 FOR TABLE1
  ACTIVE BEFORE INSERT OR UPDATE AS
  ...;
      

ii)

  CREATE TRIGGER TRIGGER2 FOR TABLE2
  ACTIVE AFTER INSERT OR UPDATE OR DELETE AS
  ...;
      

ODS Change

Encoding of field RDB$TRIGGER_TYPE (relation RDB$TRIGGERS) has been extended to allow complex trigger actions. For details, refer to the document readme.universal_triggers.txt in the /doc/sql.extensions branch of the Firebird CVS tree.

Notes

  1. One-action triggers are fully compatible at ODS level with FB 1.0.

     

  2. RDB$TRIGGER_TYPE encoding is order-dependant, i.e., BEFORE INSERT OR UPDATE and BEFORE UPDATE OR INSERT will be coded differently, although they have the same semantics and will be executed exactly the same way.

     

  3. Both OLD and NEW context variables are available in multiple-action triggers. If the trigger invocation forbids one of them (e.g. OLD context for INSERT operation), then all fields of that context will evaluate to NULL. If they are assigned to an improper context, a runtime exception will be thrown.

     

  4. The new Boolean context variables INSERTING/UPDATING/DELETING can be used to check the operation type at runtime. (See below.)

(1.5) RECREATE VIEW

Exactly the same as CREATE VIEW if the view does not already exist. If it does exist, RECREATE VIEW will try to drop it and create a completely new object. RECREATE VIEW will fail if the object is in use.

Uses the same syntax as CREATE VIEW.

(1.5) CREATE OR ALTER {TRIGGER | PROCEDURE }

Statement that will either create a new trigger or procedure (if it does not already exist) or alter it (if it already exists) and recompile it. The CREATE OR ALTER syntax preserves existing dependencies and permissions.

Syntax is as for CREATE TRIGGER | CREATE PROCEDURE, respectively, except for the additional keywords "OR ALTER".

(1.5) (1.0) Alter Trigger no longer increments the change count on tables

When the count of metadata changes on any single table reaches the maximum of 255, the database becomes unavailable. Backup and restore are required in order to reset the change count and make the database once again available. The intention of this feature is to enforce a database cleanup when table structures have undergone a lot of changes, not to inhibit useful capabilities in the engine.

Previously, each time a trigger was set ACTIVE|INACTIVE by an ALTER TRIGGER statement, the change count for the associated table would be incremented. This affected the usefulness of disabling and re-enabling trigger code for regular operations, since it would cause the change count to rise quickly. Now, it is not treated as a metadata change for table versioning purposes.

(1.5) NULLs in unique constraints and indices

Dmitry Yemanov

It is now possible to apply a UNIQUE constraint or a unique index to a column that does not have the NOT NULL constraint, in compliance with SQL-99. Be cautious about using this if you plan to revert your database to Firebird 1.0.x or any InterBase version, since those older servers will see the index as corrupt.

Syntax Details


  <unique constraint or index definition> ::=
    <unique specification> ( <unique column list UCL> )
  <unique specification> ::=
    {{[constraint-name]UNIQUE | UNIQUE INDEX index-name]} |
      [constraint-name] PRIMARY KEY}
      

where <unique column list> can contain one or more columns without the NOT NULL attribute, if <unique specification> is UNIQUE or UNIQUE INDEX index-name.

Caution

All columns in PRIMARY KEY still must be declared NOT NULL.

The constraint allows existence of only those rows for which search condition (i) or (ii) evaluates as True, according to the following logic:

  1. If the <unique specification> specifies PRIMARY KEY, then the search condition shall be:

      UNIQUE ( SELECT UCL FROM TN ) AND ( UCL ) IS NOT NULL
            

     

  2. Otherwise, the <search condition> shall be:

      UNIQUE ( SELECT UCL FROM TN )
            

    In this case, the condition UNIQUE can not be True if ( SELECT UCL FROM TN ) could output two rows where all of the corresponding non-null segment pairs match.

The constraint allows existence of only those rows for which the aforementioned <search condition> evaluates to True. In a unique index or under a UNIQUE constraint, two sets of column values will be considered distinct and thus allowed if:

  1. both sets contain only nulls, or

     

  2. there is at least one pair of corresponding values of which one is non-null, and the other either null or a different non-null value.

Examples

UNIQUE constraint:

  CREATE TABLE t (
    a INTEGER,
    b INTEGER,
    CONSTRAINT pk UNIQUE (a, b));
      

or UNIQUE index:

  CREATE TABLE t (a INTEGER, b INTEGER);
  COMMIT;

  CREATE UNIQUE INDEX uqx ON t(a, b);
  COMMIT;

  INSERT INTO t
    VALUES (NULL, NULL); /* ok, nulls allowed */

  INSERT INTO t
    VALUES (1, 2); /* as are non-nulls */

  INSERT INTO t
    VALUES (1, NULL); /* and combinations */

  INSERT INTO t
    VALUES (NULL, NULL); /* ok, all pairs of nulls are distinct */
      

but not:

  INSERT INTO t
    VALUES (1, NULL);
    /* fails because all corresponding non-null segments match */
      

It means that the PRIMARY KEY constraint doesn't allow NULLs whilst the UNIQUE constraint and unique indexes allow an arbitrary number of NULLs. For multi-column result sets of ( SELECT UCL FROM TN ), the common rules for NULLs are applied, i.e. (1, NULL) is distinct from (NULL, 1) and one (NULL, NULL) is distinct from any other (NULL, NULL).

(1.0) DROP GENERATOR

Enables unused generators to be removed from the database. Storage will be freed for re-use upon the next RESTORE. Available in SQL and DSQL.

Syntax Pattern

  DROP GENERATOR <generator name>;
      

From Firebird v.1.0.x

The following were implemented in Firebird 1.0. They are described again here for the convenience of the reader.

(1.0) RECREATE PROCEDURE

This new DDL command lets you create a new stored procedure with the same name as an existing procedure, replacing the old procedure, without needing to drop the old procedure first. The syntax is identical to CREATE PROCEDURE.

Available in SQL and DSQL.

(1.0) RECREATE TABLE

This new DDL command lets you create a new structure for an existing table without needing to drop the old table first. The syntax is identical to CREATE TABLE.

Note

Observe that RECREATE TABLE does not preserve the data in the old table.

Available in SQL and DSQL.

Prev: SQL Language EnhancementsFirebird Documentation IndexUp: SQL Language EnhancementsNext: Data Manipulation Language (DML)
Firebird Documentation IndexFirebird 1.5.6 Release NotesSQL Language Enhancements → Data Definition Language (DDL)