|
2012-01-22 11:31:28-0500 |
![]() |
Table of Contents
List of Tables
List of Examples
Table of Contents
HSQLDB (HyperSQL DataBase) is a modern relational database manager that conforms closely to the SQL:2008 Standard and JDBC 4 specifications. It supports all core features and many of the optional features of SQL:2008.
The first versions of HSQLDB were released in 2001. Version 2.0, first released in 2010, includes a complete rewrite of most parts of the database engine.
This documentation covers the latest HyperSQL version 2.2. This documentation is regularly improved and updated. The latest, updated version can be found at http://hsqldb.org/doc/2.0/
If you notice any mistakes in this document, or if you have problems with the procedures themselves, please use the HSQLDB support facilities which are listed at http://hsqldb.org/support
This document is available in several formats.
You may be reading this document right now at http://hsqldb.org/doc/2.0, or in a distribution somewhere else. I hereby call the document distribution from which you are reading this, your current distro.
http://hsqldb.org/doc/2.0 hosts the latest production versions of all available formats. If you want a different format of the same version of the document you are reading now, then you should try your current distro. If you want the latest production version, you should try http://hsqldb.org/doc/2.0.
Sometimes, distributions other than http://hsqldb.org/doc/2.0 do not host all available formats. So, if you can't access the format that you want in your current distro, you have no choice but to use the newest production version at http://hsqldb.org/doc/2.0.
Table 1. Available formats of this document
| format | your distro | at http://hsqldb.org/doc/2.0 |
|---|---|---|
| Chunked HTML | index.html | http://hsqldb.org/doc/2.0/guide/ |
| All-in-one HTML | guide.html | http://hsqldb.org/doc/2.0/guide/guide.html |
| guide.pdf | http://hsqldb.org/doc/2.0/guide/guide.pdf |
If you are reading this document now with a standalone PDF reader, the
your distro links may not work.
$Revision: 4895 $
Copyright 2002-2012 Fred Toussi. Permission is granted to distribute this document without any alteration under the terms of the HSQLDB license. Additional permission is granted to the HSQL Development Group to distribute this document with or without alterations under the terms of the HSQLDB license.
2012-01-22 11:31:28-0500
Table of Contents
The HSQLDB jar package is located in the /lib directory of the ZIP package and contains several components and programs.
Components of the Hsqldb jar package
HyperSQL RDBMS Engine (HSQLDB)
HyperSQL JDBC Driver
Database Manager (GUI database access tool, with Swing and AWT versions)
Sql Tool (command line database access tool)
The HyperSQL RDBMS and JDBC Driver provide the core functionality. An additional jar contains Sql Tool (command line database access tool). SqlTool and the DatabaseManagers are general-purpose database tools that can be used with any database engine that has a JDBC driver.
The tools are used for interactive user access to databases,
including creation of a database, inserting or modifying data, or querying
the database. All tools are run in the normal way for Java programs. In
the following example the Swing version of the Database Manager is
executed. The hsqldb.jar is located in the directory
../lib relative to the current directory.
java -cp ../lib/hsqldb.jar org.hsqldb.util.DatabaseManagerSwing
If hsqldb.jar is in the current directory, the
command would change to:
java -cp hsqldb.jar org.hsqldb.util.DatabaseManagerSwing
Main classes for the Hsqldb tools
org.hsqldb.util.DatabaseManager
org.hsqldb.util.DatabaseManagerSwing
When a tool is up and running, you can connect to a database (may be a new database) and use SQL commands to access and modify the data.
Tools can use command line arguments. You can add the command line argument --help to get a list of available arguments for these tools.
Double clicking the HSQLDB jar will start the DatabaseManagerSwing application.
Each HyperSQL database is called a catalog. There are three types of catalog depending on how the data is stored.
Types of catalog data
mem: stored entirely in RAM - without any persistence beyond the JVM process's life
file: stored in filesystem files
res: stored in a Java resource, such as a Jar and always read-only
All-in-memory, mem: catalogs can be used for test data or as sophisticated caches for an application. These databases do not have any files.
A file: catalog consists of between 2 to 6 files, all named the same but with different extensions, located in the same directory. For example, the database named "test" consists of the following files:
test.properties
test.script
test.log
test.data
test.backup
test.lobs
The properties file contains a few settings about the database. The
script file contains the definition of tables and other database objects,
plus the data for non-cached tables. The log file contains recent changes
to the database. The data file contains the data for cached tables and the
backup file is a compressed backup of the last known consistent state of
the data file. All these files are essential and should never be deleted.
For some catalogs, the test.data and
test.backup files will not be present. In addition to
those files, a HyperSQL database may link to any formatted text files,
such as CSV lists, anywhere on the disk.
While the "test" catalog is open, a test.log
file is used to write the changes made to data. This file is removed at a
normal SHUTDOWN. Otherwise (with abnormal shutdown) this file is used at
the next startup to redo the changes. A test.lck file
is also used to record the fact that the database is open. This is deleted
at a normal SHUTDOWN.
![]() | Note |
|---|---|
|
When the engine closes the database at a shutdown, it creates
temporary files with the extension |
A res: catalog consists of the files for a small, read-only database that can be stored inside a Java resource such as a ZIP or JAR archive and distributed as part of a Java application program.
In general, JDBC is used for all access to databases. This is done
by making a connection to the database, then using various methods of the
java.sql.Connection object that is returned to
access the data. Access to an in-process database
is started from JDBC, with the database path specified in the connection
URL. For example, if the file: database name is
"testdb" and its files are located in the same directory as where the
command to run your application was issued, the following code is used for
the connection:
Connection c = DriverManager.getConnection("jdbc:hsqldb:file:testdb", "SA", "");
The database file path format can be specified using forward slashes
in Windows hosts as well as Linux hosts. So relative paths or paths that
refer to the same directory on the same drive can be identical. For
example if your database path in Linux is
/opt/db/testdb and you create an identical directory
structure on the C: drive of a Windows host, you can
use the same URL in both Windows and Linux:
Connection c = DriverManager.getConnection("jdbc:hsqldb:file:/opt/db/testdb", "SA", "");
When using relative paths, these paths will be taken relative to the
directory in which the shell command to start the Java Virtual Machine was
executed. Refer to the Javadoc for JDBCConnection for more
details.
Paths and database names for file databases are treated as case-sensitive when the database is created or the first connection is made to the database. But if a second connection is made to an open database, using a path and name that differs only in case, then the connection is made to the existing open database. This measure is necessary because in Windows the two paths are equivalent.
A mem: database is specified by the mem: protocol. For mem: databases, the path is simply a name. Several mem: databases can exist at the same time and distinguished by their names. In the example below, the database is called "mymemdb":
Connection c = DriverManager.getConnection("jdbc:hsqldb:mem:mymemdb", "SA", "");
A res: database, is specified by the res: protocol. As it is a Java resource, the database path is a Java URL (similar to the path to a class). In the example below, "resdb" is the root name of the database files, which exists in the directory "org/my/path" within the classpath (probably in a Jar). A Java resource is stored in a compressed format and is decompressed in memory when it is used. For this reason, a res: database should not contain large amounts of data and is always read-only.
Connection c = DriverManager.getConnection("jdbc:hsqldb:res:org.my.path.resdb", "SA", "");
The first time in-process connection is made to a database, some general data structures are initialised and a few helper threads are started. After this, creation of connections and calls to JDBC methods of the connections execute as if they are part of the Java application that is making the calls. When the SQL command "SHUTDOWN" is executed, the global structures and helper threads for the database are destroyed.
Note that only one Java process at a time can make in-process connections to a given file: database. However, if the file: database has been made read-only, or if connections are made to a res: database, then it is possible to make in-process connections from multiple Java processes.
For most applications, in-process access is faster, as the data is not converted and sent over the network. The main drawback is that it is not possible by default to connect to the database from outside your application. As a result you cannot check the contents of the database with external tools such as Database Manager while your application is running.
Server modes provide the maximum accessibility. The database engine runs in a JVM and opens one or more in-process catalogs. It listens for connections from programs on the same computer or other computers on the network. It translates these connections into in-process connections to the databases.
Several different programs can connect to the server and retrieve or update information. Applications programs (clients) connect to the server using the HyperSQL JDBC driver. In most server modes, the server can serve an unlimited number of databases that are specified at the time of running the server, or optionally, as a connection request is received.
A Sever mode is also the prefered mode of running the database during development. It allows you to query the database from a separate database access utility while your application is running.
There are three server modes, based on the protocol used for communications between the client and server. They are briefly discussed below. More details on servers is provided in the HyperSQL Network Listeners (Servers) chapter.
This is the preferred way of running a database server and the fastest one. A proprietary communications protocol is used for this mode. A command similar to those used for running tools and described above is used for running the server. The following example of the command for starting the server starts the server with one (default) database with files named "mydb.*" and the public name of "xdb". The public name hides the file names from users.
java -cp ../lib/hsqldb.jar org.hsqldb.server.Server --database.0 file:mydb --dbname.0 xdb
The command line argument --help can be used to
get a list of available arguments.
This method of access is used when the computer hosting the database server is restricted to the HTTP protocol. The only reason for using this method of access is restrictions imposed by firewalls on the client or server machines and it should not be used where there are no such restrictions. The HyperSQL HTTP Server is a special web server that allows JDBC clients to connect via HTTP. The server can also act as a small general-purpose web server for static pages.
To run an HTTP server, replace the main class for the server in the example command line above with the following:
org.hsqldb.server.WebServer
The command line argument --help can be used to
get a list of available arguments.
This method of access also uses the HTTP protocol. It is used when
a separate servlet engine (or application server) such as Tomcat or
Resin provides access to the database. The Servlet Mode cannot be
started independently from the servlet engine. The
Servlet class, in the HSQLDB jar, should be
installed on the application server to provide the connection. The
database is specified using an application server property. Refer to the
source file
src/org/hsqldb/server/Servlet.java to see the details.
Both HTTP Server and Servlet modes can only be accessed using the JDBC driver at the client end. They do not provide a web front end to the database. The Servlet mode can serve only a single database.
Please note that you do not normally use this mode if you are using the database engine in an application server. In this situation, connections to a catalog are usually made in-process, or using a separate Server
When a HyperSQL server is running, client programs can connect to
it using the HSQLDB JDBC Driver contained in
hsqldb.jar. Full information on how to connect to a
server is provided in the Java Documentation for JDBCConnection
(located in the /doc/apidocs directory of HSQLDB
distribution). A common example is connection to the default port (9001)
used for the hsql: protocol on the same
machine:
Example 1.1. Java code to connect to the local hsql Server
try {
Class.forName("org.hsqldb.jdbc.JDBCDriver" );
} catch (Exception e) {
System.err.println("ERROR: failed to load HSQLDB JDBC driver.");
e.printStackTrace();
return;
}
Connection c = DriverManager.getConnection("jdbc:hsqldb:hsql://localhost/xdb", "SA", "");
If the HyperSQL HTTP server is used, the protocol is http: and the URL will be different:
Example 1.2. Java code to connect to the local http Server
Connection c = DriverManager.getConnection("jdbc:hsqldb:http://localhost/xdb", "SA", "");
Note in the above connection URL, there is no mention of the database file, as this was specified when running the server. Instead, the public name defined for dbname.0 is used. Also, see the HyperSQL Network Listeners (Servers) chapter for the connection URL when there is more than one database per server instance.
When a HyperSQL server is run, network access should be adequately protected. Source IP addresses may be restricted by use of our Access Control List feature, network filtering software, firewall software, or standalone firewalls. Only secure passwords should be used-- most importantly, the password for the default system user should be changed from the default empty string. If you are purposefully providing data to the public, then the wide-open public network connection should be used exclusively to access the public data via read-only accounts. (i.e., neither secure data nor privileged accounts should use this connection). These considerations also apply to HyperSQL servers run with the HTTP protocol.
HyperSQL provides two optional security mechanisms. The encrypted SSL protocol, and Access Control Lists. Both mechanisms can be specified when running the Server or WebServer. On the client, the URL to connect to an SSL server is slightly different:
Example 1.3. Java code to connect to the local secure SSL hsql and http Servers
Connection c = DriverManager.getConnection("jdbc:hsqldb:hsqls://localhost/xdb", "SA", "");
Connection c = DriverManager.getConnection("jdbc:hsqldb:https://localhost/xdb", "SA", "");
The security features are discussed in detail in the HyperSQL Network Listeners
(Servers)
chapter.
A server can provide connections to more than one database. In the
examples above, more than one set of database names can be specified on
the command line. It is also possible to specify all the databases in a
.properties file, instead of the command line. These
capabilities are covered in the HyperSQL Network Listeners
(Servers) chapter
As shown so far, a java.sql.Connection object
is always used to access the database. But the speed and performance
depends on the type of connection.
Establishing a connection and closing it has some overheads, therefore it is not good practice to create a new connection to perform a small number of operations. A connection should be reused as much as possible and closed only when it is not going to be used again for a long while.
Reuse is more important for server connections. A server connection uses a TCP port for communications. Each time a connection is made, a port is allocated by the operating system and deallocated after the connection is closed. If many connections are made from a single client, the operating system may not be able to keep up and may refuse the connection attempt.
A java.sql.Connection object has some methods
that return further java.sql.* objects. All these
objects belong to the connection that returned them and are closed when
the connection is closed. These objects can be reused, but if they are not
needed after performing the operations, they should be closed.
A java.sql.DatabaseMetaData object is used to
get metadata for the database.
A java.sql.Statement object is used to
execute queries and data change statements. A
java.sql.Statement can be reused to execute a
different statement each time.
A java.sql.PreparedStatement object is used
to execute a single statement repeatedly. The SQL statement usually
contains parameters, which can be set to new values before each reuse.
When a java.sql.PreparedStatement object is
created, the engine keeps the compiled SQL statement for reuse, until the
java.sql.PreparedStatement object is closed. As a
result, repeated use of a
java.sql.PreparedStatement is much faster than
using a java.sql.Statement object.
A java.sql.CallableStatement object is used
to execute an SQL CALL statement. The SQL CALL statement may contain
parameters, which should be set to new values before each reuse. Similar
to java.sql.PreparedStatement, the engine keeps the
compiled SQL statement for reuse, until the
java.sql.CallableStatement object is closed.
A java.sql.Connection object also has some
methods for transaction control.
The commit() method performs a
COMMIT while the rollback()
method performs a ROLLBACK SQL statement.
The setSavepoint(String name) method
performs a SAVEPOINT <name> SQL statement and
returns a java.sql.Savepoint object. The
rollback(Savepoint name) method performs a
ROLLBACK TO SAVEPOINT <name> SQL
statement.
The Javadoc for
JDBCConnection,
JDBCDriver,
JDBCDatabaseMetadata JDBCResultSet,
JDBCStatement,
JDBCPreparedStatement list all the supported JDBC methods
together with information that is specific to HSQLDB.
All databases running in different modes can be closed with the SHUTDOWN command, issued as an SQL statement.
When SHUTDOWN is issued, all active transactions are rolled back. The catalog files are then saved in a form that can be opened quickly the next time the catalog is opened.
A special form of closing the database is via the SHUTDOWN COMPACT
command. This command rewrites the .data file that
contains the information stored in CACHED tables and compacts it to its
minimum size. This command should be issued periodically, especially when
lots of inserts, updates or deletes have been performed on the cached
tables. Changes to the structure of the database, such as dropping or
modifying populated CACHED tables or indexes also create large amounts of
unused file space that can be reclaimed using this command.
Databases are not closed when the last connection to the database is
explicitly closed via JDBC. A connection property,
shutdown=true, can be specified on the first connection
to the database (the connection that opens the database) to force a
shutdown when the last connection closes.
Example 1.4. specifying a connection property to shutdown the database when the last connection is closed
Connection c = DriverManager.getConnection(
"jdbc:hsqldb:file:/opt/db/testdb;shutdown=true", "SA", "");
This feature is useful for running tests, where it may not be
practical to shutdown the database after each test. But it is not
recommended for application programs.
When a server instance is started, or when a connection is made to an in-process database, a new, empty database is created if no database exists at the given path.
With HyperSQL 2.0 the username and password that are specified for the connection are used for the new database. Both the username and password are case-sensitive. (The exception is the default SA user, which is not case-sensitive). If no username or password is specified, the default SA user and an empty password are used.
This feature has a side effect that can confuse new users. If a
mistake is made in specifying the path for connecting to an existing
database, a connection is nevertheless established to a new database. For
troubleshooting purposes, you can specify a connection property
ifexists=true to allow connection
to an existing database only and avoid creating a new database. In this
case, if the database does not exist, the
getConnection() method will throw an
exception.
Example 1.5. specifying a connection property to disallow creating a new database
Connection c = DriverManager.getConnection(
"jdbc:hsqldb:file:/opt/db/testdb;ifexists=true", "SA", "");
A database has many optional properties, described in the Deployment Guide chapter. You can specify most of these properties on the URL or in the connection properties for the first connection that creates the database. See the Properties chapter.
$Revision: 4903 $
Copyright 2002-2012 Fred Toussi. Permission is granted to distribute this document without any alteration under the terms of the HSQLDB license. Additional permission is granted to the HSQL Development Group to distribute this document with or without alterations under the terms of the HSQLDB license.
2012-01-22 11:31:28-0500
Table of Contents
HyperSQL 2.0 supports the dialect of SQL defined by SQL standards 92, 1999, 2003 and 2008. This means where a feature of the standard is supported, e.g. left outer join, the syntax is that specified by the standard text. Almost all syntactic features of SQL-92 up to Advanced Level are supported, as well as SQL:2008 core and many optional features of this standard. Work is in progress for a formal declaration of conformance.
At the time of this release, HyperSQL supports the widest range of SQL standard features among all open source RDBMS.
Various chapters of this guide list the supported syntax. When writing or converting existing SQL DDL (Data Definition Language), DML (Data Manipulation Language) or DQL (Data Query Language) statements for HSQLDB, you should consult the supported syntax and modify the statements accordingly. Some statements written for older versions may have to be modified.
Over 300 words are reserved by the standard and should not be used
as table or column names. For example, the word POSITION is reserved as it
is a function defined by the Standards with a similar role as
String.indexOf() in Java. HyperSQL does not
currently prevent you from using a reserved word if it does not support
its use or can distinguish it. For example CUBE is a reserved words that
is not currently supported by HyperSQL and is allowed as a table or column
name. You should avoid using such names as future versions of HyperSQL are
likely to support the reserved words and may reject your table definitions
or queries. The full list of SQL reserved words is in the appendix Lists of Keywords .
If you have to use a reserved keyword as the name of a database object, you can enclose it in double quotes.
HyperSQL also supports enhancements with keywords and expressions
that are not part of the SQL standard. Expressions such as SELECT
TOP 5 FROM .., SELECT LIMIT 0 10 FROM ... or
DROP TABLE mytable IF EXISTS are among such
constructs.
Many print books cover SQL Standard syntax and can be consulted. For a well-written basic guide to SQL with examples, you can also consult PostgreSQL: Introduction and Concepts by Bruce Momjian, which is available on the web. Most of the core SQL coverage in the book applies also to HyperSQL. There are some differences in keywords supported by one and not the other engine (OUTER, OID's, etc.) or used differently (IDENTITY/SERIAL, TRIGGER, SEQUENCE, etc.).
In HyperSQL version 2.0, all features of JDBC4 that apply to the
capabilities of HSQLDB are fully supported. The relevant JDBC classes are
thoroughly documented with additional clarifications and HyperSQL specific
comments. See the JavaDoc for the
org.hsqldb.jdbc.* classes.
In an SQL system, all significant data is stored in tables and sequence generators. Therefore, the first step in creating a database is defining the tables and their columns. The SQL standard supports temporary tables, which are for temporary data, and permanent base tables, which are for persistent data.
Data in TEMPORARY tables is not saved and lasts only for the lifetime of the session. The contents of each TEMP table is visible only from the session that is used to populate it.
HyperSQL supports two types of temporary tables.
The GLOBAL TEMPORARY type is a schema object.
It is created with the CREATE GLOBAL TEMPORARY TABLE
statement. The definition of the table persists, and each session has
access to the table. But each session sees its own copy of the table,
which is empty at the beginning of the session.
The LOCAL TEMPORARY type is not a schema
object. It is created with the DECLARE LOCAL TEMPORARY
TABLE statement. The table definition lasts only for the
duration of the session and is not persisted in the database. The table
can be declared in the middle of a transaction without committing the
transaction.
When the session commits, the contents of all temporary tables are cleared by default. If the table definition statements includes ON COMMIT PRESERVE ROWS, then the contents are kept when a commit takes place.
The rows in temporary tables are stored in memory by default. If
the hsqldb.result_max_memory_rows ( SET SESSION
RESULT MEMORY ROWS <row count> ) has been specified, tables with
row count above the setting are stored on disk.
HyperSQL supports the Standard definition of persistent base table, but defines three types according to the way the data is stored. These are MEMORY tables, CACHED tables and TEXT tables.
Memory tables are the default type when the CREATE TABLE command
is used. Their data is held entirely in memory but any change to their
structure or contents is written to the *.log and
*.script files. The *.script
file and the *.log file are read the next time the
database is opened, and the MEMORY tables are recreated with all their
contents. So unlike TEMPORARY tables, MEMORY tables are persistent. When
the database is opened, all the data for the memory tables is read and
inserted. This process may take a long time if the database is larger
than tens of megabytes. When the database is shutdown, all the data is
saved. This can also take a long time.
CACHED tables are created with the CREATE CACHED TABLE command. Only part of their data or indexes is held in memory, allowing large tables that would otherwise take up to several hundred megabytes of memory. Another advantage of cached tables is that the database engine takes less time to start up when a cached table is used for large amounts of data. The disadvantage of cached tables is a reduction in speed. Do not use cached tables if your data set is relatively small. In an application with some small tables and some large ones, it is better to use the default, MEMORY mode for the small tables.
TEXT tables use a CSV (Comma Separated Value) or other delimited text file as the source of their data. You can specify an existing CSV file, such as a dump from another database or program, as the source of a TEXT table. Alternatively, you can specify an empty file to be filled with data by the database engine. TEXT tables are efficient in memory usage as they cache only part of the text data and all of the indexes. The Text table data source can always be reassigned to a different file if necessary. The commands are needed to set up a TEXT table as detailed in the Text Tables chapter.
With all-in-memory databases, both MEMORY table and CACHED table declarations are treated as declarations for non-persistent memory tables. In the latest versions of HyperSQL, TEXT table declarations are allowed in all-in-memory databases.
The default type of tables resulting from future CREATE TABLE statements can be specified with the SQL command:
SET DATABASE DEFAULT TABLE TYPE { CACHED | MEMORY };
The type of an existing table can be changed with the SQL command:
SET TABLE <table name> TYPE { CACHED | MEMORY };
SQL statements access different types of tables uniformly. No change to statements is needed to access different types of table.
Lobs are logically stored in columns of tables. Their physical storage is a separate *.lobs file. This file is created as soon as a BLOB or CLOB is inserted into the database. The file will grow as new lobs are inserted into the database. In version 2.x, the *.lobs file is never deleted even if all lobs are deleted from the database (In this case you can delete the .lobs file after a SHTUDOWN).
Most other RDBMS do not conform to the SQL Standard in all areas, but they are gradually moving towards Standard conformance. When switching from another SQL dialect, the following should be considered:
Numeric types TINYINT, SMALLINT, INTEGER and BIGINT are types with fixed binary precision. These types are more efficient to store and retrieve. NUMERIC and DECIMAL are types with user-defined decimal precision. They can be used with zero scale to store very large integers, or with a non-zero scale to store decimal fractions. The DOUBLE type is a 64 bit, approximate floating point types. HyperSQL even allows you to store infinity in this type.
The BOOLEAN type is for logical values and can hold TRUE, FALSE or UNKNOWN. Although HyperSQL allows you to use one and zero in assignment or comparison, you should use the standard values for this type.
Character string types are CHAR(L), VARCHAR(L) and CLOB. CHAR is
for fixed width strings and any string that is assigned to this type
is padded with spaces at the end. Do not use this type for general
storage of strings. If you use CHAR without the length L, then it is
interpreted as a single character string. Use VARCHAR(L) for general
strings. There are only memory limits and performance implications for
the maximum length of VARCHAR(L). If the strings are larger than a few
kilobytes, consider using CLOB. The CLOB types is for very large
strings. Do not use this type for short strings as there are
performance implications. The CLOB type is a better choice for the
storage of long strings. By default LONGVARCHAR is a synonym for a
long VARCHAR and can be used without specifying the size. You can set
LONGVARCHAR to map to CLOB, with the
sql.longvar_is_lob connection property or the SET
DATABASE SQL LONGVAR IS LOB TRUE statement.
Binary string types are BINARY(L), VARBINARY(L) and BLOB. Do not
use BINARY(L) unless you are storing keys such as UUID. This type pads
short binary strings with zero bytes. BINARY without the length L
means a single byte. Use VARBINARY(L) for general binary strings, and
BLOB for large binary objects. You should apply the same
considerations as with the character string types. By default
LONGVARBINARY is a synonym for a long VARCHAR and can be used without
specifying the size. You can set LONGVARBINARY to map to BLOB, with
the sql.longvar_is_lob connection property or the
SET DATABASE SQL LONGVAR IS LOB TRUE statement.
The BIT(L) and BITVARYING(L) types are for bit maps. Do not use them for other types of data. BIT without the length L argument means a single bit and is sometimes used as a logical type. Use BOOLEAN instead of this type.
The datetime types DATE, TIME and TIMESTAMP, together with their WITH TIME ZONE variations are available. Read the details in this chapter on how to use these types.
The INTERVAL type is very powerful when used together with the
datetime types. This is very easy to use, but is supported mainly by
"big iron" database systems. Note that functions that add days or
months to datetime values are not really a substitute for the INTERVAL
type. Expressions such as (datecol - 7 DAY) >
CURRENT_DATE are optimised to use indexes when it is
possible, while the equivalent function calls are not
optimised.
The OTHER type is for storage of Java objects. If your objects are large, serialize them in your application and store them as BLOB in the database.
The ARRAY type supports all base types except LOB and OTHER types. ARRAY data objects are held in memory while being processed. It is therefore not recommended to store more than about a thousand objects in an ARRAY in normal operations with disk based databases. For specialised applications, use ARRAY with as many elements as your memory allocation can support.
HyperSQL 2.2.x has several compatibility modes which allow the type names that are used by other RDBMS to be accepted and translated into the closest SQL Standard type. For example the type TEXT, supported by MySQL and PostgreSQL is translated in these compatibility modes.
HyperSQL supports all the types defined by SQL-92, plus BOOLEAN, BINARY and LOB types that were added later to the SQL Standard. It also supports the non-standard OTHER type to store serializable Java objects.
SQL is a strongly typed language. All data stored in specific columns of tables and other objects (such as sequence generators) have specific types. Each data item conforms to the type limits such as precision and scale for the column. It also conforms to any additional integrity constraints that are defined as CHECK constraints in domains or tables. Types can be explicitly converted using the CAST expression, but in most expressions they are converted automatically.
Data is returned to the user (or the application program) as a result of executing SQL statements such as query expressions or function calls. All statements are compiled prior to execution and the return type of the data is known after compilation and before execution. Therefore, once a statement is prepared, the data type of each column of the returned result is known, including any precision or scale property. The type does not change when the same query that returned one row, returns many rows as a result of adding more data to the tables.
Some SQL functions used within SQL statements are polymorphic, but the exact type of the argument and the return value is determined at compile time.
When a statement is prepared, using a JDBC PreparedStatement object, it is compiled by the engine and the type of the columns of its ResultSet and / or its parameters are accessible through the methods of PreparedStatement.
TINYINT, SMALLINT, INTEGER, BIGINT, NUMERIC and DECIMAL (without a
decimal point) are the supported integral types. They correspond
respectively to byte,
short, int,
long, BigDecimal and
BigDecimal Java types in the range of values that
they can represent (NUMERIC and DECIMAL are equivalent). The type
TINYINT is an HSQLDB extension to the SQL Standard, while the others
conform to the Standard definition. The SQL type dictates the maximum
and minimum values that can be held in a field of each type. For example
the value range for TINYINT is -128 to +127. The bit precision of
TINYINT, SMALLINT, INTEGER and BIGINT is respectively 8, 16, 32 and 64.
For NUMERIC and DECIMAL, decimal precision is used.
DECIMAL and NUMERIC with decimal fractions are mapped to
java.math.BigDecimal and can have very large
numbers of digits. In HyperSQL the two types are equivalent. These
types, together with integral types, are called exact numeric
types.
In HyperSQL, REAL, FLOAT, DOUBLE are equivalent and all mapped to
double in Java. These types are defined by the
SQL Standard as approximate numeric types. The bit-precision of all
these types is 64 bits.
The decimal precision and scale of NUMERIC and DECIMAL types can be optionally defined. For example, DECIMAL(10,2) means maximum total number of digits is 10 and there are always 2 digits after the decimal point, while DECIMAL(10) means 10 digits without a decimal point. The bit-precision of FLOAT can also be defined, but in this case, it is ignored and the default bit-precision of 64 is used. The default precision of NUMERIC and DECIMAL (when not defined) is 100.
Note: If a database has been set to ignore type precision limits with the SET DATABASE SQL SIZE FALSE command, then a type definition of DECIMAL with no precision and scale is treated as DECIMAL(100,10). In normal operation, it is treated as DECIMAL(100).
Integral Types
In expressions, TINYINT, SMALLINT, INTEGER, BIGINT, NUMERIC and DECIMAL (without a decimal point) are fully interchangeable, and no data narrowing takes place.
If the SELECT statement refers to a simple column or function, then the return type is the type corresponding to the column or the return type of the function. For example:
CREATE TABLE t(a INTEGER, b BIGINT);
SELECT MAX(a), MAX(b) FROM t;
will return a ResultSet where the type of
the first column is java.lang.Integer and the
second column is java.lang.Long. However,
SELECT MAX(a) + 1, MAX(b) + 1 FROM t;
will return java.lang.Long and
BigDecimal values, generated as a result of
uniform type promotion for all the return values. Note that type
promotion to BigDecimal ensures the correct value
is returned if MAX(b) evaluates to
Long.MAX_VALUE.
There is no built-in limit on the size of intermediate integral
values in expressions. As a result, you should check for the type of the
ResultSet column and choose an appropriate
getXXXX() method to retrieve it. Alternatively,
you can use the getObject() method, then cast
the result to java.lang.Number and use the
intValue() or
longValue() methods on the result.
When the result of an expression is stored in a column of a
database table, it has to fit in the target column, otherwise an error
is returned. For example when 1234567890123456789012 /
12345687901234567890 is evaluated, the result can be stored in
any integral type column, even a TINYINT column, as it is a small
value.
In SQL Statements, an integer literal is treated as INTEGER, unless its value does not fit. In this case it is treated as BIGINT or DECIMAL, depending on the value.
Depending on the types of the operands, the result of the
operations is returned in a JDBC ResultSet in any
of related Java types: Integer,
Long or BigDecimal. The
ResultSet.getXXXX() methods can be used to
retrieve the values so long as the returned value can be represented by
the resulting type. This type is deterministically based on the query,
not on the actual rows returned.
Other Numeric Types
In SQL statements, number literals with a decimal point are
treated as DECIMAL unless they are written with an exponent. Thus
0.2 is considered a DECIMAL value but
0.2E0 is considered a DOUBLE value.
When an approximate numeric type, REAL, FLOAT or DOUBLE (all
synonymous) is part of an expression involving different numeric types,
the type of the result is DOUBLE. DECIMAL values can be converted to
DOUBLE unless they are beyond the Double.MIN_VALUE -
Double.MAX_VALUE range. For example, A * B, A / B, A + B, etc.
will return a DOUBLE value if either A or B is a DOUBLE.
Otherwise, when no DOUBLE value exists, if a DECIMAL or NUMERIC value is part an expression, the type of the result is DECIMAL or NUMERIC. Similar to integral values, when the result of an expression is assigned to a table column, the value has to fit in the target column, otherwise an error is returned. This means a small, 4 digit value of DECIMAL type can be assigned to a column of SMALLINT or INTEGER, but a value with 15 digits cannot.
When a DECIMAL values is multiplied by a DECIMAL or integral type, the resulting scale is the sum of the scales of the two terms. When they are divided, the result is a value with a scale (number of digits to the right of the decimal point) equal to the larger of the scales of the two terms. The precision for both operations is calculated (usually increased) to allow all possible results.
The distinction between DOUBLE and DECIMAL is important when a
division takes place. For example, 10.0/8.0 (DECIMAL)
equals 1.2 but 10.0E0/8.0E0
(DOUBLE) equals 1.25. Without division operations,
DECIMAL values represent exact arithmetic.
REAL, FLOAT and DOUBLE values are all stored in the database as
java.lang.Double objects. Special values such as
NaN and +-Infinity are also stored and supported. These values can be
submitted to the database via JDBC
PreparedStatement methods and are returned in
ResultSet objects. In order to allow division by
zero of DOUBLE values in SQL statements (which returns NaN or
+-Infinity) you should set the property hsqldb.double_nan as false (SET
DATABASE SQL DOUBLE NAN FALSE). The double values can be retrieved from
a ResultSet in the required type so long as they
can be represented. For setting the values, when
PreparedStatement.setDouble() or
setFloat() is used, the value is treated as a
DOUBLE automatically.
In short,
<numeric type> ::= <exact numeric type> |
<approximate numeric type>
<exact numeric type> ::= NUMERIC [ <left
paren> <precision> [ <comma> <scale> ] <right
paren> ] | { DECIMAL | DEC } [ <left paren> <precision> [
<comma> <scale> ] <right paren> ] | SMALLINT | INTEGER
| INT | BIGINT
<approximate numeric type> ::= FLOAT [ <left
paren> <precision> <right paren> ] | REAL | DOUBLE
PRECISION
<precision> ::= <unsigned
integer>
<scale> ::= <unsigned
integer>
The BOOLEAN type conforms to the SQL Standard and represents the
values TRUE, FALSE and
UNKNOWN. This type of column can be initialised with
Java boolean values, or with NULL for the
UNKNOWN value.
The three-value logic is sometimes misunderstood. For example, x IN (1, 2, NULL) does not return true if x is NULL.
In previous versions of HyperSQL, BIT was simply an alias for BOOLEAN. In version 2.0, BIT is a single-bit bit map.
<boolean type> ::= BOOLEAN
The SQL Standard does not support type conversion to BOOLEAN apart from character strings that consists of boolean literals. Because the BOOLEAN type is relatively new to the Standard, several database products used other types to represent boolean values. For improved compatibility, HyperSQL allows some type conversions to boolean.
Values of BIT and BIT VARYING types with length 1 can be converted to BOOLEAN. If the bit is set, the result of conversion is the TRUE value, otherwise it is FALSE.
Values of TINYINT, SMALLINT, INTEGER and BIGINT types can be converted to BOOLEAN. If the value is zero, the result is the FALSE value, otherwise it is TRUE.
The CHARACTER, CHARACTER VARYING and CLOB types are the SQL
Standard character string types. CHAR, VARCHAR and CHARACTER LARGE
OBJECT are synonyms for these types. HyperSQL also supports LONGVARCHAR
as a synonym for VARCHAR. If LONGVARCHAR is used without a length, then
a length of 16M is assigned. You can set LONGVARCHAR to map to CLOB,
with the sql.longvar_is_lob connection property or
the SET DATABASE SQL LONGVAR IS LOB TRUE statement..
HyperSQL's default character set is Unicode, therefore all possible character strings can be represented by these types.
The SQL Standard behaviour of the CHARACTER type is a remnant of legacy systems in which character strings are padded with spaces to fill a fixed width. These spaces are sometimes significant while in other cases they are silently discarded. It would be best to avoid the CHARACTER type altogether. With the rest of the types, the strings are not padded when assigned to columns or variables of the given type. The trailing spaces are still considered discardable for all character types. Therefore if a string with trailing spaces is too long to assign to a column or variable of a given length, the spaces beyond the type length are discarded and the assignment succeeds (provided all the characters beyond the type length are spaces).
The VARCHAR and CLOB types have length limits, but the strings are not padded by the system. Note that if you use a large length for a VARCHAR or CLOB type, no extra space is used in the database. The space used for each stored item is proportional to its actual length.
If CHARACTER is used without specifying the length, the length
defaults to 1. For the CLOB type, the length limit can be defined in
units of kilobyte (K, 1024), megabyte (M, 1024 * 1024) or gigabyte (G,
1024 * 1024 * 1024), using the <multiplier>. If
CLOB is used without specifying the length, the length defaults to
16M.
<character string type> ::= { CHARACTER | CHAR }
[ <left paren> <character length> <right paren> ] | {
CHARACTER VARYING | CHAR VARYING | VARCHAR } <left paren>
<character length> <right paren> | LONGVARCHAR [ <left
paren> <character length> <right paren> ] | <character
large object type>
<character large object type> ::= { CHARACTER
LARGE OBJECT | CHAR LARGE OBJECT | CLOB } [ <left paren>
<character large object length> <right paren>
]
<character length> ::= <unsigned integer>
[ <char length units> ]
<large object length> ::= <length> [
<multiplier> ] | <large object length
token>
<character large object length> ::= <large
object length> [ <char length units> ]
<large object length token> ::= <digit>...
<multiplier>
<multiplier> ::= K | M | G
<char length units> ::= CHARACTERS |
OCTETS
CHAR(10) CHARACTER(10) VARCHAR(2) CHAR VARYING(2) CLOB(1000) CLOB(30K) CHARACTER LARGE OBJECT(1M) LONGVARCHAR
The BINARY, BINARY VARYING and BLOB types are the SQL Standard
binary string types. VARBINARY and BINARY LARGE OBJECT are synonyms for
BINARY VARYING and BLOB types. HyperSQL also supports LONGVARBINARY as a
synonym for VARBINARY. You can set LONGVARBINARY to map to BLOB, with
the sql.longvar_is_lob connection property or the SET
DATABASE SQL LONGVAR IS LOB TRUE statement.
Binary string types are used in a similar way to character string types. There are several built-in functions that are overloaded to support character, binary and bit strings.
The BINARY type represents a fixed width-string. Each shorter string is padded with zeros to fill the fixed width. Similar to the CHARACTER type, the trailing zeros in the BINARY string are simply discarded in some operations. For the same reason, it is best to avoid this particular type and use VARBINARY instead.
When two binary values are compared, if one is of BINARY type, then zero padding is performed to extend the length of the shorter string to the longer one before comparison. No padding is performed with other binary types. If the bytes compare equal to the end of the shorter value, then the longer string is considered larger than the shorter string.
If BINARY is used without specifying the length, the length
defaults to 1. For the BLOB type, the length limit can be defined in
units of kilobyte (K, 1024), megabyte (M, 1024 * 1024) or gigabyte (G,
1024 * 1024 * 1024), using the <multiplier>. If
BLOB is used without specifying the length, the length defaults to
16M.
<binary string type> ::= BINARY [ <left
paren> <length> <right paren> ] | { BINARY VARYING |
VARBINARY } <left paren> <length> <right paren> |
LONGVARBINARY [ <left paren> <length> <right paren> ]
| <binary large object string type>
<binary large object string type> ::= { BINARY
LARGE OBJECT | BLOB } [ <left paren> <large object length>
<right paren> ]
<length> ::= <unsigned
integer>
BINARY(10) VARBINARY(2) BINARY VARYING(2) BLOB(1000) BLOB(30K) BINARY LARGE OBJECT(1M) LONGVARBINARY
The BIT and BIT VARYING types are the supported bit string types. These types were defined by SQL:1999 but were later removed from the Standard. Bit types represent bit maps of given lengths. Each bit is 0 or 1. The BIT type represents a fixed width-string. Each shorter string is padded with zeros to fill the fixed with. If BIT is used without specifying the length, the length defaults to 1. The BIT VARYING type has a maximum width and shorter strings are not padded.
Before the introduction of the BOOLEAN type to the SQL Standard, a sigle-bit string of the type BIT(1) was commonly used. For compatibility with other products that do not conform to, or extend, the SQL Standard, HyperSQL allows values of BIT and BIT VARYING types with length 1 to be converted to and from the BOOLEAN type. BOOLEAN TRUE is considered equal to B'1', BOOLEAN FALSE is considered equal to B'0'.
For the same reason, numeric values can be assigned to columns and variables of the type BIT(1). For assignment, the numeric value zero is converted to B'0', while all other values are converted to B'1'. For comparison, numeric values 1 is considered equal to B'1' and numeric value zero is considered equal to B'0'.
It is not allowed to perform other arithmetic or boolean operations involving BIT(1) and BIT VARYING(1). The kid of operations allowed on bit strings are analogous to those allowed on BINARY and CHARACTER strings. Several built-in functions support all three types of string.
<bit string type> ::= BIT [ <left paren>
<length> <right paren> ] | BIT VARYING <left paren>
<length> <right paren>
BIT BIT(10) BIT VARYING(2)
Any serializable JAVA Object can be inserted directly into a
column of type OTHER using any variation of
PreparedStatement.setObject() methods.
For comparison purposes and in indexes, any two Java Objects are considered equal unless one of them is NULL. You cannot search for a specific object or perform a join on a column of type OTHER.
Please note that HSQLDB is not an object-relational database. Java
Objects can simply be stored internally and no operations should be
performed on them other than assignment between columns of type OTHER or
tests for NULL. Tests such as WHERE object1 = object2
do not mean what you might expect, as any non-null object
would satisfy such a tests. But WHERE object1 IS NOT
NULL is perfectly acceptable.
The engine does not allow normal column values to be assigned to
Java Object columns (for example, assigning an INTEGER or STRING to such
a column with an SQL statement such as UPDATE mytable SET
objectcol = intcol WHERE ...).
<java object type> ::= OTHER
In older version of HyperSQL, all table column type definitions with a column length, precision or scale qualifier were accepted and ignored. HSQLDB 1.8 enforced correctness but included an option to enforce the length, precision or scale.
In HyperSQL 2.0, length, precision and scale qualifiers are always enforced. For backward compatibility, when older databases which had the property hsqldb.enforce_strict_size=false are converted to version 2.0, this property is retained. However, this is a temporary measure. You should test your application to ensure the length, precision and scale that is used for column definitions is appropriate for the application data. You can test with the default database setting, which enforces the sizes.
String types, including all BIT, BINARY and CHAR string types plus CLOB and BLOB, are generally defined with a length. If no length is specified for BIT, BINARY and CHAR, the default length is 1. For CLOB and BLOB an implementation defined length of 1M is used.
TIME and TIMESTAMP types can be defined with a fractional second precision between 0 and 9. INTERVAL type definition may have precision and, in some cases, fraction second precision. DECIMAL and NUMERIC types may be defined with precision and scale. For all of these types a default precision or scale value is used if one is not specified. The default scale is 0. The default fractional precision for TIME is 0, while it is 6 for TIMESTAMP.
Values can be converted from one type to another in two different ways: by using explicit CAST expression or by implicit conversion used in assignment, comparison and aggregation.
String values cannot be assigned to VARCHAR columns if they are longer than the defined type length. For CHARACTER columns, a long string can be assigned (with truncation) only if all the characters after the length are spaces. Shorter strings are padded with the space character when inserted into a CHARACTER column. Similar rules are applied to VARBINARY and BINARY columns. For BINARY columns, the padding and truncation rules are applied with zero bytes, instead of spaces.
Explicit CAST of a value to a CHARACTER or VARCHAR type will
result in forced truncation or padding. So a test such as CAST
(mycol AS VARCHAR(2)) = 'xy' will find the values beginning
with 'xy'. This is the equivalent of SUBSTRING(mycol FROM 1 FOR
2)= 'xy'.
For all numeric types, the rules of explicit cast and implicit conversion are the same. If cast or conversion causes any digits to be lost from the fractional part, it can take place. If the non-fractional part of the value cannot be represented in the new type, cast or conversion cannot take place and will result in a data exception.
There are special rules for DATE, TIME, TIMESTAMP and INTERVAL casts and conversions.
HSQLDB fully supports datetime and interval types and operations, including all relevant optional features, as specified by the SQL Standard since SQL-92. The two groups of types are complementary.
The DATE type represents a calendar date with YEAR, MONTH and DAY fields.
The TIME type represents time of day with HOUR, MINUTE and SECOND fields, plus an optional SECOND FRACTION field.
The TIMESTAMP type represents the combination of DATE and TIME types.
TIME and TIMESTAMP types can include WITH TIME ZONE or WITHOUT TIME ZONE (the default) qualifiers. They can have fractional second parts. For example, TIME(6) has six fractional digits for the second field.
If fractional second precision is not specified, it defaults to 0 for TIME and to 6 for TIMESTAMP.
<datetime type> ::= DATE | TIME [ <left
paren> <time precision> <right paren> ] [ <with or
without time zone> ] | TIMESTAMP [ <left paren> <timestamp
precision> <right paren> ] [ <with or without time zone>
]
<with or without time zone> ::= WITH TIME ZONE |
WITHOUT TIME ZONE
<time precision> ::= <time fractional seconds
precision>
<timestamp precision> ::= <time fractional
seconds precision>
<time fractional seconds precision> ::=
<unsigned integer>
DATE TIME(6) TIMESTAMP(2) WITH TIME ZONE
Examples of the string literals used to represent date time values, some with time zone, some without, are below:
DATE '2008-08-22' TIMESTAMP '2008-08-08 20:08:08' TIMESTAMP '2008-08-08 20:08:08+8:00' /* Beijing */ TIME '20:08:08.034900' TIME '20:08:08.034900-8:00' /* US Pacific */
Time Zone
DATE values do not take time zones. For example United Nations designates 5 June as World Environment Day, which was observed on DATE '2008-06-05' in different time zones.
TIME and TIMESTAMP values without time zone, usually have a context that indicates some local time zone. For example, a database for college course timetables usually stores class dates and times without time zones. This works because the location of the college is fixed and the time zone displacement is the same for all the values. Even when the events take place in different time zones, for example international flight times, it is possible to store all the datetime information as references to a single time zone, usually GMT. For some databases it may be useful to store the time zone displacement together with each datetime value. SQL’s TIME WITH TIME ZONE and TIMESTAMP WITH TIME ZONE values include a time zone displacement value.
The time zone displacement is of the type INTERVAL HOUR TO MINUTE. This data type is described in the next section. The legal values are between '–14:00' and '+14:00'.
Operations on Datetime Types
The expression <datetime expression> AT TIME ZONE
<time displacement> evaluates to a datetime value
representing exactly the same point of time in the specified
<time displacement>. The expression, AT
LOCAL is equivalent to AT TIME ZONE <local time
displacement>. If AT TIME ZONE is used
with a datetime operand of type WITHOUT TIME ZONE, the operand is first
converted to a value of type WITH TIME ZONE at the session’s time
displacement, then the specified time zone displacement is set for the
value. Therefore, in these cases, the final value depends on the time zone
of the session in which the statement was used.
AT TIME ZONE, modifies the field values of the datetime operand. This is done by the following procedure:
determine the corresponding datetime at UTC.
find the datetime value at the given time zone that corresponds with the UTC value from step 1.
Example a:
TIME '12:00:00' AT TIME ZONE INTERVAL '1:00' HOUR TO MINUTE
If the session’s time zone displacement is -'8:00', then in step 1, TIME '12:00:00' is converted to UTC, which is TIME '20:00:00+0:00'. In step 2, this value is expressed as TIME '21:00:00+1:00'.
Example b:
TIME '12:00:00-5:00' AT TIME ZONE INTERVAL '1:00' HOUR TO MINUTE
Because the operand has a time zone, the result is independent of the session time zone displacement. Step 1 results in TIME '17:00:00+0:00', and step 2 results in TIME '18:00:00+1:00'
Note that the operand is not limited to datetime literals used in these examples. Any valid expression that evaluates to a datetime value can be the operand.
Type Conversion
CAST is used to for all other conversions. Examples:
CAST (<value> AS TIME WITHOUT TIME ZONE) CAST (<value> AS TIME WITH TIME ZONE)
In the first example, if <value> has a time
zone component, it is simply dropped. For example TIME '12:00:00-5:00' is
converted to TIME '12:00:00'
In the second example, if <value> has no
time zone component, the current time zone displacement of the session is
added. For example TIME '12:00:00' is converted to TIME '12:00:00-8:00'
when the session time zone displacement is '-8:00'.
Conversion between DATE and TIMESTAMP is performed by removing the TIME component of a TIMESTAMP value or by setting the hour, minute and second fields to zero. TIMESTAMP '2008-08-08 20:08:08+8:00' becomes DATE '2008-08-08', while DATE '2008-08-22' becomes TIMESTAMP '2008-08-22 00:00:00'.
Conversion between TIME and TIMESTAMP is performed by removing the DATE field values of a TIMESTAMP value or by appending the fields of the TIME value to the fields of the current session date value.
Assignment
When a value is assigned to a datetime target, e.g., a value is used to update a row of a table, the type of the value must be the same as the target, but the WITH TIME ZONE or WITHOUT TIME ZONE characteristics can be different. If the types are not the same, an explicit CAST must be used to convert the value into the target type.
Comparison
When values WITH TIME ZONE are compared, they are converted to UTC values before comparison. If a value WITH TIME ZONE is compared to another WITHOUT TIME ZONE, then the WITH TIME ZONE value is converted to AT LOCAL, then converted to WITHOUT TIME ZONE before comparison.
It is not recommended to design applications that rely on comparisons and conversions between TIME values WITH TIME ZONE. The conversions may involve normalisation of the time value, resulting in unexpected results. For example, the expression: BETWEEN(TIME '12:00:00-8:00', TIME '22:00:00-8:00') is converted to BETWEEN(TIME '20:00:00+0:00', TIME '06:00:00+0:00') when it is evaluated in the UTC zone, which is always FALSE.
Functions
Several functions return the current session timestamp in different datetime types:
|
CURRENT_DATE |
DATE |
|
CURRENT_TIME |
TIME WITH TIME ZONE |
|
CURRENT_TIMESTAMP |
TIMESTAMP WITH TIME ZONE |
|
LOCALTIME |
TIMESTAMP WITHOUT TIME ZONE |
|
LOCALTIMESTAMP |
TIMESTAMP WITHOUT TIME ZONE |
Session Time Zone Displacement
When an SQL session is started (with a JDBC connection) the local time zone of the client JVM (including any seasonal time adjustments such as daylight saving time) is used as the session time zone displacement. Note that the SQL session time displacement is not changed when a seasonal time adjustment takes place while the session is open. To change the SQL session time zone displacement use the following commands:
SET TIME ZONE <time
displacement>
SET TIME ZONE LOCAL
The first command sets the displacement to the given value. The second command restores the original, real time zone displacement of the session.
Datetime Values and Java
When datetime values are sent to the database using the
PreparedStatement or
CallableStatement interfaces, the Java object is
converted to the type of the prepared or callable statement parameter.
This type may be DATE, TIME, or TIMESTAMP (with or without time zone). The
time zone displacement is the time zone of the JDBC session.
When datetime values are retrieved from the database using the
ResultSet interface, there are two representations. The
getString(…) methods of the
ResultSet interface, return an exact representation
of the value in the SQL type as it is stored in the database. This
includes the correct number of digits for the fractional second field, and
for values with time zone displacement, the time zone displacement.
Therefore if TIME '12:00:00' is stored in the database, all users in
different time zones will get '12:00:00' when they retrieve the value as a
string. The getTime(…) and
getTimestamp(…) methods of the
ResultSet interface return Java objects that are
corrected for the session time zone. The UTC millisecond value contained
the java.sql.Time or
java.sql.Timestamp objects will be adjusted to the
time zone of the session, therefore the
toString() method of these objects return the
same values in different time zones.
If you want to store and retrieve UTC values that are independent of any session's time zone, you can use a TIMESTAMP WITH TIME ZONE column. The setTime(...) and setTimestamp(...) methods of the PreparedStatement interface which have a Calendar parameter can be used to assign the values. The time zone of the given Calendar argument is used as the time zone. Conversely, the getTime(...) and getTimestamp(...) methods of the ResultSet interface which have a Calendar parameter can be used with a Calendar argument to retrieve the values.
JDBC has an unfortunate limitation and does not include type codes
for SQL datetime types that have a TIME ZONE property. Therefore, for
compatibility with database tools that are limited to the JDBC type codes,
HyperSQL reports these types by default as datetime types without TIME
ZONE. You can use the URL property
hsqldb.translate_dti_types=false to override the
default behaviour.
Interval types are used to represent differences between date time values. The difference between two date time values can be measured in seconds or in months. For measurements in months, the units YEAR and MONTH are available, while for measurements in seconds, the units DAY, HOUR, MINUTE, SECOND are available. The units can be used individually, or as a range. An interval type can specify the precision of the most significant field and the second fraction digits of the SECOND field (if it has a SECOND field). The default precision is 2. The default second precision is 0.
<interval type> ::= INTERVAL <interval
qualifier>
<interval qualifier> ::= <start field> TO
<end field> | <single datetime field>
<start field> ::= <non-second primary datetime
field> [ <left paren> <interval leading field precision>
<right paren> ]
<end field> ::= <non-second primary datetime
field> | SECOND [ <left paren> <interval fractional seconds
precision> <right paren> ]
<single datetime field> ::= <non-second primary
datetime field> [ <left paren> <interval leading field
precision> <right paren> ] | SECOND [ <left paren>
<interval leading field precision> [ <comma> <interval
fractional seconds precision> ] <right paren>
]
<primary datetime field> ::= <non-second
primary datetime field> | SECOND
<non-second primary datetime field> ::= YEAR |
MONTH | DAY | HOUR | MINUTE
<interval fractional seconds precision> ::=
<unsigned integer>
<interval leading field precision> ::=
<unsigned integer>
Examples of INTERVAL type definition:
INTERVAL YEAR TO MONTH INTERVAL YEAR(3) INTERVAL DAY(4) TO HOUR INTERVAL MINUTE(4) TO SECOND(6) INTERVAL SECOND(4,6)
The word INTERVAL indicates the general type name. The rest of the
definition is called an <interval qualifier>.
This designation is important, as in most expressions
<interval qualifier> is used without the word
INTERVAL.
Interval Values
An interval value can be negative, positive or zero. An interval type has all the datetime fields in the specified range. These fields are similar to those in the TIMESTAMP type. The differences are as follows:
The first field of an interval value can hold any numeric value up to the specified precision. For example, the hour field in HOUR(2) TO SECOND can hold values above 23 (up to 99). The year and month fields can hold zero (unlike a TIMESTAMP value) and the maximum value of a month field that is not the most significant field, is 11.
The standard function ABS(<interval value
expression>) can be used to convert a negative interval value
to a positive one.
The literal representation of interval values consists of the type definition, with a string representing the interval value inserted after the word INTERVAL. Some examples of interval literal below:
INTERVAL '145 23:12:19.345' DAY(3) TO SECOND(3) INTERVAL '3503:12:19.345' HOUR TO SECOND(3) /* equal to the first value */ INTERVAL '19.345' SECOND(4,3) /* maximum number of digits for the second value is 4, and each value is expressed with three fraction digits. */ INTERVAL '-23-10' YEAR(2) TO MONTH
Interval values of the types that are based on seconds can be cast into one another. Similarly those that are based on months can be cast into one another. It is not possible to cast or convert a value based on seconds to one based on months, or vice versa.
When a cast is performed to a type with a smaller least-significant field, nothing is lost from the interval value. Otherwise, the values for the missing least-significant fields are discarded. Examples:
CAST ( INTERVAL '145 23:12:19' DAY TO SECOND AS INTERVAL DAY TO HOUR ) = INTERVAL '145 23' DAY TO HOUR CAST(INTERVAL '145 23' DAY TO HOUR AS INTERVAL DAY TO SECOND) = INTERVAL '145 23:00:00' DAY TO SECOND
A numeric value can be cast to an interval type. In this case the numeric value is first converted to a single-field INTERVAL type with the same field as the least significant field of the target interval type. This value is then converted to the target interval type For example CAST( 22 AS INTERVAL YEAR TO MONTH) evaluates to INTERVAL '22' MONTH and then INTERVAL '1 10' YEAR TO MONTH. Note that SQL Standard only supports casts to single-field INTERVAL types, while HyperSQL allows casting to multi-field types as well.
An interval value can be cast to a numeric type. In this case the interval value is first converted to a single-field INTERVAL type with the same field as the least significant filed of the interval value. The value is then converted to the target type. For example CAST (INTERVAL '1-11' YEAR TO MONTH AS INT) evaluates to INTERVAL '23' MONTH, and then 23.
An interval value can be cast into a character type, which results in an INTERVAL literal. A character value can be cast into an INTERVAL type so long as it is a string with a format compatible with an INTERVAL literal.
Two interval values can be added or subtracted so long as the types of both are based on the same field, i.e., both are based on MONTH or SECOND. The values are both converted to a single-field interval type with same field as the least-significant field between the two types. After addition or subtraction, the result is converted to an interval type that contains all the fields of the two original types.
An interval value can be multiplied or divided by a numeric value. Again, the value is converted to a numeric, which is then multiplied or divided, before converting back to the original interval type.
An interval value is negated by simply prefixing with the minus sign.
Interval values used in expressions are either typed values,
including interval literals, or are interval casts. The expression:
<expression> <interval qualifier> is a cast
of the result of the <expression> into the
INTERVAL type specified by the <interval qualifier>. The
cast can be formed by adding the keywords and parentheses as follows: CAST
( <expression> AS INTERVAL <interval qualifier>
).
The examples below feature different forms of expression
that represent an interval value, which is then added to the given date
literal.
DATE '2000-01-01' + INTERVAL '1-10' YEAR TO MONTH /* interval literal */ DATE '2000-01-01' + '1-10' YEAR TO MONTH /* the string '1-10' is cast into INTERVAL YEAR TO MONTH */ DATE '2000-01-01' + 22 MONTH /* the integer 22 is cast into INTERVAL MONTH, same value as above */ DATE '2000-01-01' - 22 DAY /* the integer 22 is cast into INTERVAL DAY */ DATE '2000-01-01' + COL2 /* the type of COL2 must be an INTERVAL type */ DATE '2000-01-01' + COL2 MONTH /* COL2 may be a number, it is cast into a MONTH interval */
Datetime and Interval Operations
An interval can be added to or subtracted from a datetime value so long as they have some fields in common. For example, an INTERVAL MONTH cannot be added to a TIME value, while an INTERVAL HOUR TO SECOND can. The interval is first converted to a numeric value, then the value is added to, or subtracted from, the corresponding field of the datetime value.
If the result of addition or subtraction is beyond the permissible range for the field, the field value is normalised and carried over to the next significant field until all the fields are normalised. For example, adding 20 minutes to TIME '23:50:10' will result successively in '23:70:10', '24:10:10' and finally TIME '00:10:10'. Subtracting 20 minutes from the result is performed as follows: '00:-10:10', '-1:50:10', finally TIME '23:50:10'. Note that if DATE or TIMESTAMP normalisation results in the YEAR field value out of the range (1,1000), then an exception condition is raised.
If an interval value based on MONTH is added to, or subtracted from a DATE or TIMESTAMP value, the result may have an invalid day (30 or 31) for the given result month. In this case an exception condition is raised.
The result of subtraction of two datetime expressions is an interval
value. The two datetime expressions must be of the same type. The type of
the interval value must be specified in the expression, using only the
interval field names. The two datetime expressions are enclosed in
parentheses, followed by the <interval qualifier>
fields. In the first example below, COL1 and COL2 are of the same datetime
type, and the result is evaluated in INTERVAL YEAR TO MONTH type.
(COL1 – COL2) YEAR TO MONTH /* the difference between two DATE or two TIEMSTAMP values in years and months */ (CURRENT_DATE – COL3) DAY /* the number of days between the value of COL3 and the current date */ (CURRENT_DATE - DATE '2000-01-01') YEAR TO MONTH /* the number of years and months since the beginning of this century */ CURRENT_DATE - 2 DAY /* the date of the day before yesterday */ (CURRENT_TIMESTAMP - TIMESTAMP '2009-01-01 00:00:00') DAY(4) TO SECOND(2) /* days to seconds since the given date */
The individual fields of both datetime and interval values can be extracted using the EXTRACT function. The same function can also be used to extract the time zone displacement fields of a datetime value.
EXTRACT ({YEAR | MONTH | DAY | HOUR | MINUTE | SECOND |
TIMEZONE_HOUR | TIMEZONE_MINUTE | DAY_OF_WEEK | WEEK_OF_YEAR } FROM
{<datetime value> | <interval value>})
The dichotomy between interval types based on seconds, and those based on months, stems from the fact that the different calendar months have different numbers of days. For example, the expression, “nine months and nine days since an event” is not exact when the date of the event is unknown. It can represent a period of around 284 days give or take one. SQL interval values are independent of any start or end dates or times. However, when they are added to or subtracted from certain date or timestamp values, the result may be invalid and cause an exception (e.g. adding one month to January 30 results in February 30, which is invalid).
JDBC has an unfortunate limitation and does not include type codes
for SQL INTERVAL types. Therefore, for compatibility with database tools
that are limited to the JDBC type codes, HyperSQL reports these types by
default as VARCHAR. You can use the URL property
hsqldb.translate_dti_types=false to override the
default behaviour.
Array are a powerful feature of SQL:2008 and can help solve many common problems. Arrays should not be used as a substitute for tables.
HyperSQL supports arrays of values according to the SQL:2008 Standard.
Elements of the array are either NULL, or of the same data type. It is possible to define arrays of all supported types, including the types covered in this chapter and user defined types, except LOB types. An SQL array is one dimensional and is addressed from position 1. An empty array can also be used, which has no element.
Arrays can be stored in the database, as well as being used as temporary containers of values for simplifying SQL statements. They facilitate data exchange between the SQL engine and the user's application.
The full range of supported syntax allows array to be created, used in SELECT or other statements, combined with rows of tables and used in routine calls.
The type of a table column, a routine parameter, a variable, or the return value of a function can be defined as an array.
<array type> ::= <data type> ARRAY [ <left
bracket or trigraph> <maximum cardinality> <right bracket or
trigraph> ]
The word ARRAY is added to any valid type definition except BLOB
and CLOB type definitions. If the optional <maximum
cardinality> is not used, the default value is 1024. The
size of the array cannot be extended beyond maximum cardinality.
In the example below, the table contains a column of integer arrays and a column of varchar arrays. The VARCHAR array has an explicit maximum size of 10, which means each array can have between 0 and 10 elements. The INTEGER array has the default maximum size of 1024. The scores column has a default clause with an empty array. The default clause can be defined only as DEFAULT NULL or DEFAULT ARRAY[] and does not allow arrays containing elements.
CREATE TABLE t (id INT PRIMARY KEY, scores INT ARRAY DEFAULT ARRAY[], names VARCHAR(20) ARRAY[10])
An array can be constructed from value expressions or a query expression.
<array value constructor by enumeration> ::= ARRAY
<left bracket or trigraph> <array element list> <right
bracket or trigraph>
<array element list> ::= <value expression> [
{ <comma> <value expression> }... ]
<array value constructor by query> ::= ARRAY
<left paren> <query expression> [ <order by clause> ]
<right paren>
In the examples below, arrays are constructed from values, column references or variables, function calls, or query expressions.
ARRAY [ 1, 2, 3 ] ARRAY [ 'HOT', 'COLD' ] ARRAY [ var1, var2, CURRENT_DATE ] ARRAY (SELECT lastname FROM namestable ORDER BY id)
Inserting and updating a table with an ARRAY column can use array constructors, not only for updated column values, but also in equality search conditions:
INSERT INTO t VALUES 10, ARRAY[1,2,3], ARRAY['HOT', 'COLD'] UPDATE t SET names = ARRAY['LARGE', 'SMALL'] WHERE id = 12 UPDATE t SET names = ARRAY['LARGE', 'SMALL'] WHERE id < 12 AND scores = ARRAY[3,4]
When using a PreparedStatement with an ARRAY parameter, an
object of the type java.sql.Array must be used to set the parameter.
The org.hsqldb.jdbc.JDBCArrayBasic class can be
used for constructing a java.sql.Array object in the user's
application. Code fragment below:
String sql = "UPDATE t SET names = ? WHERE id = ?";
PreparedStatement ps = connection.prepareStatement(sql)
Object[] data = new Object[]{"one", "two"};
// default types defined in org.hsqldb.types.Type can be used
org.hsqldb.types.Type type = org.hsqldb.types.Type.SQL_VARCHAR_DEFAULT;
JDBCArrayBasic array = new JDBCArrayBasic(data, type);
ps.setArray(1, array);
ps.setInt(2, 1000);
ps.executeUpdate();
The most common operations on an array are element reference and assignment, which are used when reading or writing an element of the array. Unlike Java and many other languages, arrays are extended if an element is assigned to an index beyond the current length. This can result in gaps containing NULL elements. Array length cannot exceed the maximum cardinality.
Elements of all arrays, including those that are the result of function calls or other operations can be referenced for reading.
<array element reference> ::= <array value
expression> <left bracket> <numeric value expression>
<right bracket>
Elements of arrays that are table columns or routine variables can be referenced for writing. This is done in a SET statement, either inside an UPDATE statement, or as a separate statement in the case of routine variables, OUT and INOUT parameters.
<target array element specification> ::= <target
array reference> <left bracket or trigraph> <simple value
specification> <right bracket or trigraph>
<target array reference> ::= <SQL parameter
reference> | <column reference>
Note that only simple values or variables are allowed for the array index when an assignment is performed. The examples below demonstrates how elements of the array are referenced in SELECT and an UPDATE statement.
SELECT scores[ranking], names[ranking] FROM t JOIN t1 on (t.id = t1.tid) UPDATE t SET scores[2] = 123, names[2] = 'Reds' WHERE id = 10
Several SQL operations and functions can be used with arrays.
CONCATENATION
Array concatenation is performed similar to string concatenation. All elements of the array on the right are appended to the array on left.
<array concatenation> ::= <array value
expression 1> <concatenation operator> <array value
expression 2>
<concatenation operator> ::= ||
FUNCTIONS
Four functions operate on arrays. Details are described in the Built In Functions chapter.
CARDINALITY <left paren> <array value
expression> <right paren>
MAX_CARDINALITY <left paren> <array value
expression> <right paren>
Array cardinality and max cardinality are functions that return an integer. CARDINALITY returns the element count, while MAX_CARDINALITY returns the maximum declared cardinality of an array.
TRIM_ARRAY <left paren> <array value
expression> <comma> <numeric value expression> <right
paren>
The TRIM_ARRAY function returns a copy of an array with the
specified number of elements removed from the end of the array. The
<array value expression> can be any expression
that evaluates to an array.
ARRAY_SORT <left paren> <array value
expression> <right paren>
The ARRAY_SORT function returns a sorted copy of an array. NULL elements appear at the beginning of the new array. This function is a HyperSQL extension and not part of the SQL Standard.
CAST
An array can be cast into an array of a different type. Each element of the array is cast into the element type of the target array type.
UNNEST
Arrays can be converted into table references with the UNNEST keyword.
UNNEST(<array value expression>) [ WITH ORDINALITY
]
The <array value expression> can be any
expression that evaluates to an array. A table is returned that contains
one column when WITH ORDINALITY is not used, or two columns when WITH
ORDINALITY is used. The first column contains the elements of the array
(including all the nulls). When the table has two columns, the second
column contains the ordinal position of the element in the array. When
UNNEST is used in the FROM clause of a query, it implies the LATERAL
keyword, which means the array that is converted to table can belong to
any table that precedes the UNNEST in the FROM clause. This is explained
in the Data Access and Change chapter.
COMPARISON
Arrays can be compared for equality, but they cannot be compared for ordering or ranges. Array expressions are therefore not allowed in an ORDER BY clause, or in a comparison expression such as GREATER THAN. Two arrays are equal if they have the same length and the values at each index position are either equal or both NULL.
USER DEFINED FUNCTIONS and PROCEDURES
Array parameters, variables and return values can be specified in user defined functions and procedures, including aggregate functions. An aggregate function can return an array that contains all the scalar values that have been aggregated. These capabilities allow a wider range of applications to be covered by user defined functions and easier data exchange between the engine and the user's application.
HyperSQL supports PRIMARY KEY, UNIQUE and FOREIGN KEY constraints, which can span multiple columns.
The engine creates indexes internally to support PRIMARY KEY, UNIQUE and FOREIGN KEY constraints: a unique index is created for each PRIMARY KEY or UNIQUE constraint; an ordinary index is created for each FOREIGN KEY constraint.
HyperSQL allows defining indexes on single or multiple columns. You should not create duplicate user-defined indexes on the same column sets covered by constraints. This would result in unnecessary memory and speed overheads. See the discussion in the Deployment Guide chapter for more information.
Indexes are crucial for adequate query speed. When range or equality
conditions are used e.g. SELECT ... WHERE acol > 10 AND bcol =
0, an index should exist on one of the columns that has a
condition. In this example, the bcol column is the best
candidate. HyperSQL always uses the best condition and index. If there are
two indexes, one on acol, and another on bcol, it will choose the index on
bcol.
Queries always return results whether indexes exist or not, but they
return much faster when an index exists. As a rule of thumb, HSQLDB is
capable of internal processing of queries at over 100,000 rows per second.
Any query that runs into several seconds is clearly accessing thousands of
rows. The query should be checked and indexes should be added to the
relevant columns of the tables if necessary. The EXPLAIN PLAN FOR
<query> statement can be used to see which indexes are
used to process the query.
When executing a DELETE or UPDATE statement, the engine needs to find the rows that are to be deleted or updated. If there is an index on one of the columns in the WHERE clause, it is often possible to start directly from the first candidate row. Otherwise all the rows of the table have to be examined.
Indexes are even more important in joins between multiple tables.
SELECT ... FROM t1 JOIN t2 ON t1.c1 = t2.c2 is
performed by taking rows of t1 one by one and finding a matching row in
t2. If there is no index on t2.c2 then for each row of t1, all the rows of
t2 must be checked. Whereas with an index, a matching row can be found in
a fraction of the time. If the query also has a condition on t1, e.g.,
SELECT ... FROM t1 JOIN t2 ON t1.c1 = t2.c2 WHERE t1.c3 =
4 then an index on t1.c3 would eliminate the need for checking
all the rows of t1 one by one, and will reduce query time to less than a
millisecond per returned row. So if t1 and t2 each contain 10,000 rows,
the query without indexes involves checking 100,000,000 row combinations.
With an index on t2.c2, this is reduced to 10,000 row checks and index
lookups. With the additional index on t2.c2, only about 4 rows are checked
to get the first result row.
Note that in HSQLDB an index on multiple columns can be used
internally as a non-unique index on the first column in the list. For
example: CONSTRAINT name1 UNIQUE (c1, c2, c3); means
there is the equivalent of CREATE INDEX name2 ON
atable(c1);. So you do not need to specify an extra index if you
require one on the first column of the list.
In HyperSQL 2.0, a multi-column index will speed up queries that
contain joins or values on the first n columns of the index. You need NOT
declare additional individual indexes on those columns unless you use
queries that search only on a subset of the columns. For example, rows of
a table that has a PRIMARY KEY or UNIQUE constraint on three columns or
simply an ordinary index on those columns can be found efficiently when
values for all three columns, or the first two columns, or the first
column, are specified in the WHERE clause. For example, SELECT
... FROM t1 WHERE t1.c1 = 4 AND t1.c2 = 6 AND t1.c3 = 8 will use
an index on t1(c1,c2,c3) if it exists.
A multi-column index will not speed up queries on the second or third column only. The first column must be specified in the JOIN .. ON or WHERE conditions.
Sometimes query speed depends on the order of the tables in the JOIN
.. ON or FROM clauses. For example the second query below should be faster
with large tables (provided there is an index on
TB.COL3). The reason is that TB.COL3
can be evaluated very quickly if it applies to the first table (and there
is an index on TB.COL3):
(TB is a very large table with only a few rows where TB.COL3 = 4)
SELECT * FROM TA JOIN TB ON TA.COL1 = TB.COL2 AND TB.COL3 = 4;
SELECT * FROM TB JOIN TA ON TA.COL1 = TB.COL2 AND TB.COL3 = 4;
The general rule is to put first the table that has a narrowing condition on one of its columns. In certain cases, HyperSQL 2.2.x reorders the joined tables if it is obvious that this will introduce a narrowing condition.
HyperSQL features automatic, on-the-fly indexes for views and subselects that are used in a query.
Indexes are used when a LIKE condition searches from the start of the string.
Indexes are used for ORDER BY clauses if the same index is used for selection and ordering of rows. It is possible to force the use of index for ORDER BY.
HyperSQL 2.2.x changes the order of tables in a query in order to optimise processing. This happens only when one of the tables has a narrowing condition and reordering does not change the result of the query.
HyperSQL optimises queries to use indexes, for all types of range and equality conditions, including IS NULL and NOT NULL conditions. Conditions can be in join or WHERE clauses, including all types of joins.
In addition, HyperSQL will use an index (if one exists) for IN conditions, whether constants, variable, or subqueries are used on the right hand side of the IN predicate. Multicolumn IN conditions can also use an index.
HyperSQL can always use indexes when several conditions are combined with the AND operator, choosing a conditions which can use an index. This now extended to all equality conditions on multiple columns that are part of an index.
HyperSQL will also use indexes when several conditions are combined with the OR operator and each condition can use an index (each condition may use a different index). For example, if a huge table has two separate columns for first name and last name, and both columns are indexed, a query such as the following example will use the indexes and complete in a short time:
-- TC is a very large table
SELECT * FROM TC WHERE TC.FIRSTNAME = 'John' OR TC.LASTNAME = 'Smith' OR TC.LASTNAME = 'Williams'
Each subquery is considered a separate SELECT statement and uses indexes when they are available.
In each SELECT statement, at least one index per table can be used if there is a query conditions that can use the index. When conditions on a table are combined with the OR operator, and each condition can use an index, multiple indexes per table are used.
HyperSQL optimises simple row count queries in the form of
SELECT COUNT(*) FROM <table> and returns the
result immediately (this optimisation does not take place in MVCC
mode).
HyperSQL can use an index on a column for SELECT
MAX(<column>) FROM <table> and SELECT
MIN(<column>) FROM <table> queries. There should
be an index on the <column> and the query can have a WHERE
condition on the same column. In the example below the maximum value for
the TB.COL3 below 1000000 is returned.
SELECT MAX(TB.COL3) FROM TB WHERE TB.COL < 1000000
HyperSQL can use an index for simple queries containing DISTINCT or GROUP BY to avoid checking all the rows of the table. Note that indexes are always used if the query has a condition, regardless of the use of DISTINCT or GROUP BY. This particular optimisation applies to cases in which all the columns in the SELECT list are from the same table and are covered by a single index, and any join or query condition uses this index.
For example, with the large table below, a DISTINCT or GROUP BY query to return all the last names, can use an the index on the TC.LASTNAME column. Similarly, a GROUP BY query on two columns can use an index that covers the two columns.
-- TC is a very large table
SELECT DISTINCT LASTNAME FROM TC WHERE TC.LASTNAME > 'F'
SELECT STATE, LASTNAME FROM TC GROUP BY STATE, LASTNAME
HyperSQL can use an index on an ORDER BY clause if all the columns in ORDER BY are in a single-column or multi-column index (in the exact order). This is important if there is a LIMIT n (or FETCH n ROWS ONLY) clause. In this situation, the use of index allows the query processor to access only the number of rows specified in the LIMIT clause, instead of building the whole result set, which can be huge. This also works for joined tables when the ORDER BY clause is on the columns of the first table in a join. Indexes are used in the same way when ORDER BY ... DESC is specified in the query. Note that unlike other RDBMS, HyperSQL does not need or create DESC indexes. It can use any ordinary, ascending index for ORDER BY ... DESC.
If there is an equality or range condition (e.g. EQUALS, GREATER THAN) condition on the columns specified in the ORDER BY clause, the index is still used.
In the two examples below, the index on TA.COL3 is used and only up to 1000 rows are processed and returned.
(TA is a very large table with an index on TA.COL3
SELECT * FROM TA JOIN TB ON TA.COL2 = TB.COL1 WHERE TA.COL3 > 40000 ORDER BY TA.COL3 LIMIT 1000;
SELECT * FROM TA JOIN TB ON TA.COL2 = TB.COL1 WHERE TA.COL3 > 40000 AND TA.COL3 < 100000 ORDER BY TA.COL3 DESC LIMIT 1000;
But if the query contains an equality condition on another indexed column in the table, this may take precedence and no index may be used for ORDER BY. In this case USING INDEX can be added to the end of the query to force the use of the index for the LIMIT operation. In the example below there is an index on TA.COL1 as well as the index on TA.COL3. Normally the index on TA.COL1 is used, but the USING INDEX hint results in the index on TB.COL3 to be used for selecting the first 1000 rows.
(TA is a very large table with an index on TA.COL3 and a separate index on TA.COL1
SELECT * FROM TA JOIN TB ON TA.COL2 = TB.COL1 WHERE TA.COL1 = 'SENT' AND TB.COL3 > 40000 ORDER BY TB.COL3 LIMIT 1000 USING INDEX;
$Revision: 4903 $
Copyright 2010-2012 Fred Toussi. Permission is granted to distribute this document without any alteration under the terms of the HSQLDB license. Additional permission is granted to the HSQL Development Group to distribute this document with or without alterations under the terms of the HSQLDB license.
2012-01-22 11:31:28-0500
Table of Contents
All SQL statements are executed in sessions. When a connection is established to the database, a session is started. The authorization of the session is the name of the user that started the session. A session has several properties. These properties are set by default at the start according to database settings.
SQL Statements are generally transactional statements. When a transactional statement is executed, it starts a transaction if no transaction is in progress. If SQL Data is modified during a transaction, the change can be undone with a ROLLBACK statement. When a COMMIT statement is executed, the transaction is ended. If a single statement fails, the transaction is not normally terminated. However, some failures are caused by execution of statements that are in conflict with statements executed in other concurrent sessions. Such failures result in an implicit ROLLBACK, in addition to the exception that is raised.
Schema definition and manipulation statements are also transactional according to the SQL Standard. HyperSQL 2.0 performs automatic commits before and after the execution of such transactions. Therefore, schema-related statements cannot be rolled back. This is likely to change in future versions.
Some statements are not transactional. Most of these statements are used to change the properties of the session. These statements begin with the SET keyword.
If the AUTOCOMMIT property of a session is TRUE, then each transactional statement is followed by an implicit COMMIT.
The default isolation level for a session is READ COMMITTED. This
can be changed using the JDBC java.sql.Connection
object and its setTransactionIsolation(int level)
method. The session can be put in read-only mode using the
setReadOnly(boolean readOnly) method. Both
methods can be invoked only after a commit or a rollback, but not during a
transaction.
The isolation level and / or the readonly mode of a transaction can also be modified using an SQL statement. You can use the statement to change only the isolation mode, only the read-only mode, or both at the same time. This command can be issued only after a commit or rollback.
SET TRANSACTION <transaction characteristic> [
<comma> <transaction characteristic> ]
Details of the statement is described later in this chapter.
Each session has several system attributes. A session can also have user-defined session variables.
The system attributes reflect the current mode of operation for
the session. These attributes can be accessed with function calls and
can be referenced in queries. For example, they can be returned using
the VALUES <attribute function>, ...
statement.
The named attributes such as CURRENT_USER, CURRENT_SCHEMA, etc. are SQL Standard functions. Other attributes of the session, such as auto-commit or read-only modes can be read using other built-in functions. All these functions are listed in the Built In Functions chapter.
Session variables are user-defined variables created the same way as the variables for stored procedures and functions. Currently, these variables cannot be used in general SQL statements. They can be assigned to IN, INOUT and OUT parameters of stored procedures. This allows calling stored procedures which have INOUT or OUT arguments and is useful for development and debugging. See the example in the SQL-Invoked Routines chapter, under Formal Parameters.
Example 3.1. User-defined Session Variables
DECLARE counter INTEGER DEFAULT 3; DECLARE result VARCHAR(20) DEFAULT NULL; SET counter=15; CALL myroutine(counter, result)
With necessary access privileges, sessions can access all table, including GLOBAL TEMPORARY tables, that are defined in schemas. Although GLOBAL TEMPORARY tables have a single name and definition which applies to all sessions that use them, the contents of the tables are different for each session. The contents are cleared either at the end of each transaction or when the session is closed.
Session tables are different because their definition is visible only within the session that defines a table. The definition is dropped when the session is closed. Session tables do not belong to schemas.
<temporary table declaration> ::= DECLARE LOCAL
TEMPORARY TABLE <table name> <table element list> [ ON
COMMIT { PRESERVE | DELETE } ROWS ]
The syntax for declaration is based on the SQL Standard. A session table cannot have FOREIGN KEY constraints, but it can have PRIMARY KEY, UNIQUE or CHECK constraints. A session table definition cannot be modified by adding or removing columns, indexes, etc.
It is possible to refer to a session table using its name, which takes precedence over a schema table of the same name. To distinguish a session table from schema tables, the pseudo schema names, MODULE or SESSION can be used. An example is given below:
Example 3.2. User-defined Temporary Session Tables
DECLARE LOCAL TEMPORARY TABLE buffer (id INTEGER PRIMARY KEY, textdata VARCHAR(100)) ON COMMIT PRESERVE ROWS INSERT INTO module.buffer SELECT id, firstname || ' ' || lastname FROM customers -- do some more work DROP TABLE module.buffer -- or use alternative pseudo schema name DROP TABLE session.buffer
Session tables can be created inside a transaction.
Automatic indexes are created and used on session tables when necessary
for a query or other statement. By default, session table data is held
in memory. This can be changed with the SET SESSION RESULT
MEMORY ROWS statement.
HyperSQL 2.0 has been fully redesigned to support different transaction isolation models. It no longer supports the old 1.8.x model with "dirty read". Although it is perfectly possible to add an implementation of the transaction manager that supports the legacy model, we thought this is no longer necessary. The new system allows you to select the transaction isolation model while the engine is running. It also allows you to choose different isolation levels for different simultaneous sessions.
HyperSQL 2.0 supports three concurrency control models, two-phase-locking (2PL), which is the default, multiversion concurrency control (MVCC) and a hybrid model, which is 2PL plus multiversion rows. Within each model, it supports some of the 4 standard levels of transaction isolation: READ UNCOMMITTED, READ COMMITTED, REPEATABLE READ and SERIALIZABLE. The concurrency control model is a strategy that governs all the sessions and is set for the database, as opposed for individual sessions. The isolation level is a property of each SQL session, so different sessions can have different isolation levels. In the new implementation, all isolation levels avoid the "dirty read" phenomenon and do not read uncommitted changes made to rows by other transactions.
HyperSQL is fully multi threaded in all transaction models. Sessions continue to work simultaneously and can fully utilise multi-core processors.
To concurrency control model of a live database can be changed. The
SET DATABASE TRANSACTION CONTROL { LOCKS | MVLOCKS | MVCC
} can be used by a user with the DBA role.
The two-phase locking model is the default mode. It is referred to by the keyword, LOCKS. In the 2PL model, each table that is read by a transaction is locked with a shared lock (read lock), and each table that is written to is locked with an exclusive lock (write lock). If two sessions read and modify different tables then both go through simultaneously. If one session tries to lock a table that has been locked by the other, if both locks are shared locks, it will go ahead. If either of the locks is an exclusive lock, the engine will put the session in wait until the other session commits or rolls back its transaction. In some cases the engine will invalidate the transaction of the current session, if the action would result in deadlock.
HyperSQL also supports explicit locking of a group of tables for the duration of the current transaction. Use of this command blocks access to the locked tables by other sessions and ensures the current session can complete the intended reads and writes on the locked tables.
If a table is read-only, it will not be locked by any transaction.
The READ UNCOMMITTED isolation level can be used in 2PL modes for read-only operations. It is the same as READ COMMITTED plus read only.
The READ COMMITTED isolation level is the default. It keeps write locks on tables until commit, but releases the read locks after each operation.
The REPEATABLE READ level is upgraded to SERIALIZABLE. These levels keep both read and write locks on tables until commit.
It is possible to perform some critical operations at the SERIALIZABLE level, while the rest of the operations are performed at the READ COMMITTED level.
Note: two phase locking refers to two periods in the life of a transaction. In the first period, locks are acquired, in the second period locks are released. No new lock is acquired after releasing a lock.
This model is referred to as MVLOCKS. It works the same way as normal 2PL as far as updates are concerned.
SNAPSHOT ISOLATION is a multiversion concurrency strategy which uses the snapshot of the whole database at the time of the start of the transaction. In this model, read only transactions use SNAPSHOT ISOLATION. While other sessions are busy changing the database, the read only session sees a consistent view of the database and can access all the tables even when they are locked by other sessions for updates.
There are many applications for this mode of operation. In heavily updated data sets, this mode allows uninterrupted read access to the data.
When multiple connections are used to access the database, the transaction manager controls their activities. When each transaction performs only reads or writes on a single table, there is no contention. Each transaction waits until it can obtain a lock then performs the operation and commits. All contentions occur when transactions perform reads and writes on more than one table, or perform a read, followed by a write, on the same table.
For example, when sessions are working at the SERIALIZABLE level, when multiple sessions first read from a table in order to check if a row exists, then insert a row into the same table when it doesn't exist, there will be regular contention. Transaction A reads from the table, then does Transaction B. Now if either Transaction A or B attempts to insert a row, it will have to be terminated as the other transaction holds a shared lock on the table. If instead of two operations, a single MERGE statement is used to perform the read and write, no contention occurs because both locks are obtained at the same time.
Alternatively, there is the option of obtaining the necessary locks with an explicit LOCK TABLE statement. This statement should be executed before other statements and should include the names of all the tables and the locks needed. After this statement, all the other statements in the transaction can be executed and the transaction committed. The commit will remove all the locks.
HyperSQL detects deadlocks before attempting to execute a statement. When a lock is released after the completion of the statement, the first transaction that is waiting for the lock is allowed to continue.
HyperSQL is fully multi threaded. It therefore allows different transactions to execute concurrently so long as they are not waiting to lock the same table for write.
In both LOCKS and MVLOCKS models, SQL routines (functions and procedures) and triggers obtain all the read and write locks at the beginning of the routine execution. SQL statements contained in the routine or trigger are all executed without deadlock as all the locks have already been obtained. At the end of execution of the routine or trigger, read locks are released if the session isolation level is READ COMMITTED.
In the MVCC model, there are no shared, read locks. Exclusive locks are used on individual rows, but their use is different. Transactions can read and modify the same table simultaneously, generally without waiting for other transactions. The SQL Standard isolation levels are used by the user's application, but these isolation levels are translated to the MVCC isolation levels READ CONSISTENCY or SNAPSHOT ISOLATION.
When transactions are running at READ COMMITTED level, no conflict will normally occur. If a transaction that runs at this level wants to modify a row that has been modified by another uncommitted transaction, then the engine puts the transaction in wait, until the other transaction has committed. The transaction then continues automatically. This isolation level is called READ CONSISTENCY.
Deadlock is completely avoided. In theory conflict is possible if
each transaction is waiting for a different row modified by the other
transaction. In this case, one of the transactions is immediately
terminated (rolled back) unless the setting has been changed with the
<set database transaction rollback on conflict
statement>. When this setting is changed to FALSE, the
session that avoided executing the deadlock-causing statement returns an
error, but without rolling back the previous actions. This will cause
the other transaction to wait for the current transaction. The property
should not be changed unless the application can quickly perform an
alternative statement to continue or roll back the transaction. This
allows maximum flexibility and compatibility with other database engines
which do not roll back the transaction upon deadlock.
When transactions are running in REPEATABLE READ or SERIALIZABLE isolation levels, conflict is more likely to happen. There is no difference in operation between these two isolation levels. This isolation level is called SNAPSHOT ISOLATION.
In this mode, when the duration of two transactions overlaps, if
one of the transactions has modified a row and the second transaction
wants to modify the same row, the action of the second transaction will
fail. The engine will invalidate the second transaction and roll back
all its changes. If the setting is changed to false with the
<set database transaction rollback on conflict
statement>, then the second transaction will just return an
error without rolling back. The application must perform an alternative
statement to continue or roll back the transaction.
In the MVCC model, READ UNCOMMITTED is promoted to READ COMMITTED, as the new architecture is based on multi-version rows for uncommitted data and more than one version may exist for some rows.
With MVCC, when a transaction only reads data, then it will go ahead and complete regardless of what other transactions may do. This does not depend on the transaction being read-only or the isolation modes.
The SQL Standard defines the isolation levels as modes of operation that avoid the three unwanted phenomena, "dirty read", "fuzzy read" and "phantom row". The "dirty read" phenomenon occurs when a session can read a row that has been changed by another session. The "fuzzy read" phenomenon occurs when a row that was read by a session is modified by another session, then the first session reads the row again. The "phantom row" phenomenon occurs when a session performs an operation that affects several rows, for example, counts the rows or modifies them using a search condition, then another session adds one or more rows that fulfil the same search condition, then the first session performs an operation that relies on the results of its last operation. According to the Standard, the SERIALIZABLE isolation level avoids all three phenomena and also ensures that all the changes performed during a transaction can be considered as a series of uninterrupted changes to the database without any other transaction changing the database at all for the duration of these actions. The changes made by other transactions are considered to occur before the SERIALIZABLE transaction starts, or after it ends. The READ COMMITTED level avoids "dirty read" only, while the REPEATABLE READ level avoids "dirty read" and "fuzzy read", but not "phantom row".
The Standard allows the engine to return a higher isolation level than requested by the application. HyperSQL promotes a READ UNCOMMITTED request to READ COMMITTED and promotes a REPEATABLE READ request to SERIALIZABLE.
The MVCC model is not covered directly by the Standard. Research has established that the READ CONSISTENCY level fulfils the requirements of (and is stronger than) the READ COMMITTED level. The SNAPSHOT ISOLATION level is stronger than the READ CONSISTENCY level. It avoids the three anomalies defined by the Standard, and is therefore stronger than the REPEATABLE READ level as defined by the Standard. When operating with the MVCC model, HyperSQL treats a REPEATABLE READ or SERIALIZABLE setting for a transaction as SNAPSHOT ISOLATION.
All modes can be used with as many simultaneous connections as required. The default 2PL model is fine for applications with a single connection, or applications that do not access the same tables heavily for writes. With multiple simultaneous connections, MVCC can be used for most applications. Both READ CONSISTENCY and SNAPSHOT ISOLATION levels are stronger than the corresponding READ COMMITTED level in the 2PL mode. Some applications require SERIALIZABLE transactions for at least some of their operations. For these applications, one of the 2PL modes can be used. It is possible to switch the concurrency model while the database is operational. Therefore, the model can be changed for the duration of some special operations, such as synchronization with another data source.
All concurrency models are very fast in operation. When data change operations are mainly on the same tables, the MVCC model may be faster, especially with multi-core processors.
There are a few SQL statements that must access a consistent state of the database during their executions. These statements, which include CHECKPOINT and BACKUP, put an exclusive lock on all the tables of the database when they start.
Some schema manipulation statements put an exclusive lock on one or more tables. For example changing the columns of a table locks the table exclusively.
In the MVCC model, all statements that need an exclusive lock on one or more tables, put an exclusive lock on the database catalog until they complete.
The effect of these exclusive locks is similar to the execution of data manipulation statements with write locks. The session that is about to execute the schema change statement waits until no other session is holding a lock on any of the objects. At this point it starts its operation and locks the objects to prevents any other session from accessing the locked objects. As soon as the operation is complete, the locks are all removed.
It was mentioned that there is no limit on the number of sessions that can access the tables and all sessions work simultaneously in multi threaded execution. However there are internal resources that are shared. Simultaneous access to these resources can reduce the overall efficiency of the system. MEMORY and TEXT tables do not share resources and do not block multi threaded access. With CACHED tables, each row change operation blocks the file and its cache momentarily until the operation is finished. This is done separately for each row, therefore a multi-row INSERT, UPDATE, or DELETE statement will allow other sessions to access the file during its execution. With CACHED tables, SELECT operations do not block each other, but selecting from different tables and different parts of a large table causes the row cache to be updated frequently and will reduce overall performance.
The new access pattern is the opposite of the access pattern of version 1.8.x. In the old version, even when 20 sessions are actively reading and writing, only a single session at a time performs an SQL statement completely, before the next session is allowed access. In the new version, while a session is performing a SELECT statement and reading rows of a CACHED table to build a result set, another session may perform an UPDATE statement that reads and writes rows of the same table. The two operations are performed without any conflict, but the row cache is updated more frequently than when one operation is performed after the other operation has finished.
As HyperSQL is multithreaded, you can view the current sessions
and their state from any admin session. The
INFORMATION_SCHEMA.SYSTEM_SESSIONS table contains the
list of open sessions, their unique ids and the statement currently
executed or waiting to be executed by each session. For each session, it
displays the list of sessions that are waiting for it to commit, or the
session that this session is waiting for.
ALTER SESSION
alter session statement
<alter session statement> ::= ALTER SESSION
<numeric literal> { CLOSE | RELEASE }
<alter current session statement> ::= ALTER
SESSION RESET { ALL | RESULT SETS | TABLE DATA }
The <alter session statement> is used by an administrator to close another session or to release the transaction in another session. When a session is released, its current transaction is terminated with a failure. The session remains open. This statement is different from the other statements discussed in this chapter as it is not used for changing the settings of the current session.
The session ID is used as a <numeric
literal> in this statement. The administrator can use the
INFORMATION_SCHEMA.SYSTEM_SESSIONS table to find the
session IDs of other sessions.
The <alter current session statement> is used to clear and reset different states of the current session. When ALL is specified, the current transaction is rolled back, the session settings such as time zone, current schema etc. are restored to their original state at the time the session was opened and all open result sets are closed and temporary tables cleared. When RESULT SETS is specified, all currently open result sets are closed and the resources are released. When TABLE DATA is specified, the data in all temporary tables is cleared.
SET AUTOCOMMIT
set autocommit command
<set autocommit statement> ::= SET AUTOCOMMIT {
TRUE | FALSE }
When an SQL session is started by creating a JDBC connection, it
is in AUTOCOMMIT mode. In this mode, after each SQL statement a COMMIT is
performed automatically. This statement changes the mode. It is equivalent
to using the setAutoCommit( boolean autoCommit)
method of the JDBC Connection object.
START TRANSACTION
start transaction statement
<start transaction statement> ::= START
TRANSACTION [ <transaction characteristics> ]
Start an SQL transaction and set its characteristics. All transactional SQL statements start a transaction automatically, therefore using this statement is not necessary. If the statement is called in the middle of a transaction, an exception is thrown.
SET TRANSACTION
set next transaction characteristics
<set transaction statement> ::= SET [ LOCAL ]
TRANSACTION <transaction characteristics>
Set the characteristics of the next transaction in the current session. This statement has an effect only on the next transactions and has no effect on the future transactions after the next.
transaction characteristics
transaction characteristics
<transaction characteristics> ::= [
<transaction mode> [ { <comma> <transaction mode> }... ]
]
<transaction mode> ::= <isolation level> |
<transaction access mode> | <diagnostics
size>
<transaction access mode> ::= READ ONLY | READ
WRITE
<isolation level> ::= ISOLATION LEVEL <level of
isolation>
<level of isolation> ::= READ UNCOMMITTED | READ
COMMITTED | REPEATABLE READ | SERIALIZABLE
<diagnostics size> ::= DIAGNOSTICS SIZE <number
of conditions>
<number of conditions> ::= <simple value
specification>
Specify transaction characteristics.
Example 3.3. Setting Transaction Characteristics
SET TRANSACTION READ ONLY SET TRANSACTION ISOLATION LEVEL SERIALIZABLE SET TRANSACTION READ WRITE, ISOLATION LEVEL READ COMMITTED
SET CONSTRAINTS
set constraints mode statement
<set constraints mode statement> ::= SET
CONSTRAINTS <constraint name list> { DEFERRED | IMMEDIATE
}
<constraint name list> ::= ALL | <constraint
name> [ { <comma> <constraint name> }...
]
If the statement is issued during a transaction, it applies to the rest of the current transaction. If the statement is issued when a transaction is not active then it applies only to the next transaction in the current session. HyperSQL does not yet support this feature.
LOCK TABLE
lock table statement
<lock table statement> ::= LOCK TABLE <table
name> { READ | WRITE} [, <table name> { READ | WRITE}
...]}
In some circumstances, where multiple simultaneous transactions are in progress, it may be necessary to ensure a transaction consisting of several statements is completed, without being terminated due to possible deadlock. When this statement is executed, it waits until it can obtain all the listed locks, then returns. If obtaining the locks would result in a deadlock an error is raised. The SQL statements following this statements use the locks already obtained (and obtain new locks if necessary) and can proceed without waiting. All the locks are released when a COMMIT or ROLLBACK statement is issued.
When the isolation level of a session is READ COMMITTED, read locks are released immediately after the execution of the statement, therefore you should use only WRITE locks in this mode. Alternatively, you can switch to the SERIALIZABLE isolation mode before locking the tables for the specific transaction that needs to finish consistently and without a deadlock. It is best to execute this statement at the beginning of the transaction with the complete list of required read and write locks.
Currently, this command does not have any effect when the database transaction control model is MVCC.
SAVEPOINT
savepoint statement
<savepoint statement> ::= SAVEPOINT <savepoint
specifier>
<savepoint specifier> ::= <savepoint
name>
Establish a savepoint. This command is used during an SQL transaction. It establishes a milestone for the current transaction. The SAVEPOINT can be used at a later point in the transaction to rollback the transaction to the milestone.
RELEASE SAVEPOINT
release savepoint statement
<release savepoint statement> ::= RELEASE
SAVEPOINT <savepoint specifier>
Destroy a savepoint. This command is rarely used as it is not very useful. It removes a SAVEPOINT that has already been defined.
COMMIT
commit statement
<commit statement> ::= COMMIT [ WORK ] [ AND [ NO
] CHAIN ]
Terminate the current SQL-transaction with commit. This make all the changes to the database permanent.
ROLLBACK
rollback statement
<rollback statement> ::= ROLLBACK [ WORK ] [ AND [
NO ] CHAIN ]
Rollback the current SQL transaction and terminate it. The statement rolls back all the actions performed during the transaction. If NO CHAIN is specified, a new SQL transaction is started just after the rollback. The new transaction inherits the properties of the old transaction.
ROLLBACK TO SAVEPOINT
rollback statement
<rollback statement> ::= ROLLBACK [ WORK ] TO
SAVEPOINT <savepoint specifier>
Rollback part of the current SQL transaction and continue the
transaction. The statement rolls back all the actions performed after the
specified SAVEPOINT was created. The same effect can be achieved with the
rollback( Savepoint savepoint) method of the JDBC
Connection object.
Example 3.5. Rollback
-- perform some inserts, deletes, etc. SAVEPOINT A -- perform some inserts, deletes, selects etc. ROLLBACK WORK TO SAVEPOINT A -- all the work after the declaration of SAVEPOINT A is rolled back
DISCONNECT
disconnect statement
<disconnect statement> ::=
DISCONNECT
Terminate the current SQL session. Closing a JDBC connection has the same effect as this command.
SET SESSION CHARACTERISTICS
set session characteristics statement
<set session characteristics statement> ::= SET
SESSION CHARACTERISTICS AS <session characteristic
list>
<session characteristic list> ::= <session
characteristic> [ { <comma> <session characteristic> }...
]
<session characteristic> ::= <session
transaction characteristics>
<session transaction characteristics> ::=
TRANSACTION <transaction mode> [ { <comma> <transaction
mode> }... ]
Set one or more characteristics for the current SQL-session. This command is used to set the transaction mode for the session. This endures for all transactions until the session is closed or the next use of this command. The current read-only mode can be accessed with the ISREADONLY() function.
Example 3.6. Setting Session Characteristics
SET SESSION CHARACTERISTICS AS TRANSACTION READ ONLY SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL SERIALIZABLE SET SESSION CHARACTERISTICS AS TRANSACTION READ WRITE, ISOLATION LEVEL READ COMMITTED
SET SESSION AUTHORIZATION
set session user identifier statement
<set session user identifier statement> ::= SET
SESSION AUTHORIZATION <value specification>
Set the SQL-session user identifier. This statement changes the current user. The user that executes this command must have the CHANGE_AUTHORIZATION role, or the DBA role. After this statement is executed, all SQL statements are executed with the privileges of the new user. The current authorisation can be accessed with the CURRENT_USER and SESSION_USER functions.
Example 3.7. Setting Session Authorization
SET SESSION AUTHORIZATION 'FELIX' SET SESSION AUTHORIZATION SESSION_USER
SET ROLE
set role statement
<set role statement> ::= SET ROLE <role
specification>
<role specification> ::= <value
specification> | NONE
Set the SQL-session role name and the current role name for the current SQL-session context. The user that executes this command must have the specified role. If NONE is specified, then the previous CURRENT_ROLE is eliminated. The effect of this lasts for the lifetime of the session. The current role can be accessed with the CURRENT_ROLE function.
SET TIME ZONE
set local time zone statement
<set local time zone statement> ::= SET TIME ZONE
<set time zone value>
<set time zone value> ::= <interval value
expression> | LOCAL
Set the current default time zone displacement for the current SQL-session. When the session starts, the time zone displacement is set to the time zone of the client. This command changes the time zone displacement. The effect of this lasts for the lifetime of the session. If LOCAL is specified, the time zone displacement reverts to the local time zone of the session.
Example 3.8. Setting Session Time Zone
SET TIME ZONE LOCAL SET TIME ZONE INTERVAL '+6:00' HOUR TO MINUTE
SET CATALOG
set catalog statement
<set catalog statement> ::= SET <catalog name
characteristic>
<catalog name characteristic> ::= CATALOG
<value specification>
Set the default schema name for unqualified names used in SQL statements that are prepared or executed directly in the current sessions. As there is only one catalog in the database, only the name of this catalog can be used. The current catalog can be accessed with the CURRENT_CATALOG function.
SET SCHEMA
set schema statement
<set schema statement> ::= SET <schema name
characteristic>
<schema name characteristic> ::= SCHEMA <value
specification> | <schema name>
Set the default schema name for unqualified names used in SQL statements that are prepared or executed directly in the current sessions. The effect of this lasts for the lifetime of the session. The SQL Standard form requires the schema name as a single-quoted string. HyperSQL also allows the use of the identifier for the schema. The current schema can be accessed with the CURRENT_SCHEMA function.
SET PATH
set path statement
<set path statement> ::= SET <SQL-path
characteristic>
<SQL-path characteristic> ::= PATH <value
specification>
Set the SQL-path used to determine the subject routine of routine invocations with unqualified routine names used in SQL statements that are prepared or executed directly in the current sessions. The effect of this lasts for the lifetime of the session.
SET MAXROWS
set max rows statement
<set max rows statement> ::= SET MAXROWS
<unsigned integer literal>
The normal operation of the session has no limit on the number of rows returned from a SELECT statement. This command set the maximum number of rows of the result returned by executing queries.
This statement has a similar effect to the
setMaxRows(int max) method of the JDBC
Statement interface, but it affects the results
returned from the next statement execution only. After the execution of
the next statement, the MAXROWS limit is removed.
Only zero or positive values can be used with this command. The
value overrides any value specified with setMaxRows(int
max) method of a JDBC statement. The statement SET
MAXROWS 0 means no limit.
It is possible to limit the number of rows returned from SELECT statements with the FETCH <n> ROWS ONLY, or its alternative, LIMIT <n>. Therefore this command is not recommended for general use. The only legitimate use of this command is for checking and testing queries that may return very large numbers of rows.
SET SESSION RESULT MEMORY ROWS
set session result memory rows statement
<set session result memory rows statement> ::= SET
SESSION RESULT MEMORY ROWS <unsigned integer
literal>
By default the session uses memory to build result sets, subquery results and temporary tables. This command sets the maximum number of rows of the result (and temporary tables) that should be kept in memory. If the row count of the result or temporary table exceeds the setting, the result is stored on disk. The default is 0, meaning all result sets are held in memory.
This statement applies to the current session only. The general database setting is:
SET DATABASE DEFAULT RESULT MEMORY ROWS <unsigned
integer literal>
SET IGNORECASE
set ignore case statement
<set ignore case statement> ::= SET IGNORECASE {
TRUE | FALSE }
Sets the type used for new VARCHAR table columns. By default,
character columns in new databases are case sensitive. If SET
IGNORECASE TRUE is used, all VARCHAR columns in new tables are
set to VARCHAR_IGNORECASE. It is possible to specify
the VARCHAR_IGNORECASE type for the definition of
individual columns. So it is possible to have some columns case sensitive
and some not, even in the same table. This statement must be switched
before creating tables. Existing tables and their data are not
affected.
$Revision: 4903 $
Copyright 2009-2012 Fred Toussi. Permission is granted to distribute this document without any alteration under the terms of the HSQLDB license. Additional permission is granted to the HSQL Development Group to distribute this document with or without alterations under the terms of the HSQLDB license.
2012-01-22 11:31:28-0500
Table of Contents
The persistent elements of an SQL environment are database objects. The database consists of catalogs plus authorizations.
A catalog contains schemas, while schemas contain the objects that contain data or govern the data.
Each catalog contains a special schema called INFORMATION_SCHEMA. This schema is read-only and contains some views and other schema objects. The views contain lists of all the database objects that exist within the catalog, plus all authorizations.
Each database object has a name. A name is an identifier and is unique within its name-space.
In HyperSQL, there is only one catalog per database. The name of the
catalog is PUBLIC. You can rename the catalog with the ALTER
CATALOG RENAME TO statement. All schemas belong the this
catalog. The catalog name has no relation to the file name of the
database.
Each database has also an internal "unique" name which is automatically generated when the database is created. This name is used for event logging. You can also change this unique name.
Schema objects are database objects that contain data or govern or perform operations on data. By definition, each schema object belongs to a specific schema.
Schema objects can be divided into groups according to their characteristics.
Some kinds of schema objects can exist independently from other schema object. Other kinds can exist only as an element of another schema object. These dependent objects are automatically destroyed when the parent object is dropped.
Separate name-spaces exists for different kinds of schema object. Some name-spaces are shared between two similar kinds of schema objects.
There can be dependencies between various schema objects, as a schema object can include references to other schema objects. These references can cross schema boundaries. Interdependence and cross referencing between schema objects is allowed in some circumstances and disallowed in some others.
Schema objects can be destroyed with the DROP statement. If dependent schema objects exist, a DROP statement will succeed only if it has a CASCADE clause. In this case, dependent objects are also destroyed in most cases. In some cases, such as dropping DOMAIN objects, the dependent objects are not destroyed, but modified to remove the dependency.
A new HyperSQL catalog contains an empty schema called PUBLIC. By default, this schema is the initial schema when a new session is started. New schemas and schema objects can be defined and used in the PUBLIC schema, as well as any new schema that is created by the user. You can rename the PUBLIC schema.
HyperSQL allows all schemas to be dropped, except the schema that is the default initial schema for new sessions (by default, the PUBLIC schema). For this schema, a DROP SCHEMA ... CASCADE statement will succeed but will result in an empty schema, rather than no schema.
The statements for setting the initial schema for users are described in the Statements for Authorization and Access Control chapter.
The name of a schema object is an
<identifier>. The name belongs to the
name-space for the particular kind of schema object. The name is unique
within its name-space. For example, each schema has a separate
name-space for TRIGGER objects.
In addition to the name-spaces in the schema. Each table has a name-space for the names of its columns.
Because a schema object is always in a schema and a schema always
in a catalog, it is possible, and sometimes necessary, to qualify the
name of the schema object that is being referenced in an SQL statement.
This is done by forming an <identifier chain>.
In some contexts, only a simple <identifier>
can be used and the <identifier chain> is
prohibited. While in some other contexts, the use of
<identifier chain> is optional. An identifier
chain is formed by qualifying each object with the name of the object
that owns its name-space. Therefore a column name is prefixed with a
table name, a table name is prefixed with a schema name, and a schema
name is prefixed with a catalog name. A fully qualified column name is
in the form <catalog name>.<schema name>.<table
name>.<column name>, likewise, a fully qualified
sequence name is in the form <catalog name>.<schema
name>.<sequence name>.
HyperSQL extends the SQL standard to allow renaming all database objects. The ALTER ... RENAME TO command has slightly different forms depending on the type of object. If an object is referenced in a VIEW or ROUTINE definition, it is not always possible to rename it.
A CHARACTER SET is the whole or a subset of the UNICODE character set.
A character set name can only be a <regular
identifier>. There is a separate name-space for character
sets.
There are several predefined character sets. These character sets belong to INFORMATION_SCHEMA. However, when they are referenced in a statement, no schema prefix can be used in the statement that references them.
The following character sets have been specified by the SQL Standard:
SQL_TEXT, SQL_IDENTIFIER, SQL_CHARACTER, ASCII_GRAPHIC, GRAPHIC_IRV, ASCII_FULL, ISO8BIT, LATIN1, UTF32, UTF16, UTF8.
The ASCII_GRAPHIC is the same as GRAPHIC_IRV and ASCII_FULL is the same as ISO8BIT.
Most of the character sets are defined by well-known standards such as UNICODE.
The SQL_CHARACTER consists of ASCII letters, digits and the symbols used in the SQL language. The SQL_TEXT, SQL_IDENTIFIER are implementation defined. HyperSQL defines SQL_TEXT as the UNICODE character set and SQL_IDENTIFIER as the UNICODE character set minus the SQL language special characters.
The character repertoire of HyperSQL is the UTF16 character set, which covers all possible character sets. If a predefined character set is specified for a table column, then any string stored in the column must contain only characters from the specified character set.
Early releases of HyperSQL version 2.0 may not enforce the CHARACTER SET that is specified for a column and may accept any character string.
A COLLATION is the method used for ordering character strings in ordered sets and to determine equivalence of two character strings.
There are several predefined collations. These collations belong to INFORMATION_SCHEMA. However, when they are referenced in a statement, no schema prefix can be used in the statement that references them.
There is a separate name-space for collations..
Collations for a large number of languages are supported by HyperSQL.
HyperSQL version 2.1 support a single collation for the whole database. Optionally, a different collation can be specified for each table column that is defined as CHAR or VARCHAR. Also, a different collation can be used in an ORDER BY clause.
A distinct, user-defined TYPE is simply based on a built-in type. A distinct TYPE is used in table definitions and in CAST statements.
Distinct types share a name-space with domains.
A DOMAIN is a user-defined type, simply based on a built-in type. A DOMAIN can have constraints that limit the values that the DOMAIN can represent. A DOMAIN can be used in table definitions and in CAST statements.
Distinct types share a name-space with domains.
A SEQUENCE object produces INTEGER values in sequence. The SEQUENCE can be referenced in special contexts only within certain SQL statements. For each row where the object is referenced, its value is incremented.
There is a separate name-space for SEQUENCE objects.
IDENTITY columns are columns of tables which have an internal, unnamed SEQUENCE object. HyperSQL also supports IDENTITY columns that use a named SEQUENCE object.
SEQUENCE objects and IDENTITY columns are supported fully according to the latest SQL 2008 Standard syntax.
Sequences
The SQL:2008 syntax and usage is different from what is supported
by many existing database engines. Sequences are created with the
CREATE SEQUENCE command and their current value can
be modified at any time with ALTER SEQUENCE. The next
value for a sequence is retrieved with the NEXT VALUE FOR
<name> expression. This expression can be used for
inserting and updating table rows.
Example 4.1. inserting the next sequence value into a table row
INSERT INTO mytable VALUES 2, 'John', NEXT VALUE FOR mysequence;
You can also use it in select statements. For example, if you want to number the returned rows of a SELECT in sequential order, you can use:
Example 4.2. numbering returned rows of a SELECT in sequential order
SELECT NEXT VALUE FOR mysequence, col1, col2 FROM mytable WHERE ...
In version 2.0, the semantics of sequences is exactly as defined by SQL:2008. If you use the same sequence twice in the same row in an INSERT statement, you will get the same value as required by the Standard.
The correct way to use a sequence value is the NEXT VALUE FOR expression.
HyperSQL adds an extension to Standard SQL to return the last value returned by the NEXT VALUE FOR expression in the current session. After a statement containing NEXT VALUE FOR is executed, the value that was returned for NEXT VALUE FOR is available using the CURRENT VALUE FOR expression. In the example below, the NEXT VALUE FOR expression is used to insert a new row. The value that was returned by NEXT VALUE FOR is retrieved with the CURRENT VALUE FOR in the next insert statements to populate two new rows in a different table that has a parent child relationship with the first table. For example if the value 15 was returned by the sequence, the same value 15 is inserted in the three rows.
Example 4.3. using the last value of a sequence
INSERT INTO mytable VALUES 2, 'John', NEXT VALUE FOR mysequence; INSERT INTO childtable VALUES 4, CURRENT VALUE FOR mysequence; INSERT INTO childtable VALUES 5, CURRENT VALUE FOR mysequence;
The INFORMATION_SCHEMA.SEQUENCES table contains the next
value that will be returned from any of the defined sequences. The
SEQUENCE_NAME column contains the name and the NEXT_VALUE column
contains the next value to be returned. Note that this is only for
getting information and you should not use it for accessing the next
sequence value. When multiple sessions access the same sequence, the
value returned from this table by one session could also be used by a
different session, causing a sequence value to be used twice
unintentionally.
Identity Auto-Increment Columns
Each table can contain a single auto-increment column, known as the IDENTITY column. An IDENTITY column is a SMALLINT, INTEGER, BIGINT, DECIMAL or NUMERIC column with its value generated by a sequence generator.
In HyperSQL 2.0, an IDENTITY column is not by default treated as the primary key for the table (as a result, multi-column primary keys are possible with an IDENTITY column present).
The SQL standard syntax is used, which allows the initial value and other options to be specified.
<colname> [ INTEGER | BIGINT | DECIMAL | NUMERIC ] GENERATED { BY DEFAULT | ALWAYS} AS IDENTITY [( <options> )]
When you add a new row to such a table using an INSERT
INTO <tablename> ... statement, you can use the DEFAULT
keyword for the IDENTITY column, which results in an auto-generated
value for the column.
The IDENTITY() function returns the last value
inserted into any IDENTITY column by this session. Each session manages
this function call separately and is not affected by inserts in other
sessions. Use CALL IDENTITY() as an SQL statement to
retrieve this value. If you want to use the value for a field in a child
table, you can use INSERT INTO <childtable> VALUES
(...,IDENTITY(),...);. Both types of call to
IDENTITY() must be made before any additional update or insert
statements are issued by the session.
In triggers and routines, the value returned by the
IDENTITY() function is correct for the given context.
For example, if a call to a stored procedure inserts a row into a table,
causing a new identity value to be generated, a call to
IDENTITY() inside the procedure will return the new
identity, but a call outside the procedure will return the last identity
value that was generated before a call was made to the procedure.
The last inserted IDENTITY value can also be retrieved via JDBC, by specifying the Statement or PreparedStatement object to return the generated value.
The next IDENTITY value to be used can be changed with the following statement. Note that this statement is not used in normal operation and is only for special purposes, for example resetting the identity generator:
ALTER TABLE ALTER COLUMN <column name> RESTART WITH <new value>;
For
backward compatibility, support has been retained for CREATE
TABLE <tablename>(<colname> IDENTITY, ...) as a
shortcut which defines the column both as an IDENTITY column and a
PRIMARY KEY column. Also, for backward compatibility, it is possible to
use NULL as the value of an IDENTITY column in an INSERT statement and
the value will be generated automatically. You should avoid these
compatibility features as they may be removed from future versions of
HyperSQL.
In the following example, the identity value for the first INSERT statement is generated automatically using the DEFAULT keyword. The second INSERT statement uses a call to the IDENTITY() function to populate a row in the child table with the generated identity value.
CREATE TABLE star (id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, firstname VARCHAR(20), lastname VARCHAR(20)) CREATE TABLE movies (starid INTEGER, movieid INTEGER PRIMARY KEY, title VARCHAR(40)) INSERT INTO star (id, firstname, lastname) VALUES (DEFAULT, 'Felix', 'the Cat') INSERT INTO movies (starid, movieid, title) VALUES (IDENTITY(), 10, 'Felix in Hollywood')
HyperSQL 2.1 also supports IDENTITY columns that use an external, named SEQUENCE object. This feature is not part of the SQL Standard. The example below uses this type of IDENTITY. Note the use of CURRENT VALUE FOR seq here is multi-session safe. The returned value is the last value used by this session when the row was inserted into the star table. This value is available until the transaction is committed. After commit, NULL is returned by the CURRENT VALUE FOR expression until the SEQUENCE is used again.
CREATE SEQUENCE seq CREATE TABLE star (id INTEGER GENERATED BY DEFAULT AS SEQUENCE seq PRIMARY KEY, firstname VARCHAR(20), lastname VARCHAR(20)) CREATE TABLE movies (starid INTEGER, movieid INTEGER PRIMARY KEY, title VARCHAR(40)) INSERT INTO star (id, firstname, lastname) VALUES (DEFAULT, 'Felix', 'the Cat') INSERT INTO movies (starid, movieid, title) VALUES (CURRENT VALUE FOR seq, 10, 'Felix in Hollywood')
In the SQL environment, tables are the most essential components, as they hold all persistent data.
If TABLE is considered as metadata (i.e. without its actual data) it is called a relation in relational theory. It has one or more columns, with each column having a distinct name and a data type. A table usually has one or more constraints which limit the values that can potentially be stored in the TABLE. These constraints are discussed in the next section.
A single column of the table can be defined as IDENTITY. The values stored in this column are auto-generated and are based on an (unnamed) identity sequence, or optionally, a named SEQUENCE object.
A VIEW is similar to a TABLE but it does not permanently contain rows of data. A view is defined as a QUERY EXPRESSION, which is often a SELECT statement that references views and tables, but it can also consist of a TABLE CONSTRUCTOR that does not reference any tables or views.
A view has many uses:
Hide the structure and column names of tables. The view can represent one or more tables or views as a separate table. This can include aggregate data, such as sums and averages, from other tables.
Allow access to specific rows in a table. For example, allow access to records that were added since a given date, while hiding older records.
Allow access to specific columns. For example allow access to columns that contain non-confidential information. Note that this can also be achieved with the GRANT SELECT statement, using column-level privileges
A VIEW that returns the columns of a single ordinary TABLE is updatable if the query expression of the view is an updatable query expression as discussed in the Data Access and Change chapter. Some updatable views are insertable-into because the query expression is insertable-into. In these views, each column of the query expressions must be a column of the underlying table and those columns of the underlying table that are not in the view must have a default clause, or be an IDENTITY or GENERATED column. When rows of an updatable view are updated, or new rows are inserted, or rows are deleted, these changes are reflected in the base table. A VIEW definition may specify that the inserted or updated rows conform to the search condition of the view. This is done with the CHECK OPTION clause.
A view that is not updatable according to the above paragraph can be made updatable or insertable-into by adding INSTEAD OF triggers to the view. These triggers contain statements to use the submitted data to modify the contents of the underlying tables of the view separately. For example, a view that represents a SELECT statements that joins two tables can have an INSTEAD OF DELETE trigger with two DELETE statements, one for each table. Views that have an INSTEAD OF trigger are called TRIGGER INSERTABLE, TRIGGER UPDATABLE, etc. according to the triggers that have been defined.
Views share a name-space with tables.
A CONSTRAINT is a child schema object and can belong to a DOMAIN or a TABLE. CONSTRAINT objects can be defined without specifying a name. In this case the system generates a name for the new object beginning with "SYS_".
In a DOMAIN, CHECK constraints can be defined that limits the value represented by the DOMAIN. These constraints work exactly like a CHECK constraint on a single column of a table as described below.
In a TABLE, a constraint takes three basic forms.
CHECK
A CHECK constraint consists of a <search
condition> that must not be false (can be unknown) for each
row of the table. The <search condition> can
reference all the columns of the current row, and if it contains a
<subquery>, other tables and views in the
database (excluding its own table).
NOT NULL
A simple form of check constraint is the NOT NULL constraint, which applies to a single column.
UNIQUE
A UNIQUE constraint is based on an equality comparison of values of specific columns (taken together) of one row with the same values from each of the other rows. The result of the comparison must never be true (can be false or unknown). If a row of the table has NULL in any of the columns of the constraint, it conforms to the constraint. A unique constraint on multiple columns (c1, c2, c3, ..) means that in no two rows, the sets of values for the columns can be equal unless at lease one of them is NULL. Each single column taken by itself can have repeat values in different rows. The following example satisfies a UNIQUE constraint on the two columns
Example 4.4. Column values which satisfy a 2-column UNIQUE constraint
| 1, | 2 |
| 2, | 1 |
| 2, | 2 |
| NULL, | 1 |
| NULL, | 1 |
| 1, | NULL |
| NULL, | NULL |
| NULL, | NULL |
If the SET DATABASE SQL UNIQUE NULLS FALSE has been set, then if not all the values set of columns are null, the not null values are compared and it is disallowed to insert identical rows that contain at least one not-null value.
PRIMARY KEY
A PRIMARY KEY constraint is equivalent to a UNIQUE constraint on one or more NOT NULL columns. Only one PRIMARY KEY can be defined in each table.
FOREIGN KEY
A FOREIGN key constraint is based on an equality comparison between values of specific columns (taken together) of each row with the values of the columns of a UNIQUE constraint on another table or the same table. The result of the comparison must never be false (can be unknown). A special form of FOREIGN KEY constraint, based on its CHECK clause, allows the result to be unknown only if the values for all columns are NULL. A FOREIGN key can be declared only if a UNIQUE constraint exists on the referenced columns.
Constraints share a name space with assertions.
An ASSERTION is a top-level schema objects. It consists of a
<search condition> that must not be false (can
be unknown).
Assertions share a name-space with constraints
A TRIGGER is a child schema object that always belongs to a TABLE or a VIEW.
Each time a DELETE, UPDATE or INSERT is performed on the table or view, additional actions are taken by the triggers that have been declared on the table or view.
Triggers are discussed in detail in Triggers chapter.
Routines are user-defined functions or procedures. The names and usage of functions and procedures are different. FUNCTION is a routine that can be referenced in many types of statements. PROCEDURE is a routine that can be referenced only in a CALL statement.
There is a separate name-space for routines.
Because of the possibility of overloading, each routine can have more than one name. The name of the routine is the same for all overloaded variants, but each variant has a specific name, different from all other routine names and specific names in the schema. The specific name can be specified in the routine definition statement. Otherwise it is assigned by the engine. The specific name is used only for schema manipulation statements, which need to reference a specific variant of the routine. For example, if a routine has two signatures, each signature has its own specific name. This allows the user to drop one of the signatures while keeping the other.
Routines are discussed in detail in chapter SQL-Invoked Routines .
Schemas and schema objects can be created, modified and dropped. The SQL Standard defines a range of statements for this purpose. HyperSQL supports many additional statements, especially for changing the properties of existing schema objects.
These elements and statements are used for different types of object. They are described here, before the statements that can use them.
identifier
definition of identifier
<identifier> ::= <regular identifier> |
<delimited identifier> | <SQL language identifier>
<delimited identifier> ::= <double quote>
<character sequence> <double quote>
<regular identifier> ::= <special character
sequence>
<SQL language identifier> ::= <special
character sequence>
A <delimited identifier> is a sequence
of characters enclosed with double-quote symbols. All characters are
allowed in the character sequence.
A <regular identifier> is a special
sequence of characters. It consists of letters, digits and the
underscore characters. It must begin with a letter.
A <SQL language identifier> is similar
to <regular identifier> but the letters can
range only from A-Z in the ASCII character set. This type of identifier
is used for names of CHARACTER SET objects.
If the character sequence of a delimited identifier is the same
as an undelimited identifier, it represents the same identifier. For
example "JOHN" is the same identifier as JOHN. In a <regular
identifier> the case-normal form is considered for
comparison. This form consists of the upper-case of equivalent of all
the letters.
The character sequence length of all identifiers must be between 1 and 128 characters.
A reserved word is one that is used by the SQL Standard for
special purposes. It is similar to a <regular
identifier> but it cannot be used as an identifier for user
objects. If a reserved word is enclosed in double quote characters, it
becomes a quoted identifier and can be used for database
objects.
Case sensitivity rules for identifiers can be described simply as follows:
all parts of SQL statements are converted to upper case before processing, except identifiers in double quotes and strings in single quotes
identifiers, both unquoted and double quoted, are then treated as case-sensitive
most database engines follow the same rule, except MySQL, and in some respects, MS SQLServer.
CASCADE or RESTRICT
drop behavior
<drop behavior> ::= CASCADE |
RESTRICT
The <drop behavior> is a required
element of statements that drop a SCHEMA or a schema object. If
<drop behavior> is not specified then
RESTRICT is implicit. It determines the effect of the
statement if there are other objects in the catalog that reference the
SCHEMA or the schema object. If RESTRICT is specified, the statement
fails if there are referencing objects. If CASCADE is specified, all the
referencing objects are modified or dropped with cascading effect.
Whether a referencing object is modified or dropped, depends on the kind
of schema object that is dropped.
IF EXISTS
drop condition (HyperSQL)
<if exists clause> ::= IF
EXISTS
This clause is not part of the SQL standard and is a HyperSQL extension to some commands that drop objects (schemas, tables, views, sequences and indexes). If it is specified, then the statement does not return an error if the drop statement is issued on a non-existent object.
SPECIFIC
specific routine designator
<specific routine designator> ::= SPECIFIC
<routine type> <specific name>
<routine type> ::= ROUTINE | FUNCTION |
PROCEDURE
This clause is used in statements that need to specify one of
the multiple versions of an overloaded routine. The
<specific name> is the one specified in the
<routine definition> statement.
RENAME
rename statement (HyperSQL)
<rename statement> ::= ALTER <object type>
<name> RENAME TO <new name>
<object type> ::= CATALOG | SCHEMA | DOMAIN |
TYPE | TABLE | CONSTRAINT | INDEX | ROUTINE | SPECIFIC
ROUTINE
<column rename statement> ::= ALTER TABLE
<table name> ALTER COLUMN <name> RENAME TO <new
name>
This statement is used to rename an existing object. It is not
part of the SQL Standard. The specified <name>
is the existing name, which can be qualified with a schema name, while
the <new name> is the new name for the
object.
COMMENT
comment statement (HyperSQL)
<comment statement> ::= COMMENT ON { TABLE |
COLUMN | ROUTINE } <name> IS <character string
literal>
Adds a comment to the object metadata, which can later be read
from an INFORMATION_SCHEMA view. This command is not part of the SQL
Standard. The strange syntax is due to compatibility with other database
engines that support the statement. The <name>
is the name of a table, view, column or routine. The name of the column
consists of dot-separated <table name> . <column
name>. The name of the table, view or routine can be a
simple name. All names can be qualified with a schema name. If there is
already a comment on the object, the new comment will replace
it.
The comments appear in the results returned by JDBC DatabaseMetaData methods, getTables() and getColumns(). The INFORMATION_SCHEMA.SYSTEM_COMMENTS view contains the comments. You can query this view using the schema, table, and column names to retrieve the comments.
CREATE SCHEMA
schema definition
The CREATE_SCHEMA or DBA role is required in order to create a
schema. A schema can be created with or without schema objects. Schema
objects can always be added after creating the schema, or existing ones
can be dropped. Within the <schema definition>
statement, all schema object creation takes place inside the newly
created schema. Therefore, if a schema name is specified for the schema
objects, the name must match that of the new schema. In addition to
statements for creating schema objects, the statement can include
instances of <grant statement> and
<role definition>. This is a curious aspect of
the SQL standard, as these elements do not really belong to schema
creation.
<schema definition> ::= CREATE SCHEMA <schema
name clause> [ <schema character set specification> ] [
<schema element>... ]
<schema name clause> ::= <schema name> |
AUTHORIZATION <authorization identifier> | <schema name>
AUTHORIZATION <authorization identifier>
If the name of the schema is specified simply as
<schema name>, then the AUTHORIZATION is the
current user. Otherwise, the specified <authorization
identifier> is used as the AUTHORIZATION for the schema. If
<schema name> is omitted, then the name of the
schema is the same as the specified <authorization
identifier>.
<schema element> ::= <table definition> |
<view definition> | <domain definition> | <character set
definition> | <collation definition> | <transliteration
definition> | <assertion definition> | <trigger
definition> | <user-defined type definition> | <user-defined
cast definition> | <user-defined ordering definition> |
<transform definition> | <schema routine> | <sequence
generator definition> | <grant statement> | <role
definition>
An example of the command is given below. Note that a single semicolon appears at the end, there should be no semicolon between the statements:
CREATE SCHEMA ACCOUNTS AUTHORIZATION DBA
CREATE TABLE AB(A INTEGER, ...)
CREATE TABLE CD(C CHAR(10), ...)
CREATE VIEW VI AS SELECT ...
GRANT SELECT ON AB TO PUBLIC
GRANT SELECT ON CD TO JOE;
It is not really necessary to create a schema and all its objects as one command. The schema can be created first, and its objects can be created one by one.
DROP SCHEMA
drop schema statement
<drop schema statement> ::= DROP SCHEMA [ IF
EXISTS ] <schema name> [ IF EXISTS ] <drop behavior>
This command destroys an existing schema. If <drop
behavior> is RESTRICT, the schema must
be empty, otherwise an error is raised. If CASCADE is
specified, then all the objects contained in the schema are destroyed
with a CASCADE option.
CREATE TABLE
table definition
<table definition> ::= CREATE [ { <table
scope> | <table type> } ] TABLE <table name> <table
contents source> [ ON COMMIT { PRESERVE | DELETE } ROWS
]
<table scope> ::= { GLOBAL | LOCAL }
TEMPORARY
<table type> :: = MEMORY |
CACHED
<table contents source> ::= <table element
list> | <as subquery clause>
<table element list> ::= <left paren>
<table element> [ { <comma> <table element> }... ]
<right paren>
<table element> ::= <column definition> |
<table constraint definition> | <like
clause>
like clause
A <like clause> copies all column
definitions from another table into the newly created table. Its three
options indicate if the <default clause>,
<identity column specification> and
<generation clause> associated with the column
definitions are copied or not. If an option is not specified, it
defaults to EXCLUDING. The <generation
clause> refers to columns that are generated by an
expression but not to identity columns. All NOT NULL constraints are
copied with the original columns, other constraints are not. The
<like clause> can be used multiple times,
allowing the new table to have copies of the column definitions of one
or more other tables.
CREATE TABLE t (id INTEGER PRIMARY KEY, LIKE atable INCLUDING DEFAULTS EXCLUDING IDENTITY)
<like clause> ::= LIKE <table name> [
<like options> ]
<like options> ::= <like
option>...
<like option> ::= <identity option> |
<column default option> | <generation
option>
<identity option> ::= INCLUDING IDENTITY |
EXCLUDING IDENTITY
<column default option> ::= INCLUDING DEFAULTS |
EXCLUDING DEFAULTS
<generation option> ::= INCLUDING GENERATED |
EXCLUDING GENERATED
as subquery clause
<as subquery clause> ::= [ <left paren>
<column name list> <right paren> ] AS <table subquery>
{ WITH NO DATA | WITH DATA }
An <as subquery clause> used in table
definition creates a table based on a <table
subquery>. This kind of table definition is similar to a
view definition. If WITH DATA is specified, then the
new table will contain the rows of data returned by the
<table subquery>.
CREATE TABLE t (a, b, c) AS (SELECT * FROM atable) WITH DATA
column definition
A column definition consists of a <column
name> and in most cases a <data
type> or <domain name> as minimum.
The other elements of <column definition> are
optional. Each <column name> in a table is
unique.
<column definition> ::= <column name> [
<data type or domain name> ] [ <default clause> |
<identity column specification> | <identity column sequence
specification> | <generation clause> ] [ <column constraint
definition>... ] [ <collate clause> ]
<data type or domain name> ::= <data type>
| <domain name>
<column constraint definition> ::= [
<constraint name definition> ] <column constraint> [
<constraint characteristics> ]
<column constraint> ::= NOT NULL | <unique
specification> | <references specification> | <check
constraint definition>
A <column constraint definition> is a
shortcut for a <table constraint definition>. A
constraint that is defined in this way is automatically turned into a
table constraint. A name is automatically generated for the constraint
and assigned to it.
If a <collate clause> is specified,
then a UNIQUE or PRIMARY KEY constraint or an INDEX on the column will
use the specified collation. Otherwise the specified default collation
for the database is used.
generated columns
The value of a column can be autogenerated in two ways.
One way is specific to columns of integral types (INTEGER, BIGINT, etc.) and associates a sequence generator with the column. When a new row is inserted into the table, the value of the column is generated as the next available value in the sequence.
The SQL Standard supports the use of unnamed sequences with the IDENTITY keyword. In addition, HyperSQL supports the use of a named SEQUENCE object, which must be in the same schema as the table.
<identity column specification> ::= GENERATED {
ALWAYS | BY DEFAULT } AS IDENTITY [ <left paren> <common
sequence generator options> <right paren> ]
<identity column sequence specification ::=
GENERATED BY DEFAULT AS SEQUENCE <sequence name>
The <identity column specification> or
<identity column sequence specification> can be
specified for only a single column of the table.
The <identity column specification> is
used for columns which represent values based on an unnamed sequence
generator. It is possible to insert a row into the table without
specifying a value for the column. The value is then generated by the
sequence generators according to its rules. An identity column may or
may not be the primary key. Example below:
CREATE TABLE t (id INTEGER GENERATED ALWAYS AS IDENTITY(START WITH 100), name VARCHAR(20) PRIMARY KEY)
The <identity column sequence
specification> is used when the column values are based on
a named SEQUENCE object (which must already exist). Example
below:
CREATE TABLE t (id INTEGER GENERATED BY DEFAULT AS SEQUENCE s, name VARCHAR(20) PRIMARY KEY)
Inserting rows is done in the same way for a named or unnamed sequence generator. In both cases, if no value is specified to be inserted, or the DEFAULT keyword is used for the column, the value is generated by the sequence generator. If a value is specified, this value is used if the column definition has the BY DEFAULT specification. If the column definition has the ALWAYS specification, a value can be specified but the OVERRIDING SYSTEM VALUES must be specified in the INSERT statement.
The other way in which the column value is autogenerated is by using the values of other columns in the same row. This method is often used to create an index on a value that is derived from other column values.
<generation clause> ::= GENERATED ALWAYS AS
<generation expression>
<generation expression> ::= <left paren>
<value expression> <right paren>
The <generation clause> is used for
special columns which represent values based on the values held in other
columns in the same row. The <value expression>
must reference only other, non-generated, columns of the table in the
same row. Any function used in the expression must be deterministic and
must not access SQL-data. No <query expression>
is allowed. When <generation clause> is used,
<data type> must be specified.
A generated column can be part of a foreign key or unique constraints or a column of an index. This capability is the main reason for using generated columns. A generated column may contain a formula that computes a value based on the values of other columns. Fast searches of the computed value can be performed when an index is declared on the generated column. Or the computed values can be declared to be unique, using a UNIQUE constraint on the table. The computed column cannot be overridden by user supplied values. When a row is updated and the column values change, the generated columns are computed with the new values.
When a row is inserted into a table, or an existing row is updated, no value except DEFAULT can be specified for a generated column. In the example below, data is inserted into the non-generated columns and the generated column will contain 'Felix the Cat' or 'Pink Panther'.
CREATE TABLE t (id INTEGER PRIMARY KEY, firstname VARCHAR(20), lastname VARCHAR(20), fullname VARCHAR(40) GENERATED ALWAYS AS (firstname || ' ' || lastname)) INSERT INTO t (id, firstname, lastname) VALUES (1, 'Felix', 'the Cat') INSERT INTO t (id, firstname, lastname, fullname) VALUES (2, 'Pink', 'Panther', DEFAULT)
DEFAULT
default clause
A default clause can be used if GENERATED is not specified. If
a column has a <default clause> then it is
possible to insert a row into the table without specifying a value for
the column.
<default clause> ::= DEFAULT <default
option>
<default option> ::= <literal> |
<datetime value function> | USER | CURRENT_USER | CURRENT_ROLE |
SESSION_USER | SYSTEM_USER | CURRENT_CATALOG | CURRENT_SCHEMA |
CURRENT_PATH | NULL
The type of the <default option> must
match the type of the column.
In PGS (PostgreSQL) compatibility mode, a NEXTVAL function can be used. Also, in MSS compatibility mode, the default value can be enclosed in parentheses.
CONSTRAINT
constraint name and characteristics
<constraint name definition> ::= CONSTRAINT
<constraint name>
<constraint characteristics> ::= <constraint
check time> [ [ NOT ] DEFERRABLE [ <constraint check time> ]
]
<constraint check time> ::= INITIALLY DEFERRED |
INITIALLY IMMEDIATE
Specify the name of a constraint and its characteristics. By
default the constraint is NOT DEFERRABLE and
INITIALLY IMMEDIATE. This means the constraint is
enforced as soon as a data change statement is executed. If
INITIALLY DEFERRED is specified, then the constraint
is enforced when the session commits. The characteristics must be
compatible. The constraint check time can be changed temporarily for an
SQL session. HyperSQL does not support deferring constraint enforcement.
This feature of the SQL Standard has been criticised because it allows a
session to read uncommitted data that violates database integrity
constraints but has not yet been checked.
CONSTRAINT
table constraint definition
<table constraint definition> ::= [
<constraint name definition> ] <table constraint> [
<constraint characteristics> ]
<table constraint> ::= <unique constraint
definition> | <referential constraint definition> | <check
constraint definition>
Three kinds of constraint can be defined on a table: UNIQUE (including PRIMARY KEY), FOREIGN KEY and CHECK. Each kind has its own rules to limit the values that can be specified for different columns in each row of the table.
UNIQUE
unique constraint definition
<unique constraint definition> ::= <unique
specification> <left paren> <unique column list>
<right paren> | UNIQUE ( VALUE )
<unique specification> ::= UNIQUE | PRIMARY
KEY
<unique column list> ::= <column name
list>
A unique constraint is specified on a single column or on multiple columns. On each set of columns taken together, only one UNIQUE constraint can be specified. Each column of a PRIMARY KEY constraint has an implicit NOT NULL constraint.
If UNIQUE( VALUE ) is specified, the
constraint created on all columns of the table.
FOREIGN KEY
referential constraint definition
<referential constraint definition> ::= FOREIGN
KEY <left paren> <referencing columns> <right paren>
<references specification>
<references specification> ::= REFERENCES
<referenced table and columns> [ MATCH <match type> ] [
<referential triggered action> ]
<match type> ::= FULL | PARTIAL |
SIMPLE
<referencing columns> ::= <reference column
list>
<referenced table and columns> ::= <table
name> [ <left paren> <reference column list> <right
paren> ]
<reference column list> ::= <column name
list>
<referential triggered action> ::= <update
rule> [ <delete rule> ] | <delete rule> [ <update
rule> ]
<update rule> ::= ON UPDATE <referential
action>
<delete rule> ::= ON DELETE <referential
action>
<referential action> ::= CASCADE | SET NULL |
SET DEFAULT | RESTRICT | NO ACTION
A referential constraint allows links to be established between
the rows of two tables. The specified list of <referencing
columns> corresponds one by one to the columns of the
specified list of <referenced columns> in
another table (or sometimes in the same table). For each row in the
table, a row must exist in the referenced table with equivalent values
in the two column lists. There must exist a single unique constraint in
the referenced table on all the <referenced
columns>.
The [ MATCH match type ] clause is optional
and has an effect only on multi-column foreign keys and only on rows
containing at least a NULL in one of the <referencing
columns>. If the clause is not specified, MATCH SIMPLE is
the default. If MATCH SIMPLE is specified, then any
NULL means the row can exist (without a corresponding row in the
referenced table). If MATCH FULL is specified then
either all the column values must be NULL or none of them.
MATCH PARTIAL allows any NULL but the non NULL values
must match those of a row in the referenced table. HyperSQL does not
support MATCH PARTIAL.
Referential actions are specified with ON UPDATE and ON DELETE clauses. These actions take place when a row in the referenced table (the parent table) has referencing rows in the referencing table and it is deleted or modified with any SQL statement. The default is NO ACTION. This means the SQL statement that causes the DELETE or UPDATE is terminated with an exception. The RESTRICT option is similar and works exactly the same without deferrable constraints (which are not allowed by HyperSQL). The other three options, CASCADE, SET NULL and SET DEFAULT all allow the DELETE or UPDATE statement to complete. With DELETE statements the CASCADE option results in the referencing rows to be deleted. With UPDATE statements, the changes to the values of the referenced columns are copied to the referencing rows. With both DELETE or UPDATE statement, the SET NULL option results in the columns of the referencing rows to be set to NULL. Similarly, the SET DEFAULT option results in the columns of the referencing rows to be set to their default values.
CHECK
check constraint definition
<check constraint definition> ::= CHECK <left
paren> <search condition> <right
paren>
A CHECK constraint can exist for a TABLE or for a DOMAIN. The
<search condition> evaluates to an SQL BOOLEAN
value for each row of the table. Within the <search
condition> all columns of the table row can be referenced.
For all rows of the table, the <search
condition> evaluates to TRUE or UNKNOWN. When a new row is
inserted, or an existing row is updated, the <search
condition> is evaluated and if it is FALSE, the insert or
update fails.
A CHECK constraint for a DOMAIN is similar. In its
<search condition>, the term VALUE is used to
represents the value to which the DOMAIN applies.
CREATE TABLE t (a VARCHAR(20) CHECK (a IS NOT NULL AND CHARACTER_LENGTH(a) > 2))
The search condition of a CHECK constraint cannot contain any function that is not deterministic. A check constraint is a data integrity constraint, therefore it must hold with respect to the rest of the data in the database. It cannot use values that are temporal or ephemeral. For example CURRENT_USER is a function that returns different values depending on who is using the database, or CURRENT_DATE changes day-to-day. Some temporal expressions are retrospectively deterministic and are allowed in check constraints. For example, (CHECK VALUE < CURRENT_DATE) is valid, because CURRENT_DATE will not move backwards in time, but (CHECK VALUE > CURRENT_DATE) is not acceptable.
If you want to enforce the condition that a date value that is inserted into the database belongs to the future (at the time of insertion), or any similar constraint, then use a TRIGGER with the desired condition.
DROP TABLE
drop table statement
<drop table statement> ::= DROP TABLE [ IF
EXISTS ] <table name> [ IF EXISTS ] <drop
behavior>
Destroy a table. The default drop behaviour is RESTRICT and
will cause the statement to fail if there is any view, routine or
foreign key constraint that references the table. If <drop
behavior> is CASCADE, it causes all
schema objects that reference the table to drop. Referencing views are
dropped. In the case of foreign key constraints that reference the
table, the constraint is dropped, rather than the TABLE or DOMAIN that
contains it.
Table manipulation statements change the attributes of tables or modify the objects such as columns and constraints.
SET TABLE CLUSTERED
set table clustered property (HyperSQL)
<set table clustered statement> ::= SET TABLE
<table name> CLUSTERED ON <left paren> <column name
list> <right paren>
Set the row clustering property of a table. The <column name list> is a list of column names that must correspond to the columns of an existing PRIMARY KEY, UNIQUE or FOREIGN KEY index, or to the columns of a user defined index. This statement is only valid for CACHED or TEXT tables.
Tables rows are stored in the database files as they are created, sometimes at the end of the file, sometimes in the middle of the file. After a CHECKPOINT DEFRAG or SHUTDOWN COMPACT, the rows are reordered according to the primary key of the table, or if there is no primary key, in no particular order.
When several consecutive rows of a table are retrieved during query execution it is more efficient to retrieve rows that are stored adjacent to one another. After executing this command, nothing changes until a CHECKPOINT DEFRAG or SHUTDOWN COMPACT or SHUTDOWN SCRIPT is performed. After these operations, the rows are stored in the specified clustered order. The property is stored in the database and applies to all future reordering of rows. Note that if extensive inserts or updates are performed on the tables, the rows will get out of order until the next reordering.
SET TABLE writability
set table write property (HyperSQL)
<set table read only statement> ::= SET TABLE
<table name> { READ ONLY | READ WRITE }
Set the writeability property of a table. Tables are writable
by default. This statement can be used to change the property between
READ ONLY and READ WRITE. This is
a feature of HyperSQL.
SET TABLE SOURCE
set table source statement
<set table source statement> ::= SET TABLE
<table name> SOURCE <file and options>
[DESC]
<file and options>::= <doublequote>
<file path> [<semicolon> <property>...]
<doublequote>
Set the text source for a text table. This statement cannot be used for tables that are not defined as TEXT TABLE.
Supported Properties
|
quoted = { true | false } |
default is true. If false, treats double quotes as normal characters |
|
all_quoted = { true | false } |
default is false. If true, adds double quotes around all fields. |
|
encoding = <encoding name> |
character encoding for text and character fields, for example, encoding=UTF-8 |
|
ignore_first = { true | false } |
default is false. If true ignores the first line of the file |
|
cache_scale= <numeric value> |
exponent to calculate rows of the text file in cache. Default is 8, equivalent to nearly 800 rows |
|
cache_size_scale = <numeric value>r |
exponent to calculate average size of each row in cache. Default is 8, equivalent to 256 bytes per row. |
|
fs = <unquoted character> |
field separator |
|
vs = <unquoted character> |
varchar separator |
Special indicators for HyperSQL Text Table separators
|
\semi |
semicolon |
|
\quote |
quote |
|
\space |
space character |
|
\apos |
apostrophe |
|
\n |
newline - Used as an end anchor (like $ in regular expressions) |
|
\r |
carriage return |
|
\t |
tab |
|
\\ |
backslash |
|
\u#### |
a Unicode character specified in hexadecimal |
In the example below, the text source of the table is set to "myfile", the field separator to the pipe symbol, and the long varchar separator to the tilde symbol.
SET TABLE mytable SOURCE 'myfile;fs=|;vs=.;lvs=~'
Only a user with the DBA role can execute this statement.
SET TABLE SOURCE HEADER
set table source header statement
<set table source header statement> ::= SET
TABLE <table name> SOURCE HEADER <header
string>
Set the header for the text source for a text table. If this
command is used, the <header string> is used as
the first line of the source file of the text table. This line is not
part of the table data. Only a user with the DBA role can execute this
statement.
SET TABLE SOURCE on-off
set table source on-off statement
<set table source on-off statement> ::= SET
TABLE <table name> SOURCE { ON | OFF }
Attach or detach a text table from its text source. This command does not change the properties or the name of the file that is the source of a text table. When OFF is specified, the command detaches the table from its source and closes the file for the source. In this state, it is not possible to read or write to the table. This allows the user to replace the file with a different file, or delete it. When ON is specified, the source file is read. Only a user with the DBA role can execute this statement
ALTER TABLE
alter table statement
<alter table statement> ::= ALTER TABLE
<table name> <alter table action>
<alter table action> ::= <add column
definition> | <alter column definition> | <drop column
definition> | <add table constraint definition> | <drop
table constraint definition>
Change the definition of a table. Specific types of this statement are covered below.
ADD COLUMN
add column definition
<add column definition> ::= ADD [ COLUMN ]
<column definition> [ BEFORE <other column name>
]
Add a column to an existing table. The <column
definition> is specified the same way as it is used in
<table definition>. HyperSQL allows the use of
[ BEFORE <other column name> ] to specify at
which position the new column is added to the table.
If the table contains rows, the new column must have a
<default clause> or use one of the forms of
GENERATED. The column values for each row is then filled with the result
of the <default clause> or the generated
value.
DROP COLUMN
drop column definition
<drop column definition> ::= DROP [ COLUMN ]
<column name> <drop behavior>
Destroy a column of a base table. The <drop
behavior> is either RESTRICT or
CASCADE. If the column is referenced in a table
constraint that references other columns as well as this column, or if
the column is referenced in a VIEW, or the column is referenced in a
TRIGGER, then the statement will fail if RESTRICT is
specified. If CASCADE is specified, then any
CONSTRAINT, VIEW or TRIGGER object that references the column is dropped
with a cascading effect.
ADD CONSTRAINT
add table constraint definition
<add table constraint definition> ::= ADD
<table constraint definition>
Add a constraint to a table. The existing rows of the table must conform to the added constraint, otherwise the statement will not succeed.
DROP CONSTRAINT
drop table constraint definition
<drop table constraint definition> ::= DROP
CONSTRAINT <constraint name> <drop
behavior>
Destroy a constraint on a table. The <drop
behavior> has an effect only on UNIQUE and PRIMARY KEY
constraints. If such a constraint is referenced by a FOREIGN KEY
constraint, the FOREIGN KEY constraint will be dropped if
CASCADE is specified. If the columns of such a
constraint are used in a GROUP BY clause in the query expression of a
VIEW or another kind of schema object, and a functional dependency
relationship exists between these columns and the other columns in that
query expression, then the VIEW or other schema object will be dropped
when CASCADE is specified.
ALTER COLUMN
alter column definition
<alter column definition> ::= ALTER [ COLUMN ]
<column name> <alter column action>
<alter column action> ::= <set column default
clause> | <drop column default clause> | <alter column data
type clause> | <alter identity column specification> |
<alter column nullability> | <alter column name> | <add
column identity specification> | <drop column identity
specification>
Change a column and its definition. Specific types of this statement are covered below. See also the RENAME statement above.
SET DEFAULT
set column default clause
<set column default clause> ::= SET <default
clause>
Set the default clause for a column. This can be used if the column is not defined as GENERATED.
DROP DEFAULT
drop column default clause
<drop column default clause> ::= DROP
DEFAULT
Drop the default clause from a column.
SET DATA TYPE
alter column data type clause
<alter column data type clause> ::= SET DATA
TYPE <data type>
Change the declared type of a column. The (proposed) SQL Standard allows only changes to type properties such as maximum length, precision, or scale, and only changes that cause the property to enlarge. HyperSQL allows changing the type if all the existing values can be cast into the new type without string truncation or loss of significant digits.
alter column add identity generator
alter column add identity generator
<add column identity generator> ::= <identity
column specification>
Adds an identity specification to the column. The type of the column must be an integral type and the existing values must not include nulls. This option is specific to HyperSQL
ALTER TABLE mytable ALTER COLUMN id GENERATED ALWAYS AS IDENTITY (START WITH 20000)
alter column identity generator
alter identity column specification
<alter identity column specification> ::=
<alter identity column option>...
<alter identity column option> ::= <alter
sequence generator restart option> | SET <basic sequence generator
option>
Change the properties of an identity column. This command is similar to the commands used for changing the properties of named SEQUENCE objects discussed earlier and can use the same options.
ALTER TABLE mytable ALTER COLUMN id RESTART WITH 1000 ALTER TABLE mytable ALTER COLUMN id SET INCREMENT BY 5
DROP GENERATED
drop column identity generator
<drop column identity specification> ::= DROP
GENERATED
Removes the identity generator from a column. After executing this statement, the column values are no longer generated automatically. This option is specific to HyperSQL
ALTER TABLE mytable ALTER COLUMN id DROP GENERATED
SET [ NOT ] NULL
alter column nullability
<alter column nullability> ::= SET [ NOT ]
NULL
Adds or removes a NOT NULL constraint from a column. This option is specific to HyperSQL
CREATE VIEW
view definition
<view definition> ::= CREATE VIEW <table
name> <view specification> AS <query expression> [ WITH [
CASCADED | LOCAL ] CHECK OPTION ]
<view specification> ::= [ <left paren>
<view column list> <right paren> ]
<view column list> ::= <column name
list>
Define a view. The <query expression>
is a SELECT or similar statement. The <view column
list> is the list of unique names for the columns of the
view. The number of columns in the <view column
list> must match the number of columns returned by the
<query expression>. If <view column
list> is not specified, then the columns of the
<query expression> should have unique names and
are used as the names of the view column.
Some views are updatable. As covered elsewhere, an updatable
view is based on a single table or updatable view. For updatable views,
the optional CHECK OPTION clause can be specified. If
this option is specified, then if a row of the view is updated or a new
row is inserted into the view, then it should contain such values that
the row would be included in the view after the change. If WITH
CASCADED CHECK OPTION is specified, then if the
<query expression> of the view references
another view, then the search condition of the underlying view should
also be satisfied by the update or insert operation.
DROP VIEW
drop view statement
<drop view statement> ::= DROP VIEW [ IF EXISTS
] <table name> [ IF EXISTS ] <drop
behavior>
Destroy a view. The <drop behavior> is
similar to dropping a table.
ALTER VIEW
alter view statement
<alter view statement> ::= ALTER VIEW <table
name> <view specification> AS <query expression> [ WITH [
CASCADED | LOCAL ] CHECK OPTION ]
Alter a view. The statement is otherwise identical to CREATE VIEW. The new definition replaces the old. If there are database objects such as routines or views that reference the view, then these objects are recompiled with the new view definition. If the new definition is not compatible, the statement fails.
CREATE DOMAIN
domain definition
<domain definition> ::= CREATE DOMAIN <domain
name> [ AS ] <predefined type> [ <default clause> ] [
<domain constraint>... ] [ <collate clause>
]
<domain constraint> ::= [ <constraint name
definition> ] <check constraint definition> [ <constraint
characteristics> ]
Define a domain. Although a DOMAIN is not strictly a type in
the SQL Standard, it can be informally considered as a type. A DOMAIN is
based on a <predefined type>, which is a base
type defined by the Standard. It can have a <default
clause>, similar to a column default clause. It can also
have one or more CHECK constraints which limit the values that can be
assigned to a column or variable that has the DOMAIN as its
type.
CREATE DOMAIN valid_string AS VARCHAR(20) DEFAULT 'NO VALUE' CHECK (value IS NOT NULL AND CHARACTER_LENGTH(value) > 2)
ALTER DOMAIN
alter domain statement
<alter domain statement> ::= ALTER DOMAIN
<domain name> <alter domain action>
<alter domain action> ::= <set domain default
clause> | <drop domain default clause> | <add domain
constraint definition> | <drop domain constraint
definition>
Change a domain and its definition.
SET DEFAULT
set domain default clause
<set domain default clause> ::= SET <default
clause>
Set the default value in a domain.
DROP DEFAULT
drop domain default clause
<drop domain default clause> ::= DROP
DEFAULT
Remove the default clause of a domain.
ADD CONSTRAINT
add domain constraint definition
<add domain constraint definition> ::= ADD
<domain constraint>
Add a constraint to a domain.
DROP CONSTRAINT
drop domain constraint definition
<drop domain constraint definition> ::= DROP
CONSTRAINT <constraint name>
Destroy a constraint on a domain. If the <drop
behavior> is CASCADE, and the constraint
is a UNIQUE constraint which is referenced by a FOREIGN KEY constraint
on another table, then the FOREIGN KEY constraint is also
dropped.
DROP DOMAIN
drop domain statement
<drop domain statement> ::= DROP DOMAIN
<domain name> <drop behavior>
Destroy a domain. If <drop behavior>
is CASCADE, it works differently from most other
objects. If a table features a column of the specified DOMAIN, the
column survives and inherits the DEFAULT CLAUSE, and the CHECK
CONSTRAINT of the DOMAIN.
CREATE TRIGGER
trigger definition
<trigger definition> ::= CREATE TRIGGER
<trigger name> <trigger action time> <trigger event>
ON <table name> [ REFERENCING <transition table or variable
list> ] <triggered action>
<trigger action time> ::= BEFORE | AFTER |
INSTEAD OF
<trigger event> ::= INSERT | DELETE | UPDATE [
OF <trigger column list> ]
<trigger column list> ::= <column name
list>
<triggered action> ::= [ FOR EACH { ROW |
STATEMENT } ] [ <triggered when clause> ] <triggered SQL
statement>
<triggered when clause> ::= WHEN <left
paren> <search condition> <right
paren>
<triggered SQL statement> ::= <SQL procedure
statement> | BEGIN ATOMIC { <SQL procedure statement>
<semicolon> }... END | [QUEUE <integer literal>] [NOWAIT]
CALL <HSQLDB trigger class FQN>
<transition table or variable list> ::=
<transition table or variable>...
<transition table or variable> ::= OLD [ ROW ] [
AS ] <old transition variable name> | NEW [ ROW ] [ AS ] <new
transition variable name> | OLD TABLE [ AS ] <old transition table
name> | NEW TABLE [ AS ] <new transition table
name>
<old transition table name> ::= <transition
table name>
<new transition table name> ::= <transition
table name>
<transition table name> ::=
<identifier>
<old transition variable name> ::=
<correlation name>
<new transition variable name> ::=
<correlation name>
Trigger definition is a relatively complex statement. The
combination of <trigger action time> and
<trigger event> determines the type of the
trigger. Examples include BEFORE DELETE, AFTER UPDATE, INSTEAD OF
INSERT. If the optional [ OF <trigger column list>
] is specified for an UPDATE trigger, then the trigger is
activated only if one of the columns that is in the <trigger
column list> is specified in the UPDATE statement that
activates the trigger.
If a trigger is FOR EACH ROW, which is the
default option, then the trigger is activated for each row of the table
that is affected by the execution of an SQL statement. Otherwise, it is
activated once only per statement execution. In the first case, there is
a before and after state for each row. For UPDATE triggers, both before
and after states exist, representing the row before the update, and
after the update. For DELETE, triggers, there is only a before state.
For INSERT triggers, there is only an after state. If a trigger is
FOR EACH STATEMENT, then a transient table is created
containing all the rows for the before state and another transient table
is created for the after state.
The [ REFERENCING <transition table or variable>
] is used to give a name to the before and after data row or
table. This name can be referenced in the <SQL procedure
statement> to access the data.
The optional <triggered when clause>
is a search condition, similar to the search condition of a DELETE or
UPDATE statement. If the search condition is not TRUE for a row, then
the trigger is not activated for that row.
The <SQL procedure statement> is
limited to INSERT, DELETE, UPDATE and MERGE statements.
The <HSQLDB trigger class FQN> is a
delimited identifier that contains the fully qualified name of a Java
class that implements the org.hsqldb.Trigger
interface.
Early releases of HyperSQL version 2.0 do not allow the use of OLD TABLE or NEW TABLE in statement level trigger definitions.
DROP TRIGGER
drop trigger statement
<drop trigger statement> ::= DROP TRIGGER
<trigger name>
Destroy a trigger.
schema routine
SQL-invoked routine
<SQL-invoked routine> ::= <schema
routine>
<schema routine> ::= <schema procedure> |
<schema function>
<schema procedure> ::= CREATE <SQL-invoked
procedure>
<schema function> ::= CREATE <SQL-invoked
function>
<SQL-invoked procedure> ::= PROCEDURE <schema
qualified routine name> <SQL parameter declaration list>
<routine characteristics> <routine body>
<SQL-invoked function> ::= { <function
specification> | <method specification designator> }
<routine body>
<SQL parameter declaration list> ::= <left
paren> [ <SQL parameter declaration> [ { <comma> <SQL
parameter declaration> }... ] ] <right
paren>
<SQL parameter declaration> ::= [ <parameter
mode> ] [ <SQL parameter name> ] <parameter type> [
RESULT ]
<parameter mode> ::= IN | OUT |
INOUT
<parameter type> ::= <data
type>
<function specification> ::= FUNCTION <schema
qualified routine name> <SQL parameter declaration list>
<returns clause> <routine characteristics> [ <dispatch
clause> ]
<method specification designator> ::= SPECIFIC
METHOD <specific method name> | [ INSTANCE | STATIC | CONSTRUCTOR
] METHOD <method name> <SQL parameter declaration list> [
<returns clause> ] FOR <schema-resolved user-defined type
name>
<routine characteristics> ::= [ <routine
characteristic>... ]
<routine characteristic> ::= <language
clause> | <parameter style clause> | SPECIFIC <specific
name> | <deterministic characteristic> | <SQL-data access
indication> | <null-call clause> | <returned result sets
characteristic> | <savepoint level
indication>
<savepoint level indication> ::= NEW SAVEPOINT
LEVEL | OLD SAVEPOINT LEVEL
<returned result sets characteristic> ::=
DYNAMIC RESULT SETS <maximum returned result
sets>
<parameter style clause> ::= PARAMETER STYLE
<parameter style>
<dispatch clause> ::= STATIC
DISPATCH
<returns clause> ::= RETURNS <returns
type>
<returns type> ::= <returns data type> [
<result cast> ] | <returns table type>
<returns table type> ::= TABLE <table
function column list>
<table function column list> ::= <left
paren> <table function column list element> [ { <comma>
<table function column list element> }... ] <right
paren>
<table function column list element> ::=
<column name> <data type>
<result cast> ::= CAST FROM <result cast from
type>
<result cast from type> ::= <data type> [
<locator indication> ]
<returns data type> ::= <data type> [
<locator indication> ]
<routine body> ::= <SQL routine spec> |
<external body reference>
<SQL routine spec> ::= [ <rights clause> ]
<SQL routine body>
<rights clause> ::= SQL SECURITY INVOKER | SQL
SECURITY DEFINER
<SQL routine body> ::= <SQL procedure
statement>
<external body reference> ::= EXTERNAL [ NAME
<external routine name> ] [ <parameter style clause>
]
<parameter style> ::= SQL |
GENERAL
<deterministic characteristic> ::= DETERMINISTIC
| NOT DETERMINISTIC
<SQL-data access indication> ::= NO SQL |
CONTAINS SQL | READS SQL DATA | MODIFIES SQL DATA
<null-call clause> ::= RETURNS NULL ON NULL
INPUT | CALLED ON NULL INPUT
<maximum returned result sets> ::= <unsigned
integer>
Define an SQL-invoked routine. A few of the options are not used by HyperSQL and have default behaviours. See the SQL-Invoked Routines chapter for more details of various options and examples.
ALTER routine
alter routine statement
<alter routine statement> ::= ALTER <specific
routine designator> [ <alter routine characteristics> ] [
RESTRICT ] <routine body>
<alter routine characteristics> ::= <alter
routine characteristic>...
<alter routine characteristic> ::= <language
clause> | <parameter style clause> | <SQL-data access
indication> | <null-call clause> | <returned result sets
characteristic>
<alter routine body> ::= <SQL routine
body>
Alter the characteristic and the body of an SQL-invoked routine. If RESTRICT is specified and the routine is already used in a a different routine or view definition, an exception is raised. Altering the routine changes the implementation without changing the parameters. Defining recursive SQL/PSM SQL functions is only possible by altering a non-recursive routine body. An example is given in the SQL-Invoked Routines chapter.
An example is given below for a function defined as a Java method, then redefined as an SQL function.
create function zero_pad(x bigint, digits int, maxsize int)
returns char varying(100)
specific zero_pad_01
no sql deterministic
language java parameter style java
external name 'CLASSPATH:org.hsqldb.lib.StringUtil.toZeroPaddedString';
alter specific routine zero_pad_01
language sql
begin atomic
declare str varchar(128);
set str = cast(x as varchar(128));
set str = substring('0000000000000' from 1 for digits - char_length(str)) + str;
return str;
end
DROP
drop routine statement
<drop routine statement> ::= DROP <specific
routine designator> <drop behavior>
Destroy an SQL-invoked routine.
CREATE SEQUENCE
sequence generator definition
<sequence generator definition> ::= CREATE
SEQUENCE <sequence generator name> [ <sequence generator
options> ]
<sequence generator options> ::= <sequence
generator option> ...
<sequence generator option> ::= <sequence
generator data type option> | <common sequence generator
options>
<common sequence generator options> ::=
<common sequence generator option> ...
<common sequence generator option> ::=
<sequence generator start with option> | <basic sequence
generator option>
<basic sequence generator option> ::=
<sequence generator increment by option> | <sequence generator
maxvalue option> | <sequence generator minvalue option> |
<sequence generator cycle option>
<sequence generator data type option> ::= AS
<data type>
<sequence generator start with option> ::= START
WITH <sequence generator start value>
<sequence generator start value> ::= <signed
numeric literal>
<sequence generator increment by option> ::=
INCREMENT BY <sequence generator increment>
<sequence generator increment> ::= <signed
numeric literal>
<sequence generator maxvalue option> ::=
MAXVALUE <sequence generator max value> | NO
MAXVALUE
<sequence generator max value> ::= <signed
numeric literal>
<sequence generator minvalue option> ::=
MINVALUE <sequence generator min value> | NO
MINVALUE
<sequence generator min value> ::= <signed
numeric literal>
<sequence generator cycle option> ::= CYCLE | NO
CYCLE
Define a named sequence generator. A SEQUENCE object generates
a sequence of integers according to the specified rules. The simple
definition without the options defines a sequence of numbers in INTEGER
type starting at 1 and incrementing by 1. By default the
CYCLE property is set and the minimum and maximum
limits are the minimum and maximum limits of the type of returned
values. There are self-explanatory options for changing various
properties of the sequence. The MAXVALUE and
MINVALUE specify the upper and lower limits. If
CYCLE is specified, after the sequence returns the
highest or lowest value in range, the next value will respectively be
the lowest or highest value in range. If NO CYCLE is
specified, the use of the sequence generator results in an error once
the limit has been reached.
The integer types: SMALLINT, INTEGER, BIGINT, DECIMAL and NUMERIC can be used as the type of the sequence. DECIMAL and NUMERIC types must have a scale of 0 and a precision not exceeding 18.
ALTER SEQUENCE
alter sequence generator statement
<alter sequence generator statement> ::= ALTER
SEQUENCE <sequence generator name> <alter sequence generator
options>
<alter sequence generator options> ::= <alter
sequence generator option>...
<alter sequence generator option> ::= <alter
sequence generator restart option> | <basic sequence generator
option>
<alter sequence generator restart option> ::=
RESTART [ WITH <sequence generator restart value>
]
<sequence generator restart value> ::=
<signed numeric literal>
Change the definition of a named sequence generator. The same
options that are used in the definition of the SEQUENCE can be used to
alter it. The exception is the option for the start value which is
RESTART WITH for the ALTER SEQUENCE
statement.
If RESTART is used by itself (without a value), then the current value of the sequence is reset to the start value. Otherwise, the current value is reset to the given restart value.
DROP SEQUENCE
drop sequence generator statement
<drop sequence generator statement> ::= DROP
SEQUENCE [ IF EXISTS ] <sequence generator name> [ IF EXISTS ]
<drop behavior>
Destroy an external sequence generator. If the
<drop behavior> is CASCADE,
then all objects that reference the sequence are dropped. These objects
can be VIEW, ROUTINE or TRIGGER objects.
SQL procedure statement
SQL procedure statement
The definition of CREATE TRIGGER and CREATE PROCEDURE statements refers to <SQL procedure statement>. The definition of this element is given below. However, only a subset of these statements are allowed in trigger or routine definition.
<SQL procedure statement> ::= <SQL executable
statement>
<SQL executable statement> ::= <SQL schema
statement> | <SQL data statement> | <SQL control
statement> | <SQL transaction statement> | <SQL connection
statement> | <SQL session statement> | <SQL diagnostics
statement> | <SQL dynamic statement>
<SQL schema statement> ::= <SQL schema
definition statement> | <SQL schema manipulation
statement>
<SQL schema definition statement> ::= <schema
definition> | <table definition> | <view definition> |
<SQL-invoked routine> | <grant statement> | <role
definition> | <domain definition> | <character set
definition> | <collation definition> | <transliteration
definition> | <assertion definition> | <trigger
definition> | <user-defined type definition> | <user-defined
cast definition> | <user-defined ordering definition> |
<transform definition> | <sequence generator
definition>
<SQL schema manipulation statement> ::= <drop
schema statement> | <alter table statement> | <drop table
statement> | <drop view statement> | <alter routine
statement> | <drop routine statement> | <drop user-defined
cast statement> | <revoke statement> | <drop role
statement> | <alter domain statement> | <drop domain
statement> | <drop character set statement> | <drop
collation statement> | <drop transliteration statement> |
<drop assertion statement> | <drop trigger statement> |
<alter type statement> | <drop data type statement> |
<alter sequence generator statement> | <drop sequence generator
statement>
CREATE INDEX
create index statement
<create index statement> ::= CREATE INDEX
<index name> ON <table name> <left paren> {<column
name> [ASC | DESC]}, ... <right paren>
Creates an index on a group of columns of a table. The optional [ASC | DESC] specifies if the column is indexed in the ascending or descending order, but has no effect on how the index is created (it is allowed for compatibility with other database engines). HyperSQL can use all indexes in ascending or descending order as needed. Indexes should not duplicate the columns of PRIMARY KEY, UNIQUE or FOREIGN key constraints as each of these constraints creates an index automatically.
DROP INDEX
drop index statement
<drop index statement> ::= DROP INDEX [ IF
EXISTS ] <index name> [ IF EXISTS ]
Destroy an index.
ALTER INDEX
change the columns of an index
<alter index statement> ::= ALTER INDEX
<index name> <left paren> {<column name>} , ...
<right paren>
Redefine an index with a new column list. This statement is more efficient than dropping an existing index and creating a new one.
CREATE TYPE
user-defined type definition
<user-defined type definition> ::= CREATE TYPE
<user-defined type body>
<user-defined type body> ::= <schema-resolved
user-defined type name> [ AS <representation>
]
<representation> ::= <predefined
type>
Define a user-defined type. Currently only simple distinct types can be defined without further attributes.
CREATE CAST
user-defined cast definition
<user-defined cast definition> ::= CREATE CAST
<left paren> <source data type> AS <target data type>
<right paren> WITH <cast function> [ AS ASSIGNMENT
]
<cast function> ::= <specific routine
designator>
<source data type> ::= <data
type>
<target data type> ::= <data
type>
Define a user-defined cast. This feature may be supported in a future versions of HyperSQL.
DROP CAST
drop user-defined cast statement
<drop user-defined cast statement> ::= DROP CAST
<left paren> <source data type> AS <target data type>
<right paren> <drop behavior>
Destroy a user-defined cast. This feature may be supported in a future versions of HyperSQL.
CREATE CHARACTER SET
character set definition
<character set definition> ::= CREATE CHARACTER
SET <character set name> [ AS ] <character set source> [
<collate clause> ]
<character set source> ::= GET <character set
specification>
Define a character set. A new CHARACTER SET is based on an
existing CHARACTER SET. The optional <collate
clause> specifies the collation to be used, otherwise the
collation is inherited from the default collation for the source
CHARACTER SET.
DROP CHARACTER SET
drop character set statement
<drop character set statement> ::= DROP
CHARACTER SET <character set name>
Destroy a character set. If the character set name is
referenced in any database object, the command fails. Note that
CASCADE or RESTRICT cannot be
specified for this command.
CREATE COLLATION
collation definition
<collation definition> ::= CREATE COLLATION
<collation name> FOR <character set specification> FROM
<existing collation name> [ <pad characteristic>
]
<existing collation name> ::= <collation
name>
<pad characteristic> ::= NO PAD | PAD
SPACE
Define a collation. A new collation is based on an existing
COLLATION and applies to an existing CHARACTER SET. The <pad
characteristic> specifies whether strings are padded with
spaces for comparison. In HyperSQL 2.1 the padding information is
ignored, but it may be supported in future versions.
DROP COLLATION
drop collation statement
<drop collation statement> ::= DROP COLLATION
<collation name> <drop behavior>
Destroy a collation. If the <drop
behavior> is CASCADE, then all
references to the collation revert to the default collation that would
be in force if the dropped collation was not specified.
CREATE TRANSLATION
transliteration definition
<transliteration definition> ::= CREATE
TRANSLATION <transliteration name> FOR <source character set
specification> TO <target character set specification> FROM
<transliteration source>
<source character set specification> ::=
<character set specification>
<target character set specification> ::=
<character set specification>
<transliteration source> ::= <existing
transliteration name> | <transliteration
routine>
<existing transliteration name> ::=
<transliteration name>
<transliteration routine> ::= <specific
routine designator>
Define a character transliteration. This feature may be supported in a future versions of HyperSQL.
DROP TRANSLATION
drop transliteration statement
<drop transliteration statement> ::= DROP
TRANSLATION <transliteration name>
Destroy a character transliteration. This feature may be supported in a future versions of HyperSQL.
CREATE ASSERTION
assertion definition
<assertion definition> ::= CREATE ASSERTION
<constraint name> CHECK <left paren> <search
condition> <right paren> [ <constraint characteristics>
]
Specify an integrity constraint. This feature may be supported in a future versions of HyperSQL.
DROP ASSERTION
drop assertion statement
<drop assertion statement> ::= DROP ASSERTION
<constraint name> [ <drop behavior> ]
Destroy an assertion. This feature may be supported in a future versions of HyperSQL.
The Information Schema is a special schema in each catalog. The SQL Standard defines a number of character sets and domains in this schema. In addition, all the implementation-defined collations belong to the Information Schema.
The SQL Standard defines many views in the Information Schema. These views show the properties of the database objects that currently exist in the database. When a user accesses one these views, only the properties of database objects that the user can access are included.
HyperSQL supports all the views defined by the Standard, apart from a few views that report on extended user-defined types and other optional features of the Standard that are not supported by HyperSQL.
HyperSQL also adds some views to the Information Schema. These views are for features that are not reported in any of the views defined by the Standard, or for use by JDBC DatabaseMetaData.
The SQL Standard defines a number of character sets and domains in the INFORMATION SCHEMA.
These domains are used in the INFORMATION SCHEMA views:
CARDINAL_NUMBER, YES_OR_NO, CHARACTER_DATA, SQL_IDENTIFIER, TIME_STAMP
All available collations are in the INFORMATION SCHEMA.
HyperSQL supports a vast range of views in the INFORMATION_SCHEMA. These include views specified by the SQL Standard, SQL/Schemata part, plus views that are specific to HyperSQL and are used for JDBC DatabaseMetaData queries, which are based on SQL/CLI part, or other information that is not covered by the SQL Standard. The names of views that are not part of SQL/Schemata start with SYSTEM_.
The views cover different types of information. These are covered in the next sections.
Users with the special ADMIN role can see the full information on all database objects. Ordinary, non-admin users can see information on the objects for which they have some privileges.
The rows returned to a non-admin user exclude objects on which the user has no privilege. The extent of the information in visible rows varies with the user's privilege. For example, the owner of a VIEW can see the text of the view query, but a user of the view cannot see this text. When a user cannot see the contents of some column, null is returned for that column.
The names of database objects are stored in hierarchical views. The top level view is INFORMATION_SCHEMA_CATALOG_NAME.
Below this level, there is a group of views that covers authorizations and roles, without referencing schema objects. These are AUTHORIZATIONS and ADMINSTRABLE_ROLE_AUTHORIZATIONS.
Also below the top level, there is the SCHEMATA view, which lists the schemas in the catalog.
The views that refer to top-level schema objects are divided by object type. These includes ASSERTIONS, CHARACTER_SETS, COLLATIONS, DOMAINS, ROUTINES, SEQUENCES, TABLES, USER_DEFINED_TYPES and VIEWS.
There are views that refer to objects that are dependent on the top-level schema objects. These include COLUMNS and PARAMETERS, views for constraints, including CHECK_CONSTRAINTS, REFERENTIAL_CONSTRAINTS and TABLE_CONSTRAINTS, and finally the TRIGGERS view.
The usage of each type of top-level object by another is covered by several views. For example TRIGGER_SEQUENCE_USAGE or ROUTINE_TABLE_USAGE.
Several other views list the individual privileges owned or granted to each AUTHORIZATION. For example ROLE_ROUTINE_GRANTS or TABLE_PRIVILEGES.
The INFORMATION_SCHEMA contains comprehensive information on the data types of each schema object and its elements. For example, the ROUTINES view includes the return data type for each FUNCTION definition. The columns for this information contain nulls for rows that cover PROCEDURE definitions.
The COLUMNS, PARAMETERS and SEQUENCES views contain the type information in columns with similar names.
The type information for ARRAY types is returned in the ELEMENT_TYPES view. When a row of the COLUMNS or other view indicates that the type of the object is an ARRAY type, then there is a corresponding entry for this row in the ELEMENT_TYPES view. The following columns in the ELEMENTS_TYPES view identify the database object whose data type is being described: OBJECT_CATALOG, OBJECT_SCHEMA, OBJECT_NAME, OBJECT_TYPE, COLLECTION_TYPE_IDENTIFIER. The last column's counterpart in the COLUMNS view is named differently as DTD_IDENTIFIER. So in order to determine the array element type of a column, an equi-join between the COLUMNS and ELEMENT_TYPES tables on the six listed columns in the ELEMENT_TYPES view and their counterparts in the COLUMNS view is needed.
A group of views, including SQL_IMPLEMENTATION_INFO, SQL_FEATURES, SQL_SIZING and others cover the capabilities of HyperSQL in detail. These views hold static data and can be explored even when the database is empty.
There are some HyperSQL custom views cover the current state of operation of the database. These include SYSTEM_CACHEINFO, SYSTEM_SESSIONINFO and SYSTEM_SESSIONS views.
The following views are defined by the SQL Standard and supported by HyperSQL. The columns and contents exactly match the Standard requirements.
ADMINISTRABLE_ROLE_AUTHORIZATIONS
Information on ROLE authorizations, all granted by the admin role.
APPLICABLE_ROLES
Information on ROLE authorizations for the current user
ASSERTIONS
Empty view as ASSERTION objects are not yet supported.
AUTHORIZATIONS
Top level information on USER and ROLE objects in the database
CHARACTER_SETS
List of supported CHARACTER SET objects
CHECK_CONSTRAINTS
Additional information specific to each CHECK constraint, including the search condition
CHECK_CONSTRAINT_ROUTINE_USAGE
Information on FUNCTION objects referenced in CHECK constraints search conditions
COLLATIONS
Information on collations supported by the database.
COLUMNS
Information on COLUMN objects in TABLE and VIEW definitions
COLUMN_COLUMN_USAGE
Information on references to COLUMN objects from other, GENERATED, COLUMN objects
COLUMN_DOMAIN_USAGE
Information on DOMAIN objects used in type definition of COLUMN objects
COLUMN_PRIVILEGES
Information on privileges on each COLUMN object, granted to different ROLE and USER authorizations
COLUMN_UDT_USAGE
Information on distinct TYPE objects used in type definition of COLUMN objects
CONSTRAINT_COLUMN_USAGE
Information on COLUMN objects referenced by CONSTRAINT objects in the database
CONSTRAINT_TABLE_USAGE
Information on TABLE and VIEW objects referenced by CONSTRAINT objects in the database
DATA_TYPE_PRIVILEGES
Information on top level schema objects of various kinds that reference TYPE objects
DOMAINS
Top level information on DOMAIN objects in the database.
DOMAIN_CONSTRAINTS
Information on CONSTRAINT definitions used for DOMAIN objects
ELEMENT_TYPES
Information on the type of elements of ARRAY used in database columns or routine parameters and return values
ENABLED_ROLES
Information on ROLE privileges enabled for the current session
INFORMATION_SCHEMA_CATALOG_NAME
Information on the single CATALOG object of the database
KEY_COLUMN_USAGE
Information on COLUMN objects of tables that are used by PRIMARY KEY, UNIQUE and FOREIGN KEY constraints
PARAMETERS
Information on parameters of each FUNCTION or PROCEDURE
REFERENTIAL_CONSTRAINTS
Additional information on FOREIGN KEY constraints, including triggered action and name of UNIQUE constraint they refer to
ROLE_AUTHORIZATION_DESCRIPTORS
ROLE_COLUMN_GRANTS
Information on privileges on COLUMN objects granted to or by the current session roles
ROLE_ROUTINE_GRANTS
Information on privileges on FUNCTION and PROCEDURE objects granted to or by the current session roles
ROLE_TABLE_GRANTS
Information on privileges on TABLE and VIEW objects granted to or by the current session roles
ROLE_UDT_GRANTS
Information on privileges on TYPE objects granted to or by the current session roles
ROLE_USAGE_GRANTS
Information on privileges on USAGE privileges granted to or by the current session roles
ROUTINE_COLUMN_USAGE
Information on COLUMN objects of different tables that are referenced in FUNCTION and PROCEDURE definitions
ROUTINE_JAR_USAGE
Information on JAR usage by Java language FUNCTION and PROCEDURE objects.
ROUTINE_PRIVILEGES
Information on EXECUTE privileges granted on PROCEDURE and FUNCTION objects
ROUTINE_ROUTINE_USAGE
Information on PROCEDURE and FUNCTION objects that are referenced in FUNCTION and PROCEDURE definitions
ROUTINE_SEQUENCE_USAGE
Information on SEQUENCE objects that are referenced in FUNCTION and PROCEDURE definitions
ROUTINE_TABLE_USAGE
Information on TABLE and VIEW objects that are referenced in FUNCTION and PROCEDURE definitions
ROUTINES
Top level information on all PROCEDURE and FUNCTION objects in the database
SCHEMATA
Information on all the SCHEMA objects in the database
SEQUENCES
Information on SEQUENCE objects
SQL_FEATURES
List of all SQL:2008 standard features, including information on whether they are supported or not supported by HyperSQL
SQL_IMPLEMENTATION_INFO
Information on name, capabilities and defaults of the database engine software.
SQL_PACKAGES
List of the SQL:2008 Standard packages, including information on whether they are supported or not supported by HyperSQL
SQL_PARTS
List of the SQL:2008 Standard parts, including information on whether they are supported or not supported by HyperSQL
SQL_SIZING
List of the SQL:2008 Standard maximum supported sizes for different features as supported by HyperSQL
SQL_SIZING_PROFILES
TABLES
Information on all TABLE and VIEW object, including the INFORMATION_SCHEMA views themselves
TABLE_CONSTRAINTS
Information on all table level constraints, including PRIMARY KEY, UNIQUE, FOREIGN KEY and CHECK constraints
TABLE_PRIVILEGES
Information on privileges on TABLE and VIEW objects owned or given to the current user
TRANSLATIONS
TRIGGERED_UPDATE_COLUMNS
Information on columns that have been used in TRIGGER definitions in the ON UPDATE clause
TRIGGERS
Top level information on the TRIGGER definitions in the databases
TRIGGER_COLUMN_USAGE
Information on COLUMN objects that have been referenced in the body of TRIGGER definitions
TRIGGER_ROUTINE_USAGE
Information on FUNCTION and PROCEDURE objects that have been used in TRIGGER definitions
TRIGGER_SEQUENCE_USAGE
Information on SEQUENCE objects that been referenced in TRIGGER definitions
TRIGGER_TABLE_USAGE
Information on TABLE and VIEW objects that have been referenced in TRIGGER definitions
USAGE_PRIVILEGES
Information on USAGE privileges granted to or owned by the current user
USER_DEFINED_TYPES
Top level information on TYPE objects in the database
VIEWS
Top Level information on VIEW objects in the database
VIEW_COLUMN_USAGE
Information on COLUMN objects referenced in the query expressions of the VIEW objects
VIEW_ROUTINE_USAGE
Information on FUNCTION and PROCEDURE objects that have been used in the query expressions of the VIEW objects
VIEW_TABLE_USAGE
Information on TABLE and VIEW objects that have been referenced in the query expressions of the VIEW objects
The following views are specific to HyperSQL. Most of these views are used directly by JDBC DatabaseMetaData method calls and are indicated as such. Some views contain information that is specific to HyperSQL and is not covered by the SQL Standard views.
SYSTEM_BESTROWIDENTIFIER
For DatabaseMetaData.getBestRowIdentifier
SYSTEM_CACHEINFO
Contains the current settings and variables of the data cache used for all CACHED tables, and the data cache of each TEXT table.
SYSTEM_COLUMN_SEQUENCE_USAGE
Contains a row for each column that is defined as GENERATED BY DEFAULT AS SEQUENCE with the column name and sequence name
SYSTEM_COLUMNS
For DatabaseMetaData.getColumns, contains a row for each column
SYSTEM_COMMENTS
Contains the user-defined comments added to tables and their columns.
SYSTEM_CONNECTION_PROPERTIES
For DatabaseMetaData.getClientInfoProperties
SYSTEM_CROSSREFERENCE
Full list of all columns referenced by FOREIGN KEY constraints. For DatabaseMetaData.getCrossReference, getExportedKeys and getImportedKeys.
SYSTEM_INDEXINFO
For DatabaseMetaData.getIndexInfo
SYSTEM_PRIMARYKEYS
For DatabaseMetaData.getPrimaryKeys
SYSTEM_PROCEDURECOLUMNS
For DatabaseMetaData.getProcedureColumns
SYSTEM_PROCEDURES
For DatabaseMetaData.getFunctionColumns, getFunctions and getProcedures
SYSTEM_PROPERTIES
Contains the current values of all the database level properties. Settings such as SQL rule enforcement, database transaction model and default transaction level are all reported in this view. The names of the properties are listed in the Properties chapter together with the corresponding SQL statements used to change the properties.
SYSTEM_SCHEMAS
For DatabaseMetaData.getSchemas
SYSTEM_SEQUENCES
SYSTEM_SESSIONINFO
Information on the settings and properties of the current session.
SYSTEM_SESSIONS
Information on all open sessions in the database (when used by a DBA user), or just the current session.
SYSTEM_TABLES
Information on tables and views for DatabaseMetaData.getTables
SYSTEM_TABLETYPES
For DatabaseMetaData.getTableTypes
SYSTEM_TEXTTABLES
Information on the settings of each text table.
SYSTEM_TYPEINFO
For DatabaseMetaData.getTypeInfo
SYSTEM_UDTS
For DatabaseMetaData.getUDTs
SYSTEM_USERS
Contains the list of all users in the database (when used by a DBA user), or just the current user.
SYSTEM_VERSIONCOLUMNS
For DatabaseMetaData.getVersionColumns
$Revision: 4903 $
Copyright 2002-2012 Bob Preston and Fred Toussi. Permission is granted to distribute this document without any alteration under the terms of the HSQLDB license. Additional permission is granted to the HSQL Development Group to distribute this document with or without alterations under the terms of the HSQLDB license.
2012-01-22 11:31:28-0500
Table of Contents
Text Table support for HSQLDB was originally developed by Bob Preston independently from the Project. Subsequently Bob joined the Project and incorporated this feature into version 1.7.0, with a number of enhancements, especially the use of conventional SQL commands for specifying the files used for Text Tables.
In a nutshell, Text Tables are CSV or other delimited files treated as SQL tables. Any ordinary CSV or other delimited file can be used. The full range of SQL queries can be performed on these files, including SELECT, INSERT, UPDATE and DELETE. Indexes and unique constraints can be set up, and foreign key constraints can be used to enforce referential integrity between Text Tables themselves or with conventional tables.
The delimited file can be created by the engine, or an existing file can be used.
HyperSQL with Text Table support is the only comprehensive solution that employs the power of SQL and the universal reach of JDBC to handle data stored in text files.
Text Tables are defined similarly to conventional tables with the added TEXT keyword:
CREATE TEXT TABLE <tablename> (<column definition> [<constraint definition>])
The table is at first empty and cannot be written to. An additional SET command specifies the file and the separator character that the Text table uses:
SET TABLE <tablename> SOURCE <quoted_filename_and_options> [DESC]
A Text table without a file assigned to it is READ ONLY and EMPTY.
Reassigning a Text Table definition to a new file has implications in the following areas:
The user is required to be an administrator.
Existing transactions are committed at this point.
Constraints, including foreign keys referencing this table, are kept intact. It is the responsibility of the administrator to ensure their integrity.
The new source file is scanned and indexes are built when it is assigned to the table. At this point any violation of NOT NULL, UNIQUE or PRIMARY KEY constraints are caught and the assignment is aborted. However, foreign key constraints are not checked at the time of assignment or reassignment of the source file.
Empty fields are treated as NULL. These are fields where there is nothing or just spaces between the separators.
Quoted empty strings are treated as empty strings.
The default field separator is a comma (,). A different field separator can be specified within the SET TABLE SOURCE statement. For example, to change the field separator for the table mytable to a vertical bar, place the following in the SET TABLE SOURCE statement, for example:
SET TABLE mytable SOURCE "myfile;fs=|"
Since HSQLDB treats CHAR and VARCHAR strings the same, the ability to assign a different separator to the latter is provided. When a different separator is assigned to a VARCHAR, it will terminate any CSV field of that type. For example, if the first field is CHAR, and the second field VARCHAR, and the separator fs has been defined as the pipe (|) and vs as the period (.) then the data in the CSV file for a row will look like:
First field data|Second field data.Third field data
This facility in effect offers an extra, special separator which can be used in addition to the global separator. The following example shows how to change the default separator to the pipe (|), VARCHAR separator to the period (.) within a SET TABLE SOURCE statement:
SET TABLE mytable SOURCE "myfile;fs=|;vs=."
HSQLDB also recognises the following special indicators for separators:
special indicators for separators
|
\semi |
semicolon |
|
\quote |
single-quote |
|
\space |
space character |
|
\apos |
apostrophe |
|
\n |
newline - Used as an end anchor (like $ in regular expressions) |
|
\r |
carriage return |
|
\t |
tab |
|
\\ |
backslash |
|
\u#### |
a Unicode character specified in hexadecimal |
Furthermore, HSQLDB provides csv file support with three
additional boolean options: ignore_first,
quoted and all_quoted. The
ignore_first option (default false) tells HSQLDB to
ignore the first line in a file. This option is used when the first line
of the file contains column headings. The all_quoted
option (default false) tells the program that it should use quotes
around all character fields when writing to the source file. The
quoted option (default true) uses quotes only when
necessary to distinguish a field that contains the separator character.
It can be set to false to prevent the use of quoting altogether and
treat quote characters as normal characters. These options may be
specified within the SET TABLE SOURCE
statement:
SET TABLE mytable SOURCE "myfile;ignore_first=true;all_quoted=true"
When the default options all_quoted=
false and quoted=true are in
force, fields that are written to a line of the csv file will be quoted
only if they contain the separator or the quote character. The quote
character is doubled when used inside a string. When
all_quoted=false and quoted=false
the quote character is not doubled. With this option, it is not possible
to insert any string containing the separator into the table, as it
would become impossible to distinguish from a separator. While reading
an existing data source file, the program treats each individual field
separately. It determines that a field is quoted only if the first
character is the quote character. It interprets the rest of the field on
this basis.
The character encoding for the source file is ASCII
by default. To support UNICODE or source files prepared with
different encodings this can be changed to UTF-8 or
any other encoding. The default is encoding=ASCII and
the option encoding=UTF-8 or other supported
encodings can be used.
Finally, HSQLDB provides the ability to read a text file as READ ONLY, by placing the keyword "DESC" at the end of the SET TABLE SOURCE statement:
SET TABLE mytable SOURCE "myfile" DESC
Text table source files are cached in memory. The maximum number
of rows of data that are in memory at any time is controlled by the
cache_rows property. The default value for
cache_rows is 1000 and can be changed by setting the
default database property .The cache_size property
sets the maximum amount of memory used for each text table. The default
is 100 KB. The properties can be set for individual text tables. These
properties do not control the maximum size of each text table, which can
be much larger. An example is given below:
SET TABLE mytable SOURCE "myfile;ignore_first=true;all_quoted=true;cache_rows=10000;cache_size=1000"
The properties used in earlier versions, namely the
textdb.cache_scale and the
textdb.cache_size_scale can still be used.
Text tables may be disconnected from their underlying data source, i.e. the text file.
You can explicitly disconnect a text table from its file by issuing the following statement:
SET TABLE mytable SOURCE OFF
Subsequently, mytable will be empty and
read-only. However, the data source description will be preserved, and
the table can be re-connected to it with
SET TABLE mytable SOURCE ON
When a database is opened, if the source file for an existing text table is missing the table remains disconnected from its data source, but the source description is preserved. This allows the missing source file to be added to the directory and the table re-connected to it with the above command.
Disconnecting text tables from their source has several uses. While disconnected, the text source can be edited outside HSQLDB provided data integrity is respected. When large text sources are used, and several constraints or indexes need to be created on the table, it is possible to disconnect the source during the creation of constraints and indexes and reduce the time it takes to perform the operation.
The following information applies to the usage of text tables.
Text File Issues
File locations are restricted to below the directory that
contains the database, unless the
textdb.allow_full_path property is set true as a
Java system property. This feature is for security, otherwise an admin
database user may be able to open random files. The specified text
source path is interpreted differently according to this property. By
default, the path is interpreted as a relative path to the directory
path of database files, it therefore cannot contain the double dot
notation for parent directory. This path is then appended by the
engine to the directory path to form a full path. When the property is
true, the path is not appended to the directory path and is used as it
is to open the file. In this usage the path can be relative or
absolute.
All-in-memory databases can use text tables. In this usage, the
path must be an absolute path. These text tables are always read only.
To disable this capability for access control reasons, the
textdb.allow_full_path property can be set false as
a Java system property.
Blank lines are allowed anywhere in the text file, and are ignored.
It is possible to define a primary key, identity column, unique, foreign key and check constraints for text tables.
When a table source file is used with the
ignore_first=true option, the first, ignored line is
replaced with a blank line after a SHUTDOWN COMPACT, unless the SOURCE
HEADER statement has been used.
An existing table source file may include CHARACTER fields that do not begin with the quote character but contain instances of the quote character. These fields are read as literal strings. Alternatively, if any field begins with the quote character, then it is interpreted as a quoted string that should end with the quote character and any instances of the quote character within the string is doubled. When any field containing the quote character or the separator is written out to the source file by the program, the field is enclosed in quote character and any instance of the quote character inside the field is doubled.
Inserts or updates of CHARACTER type field values are allowed with strings that contains the linefeed or the carriage return character. This feature is disabled when both quoted and all_quoted properties are false.
ALTER TABLE commands that add or drop columns or constraints (apart from check constraints) are not supported with text tables that are connected to a source. First use the SET TABLE <name> SOURCE OFF, make the changes, then turn the source ON.
The database engine uses a set of defaults for text table properties. Each table's data source may override these defaults. It is also possible to override the defaults globally, so they apply to all text tables. The statement SET DATABASE TEXT TABLE DEFAULTS <properties string> can be used to override the default global properties. An example is given below:
SET DATABASE TEXT TABLE DEFAULTS 'all_quoted=true;encoding=UTF-8;cache_rows=10000;cache_size=2000'
List of supported global properties
fs=,
vs=,
quoted=false
all_quoted=false
ignore_first=false
encoding=ASCII
cache_rows=1000
cache_size=100
textdb.allow_full_path=false (a system
property)
Text tables fully support transactions. New or changed rows that have not been committed are not updated in the source file. Therefore the source file always contains committed rows.
However, text tables are not as resilient to machine crashes as other types of tables. If the crash happens while the text source is being written to, the text source may contain only some of the changes made during a committed transaction. With other types of tables, additional mechanisms ensure the integrity of the data and this situation will not arise.
$Revision: 3096 $
Copyright 2010-2012 Fred Toussi. Permission is granted to distribute this document without any alteration under the terms of the HSQLDB license. Additional permission is granted to the HSQL Development Group to distribute this document with or without alterations under the terms of the HSQLDB license.
2012-01-22 11:31:28-0500
Table of Contents
This chapter is about access control to database objects such as tables, inside the database engine. Other issues related to security include user authentication, password complexity and secure connections are covered in the System Management chapter and the HyperSQL Network Listeners (Servers) chapter.
Apart from schemas and their object, each HyperSQL catalog has USER and ROLE objects. These objects are collectively called authorizations. Each AUTHORIZATION has some access rights on some of the schemas or the objects they contain. The persistent elements of an SQL environment are database objects
Each database object has a name. A name is an identifier and is unique within its name-space. Authorizations names follow the rules described below and the case-normal form is stored in the database. When connecting to a database, the user name and password must match the case of the case-normal form.
identifier
definition of identifier
<identifier> ::= <regular identifier> |
<delimited identifier> | <SQL language identifier>
<delimited identifier> ::= <double quote>
<character sequence> <double quote>
<regular identifier> ::= <special character
sequence>
<SQL language identifier> ::= <special
character sequence>
A <delimited identifier> is a sequence
of characters enclosed with double-quote symbols. All characters are
allowed in the character sequence.
A <regular identifier> is a special
sequence of characters. It consists of letters, digits and the underscore
characters. It must begin with a letter.
A <SQL language identifier> is similar
to <regular identifier> but the letters can range
only from A-Z in the ASCII character set. This type of identifier is used
for names of CHARACTER SET objects.
If the character sequence of a delimited identifier is the same
as an undelimited identifier, it represents the same identifier. For
example "JOHN" is the same identifier as JOHN. In a <regular
identifier> the case-normal form is considered for
comparison. This form consists of the upper-case of equivalent of all the
letters.
The character sequence length of all identifiers must be between 1 and 128 characters.
A reserved word is one that is used by the SQL Standard for
special purposes. It is similar to a <regular
identifier> but it cannot be used as an identifier for user
objects. If a reserved word is enclosed in double quote characters, it
becomes a quoted identifier and can be used for database
objects.
In general, ROLE and USER objects simply control access to schema objects. This is the scope of the SQL Standard. However, there are special roles that allow the creation of USER and ROLE objects and also allow some special operations on the database as a whole. These roles are not defined by the Standard, which has left it to implementers to define such roles as they are needed for the particular SQL implementation.
A ROLE has a name a collection of zero or more other roles, plus some privileges (access rights). A USER has a name and a password. It similarly has a collection of zero or more roles plus some privileges.
USER objects existed in the SQL-92, but ROLE objects were introduced in SQL:1999. Originally it was intended that USER objects would normally be the same as the operating system USER objects and their authentication would be handled outside the SQL environment. The co-existence of ROLE and USER objects results in complexity. With the addition of ROLE objects, there is no rationale, other than legacy support, for granting privileges to USER objects directly. It is better to create roles and grant privileges to them, then grant the roles to USER objects.
The Standard effectively defines a special ROLE, named PUBLIC. All authorization have the PUBLIC role, which cannot be removed from them. Therefore any access right assigned to the PUBLIC role applies to all authorizations in the database. For many simple databases, it is adequate to create a single, non-admin user, then assign access rights to the pre-existing PUBLIC role. Access to INFORMATION_SCHEMA views is granted to PUBLIC, therefore these views are accessible to all. However, the contents of each view depends on the ROLE or USER (AUTHORIZATION) that is in force while accessing the view.
Each schema has a single AUTHORIZATION. This is commonly known as the owner of the schema. All the objects in the schema inherit the schema owner. The schema owner can add objects to the schema, drop them or alter them.
By default, the objects in a schema can only be accessed by the schema owner. The schema owner can grant access rights on the objects to other users or roles.
authorization identifier
authorization identifier
<authorization identifier> ::= <role name> |
<user name>
Authorization identifiers share the same name-space within the database. The same name cannot be used for a USER and a ROLE.
There are some pre-defined roles in each database; some defined by the SQL Standard, some by HyperSQL. These roles can be assigned to users (directly or via other, user-defined roles). In addition, there is the default initial user, SA, created with each new database.
PUBLIC
the PUBLIC role
The role that is assigned to all authorizations (roles and users) in the database. This role has access rights to all objects in the INFORMATION_SCHEMA. Any roles or rights granted to this role, are in effect granted to all users of the database.
_SYSTEM
the _SYSTEM role
This role is the authorization for the pre-defined (system) objects in the database, including the INFORMATION_SCHEMA. This role cannot be assigned to any authorization.
DBA
the DBA role (HyperSQL-specific)
This is a special role in HyperSQL. A user that has this role can perform all possible administrative tasks on the database. The DBA role can also act as a proxy for all the roles and users in the database. This means it can do everything the authorization for a schema can do, including dropping the schema or its objects, or granting rights on the schema objects to a grantee.
CREATE_SCHEMA
the CREATE_SCHEMA role (HyperSQL-specific)
An authorization that has this role, can create schemas. The DBA authorization has this role and can grant it to other authorizations.
CHANGE_AUTHORIZATION
the CHANGE_AUTHORIZATION role (HyperSQL-specific)
A user that has this role, can change the authorization for the current session to another user. The other user cannot have the DBA role (otherwise, the original user would gain DBA privileges). The DBA authorization has this role and can grant it to other authorizations.
SA
the SA user (HyperSQL-specific)
This user is automatically created with a new database and has the DBA role. Initially, the password for this user is an empty string. After connecting to the new database as this user, it is possible to change the password, create other users and created new schema objects. The SA user can be dropped by another user that has the DBA role.
By default, the objects in a schema can only be accessed by the schema owner. But the schema owner can grant privileges (access rights) on the objects to other users or roles.
Things can get far more complex, because the grant of privileges can be made WITH GRANT OPTION. In this case, the role or user that has been granted the privilege can grant the privilege to other roles and users.
Privileges can also be revoked from users or roles.
The statements for granting and revoking privileges normally
specify which privileges are granted or revoked. However, there is a
shortcut, ALL PRIVILEGES, which means all the privileges that the
<grantor> has on the schema object. The
<grantor> is normally the CURRENT_USER of the
session that issues the statement.
The user or role that is granted privileges is referred to as
<grantee> for the granted privileges.
Table
For tables, including views, privileges can be granted with different degrees of granularity. It is possible to grant a privilege on all columns of a table, or on specific columns of the table.
The DELETE privilege applies to the table, rather than its columns. It applies to all DELETE statements.
The SELECT, INSERT and UPDATE privileges may apply to all
columns or to individual columns. These privileges determine whether the
<grantee> can execute SQL data statements on
the table.
The SELECT privilege designates the columns that can be referenced in SELECT statements, as well as the columns that are read in a DELETE or UPDATE statement, including the search condition.
The INSERT privilege designates the columns into which explicit values can be inserted. To be able to insert a row into the table, the user must therefore have the INSERT privilege on the table, or at least all the columns that do not have a default value.
The UPDATE privilege simply designates the table or the specific columns that can be updated.
The REFERENCES privilege allows the
<grantee> to define a FOREIGN KEY constraint on
a different table, which references the table or the specific columns
designated for the REFERENCES privilege.
The TRIGGER privilege allows adding a trigger to the table.
Sequence, Type, Domain, Character Set, Collation, Transliteration,
For these objects, only USAGE can be granted. The USAGE privilege is needed when object is referenced directly in an SQL statement.
Routine
For routines, including procedures or functions, only EXECUTE privilege can be granted. This privilege is needed when the routine is used directly in an SQL statement.
Other Objects
Other objects such as constraints and assertions are not used directly and there is no grantable privilege that refers to them.
The statements listed below allow creation and destruction of USER and ROLE objects. The GRANT and REVOKE statements allow roles to be assigned to other roles or to users. The same statements are also used in a different form to assign privileges on schema objects to users and roles.
user definition (HyperSQL)
<user definition> ::= CREATE USER <user
name> PASSWORD <password> [ ADMIN ]
Define a new user and its password. <user
name> is an SQL identifier. If it is double-quoted it is
case-sensitive, otherwise it is turned to uppercase.
<password> is a string enclosed with single quote
characters and is case-sensitive. If ADMIN is
specified, the DBA role is granted to the new user. Only a user with the
DBA role can execute this statement.
DROP USER
drop user statement (HyperSQL)
<drop user statement> ::= DROP USER <user
name>
Drop (destroy) an existing user. If the specified user is the authorization for a schema, the schema is destroyed.
Only a user with the DBA role can execute this statement.
ALTER USER ... SET PASSWORD
set the password for a user (HyperSQL)
<alter user set password statement> ::= ALTER USER
<user name> SET PASSWORD <password>
Change the password of an existing user. <user
name> is an SQL identifier. If it is double-quoted it is
case-sensitive, otherwise it is turned to uppercase.
<password> is a string enclosed with single quote
characters and is case-sensitive.
Only a user with the DBA role can execute this command.
ALTER USER ... SET INITIAL SCHEMA
set the initial schema for a user (HyperSQL)
<alter user set initial schema statement> ::=
ALTER USER <user name> SET INITIAL SCHEMA <schema name> |
DEFAULT
Change the initial schema for a user. The initial schema is the
schema used by default for SQL statements issued during a session. If
DEFAULT is used, the default initial schema for all
users is used as the initial schema for the user. The SET SCHEMA command
allows the user to change the schema for the duration of the
session.
Only a user with the DBA role can execute this statement.
ALTER USER ... SET LOCAL
set the user authentication as local (HyperSQL)
<alter user set local> ::= ALTER USER <user
name> SET LOCAL { TRUE | FALSE }
Sets the authentication method for the user as local. This statement has an effect only when external authentication with role names is enabled. In this method of authentication, users created in the database are ignored and an external authentication mechanism, such as LDAP is used. This statement is used if you want to use local, password authentication for a specific user.
Only a user with the DBA role can execute this statement.
set password statement (HyperSQL)
<set password statement> ::= SET PASSWORD
<password>
Set the password for the current user.
<password> is a string enclosed with single quote
characters and is case-sensitive.
SET INITIAL SCHEMA
set the initial schema for the current user (HyperSQL)
<set initial schema statement> ::= SET INITIAL
SCHEMA <schema name> | DEFAULT
Change the initial schema for the current user. The initial
schema is the schema used by default for SQL statements issued during a
session. If DEFAULT is used, the default initial schema
for all users is used as the initial schema for the current user. The
separate SET SCHEMA command allows the user to change the schema for the
duration of the session. See also the Sessions and Transactions chapter.
SET DATABASE DEFAULT INITIAL SCHEMA
set the default initial schema for all users (HyperSQL)
<set database default initial schema statement>
::= SET DATABASE DEFAULT INITIAL SCHEMA <schema
name>
Sets the initial schema for new users. This schema can later be
changed with the <set initial schema statement>
command.
CREATE ROLE
role definition
<role definition> ::= CREATE ROLE <role
name> [ WITH ADMIN <grantor> ]
Defines a new role. Initially the role has no rights, except those of the PUBLIC role. Only a user with the DBA role can execute this command.
DROP ROLE
drop role statement
<drop role statement> ::= DROP ROLE <role
name>
Drop (destroy) a role. If the specified role is the authorization for a schema, the schema is destroyed. Only a user with the DBA role can execute this statement.
GRANTED BY
grantor determination
GRANTED BY <grantor>
<grantor> ::= CURRENT_USER |
CURRENT_ROLE
The authorization that is granting or revoking a role or
privileges. The optional GRANTED BY <grantor>
clause can be used in various statements that perform GRANT or REVOKE
actions. If the clause is not used, the authorization is CURRENT_USER.
Otherwise, it is the specified authorization.
GRANT
grant privilege statement
<grant privilege statement> ::= GRANT
<privileges> TO <grantee> [ { <comma> <grantee>
}... ] [ WITH GRANT OPTION ] [ GRANTED BY <grantor>
]
Assign privileges on schema objects to roles or users. Each
<grantee> is a role or a user. If [ WITH
GRANT OPTION ] is specified, then the
<grantee> can assign the privileges to other
<grantee> objects.
<privileges> ::= <object privileges> ON
<object name>
<object name> ::= [ TABLE ] <table name> |
DOMAIN <domain name> | COLLATION <collation name> | CHARACTER
SET <character set name> | TRANSLATION <transliteration name>
| TYPE <user-defined type name> | SEQUENCE <sequence generator
name> | <specific routine designator> | ROUTINE <routine
name> | FUNCTION <function name> | PROCEDURE <procedure
name>
<object privileges> ::= ALL PRIVILEGES |
<action> [ { <comma> <action> }... ]
<action> ::= SELECT | SELECT <left paren>
<privilege column list> <right paren> | DELETE | INSERT [
<left paren> <privilege column list> <right paren> ] |
UPDATE [ <left paren> <privilege column list> <right
paren> ] | REFERENCES [ <left paren> <privilege column
list> <right paren> ] | USAGE | TRIGGER |
EXECUTE
<privilege column list> ::= <column name
list>
<grantee> ::= PUBLIC | <authorization
identifier>
The <object privileges> that can be used
depend on the type of the <object name>. These
are discussed in the previous section. For a table, if
<privilege column list> is not specified, then
the privilege is granted on the table, which includes all of its columns
and any column that may be added to it in the future. For routines, the
name of the routine can be specified in two ways, either as the generic
name as the specific name. HyperSQL allows referencing all overloaded
versions of a routine at the same time, using its name. This differs from
the SQL Standard which requires the use of <specific routine
designator> to grant privileges separately on each different
signature of the routine.
Each <grantee> is the name of a role or
a user. Examples of GRANT statement are given below:
GRANT ALL ON SEQUENCE aSequence TO roleOrUser GRANT SELECT ON aTable TO roleOrUser GRANT SELECT, UPDATE ON aTABLE TO roleOrUser1, roleOrUser2 GRANT SELECT(columnA, columnB), UPDATE(columnA, columnB) ON TABLE aTable TO roleOrUser GRANT EXECUTE ON SPECIFIC ROUTINE aroutine_1234 TO rolOrUser
As mentioned in the general discussion, it is better to define a role for the collection of all the privileges required by an application. This role is then granted to any user. If further changes are made to the privileges of this role, they are automatically reflected in all the users that have the role.
GRANT
grant role statement
<grant role statement> ::= GRANT <role name>
[ { <comma> <role name> }... ] TO <grantee> [ {
<comma> <grantee> }... ] [ WITH ADMIN OPTION ] [ GRANTED BY
<grantor> ]
Assign roles to roles or users. One or more roles can be assigned
to one or more <grantee> objects. A
<grantee> is a user or a role. If the [
WITH ADMIN OPTION ] is specified, then each
<grantee> can grant the newly assigned roles to
other grantees. An example of user and role creation with grants is given
below:
CREATE USER appuser CREATE ROLE approle GRANT approle TO appuser GRANT SELECT, UPDATE ON TABLE atable TO approle GRANT USAGE ON SEQUENCE asequence to approle GRANT EXECUTE ON ROUTINE aroutine TO approle
REVOKE privilege
revoke statement
<revoke privilege statement> ::= REVOKE [ GRANT
OPTION FOR ] <privileges> FROM <grantee> [ { <comma>
<grantee> }... ] [ GRANTED BY <grantor> ] RESTRICT |
CASCADE
Revoke privileges from a user or role.
REVOKE role
revoke role statement
<revoke role statement> ::= REVOKE [ ADMIN OPTION
FOR ] <role revoked> [ { <comma> <role revoked> }... ]
FROM <grantee> [ { <comma> <grantee> }... ] [ GRANTED BY
<grantor> ] RESTRICT | CASCADE
<role revoked> ::= <role
name>
Revoke a role from users or roles.
$Revision: 4903 $
Copyright 2010-2012 Fred Toussi. Permission is granted to distribute this document without any alteration under the terms of the HSQLDB license. Additional permission is granted to the HSQL Development Group to distribute this document with or without alterations under the terms of the HSQLDB license.
2012-01-22 11:31:28-0500
Table of Contents
HyperSQL data access and data change statements are fully compatible with the latest SQL:2008 Standard. There are a few extensions and some relaxation of rules, but these do not affect statements that are written to the Standard syntax. There is full support for classic SQL, as specified by SQL-92, and many enhancements added in later versions of the standard.
An SQL statement can executed in two ways. One way is to use the
java.sql.Statement interface. The Statement object
can be reused to execute completely different SQL statements.
Alternatively a PreparedStatment can be used to
execute an SQL statement repeatedly, and the statements can be
parameterized. Using either form, if the SQL statement is a query
expression, a ResultSet is returned.
In SQL, when a query expression (SELECT or similar SQL statement) is
executed, an ephemeral table is created. When this table is returned to
the application program, it is returned as a result set, which is accessed
row-by-row by a cursor. A JDBC ResultSet represents
an SQL result set and its cursor.
The minimal definition of a cursor is a list of rows with a position that can move forward. Some cursors also allow the position to move backwards or jump to any position in the list.
An SQL cursor has several attributes. These attributes depend on the
query expression. Some of these attributes can be overridden by specifying
qualifiers in the SQL statement or by specifying values for the parameters
of the JDBC Statement or
PreparedStatement.
The columns of the rows of the result set are determined by the
query expression. The number of columns and the type and name
characteristics of each column are known when the query expression is
compiled and before its execution. This metadata information remains
constant regardless of changes to the contents of the tables used in the
query expression. The metadata for the JDBC
ResultSet is in the form of a
ResultSetMetaData object. Various methods of the
ResultSetMetaData interface return different
properties of each column of the
ResultSet.
A result set may contain 0 or more rows. The rows are determined by the execution of the query expression.
The setMaxRows(int) method of JDBC
Statement allows limiting the number of rows
returned by the statement. This limit is conceptually applied after the
result has been built, and the excess rows are discarded.
A cursor is either scrollable or not. Scrollable cursors allow accessing rows by absolute or relative positioning. No-scroll cursors only allow moving to the next row. The cursor can be optionally declared with the SQL qualifiers SCROLL, or NO SCROLL. The JDBC statement parameter can be specified as: TYPE_FORWARD_ONLY and TYPE_SCROLL_INSENSITIVE. The JDBC type TYPE_SCROLL_SENSITIVE is not supported by HSQLDB.
The default is NO SCROLL or TYPE_FORWARD_ONLY.
When a JDBC ResultSet is opened, it is
positioned before the first row. Using the
next() method the position is moved to the
first row. While the ResultSet is positioned on a
row, various getter methods can be used to access the columns of the
row.
The result returned by some query expressions is updatable. HSQLDB supports core SQL updatability features, plus some enhancements from the SQL optional features.
A query expression is updatable if it is a SELECT from a single underlying base table (or updatable view) either directly or indirectly. A SELECT statement featuring DISTINCT or GROUP BY or FETCH, LIMIT, OFFSET is not updatable. In an updatable query expression, one or more columns are updatable. An updatable column is a column that can be traced directly to the underlying table. Therefore, columns that contain expressions are not updatable. Examples of updatable query expressions are given below. The view V is updatable when its query expression is updatable. The SELECT statement from this view is also updatable:
SELECT A, B FROM T WHERE C > 5 SELECT A, B FROM (SELECT * FROM T WHERE C > 10) AS TT WHERE TT.B <10 CREATE VIEW V(X,Y) AS SELECT A, B FROM T WHERE C > 0 AND B < 10 SELECT X FROM V WHERE Y = 5
If a cursor is declared with the SQL qualifier, FOR
UPDATE OF <column name list>, then only the stated
columns in the result set become updatable. If any of the stated columns
is not actually updatable, then the cursor declaration will not
succeed.
If the SQL qualifier, FOR UPDATE is used, then all the updatable columns of the result set become updatable.
If a cursor is declared with FOR READ ONLY, then it is not updatable.
In HSQLDB, if FOR READ ONLY or FOR UPDATE is not used then all the updatable columns of the result set become updatable. This relaxes the SQL standard rule that in this case limits updatability to only simply updatable SELECT statements (where all columns are updatable).
In JDBC, CONCUR_READ_ONLY or CONCUR_UPDATABLE can be specified for
the Statement parameter. CONCUR_UPDATABLE is
required if the returning ResultSet is to be updatable. If
CONCUR_READ_ONLY, which is the default, is used, then even an updatable
ResultSet becomes read-only.
When a ResultSet is updatable, various
setter methods can be used to modify the column values. The names of the
setter methods begin with "update". After all the updates on a row are
done, the updateRow() method must be called to
finalise the row update.
An updatable ResultSet may or may not be
insertable-into. In an insertable ResultSet, all
columns of the result are updatable and any column of the base table
that is not in the result must be a generated column or have a default
value.
In the ResultSet object, a special
pseudo-row, called the insert row, is used to populate values for
insertion into the ResultSet (and consequently,
into the base table). The setter methods must be used on all the
columns, followed by a call to
insertRow().
Individual rows from all updatable result sets can be deleted one
at a time. The deleteRow() is called when the
ResultSet is positioned on a row.
While using an updatable ResultSet to modify data, it is recommended not to change the same data using another ResultSet and not to execute SQL data change statements that modify the same data.
The sensitivity of the cursor relates to visibility of changes made to the data by the same transaction but without using the given cursor. While the result set is open, the same transaction may use statements such as INSERT or UPDATE, and change the data of the tables from which the result set data is derived. A cursor is SENSITIVE if it reflects those changes. It is INSENSITIVE if it ignores such changes. It is ASENSITIVE if behaviour is implementation dependent.
The SQL default is ASENSITIVE, i.e., implantation dependent.
In HSQLDB all cursors are INSENSITIVE. They do not reflect changes to the data made by other statements.
A cursor is holdable if the result set is not automatically closed when the current transaction is committed. Holdability can be specified in the cursor declaration using the SQL qualifiers WITH HOLD or WITHOUT HOLD.
In JDBC, holdability is specified using either of the following values for the Statement parameter: HOLD_CURSORS_OVER_COMMIT, or CLOSE_CURSORS_AT_COMMIT.
The SQL default is WITHOUT HOLD.
The JDBC default for HSQLDB result sets is WITH HOLD for read-only result sets and WITHOUT HOLD for updatable result sets.
If the holdability of a ResultSet is
specified in a conflicting manner in the SQL statement and the JDBC
Statement object, the JDBC setting takes
precedence.
The autocommit property of a connection is a feature of JDBC and
ODBC and is not part of the SQL Standard. In autocommit mode, all
transactional statements are followed by an implicit commit. In
autocommit mode, all ResultSet objects are
read-only and holdable.
The JDBC settings, ResultSet.CONCUR_READONLY and ResultSet.CONCUR_UPDATABLE are the available alternatives for read-only or updatability. The default is ResultSet.CONCUR_READONLY.
The JDBC settings, ResultSet.TYPE_FORWARD_ONLY, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.TYPE_SCROLL_SENSITIVE are the available alternatives for both scrollability (navigation) and sensitivity. HyperSQL does not support ResultSet.TYPE_SCROLL_SENSITIVE. The two other alternatives can be used for both updatable and read-only result sets.
The JDBC settings ResultSet.CLOSE_CURSORS_AT_COMMIT and ResultSet.HOLD_CURSORS_OVER_COMMIT are the alternatives for the lifetime of the result set. The default is ResultSet.CLOSE_CURSORS_AT_COMMIT. The other setting can only be used for read-only result sets.
Examples of creating statements for updatable result sets are given below:
Connection c = newConnection(); Statement st; c.setAutoCommit(false); st = c.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE); st = c.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);
When a JDBC PreparedStatement or CallableStatement is used with an SQL statement that contains dynamic parameters, the data types of the parameters are resolved and determined by the engine when the statement is prepared. The SQL Standard has detailed rules to determine the data types and imposes limits on the maximum length or precision of the parameter. HyperSQL applies the standard rules with two exceptions for parameters with String and BigDecimal Java types. HyperSQL ignores the limits when the parameter value is set, and only enforces the necessary limits when the PreparedStatement is executed. In all other cases, parameter type limits are checked and enforce when the parameter is set.
In the example below the setString() calls do not raise an exception, but one of the execute() statements does.
// table definition: CREATE TABLE T (NAME VARCHAR(12), ...)
Connection c = newConnection();
PreparedStatement st = c.prepareStatement("SELECT * FROM T WHERE NAME = ?");
// type of the parameter is VARCHAR(12), which limits length to 12 characters
st.setString(1, "Eyjafjallajokull"); // string is longer than type, but no exception is raised here
set.execute(); // executes with no exception and does not find any rows
// but if an UPDATE is attempted, an exception is raised
st = c.prepareStatement("UPDATE T SET NAME = ? WHERE ID = 10");
st.setString(1, "Eyjafjallajokull"); // string is longer than type, but no exception is raised here
st.execute(); // exception is thrown when HyperSQL checks the value for update
All of the above also applies to setting the values in new and updated rows in updatable ResultSet objects.
JDBC parameters can be set with any compatible type, as supported by the JDBC specification. For CLOB and BLOB types, you can use streams, or create instances of BLOB or CLOB before assigning them to the parameters. You can even use CLOB or BLOB objects returned from connections to other RDBMS servers. The Connection.createBlob() and createClob() methods can be used to create the new LOBs. For very large LOB's the stream methods are preferable as they use less memory.
For array parameters, you must use a
java.sql.Array object that contains the array
elements before assigning to JDBC parameters. The
Connection.createArrayOf(...) method can be used to create
a new object, or you can use an Array returned from connections to other
RDBMS servers.
Data change statements, also called data manipulation statements (DML) such as INSERT, UPDATE, MERGE can be called with different executeUpdate() methods of java.sql.Statement and java.sql.PreparedStatement. Some of these methods allow you to specify how values for generated columns of the table are returned. These methods are documented in the JavaDoc for org.hsqldb.jdbc.JDBCStatement and org.hsqldb.jdbc.JDBCPreparedStatement. HyperSQL can return not just the generated columns, but any set of columns of the table. You can use this to retrieve the columns values that may be modified by a BEFORE TRIGGER on the table.
The JDBC CallableStatement interface is used to call Java or SQL procedures that have been defined in the database. The SQL statement in the form of CALL procedureName ( ... ) with constant value arguments or with parameter markers. Note that you must use a parameter marker for OUT and INOUT arguments of the procedure you are calling. The OUT arguments should not be set before executing the callable statement.
After executing the statement, you can retrieve the OUT and INOUT parameters with the appropriate getXXX() method.
Procedures can also return one or more result sets. You should call the getResultSet() and getMoreResults() methods to retrieve the result sets one by one.
SQL functions can also return a table. You can call such functions the same way as procedures and retrieve the table as a ResultSet.
The methods of the JDBC ResultSet interface can be used to return values and to convert value to different types as supported by the JDBC specification.
When a CLOB and BLOB object is returned from a ResultSet, no data is transferred until the data is read by various methods of java.sql.CLOB and java.sql.BLOB. Data is streamed in large blocks to avoid excessive memory use.
Array objects are returned as instances of java.sql.Array.
The DECLARE CURSOR statement is used within an SQL PROCEDURE body. In the early releases of HyperSQL 2.0, the cursor is used only to return a result set from the procedure. Therefore the cursor must be declared WITH RETURN and can only be READ ONLY.
DECLARE CURSOR
declare cursor statement
<declare cursor> ::= DECLARE <cursor
name>
[ { SENSITIVE | INSENSITIVE | ASENSITIVE } ] [ { SCROLL |
NO SCROLL } ]
CURSOR [ { WITH HOLD | WITHOUT HOLD } ] [ { WITH RETURN |
WITHOUT RETURN } ]
FOR <query expression>
[ FOR { READ ONLY | UPDATE [ OF <column name list>
] } ]
The query expression is a SELECT statement or similar, and is
discussed in the rest of this chapter. In the example below a cursor is
declared for a SELECT statement. It is later opened to create the result
set. The cursor is specified WITHOUT HOLD, so the result set is not kept
after a commit. Use WITH HOLD to keep the result set. Note that you need
to declare the cursor WITH RETURN as it is returned by the
CallableStatement.
DECLARE thiscursor SCROLL CURSOR WITHOUT HOLD WITH RETURN FOR SELECT * FROM INFORMATION_SCHEMA.TABLES; -- OPEN thiscursor;
The syntax elements that can be used in data access and data change statements are described in this section. The SQL Standard has a very extensive set of definitions for these elements. The BNF definitions given here are sometimes simplified.
Literals are used to express constant values. The general type of a literal is known by its format. The specific type is based on conventions.
unicode escape elements
unicode escape elements
<Unicode escape specifier> ::= [ UESCAPE
<quote><Unicode escape character><quote> ]
<Unicode escape value> ::= <Unicode 4 digit
escape value> | <Unicode 6 digit escape value> | <Unicode
character escape value>
<Unicode 4 digit escape value> ::= <Unicode
escape
character><hexit><hexit><hexit><hexit>
<Unicode 6 digit escape value> ::= <Unicode
escape character><plus sign>
<hexit><hexit><hexit><hexit><hexit><hexit>
<Unicode character escape value> ::= <Unicode
escape character><Unicode escape character>
<Unicode escape character> ::= a single
character than a <hexit> (a-f, A-F, 0-9), <plus sign>,
<quote>, <double quote>, or <white
space>
character literal
character literal
<character string literal> ::= [
<introducer><character set specification> ] <quote> [
<character representation>... ] <quote> [ {
<separator> <quote> [ <character representation>... ]
<quote> }... ]
<introducer> ::=
<underscore>
<character representation> ::= <nonquote
character> | <quote symbol>
<nonquote character> ::= any character apart
from the quote symbol.
<quote symbol> ::=
<quote><quote>
<national character string literal> ::= N
<quote> [ <character representation>... ] <quote> [ {
<separator> <quote> [ <character representation>... ]
<quote> }... ]
<Unicode character string literal> ::= [
<introducer><character set specification> ]
U<ampersand><quote> [ <Unicode representation>... ]
<quote> [ { <separator> <quote> [ <Unicode
representation>... ] <quote> }... ] <Unicode escape
specifier>
<Unicode representation> ::= <character
representation> | <Unicode escape value>
The type of a character literal is CHARACTER. The length of the string literal is the character length of the type. If the quote character is used in a string, it is represented with two quote characters. Long literals can be divided into multiple quoted strings, separated with a space or end-of-line character.
Unicode literals start with U& and can contain ordinary characters and unicode escapes. A unicode escape begins with the backslash ( \ ) character and is followed by four hexadecimal characters which specify the character code.
Example of character literals are given below:
'a literal' ' string seperated' ' into parts' 'a string''s literal form with quote character' U&'Unicode string with Greek delta \0394 and phi \03a6 letters'
binary literal
binary literal
<binary string literal> ::= X <quote> [
<space>... ] [ { <hexit> [ <space>... ] <hexit>
[ <space>... ] }... ] <quote> [ { <separator>
<quote> [ <space>... ] [ { <hexit> [ <space>...
] <hexit> [ <space>... ] }... ] <quote> }...
]
<hexit> ::= <digit> | A | B | C | D | E |
F | a | b | c | d | e | f
The type of a binary literal is BINARY. The octet length of the binary literal is the length of the type. Case-insensitive hexadecimal characters are used in the binary string. Each pair of characters in the literal represents a byte in the binary string. Long literals can be divided into multiple quoted strings, separated with a space or end-of-line character.
X'1abACD34' 'Af'
bit literal
bit literal
<bit string literal> ::= B <quote> [
<bit> ... ] <quote> [ { <separator> <quote> [
<bit>... ] <quote> }... ]
<bit> ::= 0 | 1
The type of a binary literal is BIT. The bit length of the bit literal is the length of the type. Digits 0 and 1 are used to represent the bits. Long literals can be divided into multiple quoted strings, separated with a space or end-of-line character.
B'10001001' '00010'
numeric literal
numeric literal
<signed numeric literal> ::= [ <sign> ]
<unsigned numeric literal>
<unsigned numeric literal> ::= <exact numeric
literal> | <approximate numeric literal>
<exact numeric literal> ::= <unsigned
integer> [ <period> [ <unsigned integer> ] ] |
<period> <unsigned integer>
<sign> ::= <plus sign> | <minus
sign>
<approximate numeric literal> ::=
<mantissa> E <exponent>
<mantissa> ::= <exact numeric
literal>
<exponent> ::= <signed
integer>
<signed integer> ::= [ <sign> ]
<unsigned integer>
<unsigned integer> ::=
<digit>...
The type of an exact numeric literal without a decimal point is INTEGER, BIGINT, or DECIMAL, depending on the value of the literal (the smallest type that can represent the value is the type).
The type of an exact numeric literal with a decimal point is DECIMAL. The precision of a decimal literal is the total number of digits of the literal. The scale of the literal is the total number of digits to the right of the decimal point.
The type of an approximate numeric literal is DOUBLE. An approximate numeric literal always includes the mantissa and exponent, separated by E.
12 34.35 +12E-2
boolean literal
boolean literal
<boolean literal> ::= TRUE | FALSE |
UNKNOWN
The boolean literal is one of the specified keywords.
datetime and interval literal
datetime and interval literal
<datetime literal> ::= <date literal> |
<time literal> | <timestamp literal>
<date literal> ::= DATE <date
string>
<time literal> ::= TIME <time
string>
<timestamp literal> ::= TIMESTAMP <timestamp
string>
<date string> ::= <quote> <unquoted
date string> <quote>
<time string> ::= <quote> <unquoted
time string> <quote>
<timestamp string> ::= <quote>
<unquoted timestamp string> <quote>
<time zone interval> ::= <sign> <hours
value> <colon> <minutes value>
<date value> ::= <years value> <minus
sign> <months value> <minus sign> <days
value>
<time value> ::= <hours value>
<colon> <minutes value> <colon> <seconds
value>
<interval literal> ::= INTERVAL [ <sign> ]
<interval string> <interval qualifier>
<interval string> ::= <quote> <unquoted
interval string> <quote>
<unquoted date string> ::= <date
value>
<unquoted time string> ::= <time value> [
<time zone interval> ]
<unquoted timestamp string> ::= <unquoted
date string> <space> <unquoted time
string>
<unquoted interval string> ::= [ <sign> ]
{ <year-month literal> | <day-time literal>
}
<year-month literal> ::= <years value> [
<minus sign> <months value> ] | <months
value>
<day-time literal> ::= <day-time interval>
| <time interval>
<day-time interval> ::= <days value> [
<space> <hours value> [ <colon> <minutes value>
[ <colon> <seconds value> ] ] ]
<time interval> ::= <hours value> [
<colon> <minutes value> [ <colon> <seconds
value> ] ] | <minutes value> [ <colon> <seconds
value> ] | <seconds value>
<years value> ::= <datetime
value>
<months value> ::= <datetime
value>
<days value> ::= <datetime
value>
<hours value> ::= <datetime
value>
<minutes value> ::= <datetime
value>
<seconds value> ::= <seconds integer
value> [ <period> [ <seconds fraction> ]
]
<seconds integer value> ::= <unsigned
integer>
<seconds fraction> ::= <unsigned
integer>
<datetime value> ::= <unsigned
integer>
The type of a datetime or interval type is specified in the literal. The fractional second precision is the number of digits in the fractional part of the literal. Details are described in the SQL Language chapter
DATE '2008-08-08' TIME '20:08:08' TIMESTAMP '2008-08-08 20:08:08.235' INTERVAL '10' DAY INTERVAL -'08:08' MINUTE TO SECOND
References are identifier chains, which can be a single identifiers or identifiers chains composed of single identifiers chained together with the period symbol.
identifier chain
identifier chain
<identifier chain> ::= <identifier> [ {
<period> <identifier> }... ]
<basic identifier chain> ::= <identifier
chain>
A period-separated chain of identifiers. The identifiers in an identifier chain can refer to database objects in a hierarchy. The possible hierarchies are as follows. In each hierarchy, elements from the start or the end can be missing, but the order of elements cannot be changed.
catalog, schema, database object
catalog, schema, table, column
correlation name, column
Examples of identifier chain are given below:
SELECT MYCAT.MYSCHEMA.MYTABLE.MYCOL FROM MYCAT.MYSCHEMA.MYTABLE DROP TABLE MYCAT.MYSCHEMA.MYTABLE CASCADE ALTER SEQUENCE MYCAT.MYSCHEMA.MYSEQUENCE RESTART WITH 100
column reference
column reference
<column reference> ::= <basic identifier
chain> | MODULE <period> <qualified identifier>
<period> <column name>
Reference a column or a routine variable.
SQL parameter reference
SQL parameter reference
<SQL parameter reference> ::= <basic
identifier chain>
Reference an SQL routine parameter.
contextually typed value specification
contextually typed value specification
<contextually typed value specification> ::=
<null specification> | <default
specification>
<null specification> ::=
NULL
<default specification> ::=
DEFAULT
Specify a value whose data type or value is inferred from its context. DEFAULT is used for assignments to table columns that have a default value, or to table columns that are generated either as an IDENTITY value or as an expression. NULL can be used only in a context where the type of the value is known. For example, a NULL can be assigned to a column of the table in an INSERT or UPDATE statement, because the type of the column is known. But if NULL is used in a SELECT list, it must be used in a CAST statement.
Value expression is a general name for all expressions that return a value. Different types of expressions are allowed in different contexts.
value expression primary
value expression primary
<value expression primary> ::= <parenthesized
value expression> | <nonparenthesized value expression
primary>
<parenthesized value expression> ::= <left
paren> <value expression> <right
paren>
<nonparenthesized value expression primary> ::=
<unsigned value specification> | <column reference> |
<set function specification> | <scalar subquery> | <case
expression> | <cast specification> | <next value
expression> | <current value expression> | <routine
invocation>
Specify a value that is syntactically self-delimited.
value specification
value specification
<value specification> ::= <literal> |
<general value specification>
<unsigned value specification> ::= <unsigned
literal> | <general value specification>
<target specification> ::= <host parameter
specification> | <SQL parameter reference> | <column
reference> | <dynamic parameter
specification>
<simple target specification> ::= <host
parameter specification> | <SQL parameter reference> |
<column reference> | <embedded variable
name>
<host parameter specification> ::= <host
parameter name> [ <indicator parameter> ]
<dynamic parameter specification> ::=
<question mark>
Specify one or more values, host parameters, SQL parameters, dynamic parameters, or host variables.
row value expression
row value expression
<row value expression> ::= <row value special
case> | <explicit row value constructor>
<row value predicand> ::= <row value special
case> | <row value constructor predicand>
<row value special case> ::=
<nonparenthesized value expression primary>
<explicit row value constructor> ::= <left
paren> <row value constructor element> <comma> <row
value constructor element list> <right paren>
|
ROW <left paren> <row value constructor
element list> <right paren> | <row
subquery>
Specify a row consisting of one or more elements. A comma separated list of expressions, enclosed in brackets, with the optional keyword ROW. In SQL, a row containing a single element can often be used where a single value is expected.
set function specification
set function specification
<set function specification> ::= <aggregate
function> | <grouping operation>
<grouping operation> ::= GROUPING <left
paren> <column reference> [ { <comma> <column
reference> }... ] <right paren>
Specify a value derived by the application of a function to an
argument. Early releases of HyperSQL 2.0 do not support
<grouping operation> .
COALESCE
coalesce expression
<coalesce expression> := COALESCE <left
paren> <value expression> { <comma> <value
expression> }... <right paren>
Replace null values with another value. The coalesce expression
has two or more instances of <value expression>. If the first
<value expression> evaluates to a non-null value, it is returned
as the result of the coalesce expression. If it is null, the next
<value expression> is evaluated and if it
evaluates to a non-non value, it is returned, and so on.
The type of the return value of a COALESCE expression is the
aggregate type of the types of all the <value
expression> instances. Therefore, any value returned is
implicitly cast to this type. HyperSQL also features built-in functions
with similar functionality.
NULLIF
nullif expression
<nullif expression> := NULLIF <left paren>
<value expression> <comma> <value expression>
<right paren>
Return NULL if two values are equal. If the result of the first
<value expression> is not equal to the result
of the second, then it is returned, otherwise NULL is returned. The type
of the return value is the type of the first <value
expression>.
SELECT i, NULLIF(n, 'not defined') FROM t
CASE
case specification
<case specification> ::= <simple case> |
<searched case>
<simple case> ::= CASE <case operand>
<simple when clause>... [ <else clause> ]
END
<searched case> ::= CASE <searched when
clause>... [ <else clause> ] END
<simple when clause> ::= WHEN <when operand
list> THEN <result>
<searched when clause> ::= WHEN <search
condition> THEN <result>
<else clause> ::= ELSE
<result>
<case operand> ::= <row value predicand> |
<overlaps predicate part 1>
<when operand list> ::= <when operand> [ {
<comma> <when operand> }... ]
<when operand> ::= <row value predicand> |
<comparison predicate part 2> | <between predicate part 2> |
<in predicate part 2> | <character like predicate part 2> |
<octet like predicate part 2> | <similar predicate part 2> |
<regex like predicate part 2> | <null predicate part 2> |
<quantified comparison predicate part 2> | <match predicate
part 2> | <overlaps predicate part 2> | <distinct predicate
part 2>
<result> ::= <result expression> |
NULL
<result expression> ::= <value
expression>
Specify a conditional value. The result of a case expression is always a value. All the values introduced with THEN must be of the same type.
Some simple examples of the CASE expression are given below. The first two examples return 'Britain', 'Germany', or 'Other country' depending on the value of dialcode. The third example uses IN and smaller-than predicates.
CASE dialcode WHEN 44 THEN 'Britain' WHEN 49 THEN 'Germany' ELSE 'Other country' END CASE WHEN dialcode=44 THEN 'Britain' WHEN dialcode=49 THEN 'Germany' WHEN dialcode < 0 THEN 'bad dial code' ELSE 'Other country' END CASE dialcode WHEN IN (44, 49,30) THEN 'Europe' WHEN IN (86,91,91) THEN 'Asia' WHEN < 0 THEN 'bad dial code' ELSE 'Other continent' END
The case statement can be far more complex and involve several conditions.
CAST
cast specification
<cast specification> ::= CAST <left paren>
<cast operand> AS <cast target> <right
paren>
<cast operand> ::= <value expression> |
<implicitly typed value specification>
<cast target> ::= <domain name> | <data
type>
Specify a data conversion. Data conversion takes place automatically among variants of a general type. For example numeric values are freely converted from one type to another in expressions.
Explicit type conversion is necessary in two cases. One case is to determine the type of a NULL value. The other case is to force conversion for special purposes. Values of data types can be cast to a character type. The exception is BINARY and OTHER types. The result of the cast is the literal expression of the value. Conversely, a value of a character type can be converted to another type if the character value is a literal representation of the value in the target type. Special conversions are possible between numeric and interval types, which are described in the section covering interval types.
The examples below show examples of cast with their result:
CAST (NULL AS TIMESTAMP)
CAST (' 199 ' AS INTEGER) = 199
CAST ('tRue ' AS BOOLEAN) = TRUE
CAST (INTERVAL '2' DAY AS INTEGER) = 2
CAST ('1992-04-21' AS DATE) = DATE '1992-04-21'
NEXT VALUE FOR
next value expression
<next value expression> ::= NEXT VALUE FOR
<sequence generator name>
Return the next value of a sequence generator. This expression can be used as a select list element in queries, or in assignments to table columns in data change statements. If the expression is used more than once in a single row that is being evaluated, the same value is returned for each invocation. After evaluation of the particular row is complete, the sequence generator will return a different value from the old value. The new value is generated by the sequence generator by adding the increment to the last value it generated. In the example below the expression is used in an insert statement:
INSERT INTO MYTABLE(COL1, COL2) VALUES 2, NEXT VALUE FOR MYSEQUENCE
CURRENT VALUE FOR
current value expression
<current value expression> ::= CURRENT VALUE FOR
<sequence generator name>
Return the latest value that was returned by the NEXT VALUE FOR expression for a sequence generator. In the example below, the value that was generated by the sequence for the first insert, is reused for the second insert:
INSERT INTO MYTABLE(COL1, COL2) VALUES 2, NEXT VALUE FOR MYSEQUENCE; INSERT INTO CHILDTABLE(COL1, COL2) VALUES 10, CURRENT VALUE FOR MYSEQUENCE;
value expression
value expression
<value expression> ::= <numeric value
expression> | <string value expression> | <datetime value
expression> | <interval value expression> | <boolean value
expression> | <row value expression>
An expression that returns a value. The value can be a single value, or a row consisting more than one value.
numeric value expression
numeric value expression
<numeric value expression> ::= <term> |
<numeric value expression> <plus sign> <term> |
<numeric value expression> <minus sign>
<term>
<term> ::= <factor> | <term>
<asterisk> <factor> | <term> <solidus>
<factor>
<factor> ::= [ <sign> ] <numeric
primary>
<numeric primary> ::= <value expression
primary> | <numeric value function>
Specify a numeric value. The BNF indicates that
<asterisk> and
<solidus> (the operators for multiplication and
division) have precedence over <minus sign> and
<plus sign>.
numeric value function
numeric value function
<numeric value function> ::= <position
expression> | <extract expression> | <length expression>
...
Specify a function yielding a value of type numeric. The supported numeric value functions are listed and described in the Built In Functions chapter.
string value expression
string value expression
<string value expression> ::= <string
concatenation> | <string factor>
<string factor> ::= <value expression
primary> | <string value function>
<string concatenation> ::= <string value
expression> <concatenation operator> <string
factor>
<concatenation operator> ::=
||
Specify a character string value, a binary string value, or a
bit string value. The BNF indicates that a string value expression can
be formed by concatenation of two or more <value expression
primary>. The types of the <value expression
primary> elements must be compatible, that is, all must be
string, or binary or bit string values.
character value function
string value function
<string value function> ::=
...
Specify a function that returns a character string or binary string. The supported character value functions are listed and described in the Built In Functions chapter.
datetime value expression
datetime value expression
<datetime value expression> ::= <datetime
term> | <interval value expression> <plus sign>
<datetime term> | <datetime value expression> <plus
sign> <interval term> | <datetime value expression>
<minus sign> <interval term>
<datetime term> ::= <datetime
factor>
<datetime factor> ::= <datetime primary> [
<time zone> ]
<datetime primary> ::= <value expression
primary> | <datetime value function>
<time zone> ::= AT <time zone
specifier>
<time zone specifier> ::= LOCAL | TIME ZONE
<interval primary>
Specify a datetime value. Details are described in the SQL Language chapter.
datetime value function
datetime value function
<datetime value function> ::=
...
Specify a function that returns a datetime value. The supported datetime value functions are listed and described in the Built In Functions chapter.
interval term
interval value expression
<interval value expression> ::= <interval
term> | <interval value expression 1> <plus sign>
<interval term 1> | <interval value expression 1> <minus
sign> <interval term 1> | <left paren> <datetime value
expression> <minus sign> <datetime term> <right
paren> <interval qualifier>
<interval term> ::= <interval factor> |
<interval term 2> <asterisk> <factor> | <interval
term 2> <solidus> <factor> | <term>
<asterisk> <interval factor>
<interval factor> ::= [ <sign> ]
<interval primary>
<interval primary> ::= <value expression
primary> [ <interval qualifier> ] | <interval value
function>
<interval value expression 1> ::= <interval
value expression>
<interval term 1> ::= <interval
term>
<interval term 2> ::= <interval
term>
Specify an interval value. Details are described in the SQL Language chapter.
interval absolute value function
interval value function
<interval value function> ::= <interval
absolute value function>
<interval absolute value function> ::= ABS
<left paren> <interval value expression> <right
paren>
Specify a function that returns the absolute value of an interval. If the interval is negative, it is negated, otherwise the original value is returned.
boolean value expression
boolean value expression
<boolean value expression> ::= <boolean
term> | <boolean value expression> OR <boolean
term>
<boolean term> ::= <boolean factor> |
<boolean term> AND <boolean factor>
<boolean factor> ::= [ NOT ] <boolean
test>
<boolean test> ::= <boolean primary> [ IS
[ NOT ] <truth value> ]
<truth value> ::= TRUE | FALSE |
UNKNOWN
<boolean primary> ::= <predicate> |
<boolean predicand>
<boolean predicand> ::= <parenthesized
boolean value expression> | <nonparenthesized value expression
primary>
<parenthesized boolean value expression> ::=
<left paren> <boolean value expression> <right
paren>
Specify a boolean value.
Predicates are conditions with two sides and evaluate to a
boolean value. The left side of the predicate, the <row
value predicand>, is the common element of all predicates.
This element is a generalisation of both <value
expression>, which is a scalar, and of
<explicit row value constructor>, which is a
row. The two sides of a predicate can be split in CASE statements where
the <row value predicand> is part of multiple
predicates.
The number of fields in all <row value
predicand> used in predicates must be the same and the
types of the fields in the same position must be compatible for
comparison. If either of these conditions does not hold, an exception is
raised. The number of fields in a row is called the
degree.
In many types of predicates (but not all of them), if the
<row value predicand> evaluates to NULL, the
result of the predicate is UNKNOWN. If the <row value
predicand> has more than one element, and one or more of
the fields evaluate to NULL, the result depends on the particular
predicate.
comparison predicand
comparison predicate
<comparison predicate> ::= <row value
predicand> <comp op> <row value
predicand>
<comp op> ::= <equals operator> | <not
equals operator> | <less than operator> | <greater than
operator> | <less than or equals operator> | <greater than
or equals operator>
Specify a comparison of two row values. If either
<row value predicand> evaluates to NULL, the
result of <comparison predicate> is UNKNOWN.
Otherwise, the result is TRUE, FALSE or UNKNOWN.
If the degree of <row value
predicand> is larger than one, comparison is performed
between each field and the corresponding field in the other
<row value predicand> from left to right, one
by one.
When comparing two elements, if either field is NULL then the result is UNKNOWN.
For <equals operator>, if the result
of comparison is TRUE for all field, the result of the predicate is
TRUE. If the result of comparison is FALSE for one field, the result of
predicate is FALSE. Otherwise the result is UNKNOWN.
The <not equals operator> is
translated to NOT (<row value predicand> = <row value
predicand>).
The <less than or equals operator> is
translated to (<row value predicand> = <row value
predicand>) OR (<row value predicand> < <row value
predicand>). The <greater than or equals
operator> is translated similarly.
For the <less than operator> and
<greater than operator>, if two fields at a
given position are equal, then comparison continues to the next field.
Otherwise, the result of the last performed comparison is returned as
the result of the predicate. This means that if the first field is NULL,
the result is always UNKNOWN.
The logic that governs NULL values and UNKNOWN result is as follows: Suppose the NULL values were substituted by arbitrary real values. If substitution cannot change the result of the predicate, then the result is TRUE or FALSE, based on the existing non-NULL values, otherwise the result of the predicate is UNKNOWN.
The examples of comparison given below use literals, but the literals actually represent the result of evaluation of some expression.
((1, 2, 3, 4) = (1, 2, 3, 4)) IS TRUE ((1, 2, 3, 4) = (1, 2, 3, 5)) IS FALSE ((1, 2, 3, 4) < (1, 2, 3, 4)) IS FALSE ((1, 2, 3, 4) < (1, 2, 3, 5)) IS TRUE ((NULL, 1, NULL) = (NULL, 1, NULL)) IS UNKNOWN ((NULL, 1, NULL) = (NULL, 2, NULL)) IS FALSE ((NULL, 1, NULL) <> (NULL, 2, NULL)) IS TRUE ((NULL, 1, 2) <all operators> (NULL, 1, 2)) IS UNKNOWN ((1, NULL, ...) < (1, 2, ...)) IS UNKNOWN ((1, NULL, ...) < (2, NULL, ...)) IS TRUE ((2, NULL, ...) < (1, NULL, ...)) IS FALSE
BETWEEN
between predicate
<between predicate> ::= <row value
predicand> <between predicate part 2>
<between predicate part 2> ::= [ NOT ] BETWEEN [
ASYMMETRIC | SYMMETRIC ] <row value predicand> AND <row value
predicand>
Specify a range comparison. The default is ASYMMETRIC. The
expression X BETWEEN Y AND Z is equivalent to
(X >= Y AND X <= Z). Therefore if Y > Z, the
BETWEEN expression is never true. The expression X BETWEEN
SYMMETRIC Y AND Z is equivalent to (X >= Y AND X
<= Z) OR (X >= Z AND X <= Y). The expression
Z NOT BETWEEN ... is equivalent to NOT (Z
BETWEEN ...). If any of the three <row value
predicand> evaluates to NULL, the result is
UNKNOWN.
IN
in predicate
<in predicate> ::= <row value predicand> [
NOT ] IN <in predicate value>
<in predicate value> ::= <table subquery>
| <left paren> <in value list> <right paren>
| <left paren> UNNEST <left paren>
<array value expression> <right paren> <right
paren>
<in value list> ::= <row value expression>
[ { <comma> <row value expression> }...
]
Specify a quantified comparison. The expression X NOT
IN Y is equivalent to NOT (X IN Y). The
( <in value list> ) is converted into a table
with one or more rows. The expression X IN Y is
equivalent to X = ANY Y, which is a
<quantified comparison predicate>.
If the <table subquery> returns no
rows, the result is FALSE. Otherwise the <row value
predicand> is compared one by one with each row of the
<table subquery>.
If the comparison is TRUE for at least one row, the result is TRUE. If the comparison is FALSE for all rows, the result is FALSE. Otherwise the result is UNKNOWN.
HyperSQL supports an extension to the SQL Standard to allow an array to be used in the <in predicate value>. This is intended to be used with prepared statements where a variable length array of values can be used as the parameter value for each call. The example below shows how this is used in SQL. The JDBC code must create a new java.sql.Array object that contains the values and set the parameter with this array.
SELECT * FROM customer WHERE firstname IN ( UNNEST(?) )
Connection conn;
PreparedStatement ps;
// conn and ps are instantiated here
Array arr = conn.createArrayOf("INTEGER", new Integer[] {1, 2, 3});
ps.setArray(1, arr);
ResultSet rs = ps.executeQuery();
LIKE
like predicate
<like predicate> ::= <character like
predicate> | <octet like predicate>
<character like predicate> ::= <row value
predicand> [ NOT ] LIKE <character pattern> [ ESCAPE <escape
character> ]
<character pattern> ::= <character value
expression>
<escape character> ::= <character value
expression>
<octet like predicate> ::= <row value
predicand> [ NOT ] LIKE <octet pattern> [ ESCAPE <escape
octet> ]
<octet pattern> ::= <binary value
expression>
<escape octet> ::= <binary value
expression>
Specify a pattern-match comparison for character or binary
strings. The <row value predicand> is always a
<string value expression> of character or
binary type. The <character pattern> or
<octet pattern> is a <string value
expression> in which the underscore and percent characters
have special meanings. The underscore means match any one character,
while the percent means match a sequence of zero or more characters. The
<escape character> or <escape
octet> is also a <string value
expression> that evaluates to a string of exactly one
character length. If the underscore or the percent is required as normal
characters in the pattern, the specified <escape
character> or <escape octet> can
be used in the pattern before the underscore or the percent. The
<row value predicand> is compared with the
<character pattern> and the result of
comparison is returned. If any of the expressions in the predicate
evaluates to NULL, the result of the predicate is UNKNOWN. The
expression A NOT LIKE B is equivalent to NOT
(A LIKE B). If the length of the escape is not 1 or it is used
in the pattern not immediately before an underscore or a percent
character, an exception is raised.
IS NULL
null predicate
<null predicate> ::= <row value predicand>
IS [ NOT ] NULL
Specify a test for a null value. The expression X IS
NOT NULL is NOT equivalent to NOT (X IS
NULL)if the degree of the <row value
predicand> is larger than 1. The rules are: If all fields
are null, X IS NULL is TRUE and X IS NOT
NULL is FALSE. If only some fields are null, both X
IS NULL and X IS NOT NULL are FALSE. If all
fields are not null, X IS NULL is FALSE and
X IS NOT NULL is TRUE.
ALL and ANY
quantified comparison predicate
<quantified comparison predicate> ::= <row
value predicand> <comp op> <quantifier> <table
subquery>
<quantifier> ::= <all> |
<some>
<all> ::= ALL
<some> ::= SOME | ANY
Specify a quantified comparison. For a quantified comparison,
the <row value predicand> is compared one by
one with each row of the <table sub
query>.
If the <table subquery> returns no
rows, then if ALL is specified the result is TRUE,
but if SOME or ANY is specified
the result is FALSE.
If ALL is specified, if the comparison is
TRUE for all rows, the result of the predicate is TRUE. If the
comparison is FALSE for at least one row, the result is FALSE. Otherwise
the result is UNKNOWN.
If SOME or ANY is
specified, if the comparison is TRUE for at least one row, the result is
TRUE. If the comparison is FALSE for all rows, the result is FALSE.
Otherwise the result is UNKNOWN. Note that the IN predicate is
equivalent to the SOME or ANY predicate using the <equals
operator>.
In the examples below, the date of an invoice is compared to holidays in a given year. In the first example the invoice date must equal one of the holidays, in the second example it must be later than all holidays (later than the last holiday), in the third example it must be on or after some holiday (on or after the first holiday), and in the fourth example, it must be before all holidays (before the first holiday).
invoice_date = SOME (SELECT holiday_date FROM holidays) invoice_date > ALL (SELECT holiday_date FROM holidays) invoice_date >= ANY (SELECT holiday_date FROM holidays) invoice_date < ALL (SELECT holiday_date FROM holidays)
EXISTS
exists predicate
<exists predicate> ::= EXISTS <table
subquery>
Specify a test for a non-empty set. If the evaluation of
<table subquery> results in one or more rows,
then the expression is TRUE, otherwise FALSE.
UNIQUE
unique predicate
<unique predicate> ::= UNIQUE <table
subquery>
Specify a test for the absence of duplicate rows. The result of
the test is either TRUE or FALSE (never UNKNOWN). The rows of the
<table subquery> that contain one or more NULL
values are not considered for this test. If the rest of the rows are
distinct from each other, the result of the test is TRUE, otherwise it
is FALSE. The distinctness of rows X and Y is tested with the predicate
X IS DISTINCT FROM Y.
MATCH
match predicate
<match predicate> ::= <row value
predicand> MATCH [ UNIQUE ] [ SIMPLE | PARTIAL | FULL ] <table
subquery>
Specify a test for matching rows. The default is MATCH SIMPLE without UNIQUE. The result of the test is either TRUE or FALSE (never UNKNOWN).
The interpretation of NULL values is different from other
predicates and quite counter-intuitive. If the <row value
predicand> is NULL, or all of its fields are NULL, the
result is TRUE.
Otherwise, the <row value predicand>
is compared with each row of the <table
subquery>.
If SIMPLE is specified, if some field of <row value
predicate> is NULL, the result is TRUE. Otherwise if
<row value predicate> is equal to one or more
rows of <table subquery> the result is TRUE if
UNIQUE is not specified, or if UNIQUE is specified and only one row
matches. Otherwise the result is FALSE.
If PARTIAL is specified, if the non-null values
<row value predicate> are equal to those in one
or more rows of <table subquery> the result is
TRUE if UNIQUE is not specified, or if UNIQUE is specified and only one
row matches. Otherwise the result is FALSE.
If FULL is specified, if some field of <row value
predicate> is NULL, the result is FALSE. Otherwise if
<row value predicate> is equal to one or more
rows of <table subquery> the result is TRUE if
UNIQUE is not specified, or if UNIQUE is specified and only one row
matches.
Note that MATCH can also used be used in FOREIGN KEY constraint definitions. The exact meaning is described in the Schemas and Database Objects chapter.
OVERLAPS
overlaps predicate
<overlaps predicate> ::= <row value
predicand> OVERLAPS <row value predicand>
Specify a test for an overlap between two datetime periods.
Each <row value predicand> must have two fields
and the fields together represent a datetime period. So the predicates
is always in the form (X1, X2) OVERLAPS (Y1, Y2). The
first field is always a datetime value, while the second field is either
a datetime value or an interval value.
If the second value is an interval value, it is replaced with
the sum of the datetime value and itself, for example (X1, X1 +
X2) OVERLAPS (Y1, Y1 + Y 2).
If any of the values is NULL, the result is UNKNOWN.
The expression is true if there is there is any overlap between the two datetime periods. In the example below, the period is compared with a week long period ending yesterday.
(startdate, enddate) OVERLAPS (CURRENT_DATE - 7 DAY, CURRENT_DATE - 1 DAY)
IS DISTINCT
is distinct predicate
<distinct predicate> ::= <row value
predicand> IS [ NOT ] DISTINCT FROM <row value
predicand>
Specify a test of whether two row values are distinct. The
result of the test is either TRUE or FALSE (never UNKNOWN). The
degree the two <row value
predicand> must be the same. Each field of the first
<row value predicand> is compared to the field
of the second <row value predicand> at the same
position. If one field is NULL and the other is not NULL, or if the
elements are NOT equal, then the result of the expression is TRUE. If no
comparison result is TRUE, then the result of the predicate is FALSE.
The expression X IS NOT DISTINCT FROM Y is equivalent
to NOT (X IS DISTINCT FORM Y). The following check
returns true if startdate is not equal to enddate. It also returns true
if either startdate or enddate is NULL. It returns false in other
cases.
startdate IS DISTINCT FROM enddate
search condition
search condition
<search condition> ::= <boolean value
expression>
Specify a condition that is TRUE, FALSE, or UNKNOWN. A search condition is often a predicate.
PATH
path specification
<path specification> ::= PATH <schema name
list>
<schema name list> ::= <schema name> [ {
<comma> <schema name> }... ]
Specify an order for searching for a user-defined SQL-invoked routine. This is not currently supported by HyperSQL.
routine invocation
routine invocation
<routine invocation> ::= <routine name>
<SQL argument list>
<routine name> ::= [ <schema name>
<period> ] <qualified identifier>
<SQL argument list> ::= <left paren> [
<SQL argument> [ { <comma> <SQL argument> }... ] ]
<right paren>
<SQL argument> ::= <value expression> |
<target specification>
Invoke an SQL-invoked routine. Examples are given in the SQL-Invoked Routines chapter.
COLLATE
collate clause
<collate clause> ::= COLLATE <collation
name>
Specify a default collation for a column or for an ORDER BY expression. This is supported by HyperSQL from version 2.1.
CONSTRAINT
constraint name definition
<constraint name definition> ::= CONSTRAINT
<constraint name>
<constraint characteristics> ::= <constraint
check time> [ [ NOT ] DEFERRABLE ] | [ NOT ] DEFERRABLE [
<constraint check time> ]
<constraint check time> ::= INITIALLY DEFERRED |
INITIALLY IMMEDIATE
Specify the name of a constraint and its characteristics. This is an optional element of CONSTRAINT definition, not yet supported by HyperSQL.
aggregate function
aggregate function
<aggregate function> ::= COUNT <left
paren> <asterisk> <right paren> [ <filter clause> ]
| <general set function> [ <filter clause> ] | <array
aggregate function> [ <filter clause> ]
<general set function> ::= <set function
type> <left paren> [ <set quantifier> ] <value
expression> <right paren>
<set function type> ::= <computational
operation>
<computational operation> ::= AVG | MAX | MIN |
SUM | EVERY | ANY | SOME | COUNT | STDDEV_POP | STDDEV_SAMP | VAR_SAMP |
VAR_POP | MEDIAN
<set quantifier> ::= DISTINCT |
ALL
<filter clause> ::= FILTER <left paren>
WHERE <search condition> <right paren>
<array aggregate function> ::= { ARRAY_AGG |
GROUP_CONCAT } <left paren> [ <set quantifier> ] <value
expression> [ <order by clause> ] [ <separator> ]
<right paren>
<separator> ::= <character string
literal>
Specify a value computed from a collection of rows.
An aggregate function is used exclusively in a
<query specification> and its use transforms a
normal query into an aggregate query returning a single row instead of
the multiple rows that the original query returns. For example,
SELECT acolumn <table expression> is a query
that returns the value of acolumn for all the rows the satisfy the given
condition. But SELECT MAX(acolumn) <table
expression> returns only one row, containing the largest
value in that column. The query SELECT COUNT(*) <table
expression> returns the count of rows, while
SELECT COUNT(acolumn) <table expression>
returns the count of rows where acolumn IS NOT
NULL.
If the <table expression> is a grouped
table (has a GROUP BY clause), the aggregate function
returns the result of the COUNT or
<computational operation> for each group. In
this case the result has the same number of rows as the original grouped
query. For example SELECT SUM(acolumn) <table
expression> when <table
expression> has a GROUP BY clause,
returns the sum of values for acolumn in each
group.
The SUM operations can be performed on numeric expressions only. AVG and MEDIAN can be performed on numeric or datetime expressions. AVG returns the average value, while SUM returns the sum of all values. If all values are NULL, the operations return NULL. MEDIAN returns the middle value in the sorted list of values.
MAX and MIN can be performed on all types of expressions and return the minimum or the maximum value. If all values are NULL, the operations return NULL.
COUNT(*) returns the count of all values,
including nulls, while COUNT(<value
expression>) returns the count of non-NULL
values.
The EVERY, ANY and SOME operations can be performed on boolean expressions only. EVERY returns TRUE if all the values are TRUE, otherwise FALSE. ANY and SOME are the same operation and return TRUE if one of the values is TRUE, otherwise it returns FALSE.
The other operations perform the statistical functions STDDEV_POP, STDDEV_SAMP, VAR_SAMP, VAR_POP on numeric values. NULL values are ignored in calculations.
User defined aggregate functions can be defined and used instead of the built-in aggregate functions. Syntax and examples are given in the SQL-Invoked Routines chapter.
The <filter clause> allows you to add a
search condition. When the search condition evaluates to TRUE for a row,
the row is included in aggregation. Otherwise the row is not included.
In the example below a single query returns two different filtered
counts:
SELECT COUNT(ITEM) FILTER (WHERE GENDER = 'F') AS "FEMALE COUNT", COUNT(ITEM) FILTER (WHERE GENDER = 'M') AS "MALE COUNT" FROM PEOPLE
ARRAY_AGG is different from all other aggregate functions, as
it does not ignore the NULL values. This set function returns an array
that contains all the values, for different rows, for the
<value expression>. For example, if the
<value expression> is a column reference, the
SUM function adds the values for all the row together, while the
ARRAY_AGG function adds the value for each row as a separate element of
the array. ARRAY_AGG can include an optional <order by clause>. If
this is used, the elements of the returned array are sorted according to
the <order by clause>, which can reference all
the available columns of the query, not just the <value
expression> that is used as the ARRAY_AGG argument. The
<order by clause> can have multiple elements
and each element can include NULLS LAST or DESC qualifiers. No
<separator> is used with this
function.
GROUP_CONCAT is a specialised function derived from ARRAY_AGG. This function computes the array in the same way as ARRAY_AGG, removes all the NULL elements, then returns a string that