FirebirdSQL logo

The CREATE DATABASE statement

Now you can create your new database interactively.Let’s suppose that you want to create a database named test.fdb and store it in a directory named data on your D drive:

SQL>create database 'D:\data\test.fdb' page_size 8192[chevron circle left]
CON>user 'sysdba' password 'masterkey';[chevron circle left]
Important
  • In the CREATE DATABASE statement it is mandatory to place quote characters (single or double) around path and password.This is different from the CONNECT statement.Quoting the username is optional, unless it is case-sensitive or contains spaces, international characters or any other character that is not allowed in a regular (unquoted) identifier.

  • If the connection string doesn’t start with a host or protocol name, creation of the database file is attempted with your OS login as the owner.This may or may not be what you want (think of access rights if you want others to be able to connect).If you prepend localhost: or a protocol to the path or alias, the server process will create and own the file.

The database will be created and, after a few moments, the SQL prompt will reappear.You are now connected to the new database and can proceed to create some test objects in it.

To verify that there really is a database there, let’s first type in this query:

SQL>select * from rdb$relations;[chevron circle left]

Although you haven’t created any tables yet, the screen will fill up with a large amount of data!This query selects all rows in the system table RDB$RELATIONS, where Firebird stores the metadata for tables.An “empty” database is not really empty: it contains a number of system tables and other objects.The system tables will grow as you add more user objects to your database.

To get back to the command prompt type QUIT or EXIT, as explained in the section on connecting.

Creating a database as a non-privileged user

In Firebird 5, if you try to create a database other than in embedded mode as someone who is not a Firebird admin (i.e. SYSDBA or an account with equal rights), you may be in for a surprise:

SQL>create database 'xnet://D:\data\mydb.fdb' user 'john' password 'lennon';[chevron circle left]
Statement failed, SQLSTATE = 28000
no permission for CREATE access to DATABASE D:\DATA\MYDB.FDB

Non-admin users must explicitly be granted the right to create databases by a Firebird admin:

SQL>grant create database to user john;[chevron circle left]

After that, they can create databases.

Notice that with a serverless connection, i.e. without specifying a host name or protocol before the database name (and Engine13 enabled!), Firebird won’t deny any CREATE DATABASE statement.It will only fail if the client process doesn’t have sufficient rights in the directory where the database is to be created.

docnext count = 20

Firebird SQL

Every database management system has its own idiosyncrasies in the ways it implements SQL.Firebird adheres to the SQL standard more rigorously than most other RDBMSes.Developers migrating from products that are less standards-compliant often wrongly suppose that Firebird is quirky, whereas many of its apparent quirks are not quirky at all.

Division of an integer by an integer

Firebird accords with the SQL standard by truncating the result (quotient) of an integer/integer calculation to the next lower integer.This can have bizarre results unless you are aware of it.

For example, this calculation is correct in SQL:

1 / 3 = 0

If you are upgrading from an RDBMS which resolves integer/integer division to a float quotient, you will need to alter any affected expressions to use a float or scaled numeric type for either dividend, divisor, or both.

For example, the calculation above could be modified thus to produce a non-zero result:

1.000 / 3 = 0.333
String delimiter symbol

Strings in Firebird are delimited by a pair of single quote (apostrophe) symbols: 'I am a string' (ASCII code 39, not 96).If you used earlier versions of Firebird’s relative, InterBase®, you might recall that double and single quotes were interchangeable as string delimiters.Double quotes cannot be used as string delimiters in Firebird SQL statements.

Apostrophes in strings

If you need to use an apostrophe inside a Firebird string, you can “escape” the apostrophe character by preceding it with another apostrophe.

For example, this string will give an error:

'Joe's Emporium'

because the parser encounters the apostrophe and interprets the string as 'Joe' followed by some unknown keywords.To make it a legal string, double the apostrophe character:

'Joe''s Emporium'

Notice that this is two single quotes, not one double-quote.

You can also use the alternative quote string literal, allowing you to embed the quote without escaping:

q'{Joe's Emporium}'
Concatenation of strings

The concatenation symbol in SQL is two “pipe” symbols (“||”, or a pair of ASCII 124 without space between).In SQL, the “+” symbol is an arithmetic operator, and it will cause an error if you attempt to use it for concatenating strings.The following expression prefixes a character column value with the string “Reported by:”:

'Reported by: ' || LastName

Firebird will raise an error if the result of a string concatenation exceeds the maximum (var)char size of 32 Kb.If only the potential result — based on variable or field size — is too long you’ll get a warning, but the operation will be completed successfully.(In pre-2.0 Firebird, this too would cause an error and halt execution.)

See also the section below, [qsg5-nulls], about concatenating in expressions involving NULL.

Double-quoted identifiers

Before the SQL-92 standard, it was not legal to have object names (identifiers) in a database that duplicated keywords in the language, were case-sensitive or contained spaces or special characters[1].SQL-92 introduced a new syntax to make any of them legal, provided that the identifiers are defined within pairs of double-quote symbols (ASCII 34) and were always referred to using double-quote delimiters (so called quoted or delimited identifiers).

The purpose of this “gift” was to make it easier to migrate metadata from non-standard RDBMSes to standards-compliant ones.The downside is that, if you choose to define an identifier in double quotes, its case-sensitivity and the enforced double-quoting will remain mandatory.

Firebird does permit a slight relaxation under a very limited set of conditions.If the identifier which was defined in double-quotes:

  1. is defined as all upper-case,

  2. is not a keyword, and

  3. conforms to the other rules of regular identifiers[1],

...then it can be used in SQL unquoted and case-insensitively.(But as soon as you put double-quotes around it, you must match the case again!)

Warning

Don’t get too smart with this!For instance, if you have tables “TESTTABLE” and “TestTable”, both defined within double-quotes, and you issue the command:

SQL>select * from TestTable;

...you will get the records from “TESTTABLE”, not “TestTable”!

Unless you have a compelling reason to define quoted identifiers, it is recommended that you avoid them.Firebird happily accepts a mix of quoted and unquoted identifiers — so there is no problem including that keyword which you inherited from a legacy database, if you need to.

Tip

Some database admin tools enforce double-quoting of all identifiers by default.Try to choose a tool which makes double-quoting optional.


1. Only a-z, A-Z, 0-9 and _ are allowed in regular identifiers, Firebird also allows $, and the first character must be a-z or A-Z

Expressions involving NULL

In SQL, NULL is not a value.It is a condition, or state, of a data item, in which its value is unknown.Because it is unknown, NULL cannot behave like a value.When you try to perform arithmetic on NULL, or involve it with values in other expressions, the result of the operation will almost always be NULL.It is not zero or blank or an “empty string”, and it does not behave like any of these values.

Below are some examples of the types of surprises you will get if you try to perform calculations and comparisons with NULL.

The following expressions all return NULL:

  • 1 + 2 + 3 + NULL

  • not (NULL)

  • 'Home ' || 'sweet ' || NULL

You might have expected 6 from the first expression and “Home sweet” from the third, but as we just said, NULL is not like the number 0 or an empty string — it’s far more destructive!

The following expression:

FirstName || ' ' || LastName

will return NULL if either FirstName or LastName is NULL.Otherwise, it will nicely concatenate the two names with a space in between — even if any one of the variables is an empty string.

Tip

Think of NULL as UNKNOWN and these strange results suddenly start to make sense!If the value of Number is unknown, the outcome of ‘1 + 2 + 3 + Number’ is also unknown (and therefore NULL).If the content of MyString is unknown, then so is ‘MyString || YourString’ (even if YourString is non-NULL).Et cetera.

Now let’s examine some PSQL (Procedural SQL) examples with if-constructs:

  • Equals (‘=’)

    if (a = b) then
      MyVariable = 'Equal';
    else
      MyVariable = 'Not equal';

    After executing this code, MyVariable will be 'Not equal' if both a and b are NULL.The reason is that a = b yields NULL if at least one of them is NULL.If the test expression of an “if” statement is NULL, it behaves like false: the ‘then’ block is skipped, and the ‘else’ block executed.

    Warning

    Although the expression may behave like false in this case, it’s still NULL.If you try to invert it using not(), what you get is another NULL — not “true”.

  • Not equals (‘<>’)

    if (a <> b) then
      MyVariable = 'Not equal';
    else
      MyVariable = 'Equal';

    Here, MyVariable will be 'Equal' if a is NULL and b isn’t, or vice versa.The explanation is analogous to that of the previous example.

The DISTINCT keyword comes to the rescue!

Firebird 2 and above implement IS [NOT] DISTINCT allowing you to perform (in)equality tests that take NULL into account.The semantics are as follows:

  • Two expressions are DISTINCT if they have different values or if one is NULL and the other isn’t;

  • They are NOT DISTINCT if they have the same value or if they are both NULL.

Notice that if neither operand is NULL, IS DISTINCT works exactly like the “<>” operator, and IS NOT DISTINCT like the “=” operator.

IS DISTINCT and IS NOT DISTINCT always return true or false, never NULL.

Using DISTINCT, you can rewrite the first PSQL example as follows:

if (a is not distinct from b) then
  MyVariable = 'Equal';
else
  MyVariable = 'Not equal';

And the second as:

if (a is distinct from b) then
  MyVariable = 'Not equal';
else
  MyVariable = 'Equal';

These versions will give you the results that a normal (i.e. not SQL-brainwashed) human being would expect, whether there are NULLs involved or not.

Backup

Firebird comes with two utilities for backing up and restoring your databases: gbak and nbackup.Both can be found in the Firebird installation directory (Windows) or its bin subdirectory (Linux).Firebird databases can be backed up while users are connected to the system and going about their normal work.The backup will be taken from a snapshot of the database at the time the backup began.

Regular backups and occasional restores should be a scheduled part of your database management activity.

Warning

Except in nbackup’s lock mode, do not use external proprietary backup utilities or file-copying tools such as WinZip, tar, copy, xcopy, etc., on a database which is running.Not only will the backup be unreliable, but the disk-level blocking used by these tools can corrupt a running database.

Important

Study the warnings in the next section about database activity during restores!

More information about gbak can be found here (HTML and PDF version, same content):

The nbackup manual is here (again same content in HTML and PDF):

How to corrupt a database

The following sections constitute a summary of things not to do if you want to keep your Firebird databases in good health.

Disabling forced writes

Firebird is installed with forced writes (synchronous writes) enabled by default.Modifications are written to disk immediately upon posting.

It is possible to configure a database to use asynchronous data writes — whereby modified or new data are held in the memory cache for periodic flushing to disk by the operating system’s I/O subsystem.The common term for this configuration is forced writes off (or disabled).It is sometimes resorted to in an attempt to improve performance during large batch operations.

Disabling forced writes on Windows

The big warning here is: do not disable forced writes on a Windows server.It has been observed that the Windows server platforms do not flush the write cache until the Firebird service is shut down.Apart from power interruptions, there is just too much that can go wrong on a Windows server.If it should hang, the I/O system goes out of reach and your users' work will be lost in the process of rebooting.

Disabling forced writes on Linux

Linux servers are safer for running an operation with forced writes disabled temporarily.Still, do not leave it disabled once your large batch task is completed, unless you have a very robust fall-back power system.

Restoring a backup to a running database

One of the restore options in the gbak utility (gbak -rep[lace_database]) allows you to restore a gbak file over an existing database.It is possible for this style of restore to proceed without warning while users are logged in to the database.Database corruption is almost certain to be the result.

Note

Notice that the shortest form of this command is gbak -rep, not gbak -r as it used to be in older Firebird versions.What happened to gbak -r?It is now short for gbak -recreate_database, which functions the same as gbak -c[reate] and throws an error if the specified database already exists.You can force overwriting of the existing database by adding the o[verwrite] flag though.This flag is only supported with gbak -r, not with gbak -c.

These changes have been made because many users thought that the -r switch meant restore instead of replace — and only found out otherwise when it was too late.

Warning

Be aware that you will need to design your admin tools and procedures to prevent any possibility for any user (including SYSDBA) to restore to your active database if any users are logged in.

If is practicable to do so, it is recommended to restore to spare disk space using the gbak -c option and test the restored database using isql or your preferred admin tool.If the restored database is good, shut down the old database (you can use the gfix command-line tool for this;see Firebird Database Housekeeping Utility (HTML) or Firebird Database Housekeeping Utility (PDF)).Make a filesystem copy of the old database just in case and then copy the restored database file(s) over their existing counterparts.

Allowing users to log in during a restore

If you do not block access to users while performing a restore using gbak -rep then users may be able to log in and attempt to do operations on data.Corrupted structures will result.

How to get help

The community of willing helpers around Firebird goes a long way back, to many years before the source code for its ancestor, InterBase® 6, was made open source.Collectively, the Firebird community does have all the answers!It even includes some people who have been involved with it since it was a design on a drawing board in a bathroom in Boston.

How to give help

Firebird exists, and continues to be improved, thanks to a community of volunteers who donate their time and skills to bring you this wonderful piece of software.But volunteer work alone is not enough to keep an enterprise-level RDBMS such as Firebird up-to-date.The Firebird Foundation supports Firebird development financially by issuing grants to designers and developers.If Firebird is useful to you, and you’d like to give something back, please visit the Foundation’s pages and consider making a donation or becoming a member or sponsor.