Befehlsreferenz |
Dieses Kapitel ist das Kernstück von SQL in a Nutshell; hier werden in alphabetischer Reihenfolge alle SQL-Befehle detailliert und anhand von Beispielen erläutert. Bei jedem Befehl und jeder Funktion ist in einer Haupttabelle angegeben, inwieweit die in diesem Buch behandelten vier SQL-Dialekte (SQL Server, MySQL, Oracle und PostgreSQL) diese(n) unterstützen: "Unterstützt", "Unterstützt, mit Variationen", "Unterstützt, mit Einschränkungen" und "Nicht unterstützt". Nach einer kurzen Beschreibung des SQL99-Standards werden die Datenbanksysteme der einzelnen Hersteller kurz aber gründlich mit Beispielen und Beispielcode erklärt.

ALTER PROCEDURE |
Mit der Anweisung ALTER PROCEDURE kann eine bestehende gespeicherte Prozedur verändert werden. Welche Änderungen in welchem Umfang vorgenommen werden können, hängt vom Hersteller ab.
In SQL Server wird mit dieser Anweisung eine zuvor mit CREATE PROCEDURE erzeugte Prozedur geändert, wobei dies jedoch weder Auswirkungen auf Zugriffsrechte noch auf abhängige gespeicherte Prozeduren oder Trigger hat.
In Oracle wird mit diesem Befehl einfach eine gespeicherte PL/SQL-Prozedur neu kompiliert, wobei sich der Code aber nicht ändern lässt. Dazu müssen Sie in Oracle den Befehl CREATE OR REPLACE PROCEDURE verwenden.
Hersteller | Befehl
--- | ---
SQL Server | Unterstützt, mit Variationen
MySQL | Nicht unterstützt
Oracle | Unterstützt, mit Variationen
PostgreSQL | Nicht unterstützt
SQL99: Syntax und Beschreibung
    ALTER PROCEDURE procedure_name {CASCADE | RESTRICT}
    [LANGUAGE | PARAMETER STYLE | <SQL data access> | <null clause behavior> | DYNAMIC RESULT SETS | NAME]
    [parameter datatype [,...n]
Wie unter CREATE PROCEDURE beschrieben, können LANGUAGE, PARAMETER STYLE, die SQL-Datenzugriffsmethode (d. h. NO SQL, CONTAINS SQL usw.), das Null-Klausel-Verhalten (d. h. CALL ON NULL INPUT), DYNAMIC RESULT SET und der Prozedur-NAME allesamt geändert werden.
Der Befehl ALTER PROCEDURE kann auch verwendet werden, um die Anzahl oder den Typ der Eingabeparameter zu ändern.
Microsoft SQL Server: Syntax und Variationen
    ALTER PROC[EDURE] procedure_name [;number]
    [ {@parameter datatype } [VARYING] [= default] [OUTPUT] ][,...n]
    [WITH { RECOMPILE | ENCRYPTION  | RECOMPILE , ENCRYPTION } ]
    [FOR REPLICATION]
    AS
    T-SQL Block
In SQL Server können mit diesem Befehl alle bestehenden Parameter für zuvor erzeugte gespeicherte Prozeduren geändert werden. Eigentlich ist dieser Befehl nur eine Kurzversion der Anweisung DROP PROCEDURE, gefolgt von einer modifizierten CREATE PROCEDURE-Anweisung. Die Zugriffsrechte der gespeicherten Prozedur müssen so nicht neu eingerichtet werden. Eine vollständige Beschreibung der Syntax finden Sie unter CREATE PROCEDURE. Dieser Befehl kann in SQL Server vom Eigentümer der gespeicherten Prozedur sowie von einem Mitglied der festen Datenbankrollen db_owner und ddl_admin ausgeführt werden.
Oracle: Syntax und Variationen
    ALTER PROCEDURE [user.]procedure_name COMPILE [DEBUG];
In Oracle muss der Name der Prozedur oder des Package, das kompiliert werden soll, angegeben werden. Das Schlüsselwort COMPILE ist ebenfalls erforderlich. Mit der Option COMPILE [DEBUG] wird der PL/SQL-Code neu generiert. Dieser Befehl kann nur vom Eigentümer der gespeicherten Prozedur oder von Personen mit dem Privileg ALTER ANY PROCEDURE ausgeführt werden.
Beispiel
In diesem Beispiel für Microsoft SQL Server wird eine Prozedur mit dem Namen get_next_br erzeugt, die einen eindeutigen CHAR(22)-Ausgabestring generiert. Dann soll diese Prozedur dahingehend geändert werden, dass ein eindeutiger INT-Wert zurückgegeben wird. Dazu wird ALTER PROCEDURE verwendet:
    -- Gespeicherte Prozedur in Microsoft SQL Server
    CREATE PROCEDURE get_next_nbr
       @next_nbr CHAR(22) OUTPUT
    AS
    BEGIN
      DECLARE @random_nbr INT
      SELECT @random_nbr = RAND(  ) * 1000000

    SELECT @next_nbr =
      RIGHT('000000' + CAST(ROUND(RAND(@random_nbr)*1000000,0))AS CHAR(6), 6) +
      RIGHT('0000' + CAST(DATEPART (yy, GETDATE(  ) ) AS CHAR(4)), 2) +
      RIGHT('000'  + CAST(DATEPART (dy, GETDATE(  ) ) AS CHAR(3)), 3) +
      RIGHT('00'   + CAST(DATEPART (hh, GETDATE(  ) ) AS CHAR(2)), 2) +
      RIGHT('00'   + CAST(DATEPART (mi, GETDATE(  ) ) AS CHAR(2)), 2) +
      RIGHT('00'   + CAST(DATEPART (ss, GETDATE(  ) ) AS CHAR(2)), 2) +
      RIGHT('000'  + CAST(DATEPART (ms, GETDATE(  ) ) AS CHAR(3)), 3)
    END
    GO

    ALTER PROCEDURE get_next_nbr
       @next_nbr INT OUTPUT
    AS
    BEGIN
      DECLARE @convert_to_nbr CHAR(22)
      DECLARE @random_nbr INT
      SELECT  @random_nbr = RAND(  ) * 1000000

    SELECT @convert_to_nbr =
      RIGHT('000000' + CAST(ROUND(RAND(@random_nbr)*1000000,0))AS CHAR(6), 6) +
      RIGHT('0000' + CAST(DATEPART (yy, GETDATE(  ) ) AS CHAR(4)), 2) +
      RIGHT('000'  + CAST(DATEPART (dy, GETDATE(  ) ) AS CHAR(3)), 3) +
      RIGHT('00'   + CAST(DATEPART (hh, GETDATE(  ) ) AS CHAR(2)), 2) +
      RIGHT('00'   + CAST(DATEPART (mi, GETDATE(  ) ) AS CHAR(2)), 2) +
      RIGHT('00'   + CAST(DATEPART (ss, GETDATE(  ) ) AS CHAR(2)), 2) +
      RIGHT('000'  + CAST(DATEPART (ms, GETDATE(  ) ) AS CHAR(3)), 3)

    SELECT @next_nbr = CAST(@convert_to_nbr AS INT)

    END
    GO

ALTER TABLE |
Mit der Anweisung ALTER TABLE kann eine bestehende Tabelle geändert werden, ohne dass diese gelöscht wird oder dies Auswirkungen auf die Zugriffsrechte der Tabelle hat. Damit können auf einfache Art und Weise inkrementelle Änderungen an einer Tabelle durchgeführt werden.
Sowohl Oracle als auch Microsoft SQL Server unterstützen diesen Befehl mit einer Reihe von Variationen, die die verschiedenen Methoden zur Zuweisung physischer Dateien abdecken.
Hersteller | Befehl
--- | ---
SQL Server | Unterstützt, mit Variationen
MySQL | Unterstützt, mit Einschränkungen
Oracle | Unterstützt, mit Variationen
PostgreSQL | Unterstützt, mit Variationen
SQL99: Syntax und Beschreibung
    ALTER TABLE table_name
    [ADD [COLUMN] column_name datatype attributes]
    | [ALTER [COLUMN] column_name SET DEFAULT default_value]
    | [ALTER [COLUMN] column_name DROP DEFAULT]
    | [ALTER [COLUMN] column_name ADD SCOPE table_name
    | [ALTER [COLUMN] column_name DROP SCOPE {RESTRICT | CASCADE}]
    | [DROP [COLUMN] column_name {RESTRICT | CASCADE}]
    | [ADD table_constraint_name]
    | [DROP CONSTRAINT table_constraint_name {RESTRICT | CASCADE}]
Mit der SQL99-Anweisung ALTER TABLE können viele nützliche Änderungen an einer bestehenden Tabelle vorgenommen werden. Dieser vielseitige Befehl bietet die Möglichkeit, Spalten- und Tabellen-Constraints hinzuzufügen, DEFAULT-Werte festzulegen und zu löschen, den SCOPE-Wert von Spalten, die einen benutzerdefinierten Typ referenzieren, hinzuzufügen oder zu löschen und mit DROP sowohl Spalten- als auch Tabellen-Constraints zu löschen. DROP RESTRICT fordert das Host-DBMS auf, die Ausführung des Befehls abzubrechen, wenn festgestellt wird, dass andere Objekte in der Datenbank von dem Spalten- oder Tabellen-Constraint abhängen. DROP CASCADE teilt dem Host-DBMS mit, dass alle Datenbankobjekte gelöscht werden sollen, die von dem Spalten- oder Tabellen-Constraint abhängen. Nähere Erläuterungen zu diesem Befehl finden Sie unter CREATE TABLE.
Microsoft SQL Server: Syntax und Variationen
    ALTER TABLE table_name
    [ALTER COLUMN column_name new_data_type attributes {ADD | DROP}
       ROWGUIDCOL]
    | [ADD [COLUMN] column_name datatype attributes][,...n]
    | [WITH CHECK | WITH NOCHECK] ADD table_constraint][,...n]
    | [DROP { [ CONSTRAINT ] constraint_name | COLUMN column_name }] [,...n]
    | [{ CHECK | NOCHECK } CONSTRAINT { ALL | constraint_name [,...n] }]
    | [{ ENABLE | DISABLE } TRIGGER { ALL | trigger_name [,...n] }]
Die Microsoft SQL Server-Implementierung von ALTER TABLE bietet eine Vielzahl von Möglichkeiten. Mit ALTER COLUMN können bestehende Spalten im Hinblick auf Datentyp, Null-Zulässigkeit, Identitätsfunktionen usw. geändert werden. Mit ADD wird der Tabelle an der letzten Spaltenposition eine neue Spalte, eine berechnete Spalte oder ein Constraint hinzugefügt. (Derzeit gibt es keine Möglichkeit, eine Spalte in der Mitte oder an einer anderen Stelle der Tabelle einzufügen.) Das optionale Wort COLUMN wird nur aus Gründen der Lesbarkeit angegeben, ist aber nicht notwendig. Die neue Spalte muss genauso wie bei der Anweisung CREATE TABLE definiert werden, einschließlich aller Constraints, Standardwerte und Sortierreihenfolgen.
Die Klauseln WITH CHECK und WITH NOCHECK teilen SQL Server mit, ob die Tabellendaten anhand der neu hinzugefügten Constraints oder Schlüssel validiert werden sollen. Wenn Constraints mit WITH NOCHECK hinzugefügt werden, ignoriert der Abfrageoptimierer sie, bis sie mit ALTER TABLE table_name CHECK CONSTRAINT ALL aktiviert werden. Constraints können mit DROP CONSTRAINT gelöscht (das Schlüsselwort CONSTRAINT ist dabei nicht erforderlich) und mit CHECK CONSTRAINT und NOCHECK CONSTRAINT aktiviert bzw. deaktiviert werden.
In ähnlicher Weise kann ein benannter Trigger für eine Tabelle mit der Klausel ENABLE TRIGGER aktiviert und mit der Klausel DISABLE TRIGGER deaktiviert werden. Die Trigger für eine Tabelle können auch alle auf einmal mit dem Schlüsselwort ALL anstatt dem Tabellennamen aktiviert werden wird, wie zum Beispiel in ALTER TABLE employee DISABLE TRIGGER ALL.
MySQL: Syntax und Variationen
    ALTER [IGNORE] TABLE table_name
    [ADD [COLUMN] column_name datatype attributes ]
       [FIRST | AFTER column_name]] [,...n]
    | [ADD INDEX [index_name] (index_col_name,...)] [,...n]
    | [ADD PRIMARY KEY (index_col_name,...)] [,...n]
    | [ADD UNIQUE [index_name] (index_col_name,...)] [,...n]
    | [ALTER [COLUMN] column_name {SET DEFAULT literal | DROP DEFAULT}] [,...n]
    | [CHANGE [COLUMN] old_col_name create_definition] [,...n]
    | [MODIFY [COLUMN] column_name datatype attributes] [,...n]
    | [DROP [COLUMN] column_name] [,...n]
    | [DROP PRIMARY KEY] [,...n]
    | [DROP INDEX index_name] [,...n]
    | [RENAME [AS] new_tbl_name] [,...n]
    | [table_options]
Nähere Informationen zu den zulässigen Spaltenattributen und Tabellen-Constraints finden Sie unter der Anweisung CREATE TABLE.
Mit der Option IGNORE wird MySQL aufgefordert, doppelte Zeilen zu löschen, wenn ein neuer eindeutiger Schlüssel definiert wird. Wenn IGNORE nicht angegeben ist, wird die Operation abgebrochen, wenn es für den eindeutigen Schlüssel mehrere Datensätze gibt.
Die Option FIRST wird verwendet, wenn eine neue Spalte als erste Spalte der Tabelle hinzugefügt werden soll. Mit AFTER column_name kann eine neue Spalte nach einer vorhandenen Spalte (column_name) in die Tabelle eingefügt werden.
Bei der Anweisung ALTER TABLE bietet MySQL zusätzliche Flexibilität, weil der Benutzer die Möglichkeit hat, mehrere ADD-, ALTER-, DROP- und CHANGE-Klauseln in eine einzige ALTER TABLE-Anweisung zu stellen. Es sei jedoch darauf hingewiesen, dass die Klauseln CHANGE column_name und DROP INDEX MySQL-Erweiterungen sind, die es im SQL99-Standard nicht gibt. MySQL unterstützt außerdem die Oracle-Erweiterung MODIFY column_name. Mit der Klausel ALTER COLUMN kann ein neuer Standardwert für eine Spalte festgelegt oder gelöscht werden.
Eine Tabelle kann mit RENAME AS umbenannt werden, und eine Spalte mit CHANGE. Mit dem nachfolgenden Code wird zum Beispiel sowohl eine Tabelle als auch eine Spalte umbenannt:
    ALTER TABLE employee RENAME AS emp;
    ALTER TABLE employee CHANGE employee_ssn emp_ssn INTEGER;
Weil MySQL es erlaubt, Indizes nur für Teile einer Spalte zu erstellen (zum Beispiel die ersten zehn Zeichen), können die Befehle CHANGE und MODIFY nicht dazu verwendet werden, eine Spalte zu erzeugen, die kürzer ist als die entsprechenden Indizes. Bei Benutzung von DROP COLUMN wird die Spalte sowohl aus der Tabelle als auch aus allen Indizes, die auf dieser Spalte basieren, gelöscht.
DROP PRIMARY KEY schlägt nicht automatisch fehl, wenn auf der Tabelle kein Primärschlüssel liegt. In diesem Fall löscht MySQL den ersten eindeutigen Index der Tabelle.
In MySQL kann der Datentyp einer bestehenden Spalte umdefiniert werden, ohne dass Daten verloren gehen. Die in der Spalte enthaltenen Werte müssen mit dem neuen Datentyp kompatibel sein. Beispielsweise kann eine Datumsspalte in eine Zeichenspalte umdefiniert werden, nicht aber eine Zeichenspalte in eine Integerspalte. Dazu ein Beispiel:
    ALTER TABLE mytable MODIFY mycolumn LONGTEXT
MySQL erlaubt die Klauseln FOREIGN KEY, CHECK und REFERENCES, diese sind allerdings leer. Befehle, die diese Klauseln enthalten, können zwar ausgeführt werden, sie haben jedoch keine Auswirkung. Sie stehen hauptsächlich zur Verfügung, um das Portieren zu erleichtern.
Oracle: Syntax und Variationen
    ALTER TABLE [owner_name.]table_name
    [ADD column_name datatype attributes]
    | [MODIFY {column_name datatype
       | column_constraint
       | physical_storage_attributes [LOGGING | NOLOGGING]
       | nested_table_attributes}]
    | [MODIFY CONSTRAINT {constraint_name {constraint_state}
       | drop_constraint_clause
       | drop_column_clause
       | [ALLOCATE | DEALLOCATE extent_clause]
       | [CACHE | NOCACHE]
       | [LOGGING | NOLOGGING]
       | [MONITORING | NOMONITORING] ]
    | [DROP {[COLUMN] column_name | constraint_name}]
    | [ALLOCATE EXTENT details]
    | [DEALLOCATE UNUSED details]
    | [RENAME TO new_table_name]
    | [OVERFLOW physical_storage_attributes]
    | [ADD OVERFLOW physical_storage_attributes]
    | [{ADD | DROP | MODIFY | MOVE | TRUNCATE | SPLIT | EXCHANGE | MODIFY}
       PARTITION partition_details]
Die Anweisung ALTER TABLE in Oracle zeigt die zahlreichen Möglichkeiten zur Steuerung des physischen Speichers und zur Manipulation von Tabellen, wie zum Beispiel die Handhabung von Daten-Extents und Overflow-Extents und die Partitionierung von Tabellen zur besseren Verteilung extremer Nutzungslasten. Die Syntax, die für bestimmte oben aufgeführte Zeilen wie column_constraint, physical_storage_attributes und nested_table_attributes zulässig ist, wird im Abschnitt zur Oracle-Implementierung von CREATE TABLE beschrieben.
Dieser Befehl kann verwendet werden, um mit ADD eine neue Spalte oder einen neuen Constraint hinzuzufügen oder um mit MODIFY und DROP bestehende Spalten und Constraints zu ändern bzw. zu löschen. Wenn eine neue Spalte hinzugefügt wird, sollte diese als NULL definiert werden, es sei denn, die Tabelle enthält keine Zeilen. Mit dem Schlüsselwort MODIFY können Sie die Eigenschaften einer zuvor erzeugten Tabelle ändern. Mit MODIFY CONSTRAINT können Sie Tabellen-Constraints löschen oder ändern und unter anderem auch festlegen, ob LOGGING, CACHE oder MONITOR aktiviert und ob Speicher-Extents alloziert (ALLOCATE) oder dealloziert (DEALLOCATE) werden sollen. Weiterhin werden die Schlüsselwörter ENABLE und DISABLE zum Aktivieren und Deaktivieren von Tabellen-Constraints unterstützt.
Die Oracle-Implementierung von ALTER TABLE ist sehr vielfältig und komplex. Umfassende Informationen zu Unterklauseln für gemeinsame Befehle finden Sie unter der Anweisung CREATE TABLE.
Der folgende Code fügt einer Tabelle in Oracle beispielsweise eine neue Spalte hinzu und legt einen neuen, eindeutigen Constraint auf diese Tabelle:
    ALTER TABLE titles
    ADD subtitle VARCHAR2(32) NULL
    CONSTRAINT unq_subtitle UNIQUE;
Wenn einer Tabelle ein Fremdschlüssel-Constraint hinzugefügt wird, überprüft das DBMS, ob alle Daten in der Tabelle diese Integritätsregel erfüllen. Ist dies nicht der Fall, schlägt ALTER TABLE fehl.
Alle Anwendungen, die SELECT * verwenden, geben die neuen Spalten zurück, auch wenn dies nicht geplant war. Andererseits geben vorkompilierte Objekte wie gespeicherte Prozeduren möglicherweise keine neuen Spalten zurück.
Oracle lässt auch mehrfache Aktionen wie ADD oder MODIFY in mehreren Spalten zu, wobei die Aktion in runde Klammern gesetzt werden muss. Mit dem folgenden Befehl werden beispielsweise einer Tabelle in einer einzigen Anweisung mehrere Spalten hinzugefügt:
    ALTER TABLE titles
    ADD (subtitles VARCHAR2(32) NULL,
       year_of_copyright INT,
       date_of_origin DATE);
PostgreSQL: Syntax und Variationen
    ALTER TABLE table [*]
    [ADD [COLUMN] column_name datatype attributes]
    | [ALTER [COLUMN] column_name {SET DEFAULT value | DROP DEFAULT}]
    | [RENAME [COLUMN] column_name TO new_column_name]
    | [RENAME TO new_table_name]
Die PostgreSQL-Implementierung von ALTER TABLE ermöglicht das Hinzufügen weiterer Spalten mit dem Schlüsselwort ADD . Bestehenden Spalten können mit ALTER COLUMN . . . SET DEFAULT neue Standardwerte zugewiesen werden, während sich mit ALTER COLUMN . . . DROP DEFAULT ein spaltenbasierter Standardwert vollständig löschen lässt. Darüber hinaus können mit der Klausel ALTER neue Standardwerte zu Spalten hinzugefügt werden, wobei davon aber nur neu eingefügte Zeilen betroffen sind. Mit RENAME können bestehende Spalten und Tabellen umbenannt werden.

ALTER TRIGGER |
Mit der Anweisung ALTER TRIGGER kann eine vorhandene Triggerdefinition geändert werden, ohne dass dies Auswirkungen auf Zugriffsrechte oder Abhängigkeiten hat.
Hersteller | Befehl
--- | ---
SQL Server | Unterstützt, mit Variationen
MySQL | Nicht unterstützt
Oracle | Unterstützt, mit Variationen
PostgreSQL | Nicht unterstützt
SQL99: Syntax und Beschreibung
Derzeit gibt es keinen SQL99-Standard für diesen Befehl.
Microsoft SQL Server: Syntax und Variationen
    ALTER TRIGGER trigger_name
    ON {table_name | view_name}
    [WITH ENCRYPTION]
    {FOR | AFTER | INSTEAD OF} {[DELETE] [,] [INSERT] [,] [UPDATE]}
    [WITH APPEND]
    [NOT FOR REPLICATION]
    AS
      T-SQL_block
    | [FOR { [INSERT] [,] [UPDATE] }
    [NOT FOR REPLICATION]
    AS

      { IF UPDATE(column) [{AND | OR} UPDATE(column)] [...n]
        |
        IF (COLUMNS_UPDATED(  ) {bitwise_operator} updated_bitmask)
        { comparison_operator} column_bitmask [...n] }
        T-SQL_block ] } ]
Microsoft SQL Server ermöglicht die Angabe von FOR | AFTER | INSTEAD OF { [DELETE] [,] [UPDATE] [,][INSERT] } | { [INSERT] [,] [UPDATE] }, um zu beschreiben, welcher Trigger einer Anweisung zur Datenmodifikation von dem Befehl betroffen ist. Es muss mindestens einer dieser Werte angegeben werden. Es ist jedoch jede beliebige Kombination möglich, wobei die zusätzlichen Optionen durch Kommas zu trennen sind. Die Optionen FOR und AFTER sind im Prinzip gleich und sorgen dafür, dass der Triggercode ausgelöst wird, sobald die Datenmanipulationsoperation abgeschlossen ist. Alternativ dazu fordert die Klausel INSTEAD OF SQL Server auf, die Datenmanipulationsoperation vollständig durch den Code des Triggers zu ersetzen.
Mit WITH APPEND wird SQL Server mitgeteilt, dass der Basistabelle ein weiterer Trigger des angegebenen Typs hinzugefügt werden soll. Dies ist nur bei FOR-Triggern möglich. Die Klausel NOT FOR REPLICATION teilt SQL Server mit, den Trigger nicht auszuführen, wenn die Aktion durch ein Replikations-Login wie sqlrepl ausgelöst wird. Die Klausel IF UPDATE (column) prüft, ob eine INSERT- oder UPDATE-Aktion (aber nicht DELETE) für eine bestimmte Spalte vorliegt. Sie ist sehr nützlich, wenn es um zeilenbasierte Operationen mit Cursorn geht. Mit den Operatoren {AND | OR} können zusätzliche Spalten in derselben Klausel getestet werden. Mit IF (COLUMNS_UPDATED( )) wird ein INSERT- oder UPDATE-Trigger abgefragt, um herauszufinden, ob die angegebenen Spalten betroffen waren. Die Ergebnisse werden als Bit-Operatoren zurückgegeben.
Oracle: Syntax und Variationen
    ALTER TRIGGER [user.]trigger_name [ENABLE | DISABLE | COMPILE [DEBUG] ];
In Oracle kann der dem Trigger zugrunde liegende Code mit diesem Befehl nicht vollständig geändert werden (dies lässt sich mit der Oracle-Implementierung von CREATE OR REPLACE TRIGGER) erreichen. Mit ALTER TRIGGER kann in Oracle ein Trigger aktiviert, deaktiviert oder neu kompiliert werden. Mit der Option COMPILE [DEBUG] werden PL/SQL-Informationen neu generiert.
Oracle erlaubt Trigger nur für Tabellen (auch wenn INSTEAD OF-Trigger für Views erlaubt sind). Microsoft SQL Server erlaubt Trigger für Tabellen und aktualisierbare Views.

ALTER VIEW |
Derzeit gibt es keinen SQL99-Standard für die ALTER VIEW -Anweisung. Es ist daher wichtig zu wissen, dass sich dieser Befehl in jeder unterstützten Implementierung anders verhält. Oracle verwendet diesen Befehl zum Neukompilieren eines Views, Microsoft SQL Server dagegen zum Ändern von Views, ohne dass gleichzeitig davon abhängige gespeicherte Prozeduren, Trigger oder Zugriffsrechte aktualisiert werden.
Hersteller | Befehl
--- | ---
SQL Server | Unterstützt, mit Variationen
MySQL | Nicht unterstützt
Oracle | Unterstützt, mit Variationen
PostgreSQL | Nicht unterstützt
SQL99: Syntax und Beschreibung
Derzeit gibt es keinen SQL99-Standard für diesen Befehl.
Microsoft SQL Server: Syntax und Variationen
    ALTER VIEW view_name [(column [,...n])]
    [WITH {ENCRYPTION | SCHEMABINDING | VIEW_METADATA]
    AS
    select_statement
    [WITH CHECK OPTION]
Genau wie bei der Anweisung CREATE VIEW hat der Programmierer auch bei ALTER VIEW die Möglichkeit, die Spalten-Aliasnamen festzulegen, die der View zur Benennung der Spalten verwenden soll. Darüber hinaus kann die gesamte SELECT-Anweisung angegeben werden, die dem View zugrunde liegt.
Die anderen Klauseln der Anweisung ALTER VIEW sind unter CREATE VIEW beschrieben.
Microsoft SQL Server kann die Spaltenzugriffsrechte nur verwalten, wenn die Spaltennamen nach der Ausführung des Befehls unverändert bleiben. Mit dem Schlüsselwort ENCRYPTION kann der Code von Views in der Systemtabelle syscomments von SQL Server verschlüsselt werden. Die CHECK OPTION-Schlüsselwörter bewirken, dass alle Datenänderungen, die im View ausgeführt werden, die Kriterien der definierenden SELECT-Anweisung (select_statement) erfüllen. Wenn der View vorher eine dieser beiden Optionen enthielt, müssen diese mit der Anweisung ALTER VIEW aktiviert werden, um aktiv zu bleiben.
Oracle: Syntax und Variationen
    ALTER VIEW [user.]view_name COMPILE
Mit der Anweisung ALTER VIEW wird ein View in Oracle neu kompiliert. Sie ist nützlich, um sicherzustellen, dass ein View noch gültig ist, nachdem Änderungen an der Basistabelle vorgenommen wurden. Ein View wird ungültig, wenn seine Basistabellen geändert wurden und er nicht neu kompiliert wurde.
Beispiel
In diesem Beispiel aus SQL Server wird ein View mit dem Namen california_authors erzeugt, der Autoren aus Kalifornien enthält. Dann wird ALTER VIEW verwendet, um den View zu erweitern und zu ersetzen:
    CREATE VIEW california_authors
    AS
    SELECT au_lname, au_fname, city, state
    FROM authors
    WHERE state = 'CA'
    WITH CHECK OPTION
    GO

    ALTER VIEW california_authors
    AS
    SELECT au_fname, au_lname, address, city, state, zip
    FROM pubs..authors
    WHERE state = "CA"
    GO

CALL |
Mit der Anweisung CALL wird eine gespeicherte Prozedur aufgerufen.
Hersteller | Befehl
--- | ---
SQL Server | Nicht unterstützt
MySQL | Nicht unterstützt
Oracle | Unterstützt
PostgreSQL | Unterstützt
SQL99: Syntax und Beschreibung
    CALL procedure_name [(parameter [,...n] )]
Mit der Anweisung CALL lässt sich schnell und einfach eine gespeicherte Prozedur aufrufen. Sie brauchen lediglich den Namen der gespeicherten Prozedur und in Klammern eingeschlossen die von der gespeicherten Prozedur verwendeten Parameter anzugeben. Wenn die gespeicherte Prozedur nur OUT-Parameter oder überhaupt keine Parameter hat, können die Klammern leer bleiben.
Microsoft SQL Server unterstützt die CALL-Anweisung nicht. Eine nahezu identische Funktionalität erreichen Sie aber mit der Anweisung EXECUTE . Umfassende Informationen über diese SQL Server-Erweiterung finden Sie in der Dokumentation des Herstellers.
Oracle: Syntax und Variationen
    CALL [schema.][{type_name | package_name}.]procedure_name@dblink
    [(parameter [,...n] )]
    [INTO :variable_name [INDICATOR :indicator_name] ]
Mit der Oracle-Anweisung CALL können unabhängige gespeicherte Prozeduren, Funktionen und Methoden sowie gespeicherte Prozeduren und Funktionen in einem Typ oder Package aufgerufen werden. Wenn sich die Prozedur oder die Funktion in einer anderen Datenbank befindet, deklarieren Sie die Datenbank einfach mit einer dblink-Anweisung, die angibt, wo sich das Objekt befindet. dblink muss ein zuvor erzeugter Datenbank-Link sein.
Wenn die aufgerufene Routine eine Funktion ist, erfordert Oracle die INTO -Klausel. Umgekehrt kann INTO nur verwendet werden, wenn Funktionen aufgerufen werden. Die Variable, in der der von der Funktion zurückgegebene Wert gespeichert werden soll, muss ebenfalls angegeben werden. Zum Schluss kann noch ein Indikator angegeben werden, der die Bedingung der Hostvariablen enthält, wenn die Funktion eine vorkompilierte Pro*C/C++-Routine ist.
Beispiel
In diesem Beispiel wird eine einfache gespeicherte Prozedur erzeugt, die anschließend unabhängig davon aufgerufen wird:
    CREATE PROCEDURE update_employee_salary
    (emp_id NUMBER, updated_salary NUMBER)
    IS
    BEGIN
      UPDATE employee SET salary = updated_salary WHERE employee_id =emp_id ;
    END;

    CALL update_employee_salary(1517, 95000);

CASE |
Die Funktion CASE stellt eine IF-THEN-ELSE-Funktionalität in einer SELECT- oder UPDATE-Anweisung zur Verfügung. Sie wertet eine Liste von Bedingungen aus und gibt einen von mehreren möglichen Werten zurück.
Hersteller | Befehl
--- | ---
SQL Server | Unterstützt
MySQL | Unterstützt
Oracle | Nicht unterstützt (Sie können stattdessen die Funktion DECODE verwenden, Näheres dazu finden Sie in der Dokumentation des Herstellers)
PostgreSQL | Unterstützt
CASE kennt zwei Verwendungsarten: einfach und komplex. Bei einfachen CASE-Ausdrücken wird ein Wert - der input_value - mit einer Liste anderer Werte verglichen und das Ergebnis zurückgegeben, das zu dem ersten übereinstimmenden Wert passt. Komplexe CASE-Ausdrücke ermöglichen die Analyse verschiedener logischer Bedingungen und geben das Ergebnis zurück, das zur ersten wahren Bedingung gehört.
SQL99: Syntax und Beschreibung
    -- Einfache Vergleichsoperation
    CASE input_value
    WHEN when_condition THEN resulting_value
    [...n]
    [ELSE else_result_value]
    END

    -- Boolesche Suchoperation
    CASE
    WHEN Boolean_condition THEN resulting_value
    [...n]
    [ELSE else_result_expression]
    END
Bei einer einfachen CASE-Funktion wird der input_value mit jeder WHEN-Klausel verglichen. Der resulting_value wird für die erste wahre Instanz (TRUE) zurückgegeben, bei der gilt input_value = when_condition. Wenn keine when_condition TRUE ist, wird der else_result_value zurückgegeben. Ist kein else_result_value angegeben, wird NULL zurückgegeben.
Die Struktur der komplexeren Booleschen Operation ähnelt im Prinzip der einfachen Vergleichsoperation, unterscheidet sich aber dadurch, dass jede WHEN-Klausel ihren eigenen Booleschen Vergleichsoperator hat.
Bei beiden Verwendungsformen können mehrere WHEN-Klauseln verwendet werden, auch wenn nur eine ELSE-Klausel erforderlich ist.
Beispiele
Nachfolgend eine einfache Vergleichsoperation, bei der mit der Funktion CASE die Anzeige in der Spalte "contract" geändert wird, um sie besser lesbar zu machen:
    SELECT  au_fname,
            au_lname,
            CASE contract
                WHEN 1 THEN 'Yes'
                ELSE 'No'
            END 'contract'
    FROM    authors
    WHERE   state = 'CA'
Zum Vergleich eine komplexe CASE-Funktion in einer SELECT-Anweisung, die Auskunft darüber gibt, wie viele Titel in bestimmten Zeiträumen verkauft wurden:
    SELECT CASE
               WHEN ytd_sales IS NULL  THEN 'Unknown'
               WHEN ytd_sales <=   200 THEN 'Not more than 200'
               WHEN ytd_sales <=  1000 THEN 'Between  201 and  1000'
               WHEN ytd_sales <=  5000 THEN 'Between 1001 and  5000'
               WHEN ytd_sales <= 10000 THEN 'Between 5001 and 10000'
               ELSE 'Over 10000'
           END 'YTD Sales',
           COUNT(*) 'Number of Titles'
    FROM   titles
    GROUP BY CASE
               WHEN ytd_sales IS NULL  THEN 'Unknown'
               WHEN ytd_sales <=   200 THEN 'Not more than 200'
               WHEN ytd_sales <=  1000 THEN 'Between  201 and  1000'
               WHEN ytd_sales <=  5000 THEN 'Between 1001 and  5000'
               WHEN ytd_sales <= 10000 THEN 'Between 5001 and 10000'
               ELSE 'Over 10000'
             END
    ORDER BY MIN( ytd_sales )
Die Ergebnisse sehen folgendermaßen aus:
    YTD Sales              Number of Titles
    ---------------------- ----------------
    Unknown                2
    Not more than 200      1
    Between  201 and  1000 2
    Between 1001 and  5000 9
    Between 5001 and 10000 1
    Over 10000             3
Als nächstes haben wir eine UPDATE-Anweisung, mit der für alle Titel ein Rabatt festgelegt werden soll. Der etwas komplexere Befehl gewährt auf alle PC-Titel einen Rabatt von 25 %, auf alle anderen Titel 10 % und auf alle Titel, die bisher mehr als 10.000 Mal verkauft wurden, einen Rabatt von nur 5 %.
Die folgende UPDATE-Abfrage verwendet einen komplexen CASE-Ausdruck, um die Preise anzupassen:
    UPDATE  titles
    SET     price = price *
            CASE
                WHEN ytd_sales > 10000     THEN 0.95  -- 5% discount
                WHEN type = 'popular_comp' THEN 0.75  -- 25% discount
                ELSE 0.9                              -- 10% discount
            END
    WHERE   pub_date IS NOT NULL
Hier wurden also drei verschiedene Aktualisierungsoperationen mit einer einzigen Anweisung ausgeführt.

CAST |
Mit dem Befehl CAST wird ein Ausdruck explizit in einen anderen Datentyp umgewandelt.
Hersteller | Befehl
--- | ---
SQL Server | Unterstützt
MySQL | Nicht unterstützt
Oracle | Nicht unterstützt
PostgreSQL | Unterstützt
SQL99: Syntax und Beschreibung
    CAST(expression AS data_type[(length)])
Mit der Funktion CAST kann ein beliebiger Ausdruck wie beispielsweise ein Spaltenwert oder eine Variable in einen anderen definierten Datentyp konvertiert werden. Optional kann bei Datentypen, die Längenangaben unterstützen (wie CHAR oder VARCHAR), auch eine Länge angegeben werden.
Beachten Sie, dass es bei manchen Konvertierungen wie zum Beispiel von DECIMAL-Werten in INTEGER-Werte zu Rundungen kommen kann. Manche Konvertierungsoperationen lösen auch einen Fehler aus, wenn der neue Datentyp über nicht genügend Platz zur Anzeige des konvertierten Wertes verfügt.
Beispiel
Im folgenden Beispiel wird der bisher erzielte Umsatz als CHAR abgerufen und mit einer Literalzeichenfolge und einem Teil des Buchtitels verknüpft. Hier wird ytd_sales zu CHAR(5) konvertiert und die Länge des title verkürzt, um die Ergebnisse leichter lesbar zu machen:
    SELECT CAST(ytd_sales AS CHAR(5)) + "Copies sold of " + CAST(title AS
    VARCHAR(30))
    FROM titles
    WHERE ytd_sales IS NOT NULL
      AND ytd_sales > 10000
    ORDER BY ytd_sales DESC
Die Ergebnisse sehen folgendermaßen aus:
    ---------------------------------------------------
    22246 Copies sold of The Gourmet Microwave
    18722 Copies sold of You Can Combat Computer Stress
    15096 Copies sold of Fifty Years in Buckingham Pala

CLOSE CURSOR |
Mit dem Befehl CLOSE CURSOR wird ein serverseitiger Cursor geschlossen, der mit der Anweisung DECLARE CURSOR erzeugt wurde. MySQL unterstützt zwar keine serverseitigen Cursor, dafür aber umfassende Erweiterungen in der Programmiersprache C.
Hersteller | Befehl
--- | ---
SQL Server | Unterstützt
MySQL | Nicht unterstützt
Oracle | Unterstützt
PostgreSQL | Unterstützt
SQL99: Syntax und Beschreibung
    CLOSE { cursor_name }
Mit cursor_name ist der Name des Cursors gemeint, der mit dem Befehl DECLARE CURSOR erzeugt wurde.
Beispiel
Das folgende Beispiel aus Microsoft SQL Server öffnet einen Cursor und liest alle Zeilen aus:
    DECLARE employee_cursor CURSOR FOR
      SELECT lname, fname
      FROM pubs.dbo.authors
      WHERE lname LIKE 'K%'

    OPEN employee_cursor

    FETCH NEXT FROM employee_cursor

    WHILE @@FETCH_STATUS = 0
    BEGIN
      FETCH NEXT FROM Employee_Cursor
    END

    CLOSE employee_cursor

    DEALLOCATE employee_cursor
Mit der Anweisung DEALLOCATE in Microsoft SQL Server werden die vom Cursor beanspruchten Ressourcen und Datenstrukturen freigegeben; Oracle, PostgreSQL und MySQL verwenden diese Anweisung nicht.

COMMIT TRANSACTION |
Mit der Anweisung COMMIT TRANSACTION wird eine offene Transaktion explizit beendet, unabhängig davon, ob diese explizit mit BEGIN oder implizit als Bestandteil einer INSERT-, UPDATE- oder DELETE-Anweisung geöffnet wurde. Mit diesem Befehl kann eine Datenmanipulationsoperation manuell und dauerhaft beendet werden.
Hersteller | Befehl
--- | ---
SQL Server | Unterstützt, mit Variationen
MySQL | Nicht unterstützt
Oracle | Unterstützt
PostgreSQL | Unterstützt
SQL99: Syntax und Beschreibung
    COMMIT [WORK]
Mit COMMIT lassen sich nicht nur einzelne oder mehrere Datenmanipulationsoperationen beenden, vielmehr hat diese Anweisung auch interessante Auswirkungen auf andere Aspekte einer Transaktion. Zunächst einmal werden sämtliche zugehörigen offenen Cursor geschlossen. Zweitens werden alle Daten aus mit ON COMMIT DELETE ROWS angegebenen Tabellen gelöscht. Drittens werden alle Sperren, die im Rahmen der Transaktion angelegt wurden, aufgehoben. Zum Schluss werden noch alle verzögerten Constraints überprüft. Wenn gegen die verzögerten Constraints verstoßen wird, wird die Transaktion zurückgenommen.
SQL99 schreibt vor, dass Transaktionen implizit geöffnet werden, wenn eine der folgenden Anweisungen ausgeführt wird:
ALTER CLOSE COMMIT AND CHAIN (neu in SQL99) CREATE DELETE DROP FETCH FREE LOCATOR GRANT HOLD LOCATOR INSERT OPEN RETURN REVOKE ROLLBACK AND CHAIN (neu in SQL99) SELECT START TRANSACTION (neu in SQL99) UPDATE
Der SQL99-Standard beinhaltet die neuen optionalen Schlüsselwörter AND CHAIN. Bislang wird dieser Befehl noch von keinem der in diesem Buch behandelten Hersteller unterstützt. Diese neue Syntax sieht folgendermaßen aus:
    COMMIT [WORK] [AND [NO] CHAIN]
Mit der Option AND CHAIN wird das DBMS aufgefordert, die nachfolgende Transaktion so zu behandeln, als sei sie Bestandteil der vorhergehenden Transaktion. Die beiden Transaktionen stellen zwar separate Arbeitseinheiten dar, aber sie teilen sich eine gemeinsame Transaktionsumgebung (wie beispielsweise die Isolationsebene). Mit der Option AND NO CHAIN wird die einzelne Transaktion einfach beendet. Der Befehl COMMIT hat dieselbe Funktion wie COMMIT WORK AND NO CHAIN.
Microsoft SQL Server: Syntax und Variationen
    COMMIT [TRAN[SACTION] [transaction_name | @tran_name_variable] ]
    |
    COMMIT [WORK]
    GO
Microsoft SQL Server bietet die Möglichkeit, eine bestimmte benannte Transaktion festzuschreiben. Der Befehl COMMIT muss immer mit einem BEGIN TRAN-Befehl kombiniert werden. Mit Hilfe der COMMIT TRANSACTION-Syntax kann der Programmierer eine explizite Transaktion angeben, die geschlossen werden oder deren Name in einer Variablen gespeichert werden soll. Seltsamerweise schreibt SQL Server aber dennoch nur die letzte offene Transaktion fest, auch wenn der Name der Transaktion angegeben wird. Wenn Sie COMMIT WORK verwenden, darf kein Transaktionsname und keine Variable, die einen Transaktionsnamen enthält, angegeben werden.
Wenn es um verschachtelte benannte Trigger geht, ist diese Syntax jedoch irreführend, weil damit die äußerste Transaktion geschlossen wird. Transaktionen in SQL Server werden numerisch durch die globale Variable @@TRANCOUNT identifiziert. Alle Transaktionen werden nur dann festgeschrieben, wenn @@TRANCOUNT = 0 ist.
Oracle: Syntax und Variationen
    COMMIT [WORK];
Oracle lässt keine speziell benannten Transaktionen zu (Savepoints sind allerdings erlaubt). Aus diesem Grunde werden mit dem Befehl COMMIT einfach alle Datenmanipulationsoperationen seit dem letzten impliziten oder expliziten COMMIT festgeschrieben. Oracle unterstützt das Schlüsselwort WORK, dieses ist jedoch vollkommen optional.
PostgreSQL: Syntax und Variationen
    COMMIT [WORK | TRANSACTION];
In PostgreSQL sind die beiden Schlüsselwörter WORK und TRANSACTION optional. Die Wirkung des Befehls ist immer gleich, egal ob mit oder ohne die beiden Schlüsselwörter. Nach der Ausführung sind alle festgeschriebenen Transaktionen auf der Festplatte vorhanden und für andere Benutzer sichtbar.
Beispiel
    INSERT INTO sales VALUES('7896','JR3435','Oct 28
    1997',25,'Net
    60','BU7832');

    COMMIT WORK;

Verkettungsoperatoren |
Sollte es erforderlich sein, die Daten mehrerer Spalten in einer einzigen Spalte der Ergebnismenge von SELECT zusammenzufassen, kann dazu das vom jeweiligen DBMS unterstützte Verkettungssymbol verwendet werden.
Hersteller | Befehl
--- | ---
SQL Server | Unterstützt, mit Variationen
MySQL | Unterstützt, mit Variationen
Oracle | Unterstützt
PostgreSQL | Unterstützt
Beispiel und Beschreibung
    SELECT lname || ', ' || fname FROM customers WHERE cust_id = 41;
Der ANSI-Standard für den Verkettungsoperator ist ein doppelter senkrechter Strich ( || ), wie im vorherigen Codebeispiel zu sehen ist. Dieser wird von Oracle und PostgreSQL unterstützt.
Microsoft SQL Server verwendet ein Pluszeichen ( + ) als Verkettungssymbol.
MySQL verwendet die Funktion CONCAT(string1, numeric1, string2, numeric2 [,...n]) zur Verkettung.

CONNECT |
Mit der Anweisung CONNECT wird eine Verbindung zum DBMS und zu einer bestimmten Datenbank innerhalb des DBMS aufgebaut.
Hersteller | Befehl
--- | ---
SQL Server | Unterstützt, mit Einschränkungen
MySQL | Nicht unterstützt
Oracle | Unterstützt
PostgreSQL | Nicht unterstützt
SQL99: Syntax und Beschreibung
    CONNECT [TO] DEFAULT
    | {[server_specification] [AS connection_name] [USER user_name ] }
Wenn die Anweisung CONNECT aufgerufen wird, ohne dass die aktuelle Verbindung explizit geschlossen wurde, wird die alte Sitzung in den Ruhezustand versetzt und die neue Sitzung aktiv. Der Zeitraum zwischen der Ausführung der Anweisungen CONNECT und DISCONNECT wird üblicherweise als Sitzung (oder Session) bezeichnet . In der Regel führt der Benutzer alle Arbeiten an einem DBMS in einer explizit eingeleiteten Sitzung aus.
Das Oracle-Tool SQL*Plus verwendet den Befehl CONNECT in etwas anderer Form, und zwar wird der Benutzer mit einem bestimmten Schema verbunden.
Die Ergebnisse der Anweisung CONNECT TO DEFAULT variieren von Hersteller zu Hersteller aufgrund der unterschiedlichen Implementierung. Laut Standard sollte mit diesem Befehl eine Standardsitzung mit dem Server begonnen werden, wobei sowohl für die Benutzerautorisierung als auch für die aktuelle Datenbank der Standardwert verwendet wird.
Im Gegensatz zu CONNECT TO DEFAULT können Sie bei CONNECT TO server_name den Servernamen angeben. In diesem Fall wird die Verbindung zu dem explizit genannten Server aufgebaut. Darüber hinaus kann die Verbindung mit AS und ein Benutzer mit USER deklariert werden.
Oracle: Syntax und Variationen
    CONN[ECT] [[username/password] [AS [SYSOPER | SYSDBA] ] ]
Mit der Klausel CONNECT kann eine Datenbankverbindung unter einem bestimmten Benutzernamen angegeben werden. Alternativ dazu können Sonderrechte mit AS SYSOPER oder AS SYSDBA angefordert werden. Wenn bereits eine andere Verbindung geöffnet ist, werden mit CONNECT alle offenen Transaktionen festgeschrieben, die aktuelle Sitzung wird geschlossen und die neue geöffnet.
PostgreSQL unterstützt den Befehl CONNECT nicht explizit. Es wird aber die Anweisung SPI_CONNECT im Server Programming Interface und PG_CONNECT im PG/tcl-Paket unterstützt.
Beispiele
Um mit einer bestimmten Benutzer-ID eine Verbindung aufzubauen, könnte der Benutzer oder ein automatisiertes Programm folgenden Befehl verwenden:
    CONNECT TO USER pubs_admin
Wenn das DBMS benannte Verbindungen erfordert, könnte alternativ die folgende Syntax verwendet werden:
    CONNECT TO USER pubs_admin AS pubs_administrative_session;
Microsoft SQL Server unterstützt CONNECT TO nur in ESQL (Embedded SQL):
    EXEC SQL CONNECT TO new_york.pubs USER pubs_admin

CREATE DATABASE |
In SQL99 ist die Anweisung CREATE DATABASE nicht enthalten. Die SQL99-Anweisungen CREATE SCHEMA und CREATE CATALOG kommen der Anweisung CREATE DATABASE noch am nächsten. (CREATE SCHEMA wird weiter unten erläutert.) Es ist jedoch fast unmöglich, eine SQL-Datenbank ohne diesen Befehl zu betreiben. Fast alle Datenbankhersteller unterstützten daher irgendeine Version dieses Befehls.
Hersteller | Befehl
--- | ---
SQL Server | Unterstützt, mit Variationen
MySQL | Unterstützt
Oracle | Unterstützt
PostgreSQL | Unterstützt, mit Variationen
SQL99: Syntax und Beschreibung
    CREATE database_name
In dieser Syntax ist database_name die ID der neu anzulegenden Datenbank. Mit diesem Befehl wird eine neue, leere Datenbank mit einem bestimmten Namen erstellt. Bei den meisten Herstellern muss der Benutzer in der Root-, Master- oder Systemdatenbank stehen, wenn er eine neue Datenbank erstellen möchte. Sobald die neue Datenbank angelegt ist, kann sie mit Datenbankobjekten (Tabellen, Views, Trigger usw.) bestückt werden. Anschließend werden die Tabellen mit Daten gefüllt.
Microsoft SQL Server: Syntax und Variationen
In SQL Server und Oracle wird die Datenbank in einer vorbereiteten Dateistruktur instanziiert. Diese Dateien diesen als Verbindungsstücke zwischen dem Datenbanksystem und dem Betriebssystem. Aus diesem Grunde sind die SQL Server- und Oracle-Varianten von CREATE DATABASE um einiges komplexer.
Die Syntax für Microsoft SQL Server sieht folgendermaßen aus:
    CREATE DATABASE database_name
    [ ON [PRIMARY]
    [ <file> [,...n] ]
    [, <file_group> [,...n] ]
    ]
    [ LOG ON { <file> [,...n]} ]
    [ FOR LOAD | FOR ATTACH ]
    GO
Bei dieser Implementierung kann nicht nur der Name der Datenbank angegeben werden, sondern auch der Ort, an dem die Datenbank gespeichert werden soll. Sowohl Oracle als auch SQL Server verwenden Dateien (vordefinierter Platz auf der Festplatte) als Repository für Datenbanken. Die Datenbanken können in einer oder mehreren Dateien oder Dateigruppen gespeichert werden. SQL Server bietet auch die Möglichkeit, die Transaktionsprotokolle mit Hilfe der Klausel LOG ON an einem anderen Ort zu speichern als die Datenbank. Diese Funktionen ermöglichen eine umfassende Planung im Hinblick auf den optimalen Festplattendurchsatz.
Mit den FOR LOAD-Klauseln wird festgelegt, dass die Datenbank unmittelbar nach der Erstellung aus einer Backup-Kopie geladen wird. Auf diese Weise wird der anfängliche Erstellungsvorgang beschleunigt. Mit der Klausel FOR ATTACH wird SQL Server mitgeteilt, dass die Datenbank aus einer bestehenden Betriebssystem-Dateistruktur, wie zum Beispiel einer DVD-ROM, einer CD-ROM oder einer tragbaren Festplatte, angehängt wird.
MySQL und PostgreSQL: Syntax und Variationen
In MySQL wird mit CREATE DATABASE im Wesentlichen ein neues Verzeichnis erzeugt, in dem die Datenbankobjekte abgelegt werden. Bei diesen beiden Herstellern ist somit das Anlegen einer Datenbank kaum schwieriger als das Anlegen eines Verzeichnisses im Dateisystem. Die Datenbank wird als Verzeichnis unter dem Hauptverzeichnis des Herstellers angelegt, und alle in der Datenbank neu erzeugten Objekte werden in diesem Verzeichnis abgelegt. PostgreSQL bietet dieselbe Funktionalität, es besteht jedoch zusätzlich die Möglichkeit, den Speicherort der Datenbank mit der Option WITH LOCATION anzugeben:
    CREATE DATABASE name [ WITH LOCATION = 'dbpath' ];
So wird beispielsweise die Datenbank sales_revenue im Verzeichnis /home/teddy/private_db erstellt:
    CREATE DATABASE sales_revenue WITH LOCATION = '/home/teddy/private_db';
Oracle: Syntax und Variationen
    CREATE DATABASE [database_name]
    [CONTROLFILE REUSE]
    [LOGFILE [GROUP1 integer] file1 integer [K | M] [,...n] [REUSE]]
       [MAXLOGFILES integer]
       [[MAXLOGMEMBERS] integer]
       [[MAXLOGHISTORY] integer]
    [DATAFILE file1 [AUTOEXTEND [,...n] [ON | OFF]]
          [NEXT integer [K | M]]
          [MAXSIZE [UNLIMITED | integer [K | M]]
       [MAXDATAFILES integer]
       [,...n]]
    [MAXINSTANCES integer]
    [MAXDATAFILES integer]
    [ARCHIVELOG | NOARCHIVELOG]
    {CHARACTER SET charset}
    {NATIONAL CHARACTER SET charset};
CREATE DATABASE ist ein sehr mächtiger Befehl in Oracle und sollte daher nur von erfahrenen Datenbankadministratoren eingesetzt werden. Neulingen müssen sich im Klaren darüber sein, dass die bestehende Datenbank mit diesem Befehl zerstört werden kann.
Genau wie bei Microsoft SQL Server gehen auch bei Oracle die Möglichkeiten zur Steuerung der Datenbank-Dateistrukturen weit über das bloße Benennen der Datenbank und das Festlegen eines Pfads für die Datenbankdateien hinaus. Oracle-spezifisch ist die Datei INIT.ORA, die den Namen der Datenbank sowie eine Vielzahl anderer Optionen für das Anlegen und Starten der Datenbank enthält. Die Datei INIT.ORA muss immer verwendet werden und auf die Steuerdateien verweisen, sonst kann die Datenbank nicht gestartet werden.
Wenn die Option the file1 [,...n] zur Verfügung steht, können der Dateiname und die Dateigröße (in Byte, Kilobyte oder Megabyte) angegeben werden. Das Format dafür sieht folgendermaßen aus:
    'file_path_and_name' SIZE bytes [K | M] REUSE
Bei Angabe der Optionen [K | M] wird die Byte-Größe der Datei mit 1024 bzw. 1048576 multipliziert. Die Option REUSE erstellt die Datei, wenn sie noch nicht existiert, und verwendet die alte Datei, wenn es sie schon gibt; bei Angabe der Option CONTROLFILE REUSE werden hingegen die Steuerdateien überschrieben, genau wie bei LOGFILE . . . REUSE die Logdateien.
Wenn eine Gruppe von Logdateien angegeben wird, stehen diese in der Regel in runden Klammern. Die Klammern sind nicht erforderlich, wenn eine Gruppe mit nur einem Element erzeugt wird; dies ist jedoch selten der Fall. Nachfolgend ein Beispiel für eine Liste von Logdateien in runden Klammern:
    CREATE DATABASE publications
    LOGFILE ('/s01/oradata/loga01','/s01/oradata/loga02') SIZE 5M
    DATAFILE
Darüber hinaus ermöglichen die Optionen LOGFILE und DATAFILE und deren Unteroptionen die genaue Steuerung der Größe und des Wachstumsverhaltens der Redo-Logs (Wiederholungsprotokolle) und Datenbankdateien. Mit MAXLOGFILES und MAXDATAFILES werden die Obergrenzen für die Redo-Logs bzw. die Datenbankdateien definiert. Wenn AUTOEXTEND aktiviert ist, wächst die Datendatei in Schritten von NEXT, bis MAXSIZE erreicht ist, es sei denn, sie ist auf UNLIMITED gesetzt. Mit MAXLOGMEMBERS wird gesteuert, wie viele Kopien einer Redo-Log-Gruppe angelegt werden dürfen. MAXLOGHISTORY wird in Oracle Parallel Server verwendet und gibt die maximale Anzahl archivierter Redo-Logs an, damit in der Steuerdatei der richtige Platzverbrauch erfasst wird.
Mit dem Parameter MAXINSTANCES wird die maximale Anzahl von Instanzen festgelegt, die die gerade erstellte Datenbank mounten dürfen. ARCHIVELOG | NOARCHIVELOG sind Optionen, die sich gegenseitig ausschließen und die Funktionsweise der Redo-Logs angeben. Mit ARCHIVELOG werden die Daten aus Gründen der Wiederherstellbarkeit in einer zusätzlichen Archivierungsdatei gesichert. Bei beiden Optionen ist eine Datenwiederherstellung möglich, bei NOARCHIVELOG, dem Standard, normalerweise aber keine Wiederherstellung von Medien. CHARACTER SET hängt vom Betriebssystem ab und legt die Sprache und den Zeichensatz für die Speicherung der Daten fest.

CREATE FUNCTION |
Mit der Anweisung CREATE FUNCTION wird eine benutzerdefinierte Funktion (UDF) erzeugt, die Eingabeargumente erwartet und genau wie CAST( ) einen einzelnen Wert zurückgibt. Eine UDF kann in einer Abfrage genau wie eine Systemfunktion verwendet werden.
In Kapitel 4finden Sie eine vollständige Beschreibung der SQL-Funktionen und deren Implementierungen durch die einzelnen Hersteller.
Hersteller | Befehl
--- | ---
SQL Server | Unterstützt, mit Variationen
MySQL | Unterstützt, mit Variationen
Oracle | Unterstützt, mit Variationen
PostgreSQL | Unterstützt, mit Variationen
Mit der Anweisung CREATE FUNCTION können Datenbankprogrammierer benutzerdefinierte Funktionen schreiben. Diese Funktionen können dann in Abfragen und Datenmanipulationsoperationen wie INSERT, UPDATE und der WHERE-Klausel von DELETE-Anweisungen verwendet werden. Auch wenn die grundlegende Syntax für diese Anweisung bereits erläutert wurde, gibt es so viele herstellerspezifische Unterschiede im Hinblick auf die Implementierung, dass diese nachfolgend einzeln beschrieben werden.
SQL99: Syntax und Beschreibung
    CREATE FUNCTION function_name
    [(parameter datatype attributes [,...n])]
    RETURNS datatype

      [LANGUAGE {ADA | C | FORTRAN | MUMPS | PASCAL | PLI | SQL}]
      [PARAMETER STYLE {SQL | GENERAL}]
      [SPECIFIC specific_name]
      [DETERMINISTIC | NOT DETERMINISTIC]
      [NO SQL | CONTAINS SQL | READS SQL DATA | MODIFIES SQL DATA]
      [RETURNS NULL ON NULL INPUT | CALL ON NULL INPUT]
      [STATIC DISPATCH]

    code block
Der SQL99-Standard sieht für die Anweisung CREATE FUNCTION eine Hauptkomponente und eine weiterführende Komponente vor, die allerdings seltener verwendet wird. In den meisten UDF definiert der Benutzer den Funktionsnamen, eventuelle Eingabeparameter und den Wert, den die UDF zurückgibt. So sieht auch die Grundform für die Verwendung dieses Befehls aus.
Der SQL99-Standard bietet jedoch noch viel mehr. Mit der Klausel LANGUAGE kann die Sprache, in der die Funktion geschrieben wurde (z. B. PostgreSQL), angegeben werden. Mit der Klausel PARAMETER STYLE wird ein anderer Parameterstil als der typische SQL-Stil deklariert, und zwar über das Schlüsselwort GENERAL. (Der Standardwert ist SQL.) Mit der Deklaration SPECIFIC wird der Funktionsname in einem benutzerdefinierten Datentyp näher bestimmt. Die Klauseln DETERMINISTIC und NOT DETERMINISTIC teilen dem Host-DBMS mit, ob die Funktion bei gleichen Eingabeparametern immer dasselbe Ergebnis zurückgibt (= deterministisch) oder nicht. In Constraints dürfen nur deterministische Funktionen verwendet werden.
Mit der SQL-Datenzugriffsklausel wird dem Host-DBMS mitgeteilt, ob die Funktion keinen SQL-Code enthält (NO SQL), SQL-Code enthält (CONTAINS SQL), die Anweisung SELECT oder FETCH verwendet (READS SQL DATA) und ob datenmodifizierende Anweisungen eingesetzt werden (MODIFIES SQL DATA). Standard ist CONTAINS SQL.
Für Hostsprachen, die Nullwerte nicht verarbeiten können, kann RETURNS NULL ON NULL INPUT deklariert werden. Die Funktion gibt dann unmittelbar einen Nullwert zurück, wenn eine Null übergeben wird. Im Gegensatz dazu wird bei CALL ON NULL INPUT, dem Standard, der Nullparameter ganz normal mit möglicherweise unbekannten Ergebnissen weiterverarbeitet.
Die Klausel STATIC DISPATCH ist für Nicht-SQL-Funktionen mit Parametern gedacht, die benutzerdefinierte Typen oder ARRAYS verwenden.
Microsoft SQL Server: Syntax und Variationen
    CREATE FUNCTION [owner_name.]function_name
    ( [ {@parameter1 datatype [=default]} [,...n] ] )
    RETURNS {datatype | TABLE]
    [WITH {ENCRYPTION | SCHEMABINDING}]
    AS <Transact-SQL body>
    GO
SQL Server-Funktionen können über den Datentyp TABLE mehrere Werte zurückgeben. Der Datentyp TABLE wird als inline betrachtet, wenn er über keine zugehörige Spaltenliste verfügt und in einer einzigen SELECT-Anweisung definiert ist. Wenn die Klausel RETURN über den Datentyp TABLE mehrere Werte zurückgibt und wenn in TABLE Spalten und deren Datentypen definiert sind, handelt es sich um eine tabellenwertige Funktion vom Typ Multistatement, die mehrere Anweisungen enthält.
In SQL Server müssen ein oder mehrere vom Benutzer übergebene Parameter für eine benutzerdefinierte Funktion deklariert werden. Alle SQL Server-Datentypen außer timestamp können als Parameter verwendet werden. Von der Funktion können alle Datentypen mit Ausnahme von timestamp, text, ntext und image zurückgegeben werden. Wenn ein Inline-Tabellenwert erforderlich ist, kann die Option TABLE ohne zugehörige Spaltenliste verwendet werden.
Benutzerdefinierte Funktionen in Microsoft SQL können, wie viele andere Datenbankobjekte in SQL Server auch, mit den Optionen ENCRYPTION oder SCHEMABINDING erstellt werden. Mit der Option ENCRYPTION wird SQL Server aufgefordert, die Systemspaltentabelle, in der der Text der Funktion gespeichert ist, zu verschlüsseln. Auf diese Weise kann der Funktionscode nicht von Unbefugten eingesehen werden. Die Option SCHEMABINDING gibt an, dass die Funktion an ein bestimmtes Datenbankobjekt wie eine Tabelle oder einen View gebunden ist. Dieses Datenbankobjekt kann nicht verändert oder gelöscht werden, solange die Funktion existiert (bzw. die Option SCHEMABINDING verwendet wird).
Der Coderumpf in Transact-SQL ist entweder eine einzelne SELECT-Anweisung im Format RETURN (SELECT . . . ) bei Inline-Funktionen oder eine Reihe von Transact-SQL-Anweisungen bei Operationen, die aus mehreren Anweisungen bestehen. Der Transact-SQL-Rumpf in einem BEGIN . . . END-Block darf keine dauerhaften Änderungen an Daten vornehmen und auch sonst keine andauernden Nebeneffekte haben. Die letzte Anweisung im Block muss ein bedingungsloses RETURN sein, das einen einzelnen Datentyp-Wert oder TABLE-Wert zurückgibt.
Der Transact-SQL-Block darf keine globalen Variablen enthalten, deren Werte sich ständig ändern, wie beispielsweise @@CONNECTIONS oder GETDATE. Erlaubt sind hingegen globale Variablen, deren Wert sich nicht verändert, wie etwa @@SERVERNAME. Es gibt noch eine Reihe anderer Einschränkungen, da der Code weder dauerhafte Änderungen an Daten vornehmen oder sonstige andauernde Nebeneffekte haben darf. Aus diesem Grunde dürfen INSERT-, UPDATE- und DELETE-Anweisungen nur die lokalen TABLE-Variablen ändern.
Nachfolgend ein Beispiel für eine Skalarfunktion, die einen einzelnen Wert zurückgibt:
    CREATE FUNCTION metric_volume -- Input dimensions in centimeters.
       (@length decimal(4,1),
       @width decimal(4,1),
       @height decimal(4,1) )
    RETURNS decimal(12,3) -- Cubic Centimeters.
    AS BEGIN
          RETURN ( @length * @width * @height )
       END
    GO
Diese benutzerdefinierte Funktion kann dann wie jede andere Funktion in einer Abfrage oder einer anderen Operation verwendet werden. So können zum Beispiel mit der folgenden Abfrage der Projektname und das Volumen aller Bauprojekte mit einem Volumen von mehr als 300.000 Kubikmetern ausgegeben werden:
    SELECT project_name,
       metric_volume(construction_height,
          construction_length,
          construction_width)
    FROM housing_construction
    WHERE metric_volume(construction_height,
          construction_length,
          construction_width) >= 300000
    GO
Benutzerdefinierte Funktionen, die einen Tabellenwert zurückgeben, werden oftmals als Ergebnismengenwert ausgewählt oder in der FROM-Klausel einer SELECT-Anweisung verwendet, genau wie eine ganz normale Tabelle. In einer FROM-Klausel kann wie bei einer normalen Tabelle eine Tabellenaliasfunktion zugewiesen werden. Dazu ein Beispiel:
    SELECT co.order_id, co.order_price
    FROM   construction_orders AS co,
           fn_construction_projects('Cancelled') AS fcp
    WHERE  co.construction_id = fcp.construction_id
    ORDER BY co.order_id
    GO
MySQL: Syntax und Variationen
    CREATE [AGGREGATE] FUNCTION function_name
    RETURNS {STRING | REAL | INTEGER}
    SONAME shared_program_library_name ;
In MySQL werden mit CREATE FUNCTION benutzerdefinierte Funktionen wie SUM( ) und COUNT( ) mit Hilfe der Option AGGREGATE aggregiert. Der Typ des Rückgabewertes kann entweder STRING für Zeichendaten, REAL für Fließkommazahlen oder INTEGER für Ganzzahlen sein.
Die Implementierung von CREATE FUNCTION in MySQL unterscheidet sich erheblich von der anderer Hersteller, da der prozedurale Code in C/C++ geschrieben sein muss und vorausgesetzt wird, dass das Betriebssystem das dynamische Laden von Bibliotheken unterstützt. Das C/C++-Programm wird in der Option shared_program_library_name angegeben. Die Funktion kann entweder direkt in den MySQL-Server kompiliert werden und steht dann permanent zur Verfügung, oder sie wird als dynamisch aufrufbares Programm verwendet. Da die benutzerdefinierten Funktionen in C/C++ geschrieben werden, würde eine ausführliche Beschreibung dieser Implementierung über den Rahmen dieses Buches hinausgehen.
Oracle: Syntax und Variationen
    CREATE [OR REPLACE] FUNCTION [owner_name.]function_name
    [(parameter1 [IN | OUT | IN OUT] [NOCOPY] datatype][,...n)]]
    RETURN datatype [DETERMINISTIC | AUTHID {CURRENT_USER | DEFINER} ]
      {IS | AS} {PL/SQL block | external program};
In Oracle sind benutzerdefinierte Funktionen und gespeicherte Prozeduren im Hinblick auf den Aufbau und die Struktur sehr ähnlich. Der Hauptunterschied besteht darin, dass gespeicherte Prozeduren keinen Wert an den aufrufenden Prozess zurückgeben können, während bei Funktionen ein einzelner Wert zurückgegeben werden kann.
In Oracle sind als Argumente und Parameter für benutzerdefinierte Funktionen u. a. IN, OUT und IN OUT zulässig. Der Qualifier IN wird beim Aufruf der Funktion angegeben und gibt einen Wert an die Funktion zurück; OUT-Argumente geben einen Wert an den aufrufenden Prozess zurück. Mit anderen Worten, der Qualifier IN wird vom Benutzer oder von dem Prozess, der die Funktion aufruft, angegeben, während das OUT-Argument von der Funktion zurückgegeben wird. IN OUT ist eine Kombination aus IN und OUT. Das Schlüsselwort NOCOPY wird verwendet, um die Leistung zu verbessern, wenn ein OUT- oder IN OUT-Argument sehr groß ist, wie zum Beispiel ein Varray oder ein Datensatz.
Mit dem Schlüsselwort RETURN wird der Datentyp des von der Funktion zurückgegebenen Wertes festgelegt. Das Schlüsselwort DETERMINISTIC wird verwendet, um die Verarbeitung von Funktionen zu beschleunigen, die explizit als deterministisch deklariert wurden. Der gespeicherte Rückgabewert kann von einem materialisierten View, einem anderen gleichzeitigen Aufruf derselben Funktion oder einem funktionsbasierten Index stammen. Mit AUTHID CURRENT_USER und AUTHID DEFINER kann darüber hinaus festgelegt werden, dass die Funktion im Zugriffsrechtekontext des aktuellen Benutzers oder des Benutzers, der die Funktion definiert hat, laufen soll.
So kann zum Beispiel der Gewinn eines Bauprojekts durch Übergabe des Projektnamens in der folgenden Funktion ermittelt werden:
    CREATE FUNCTION project_revenue (project IN varchar2)
    RETURN NUMBER
    AS
       proj_rev NUMBER(10,2);
    BEGIN
       SELECT SUM(DECODE(action,'COMPLETED',amount,0)) -
              SUM(DECODE(action,'STARTED',amount,0))   +
              SUM(DECODE(action,'PAYMENT',amount,0))
       INTO proj_rev
       FROM construction_actions
       WHERE project_name = project;
       RETURN (proj_rev);
    END;
In diesem Beispiel erwartet die benutzerdefinierte Funktion den Projektnamen als Argument. Anschließend wird im Hintergrund der Projektumsatz berechnet, indem die Anfangskosten von der Schlusszahlung abgezogen und eventuelle weitere Zahlungen hinzuaddiert werden. Die Zeile RETURN(proj_rev); gibt den Betrag an den aufrufenden Prozess zurück.
PostgreSQL: Syntax und Variationen
    CREATE FUNCTION name ( [ parameter1 [,...n] ] )
    RETURNS datatype
    AS {definition | object_file, link_symbol}
    LANGUAGE {'C' | 'SQL' | 'PLPGSQL' | 'PLTCL' | 'PLTCLU' | 'PLPERL'
       | 'internal'}
    [WITH ISCACHABLE];
Die PostgreSQL-Variation von CREATE FUNCTION gehört zu den flexibelsten Implementierungen dieses Befehls. Wie bei den anderen Implementierungen werden Parameter übergeben, die einen Wert eines bestimmten Datentyps zurückgeben. PostgreSQL ermöglicht darüber hinaus das Überladen von Funktionen, wobei derselbe Funktionsname für verschiedene Funktionen verwendet werden kann, solange die Eingabeparameter unterschiedlich sind.
Mit dem Datentypattribut WITH ISCACHABLE wird die Leistung von PostgreSQL optimiert, indem angegeben wird, dass die Funktion immer den gleichen Wert für die gleichen Eingabewerte zurückgibt. Mit dieser Einstellung kann der Optimierer den Funktionsaufruf dann schon im Vornherein auswerten.
Die Definition kann ein String sein, der die Funktion definiert (in Abhängigkeit von der Sprache, in der die Funktion geschrieben wurde), zum Beispiel ein interner Funktionsname, der Pfad und Name einer Objektdatei, eine SQL-Abfrage oder der Text einer prozeduralen Sprache. Die Definition kann auch eine Objektdatei oder ein Verknüpfungssymbol einer in C geschriebenen Funktion sein.
Nachfolgend ein Beispiel für eine einfache SQL-Funktion in PostgreSQL:
    CREATE FUNCTION max_project_nbr
    RETURNS int4
    AS "SELECT MAX(project_ID) FROM housing_construction AS RESULT"
    LANGUAGE 'sql';
PostgreSQL verwendet CREATE FUNCTION als Ersatz für CREATE PROCEDUREsowie zum Definieren von Aktionen für CREATE TRIGGER.
Mit dem Schlüsselwort LANGUAGE kann die PostgreSQL-Funktion ein externes Programm aufrufen. Da es sich dabei um Programme handelt, die in anderen Sprachen geschrieben wurden, würde eine detaillierte Beschreibung an dieser Stelle zu weit führen. Die Klausel LANGUAGE 'sql' sollten Sie aber auf jeden Fall verwenden, wenn Sie benutzerdefinierte Funktionen in SQL schreiben.

CREATE INDEX |
Indizes sind spezielle Objekte, die auf Tabellen aufsetzen und viele Datenmanipulationsoperationen wie SELECT-, UPDATE- und DELETE-Anweisungen beschleunigen. Bei Erstellung eines Index wird die Position und Verteilung der Werte ("Statistik" genannt) für die indizierte Spalte berechnet. Wie selektiv eine WHERE-Klausel ist, hängt in der Regel von der Qualität der Indizes für die betreffende Tabelle ab.
Hersteller | Befehl
--- | ---
SQL Server | Unterstützt, mit Variationen
MySQL | Unterstützt, mit Variationen
Oracle | Unterstützt, mit Variationen
PostgreSQL | Unterstützt, mit Variationen
Der Befehl CREATE INDEX ist von Hersteller zu Hersteller verschieden. Dies ist unter anderem darauf zurückzuführen, dass bei manchen DBMS der Befehl CREATE INDEX bestimmt, wie die Daten in einer indizierten Tabelle physisch sortiert und auf der Festplatte gespeichert werden.
SQL99: Syntax und Beschreibung
    CREATE INDEX index_name ON table_name (column_name [, ...n])
Alle wichtigen Hersteller unterstützen zusammengesetzte Indizes,auch verkettete Indizes genannt. Diese Indizes werden verwendet, wenn zwei oder mehrere Spalten sinnvollerweise als Einheit zu durchsuchen sind, beispielsweise Nachname und Vorname.
Microsoft SQL Server: Syntax und Variationen
    CREATE [UNIQUE] [CLUSTERED | NONCLUSTERED] INDEX index_name
    ON {table | view} (column [ASC | DESC] [,...n])
    [WITH [PAD_INDEX]
       [[,] FILLFACTOR = fillfactor]
       [[,] IGNORE_DUP_KEY]
       [[,] DROP_EXISTING]
       [[,] STATISTICS_NORECOMPUTE] ]
    [ON filegroup]
    GO
Microsoft SQL Server kennt einige wichtige Optionen. Zum Beispiel können aufsteigende oder absteigende Indizes für Tabellen sowie Indizes für Views und berechnete Spalten (wie UPPER(book_name) oder ((qty * amt) / royalty)) erstellt werden. SQL Server unterstützt darüber hinaus noch weitere optionale Argumente: UNIQUE, CLUSTERED und NONCLUSTERED (Standard). Bei eindeutigen Indizes darf es in den indizierten Spalten keine identischen Werte geben. Jeder Versuch, einen Wert so einzufügen oder zu verändern, dass es zu einer Duplikation im Index kommt, würde einen Fehler auslösen. Geclusterte Indizes geben die physische Sortierreihenfolge der Daten auf der Festplatte an. Nicht-geclustere Indizes sorgen für eine logische Tabellensortierung, wodurch Datenmanipulationsoperationen beschleunigt werden.
Weitere Syntax-Merkmale in SQL Server:
PAD_INDEX gibt an, dass auf jeder Indexdatenseite ein bestimmter Platz entsprechend der Einstellung FILLFACTOR freigelassen werden soll. FILLFACTOR ist ein Prozentwert (zwischen 1 und 100), der SQL Server mitteilt, welcher Teil einer 8 KB großen Datenseite bei der Indexerstellung gefüllt werden soll. Dies ist nützlich, um das Aufbrechen von Seiten zu vermeiden, wenn eine 8 KB große Datenseite voll wird, und um I/O-intensive Festplattenoperationen auf ein Minimum zu reduzieren. Durch Erstellung eines geclusterten Index mit explizit definiertem Füllfaktor lässt sich u. U. der Index vergrößern und die Verarbeitung beschleunigen. Mit IGNORE_DUP_KEY wird festgelegt, was passiert, wenn ein doppelter Datensatz im Zuge einer Einfügungs- oder Aktualisierungsoperation in einen eindeutigen Index gelangt. Wenn dieser Wert für eine Spalte gesetzt ist, wird nur die doppelte Zeile von der Operation ausgeschlossen. Ist der Wert nicht gesetzt, werden alle betroffenen Datensätze (auch die nicht duplizierten) zurückgeführt. DROP_EXISTING ist ein nützliches Merkmal, mit dem SQL Server aufgefordert werden kann, bereits bestehende Indizes zu löschen und den angegebenen Index neu anzulegen. Mit STATISTICS_NORECOMPUTE wird SQL Server daran gehindert, die Indexstatistiken neu zu berechnen. Auf diese Weise kann die CREATE INDEX-Operation beschleunigt werden, was den Index jedoch weniger nützlich macht. Mit ON filegroup wird ein Index in einer bereits vorhandenen Dateigruppe erzeugt. Auf diese Weise können Indizes auf eine bestimmte Festplatte oder ein RAID-Gerät gelegt werden.
Zur Erstellung eines Index ist in der Regel 1,2 bis 1,5 Mal mehr Platz erforderlich als die Tabelle derzeit belegt. Der größte Teil des Plattenspeichers wird wieder freigegeben, sobald der Index erstellt ist.
MySQL: Syntax und Variationen
    CREATE [UNIQUE] INDEX index_name ON table_name (column_name(length) [,...n])
MySQL unterstützt den grundlegenden ANSI-Standard für die Anweisung CREATE INDEX, einschließlich der Möglichkeit, einen Index auf mehreren Spalten zu erstellen. Ein Index kann außerdem als UNIQUE definiert werden, was bedeutet, dass dieser Index nur eindeutige Werte akzeptiert. Wird versucht, einen nichteindeutigen Wert in eine Tabelle mit einem Index vom Typ UNIQUE einzufügen, tritt ein Fehler auf.
Interessanterweise bietet MySQL auch die Möglichkeit, einen Index auf die ersten (length) Zeichen einer CHAR- oder VARCHAR-Spalte zu erstellen. Dies kann nützlich sein, wenn zum Beispiel die ersten 10 Zeichen einer Spalte aussagekräftig genug sind, oder wenn der Festplattenplatz knapp ist.
Oracle: Syntax und Variationen
    CREATE [UNIQUE | BITMAP] INDEX [owner_name.]index_name
    ON [schema.]{table ({column | expression} [ASC | DESC] [,...n])
       | CLUSTER cluster_name}
    [physical_attributes_clause | {LOGGING | NOLOGGING} |
      | [ONLINE] | [COMPUTE [STATISTICS] ]
      | {TABLESPACE tablespace_name | DEFAULT}
      | {COMPRESS int | NOCOMPRESS}
      | {NOSORT |REVERSE} ],...
     [GLOBAL PARTITION BY RANGE (column_list)
       (PARTITION [partition_name] VALUES LESS THAN (value_list)
       [physical_attributes_clause | {LOGGING | NOLOGGING} ] ,...n )
    | LOCAL [ (PARTITION [partition_name]
       [physical_attributes_clause | {LOGGING | NOLOGGING} ] ,...n ) ] ]
    [PARALLEL [int] | NOPARALLEL]
Oracle ermöglicht die Erstellung von Indizes, die nicht nur auf Spaltenwerten basieren, sondern auch auf berechneten Ausdrücken wie UPPER(book_name) oder ((qty * amt) / royalty). Indizes können UNIQUE oder nichteindeutig sein. In Oracle können auch BITMAP-Indizes erzeugt werden, was nützlich ist bei Spalten mit nur wenigen unterschiedlichen Werten. Darüber hinaus können in Oracle sowohl aufsteigende (ASC) als auch absteigende (DESC) Indizes angelegt werden. Beachten Sie aber, dass Oracle DESC-Indizes wie funktionsbasierte Indizes behandelt. Es gibt einen funktionalitätsbezogenen Unterschied zwischen ASC-Indizes und DESC-Indizes. Ein Cluster-Schlüssel für den Index kann mit der Option CLUSTER ebenfalls angegeben werden. (Cluster werden mit dem Oracle-spezifischen Befehl CREATE CLUSTER erstellt. )
Oracle und SQL Server unterscheiden sich erheblich in ihren Definitionen eines geclusterten Index. In SQL Server gibt ein geclusterter Index die physische Sortierreihenfolge der Daten in der Tabelle an. In Oracle ist ein Cluster ein spezieller Index zwischen zwei oder mehr Tabellen, mit dem sich Join-Operationen erheblich beschleunigen lassen.
Die Klausel physical_attributes_clause bezieht sich auf die folgenden Einstellungen:
    [ PCTFREE int
    | PCTUSED int
    | INITRANS int
    | MAXTRANS int
    | STORAGE storage...]
PCTFREE ist vergleichbar mit FILLFACTOR in SQL Server und gibt in Prozent den Platz an, der für neue Einträge und Aktualisierungen freigelassen werden muss. PCTFREE kann nur für Indizes verwendet werden, die nicht UNIQUE sind. PCTUSED gibt in Prozent den Platz an, der in einem Block zur Verfügung stehen muss, damit Oracle Einfügungen in diesem Block zulässt. PCTUSED kann für Tabellen, aber nicht für Indizes verwendet werden. Erläuterungen zu STORAGE, INITRANS und MAXTRANS finden Sie unter der Anweisung CREATE TABLE in Abschnitt .
Mit der Klausel TABLESPACE wird der Index einem bestimmten Tablespace zugewiesen. Wenn diese Klausel weggelassen wird, befindet sich der Index im Standard-Tablespace; dasselbe erreichen Sie auch mit dem Schlüsselwort DEFAULT.
Mit LOGGING wird Oracle angewiesen, die Erstellung eines Index in einer Redo-Log-Datei zu erfassen. Mit NOLOGGING hingegen wird eine solche Erfassung verhindert. Dieses Schlüsselwort legt auch das Standardverhalten für nachfolgendes Bulk-Loading mit dem Oracle Direct Loader fest. Im Zusammenhang mit dem Aufbau von Indexpartitionen gibt es noch einige Besonderheiten bei diesen Schlüsselwörtern. Vor deren Anwendung sollten Sie sich daher in der Dokumentation des Herstellers informieren.
Mit ONLINE wird Oracle mitgeteilt, dass während der Erstellung des Index Datenmanipulationen zulässig sind. Mit dem Befehl COMPUTE STATISTICS werden während der Erstellung des Index Statistiken gesammelt, was relativ unaufwändig ist. COMPRESS aktiviert die Komprimierung von Schlüsseln in nichtpartitionierten Indizes. Dafür wird weniger Platz benötigt, weil mehrfach auftretende Schlüsselwerte eliminiert werden. Der Integer in COMPRESS gibt an, wie viele Präfixspalten komprimiert werden sollen. Mit NOCOMPRESS, dem Standard, wird die Komprimierung deaktiviert.
Oracle ermöglicht die Erstellung von partitionierten Indizes und Tabellen mit Hilfe der Klausel PARTITION. Deshalb unterstützen Oracle-Indizes auch partitionierte Tabellen. Mit der Klausel LOCAL wird Oracle angewiesen, für jede Partition einer Tabelle einen eigenen Index zu erstellen. Mit der Klausel GLOBAL wird ein gemeinsamer Index für alle Partitionen erzeugt, wobei sich bestimmte Indexwertebereiche von den auf den Partitionen gespeicherten Wertebereichen unterscheiden können.
Mit der OptionNOSORT lässt sich schnell ein Index für eine Spalte erstellen, die bereits in aufsteigender Reihenfolge sortiert ist. Wenn die Werte der Spalte nicht perfekt aufsteigend sortiert sind, wird die Operation abgebrochen und kann ohne die Option NOSORTOption noch einmal versucht werden. Mit REVERSE werden dagegen die Indexblöcke in umgekehrter Reihenfolge auf dem Speichermedium abgelegt; die Zeilensortierung ist davon jedoch nicht betroffen. REVERSE und NOSORT schließen sich gegenseitig aus. REVERSE kann nicht bei einem Bitmap-Index oder einer indexorganisierten Tabelle verwendet werden.
Mit der Klausel PARALLEL kann die Erstellung des Index auf mehrere CPUs verteilt und somit beschleunigt werden. Ein optionaler Integerwert gibt an, wie viele parallele Threads dabei zu verwenden sind. Mit NOPARALLEL, dem Standard, wird der Index seriell erzeugt.
PostgreSQL: Syntax und Variationen
    CREATE [UNIQUE] INDEX index_name ON table
    [USING [BTREE | RTREE | HASH] ]
    (function_name (column [operator_class] [, ...] ))
In PostgreSQL können normale Indizes in aufsteigender Reihenfolge wie auch UNIQUE-Indizes erstellt werden. Darüber hinaus ermöglicht die Implementierung mit der Klausel WITH access_method auch die Steigerung der Performanz. Mit Hilfe dieser Klausel kann eine von drei dynamischen Zugriffsmethoden zur Leistungsoptimierung angegeben werden:
BTREE Dies ist die Standardmethode, wenn nichts anderes angegeben ist. Sie beruht auf den Mehrweg-B-Bäumen nach Lehman/Yao. RTREE Diese Methode verwendet normale R-Bäume mit dem Split-Algorithmus mit quadratischem Aufwand nach Guttman. HASH Diese Methode ist eine Implementierung des linearen Hashing von Litwin.
In PostgreSQL kann Spalten auch eine Operatorklasse zugewiesen werden, die sich nach dem Datentyp der Spalte richtet. Eine Operatorklasse gibt die Operatoren für einen bestimmten Index an. Der Benutzer kann zwar eine beliebige zulässige Operatorklasse für eine Spalte definieren, aber die Standard-Operatorklasse ist die für den jeweiligen Feldtyp passendste.
In PostgreSQL haben Sie auch die Möglichkeit, einen Index für eine Funktion, eine benutzerdefinierte Funktion oder einen Ausdruck zu definieren. So kann zum Beispiel ein Index für UPPER(book_name) definiert werden, um eine Transformationsoperation zu beschleunigen, die regelmäßig mit den Daten, die dem Index zugrunde liegen, durchgeführt wird.
Beispiele
In diesem Beispiel aus MySQL wird ein einfacher aufsteigender Index für die Spalte au_id der Tabelle authors erstellt:
    CREATE INDEX au_id_ind
    ON authors (au_id);
Im Beispiel unten wird eine Tabelle mit dem Namen housing_construction erstellt (wie auch bei der Beschreibung von CREATE FUNCTION verwendet) und auf dieser ein geclusterter Index angelegt. Dieser Index sortiert die Daten physisch auf der Festplatte, da die Klausel CLUSTERED angegeben ist:
    CREATE TABLE housing_construction
       (project_number      INT NOT NULL,
       project_date         DATETIME NULL,
       project_name         VARCHAR(50)
           COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
       construction_color   NCHAR(20)
           COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
       construction_height  DECIMAL(4, 1) NULL ,
       construction_length  DECIMAL(4, 1) NULL ,
       construction_width   DECIMAL(4, 1) NULL ,
       construction_volume  INT NULL
    GO

    CREATE UNIQUE CLUSTERED INDEX project_id_ind
    ON housing_construction(project_id)
    GO
Oftmals braucht man Indizes, die mehrere Spalten abdecken, d. h. einen zusammengesetzten Schlüssel. Dazu ein Beispiel:
    CREATE UNIQUE INDEX project2_ind
    ON housing_construction(project_name, project_date)
    WITH PAD_INDEX, FILLFACTOR = 80
    GO
Durch Hinzufügen der Klausel PAD_INDEX und durch Setzen des FILLFACTOR auf 80 wird SQL Server angewiesen, die Index- und Datenseiten nur zu 80 % und nicht zu 100 % zu füllen.
Im folgenden Beispiel wird derselbe Index in Oracle erzeugt, und zwar in einem bestimmten Tablespace zusammen mit Anweisungen, wie die Daten gespeichert werden sollen:
    CREATE UNIQUE INDEX project2_ind
    ON housing_construction(project_name, project_date)
    STORAGE (INITIAL 10M NEXT 5M PCTINCREASE 0)
    TABLESPACE construction;
Wenn die Tabelle housing_construction als partitionierte Tabelle auf einem Oracle-Server erstellt wird, sollte auch ein partitionierter Index angelegt werden:
    CREATE UNIQUE CLUSTERED INDEX project_id_ind
    ON housing_construction(project_id)
    GLOBAL PARTITION BY RANGE (project_id)
       (PARTITION part1 VALUES LESS THAN ('K')
          TABLESPACE construction_part1_ndx_ts,
       PARTITION part2 VALUES LESS THAN (MAXVALUE)
          TABLESPACE construction_part2_ndx_ts);

CREATE PROCEDURE |
Gespeicherte Prozeduren ermöglichen bedingte Verarbeitungs- und Programmiermöglichkeiten in der Datenbankserver-Umgebung. Gespeicherte Prozeduren sind in sich geschlossene Codestücke, die übergebene Parameter annehmen und komplizierte Aufgaben ausführen können. Gespeicherte Prozeduren sind außerdem sehr nützlich, weil sie vorkompiliert sind: Sie führen die Aufgaben schnell und effizient aus, weil der Datenbankoptimierer bereits einen Ausführungsplan für den Code hat.
Hersteller | Befehl
--- | ---
SQL Server | Unterstützt
MySQL | Nicht unterstützt (siehe Befehl CREATE FUNCTION)
Oracle | Unterstützt
PostgreSQL | Nicht unterstützt
Wie bei vielen anderen CREATE-Anweisungen auch gibt es große herstellerspezifische Unterschiede.
SQL99: Syntax und Beschreibung
    CREATE PROCEDURE procedure_name
    [parameter data_type attributes ][,...n]
    AS
    code block
Eine umfassendere Beschreibung der SQL99-Syntax finden Sie unter CREATE FUNCTION. Die erweiterten Möglichkeiten von CREATE FUNCTION gelten auch für CREATE PROCEDURE.
Weil jeder Hersteller eigene prozedurale Erweiterungen der SQL-Sprache implementiert hat, würde eine ausführliche Beschreibung zur Programmierung von gespeicherten Prozeduren hier zu weit führen. Die Grundlagen der Programmierung von gespeicherten Prozeduren werden jedoch besprochen. Andere Bücher von O'Reilly wie Transact-SQL Programming von Kevin Kline, Lee Gould und Andrew Zanevsky (1999) und Oracle PL/SQL Programming, Second Edition von Steven Feuerstein und Bill Pribyl (1997) sind hervorragende Informationsquellen für die jeweiligen Programmiersprachen.
Microsoft SQL Server: Syntax und Variationen
    CREATE PROC[EDURE] procedure_name [;number]
    [{@parameter_name datatype} [VARYING] [= default] [OUTPUT]][,...n]
    [WITH {RECOMPILE | ENCRYPTION | RECOMPILE, ENCRYPTION}]
    [FOR REPLICATION]
    AS
    Transact-SQL_block
    GO
Neben dem Prozedurnamen können Sie in Microsoft SQL Server auch eine Versionsnummer im Format procedure_name;1, angeben, wobei 1 ein Ganzzahlwert ist, der die Versionsnummer angibt. Dies ermöglicht den Zugriff auf mehrere Versionen einer einzigen gespeicherten Prozedur.
Wie bei Tabellen (siehe CREATE TABLE) können auch hier lokale und globale temporäre Prozeduren deklariert werden, indem dem Namen der Prozedur ein Nummernzeichen (#) und doppeltes Nummernzeichen (##) vorangestellt wird. Temporäre Prozeduren bestehen nur während der Benutzer- oder Prozesssitzung, in der sie erzeugt wurden. Wenn die Sitzung endet, löscht sich die temporäre Prozedur automatisch selbst.
Eine gespeicherte Prozedur in SQL Server kann bis zu 1024 Eingabeparameter haben, die mit einem at-Zeichen (@) und einem beliebigen zulässigen SQL Server-Datentyp gekennzeichnet werden. (Parameter vom Datentyp "Cursor" müssen sowohl auf VARYING als auch auf OUTPUT gesetzt sein.) Das Schlüsselwort VARYING wird nur bei Parametern vom Datentyp "Cursor" verwendet, um anzugeben, dass die Ergebnismenge von der Prozedur dynamisch aufgebaut wird.
Die Werte der Eingabeparameter müssen vom Benutzer oder dem aufrufenden Prozess übergeben werden. Es kann aber auch ein Standardwert angegeben werden, damit die Prozedur ohne einen vom Benutzer oder aufrufenden Prozess angegebenen Wert ausgeführt werden kann. Der Standardwert muss eine Konstante oder NULL sein, kann aber Wildcard-Zeichen enthalten, die unter LIKE besprochen werden.
In ähnlicher Weise kann ein Parameter mit dem Schlüsselwort OUTPUT als Rückgabeparameter deklariert werden. Der im Rückgabeparameter gespeicherte Wert wird über die Rückgabevariablen des SQL-Server-Befehls EXEC[UTE] an die aufrufende Prozedur zurückgegeben. Rückgabeparameter können jeden beliebigen Datentyp außer TEXT und IMAGE annehmen.
Die Optionen WITH RECOMPILE, WITH ENCRYPTION und WITH RECOMPILE, ENCRYPTION haben folgende Bedeutungen:
WITH RECOMPILE Teilt SQL Server mit, keinen Cacheplan für die gespeicherte Prozedur zu speichern, sondern statt dessen den Cacheplan bei jeder Ausführung neu zu berechnen. Dies ist nützlich, wenn atypische oder temporäre Werte in der Prozedur verwendet werden. WITH ENCRYPTION Verschlüsselt den Code der gespeicherten Prozedur in der syscomments-Tabelle von SQL Server. WITH RECOMPILE, ENCRYPTION Erlaubt beide Optionen auf einmal.
Mit der Klausel FOR REPLICATION, die nicht zusammen mit der Klausel WITH RECOMPILE verwendet werden kann, wird die Ausführung der gespeicherten Prozedur auf einem abonnierenden Server deaktiviert. Sie wird hauptsächlich dazu verwendet, eine Filterprozedur zu schreiben, die nur von der eingebauten Replikationsengine in SQL Server ausgeführt wird.
Die Klausel AS Transact-SQL_block enthält einen oder mehrere Transact-SQL-Befehle bis zu einer maximalen Größe von 128 MB. Microsoft SQL Server unterstützt die meisten zulässigen Transact-SQL-Anweisungen, nicht aber SET SHOWPLAN_TEXT und SET SHOWPLAN_ALL. Einige andere Befehle können in gespeicherten Prozeduren nur eingeschränkt verwendet werden. Dazu gehören ALTER TABLE, CREATE INDEX, CREATE TABLE, alle DBCC-Anweisungen, DROP TABLE, DROP INDEX, TRUNCATE TABLE und UPDATE STATISTICS.
SQL Server unterstützt die verzögerte Namensauflösung, was bedeutet, dass die gespeicherte Prozedur auch dann fehlerfrei kompiliert wird, wenn sie ein noch nicht erzeugtes Objekt referenziert. Sie erzeugt einen Ausführungsplan und schlägt nur fehl, wenn das Objekt dann immer noch nicht existiert.
Gespeicherte Prozeduren können in SQL Server leicht verschachtelt werden. Immer wenn eine gespeicherte Prozedur eine andere gespeicherte Prozedur aufruft, wird die Systemvariable @@NESTLEVEL um 1 erhöht. Wenn die aufgerufene Prozedur beendet ist, wird die Variable wieder um 1 verringert. Mit SELECT @@NESTLEVEL lässt sich herausfinden, wie viele Verschachtelungsebenen in der aktuellen Sitzung auftreten.
Oracle: Syntax und Variationen
    CREATE [OR REPLACE] PROCEDURE [owner_name.]procedure_name
    [(parameter1 [IN | OUT | IN OUT] [NOCOPY] datatype][,...n)]]
    [AUTHID {CURRENT_USER | DEFINER} ]
    {IS | AS} {PL/SQL block | LANGUAGE {java_spec | C_spec}};
In Oracle sind benutzerdefinierte Funktionen und gespeicherte Prozeduren im Hinblick auf den Aufbau und die Struktur sehr ähnlich. Der Hauptunterschied besteht darin, dass gespeicherte Prozeduren keinen Wert an den aufrufenden Prozess zurückgeben können, während bei Funktionen ein einzelner Wert zurückgegeben werden kann.
In einer gespeicherten Prozedur in Oracle werden die Argumente und Parameter jemals mit IN, OUT und IN OUT gekennzeichnet. IN wird verwendet, wenn ein Wert an die Prozedur übergeben wird, OUT, wenn ein Wert an den aufrufenden Prozess zurückgegeben wird. Mit anderen Worten, der Qualifier IN wird vom Benutzer oder von dem Prozess, der die Funktion aufruft, angegeben, während das OUT-Argument von der Funktion zurückgegeben wird. IN OUT ist eine Kombination aus IN und OUT. Das Schlüsselwort NOCOPY wird verwendet, um die Leistung zu verbessern, wenn ein OUT- oder IN OUT-Argument sehr groß ist, wie zum Beispiel ein Varray oder ein Datensatz.
Mit AUTHID CURRENT_USER und AUTHID DEFINER kann darüber hinaus festgelegt werden, dass die Funktion im Zugriffsrechtekontext des aktuellen Benutzers oder des Benutzers, der die Funktion definiert hat, laufen soll.
In Oracle kann die die Prozedur mit dem Schlüsselwort LANGUAGE auch externe Programme aufrufen. Das externe Programm muss ein C- oder Java-Programm sein. Die Beschreibung der spezifischen Syntax für den Aufruf externer Programme würde über das Ziel dieses Buches hinausgehen. Nähere Informationen dazu finden Sie in der Dokumentation des Herstellers.
Gespeicherte Prozeduren in Microsoft SQL Server können Ergebnismengen zurückgeben, gespeicherte Prozeduren in Oracle nicht.
Beispiel
Die folgende gespeicherte Prozedur in Microsoft SQL Server erzeugt (basierend auf den Elementen des Systemdatums und der Systemzeit) einen eindeutigen 22-stelligen Wert und gibt diesen an den aufrufenden Prozess zurück:
    -- Gespeicherte Prozedur in Microsoft SQL Server
    CREATE PROCEDURE get_next_nbr
       @next_nbr CHAR(22) OUTPUT
    AS
    BEGIN
      DECLARE @random_nbr INT
      SELECT @random_nbr = RAND(  ) * 1000000

    SELECT @next_nbr =
      RIGHT('000000' + CAST(ROUND(RAND(@random_nbr)*1000000,0))AS CHAR(6), 6) +
      RIGHT('0000' + CAST(DATEPART (yy, GETDATE(  ) ) AS CHAR(4)), 2) +
      RIGHT('000'  + CAST(DATEPART (dy, GETDATE(  ) ) AS CHAR(3)), 3) +
      RIGHT('00'   + CAST(DATEPART (hh, GETDATE(  ) ) AS CHAR(2)), 2) +
      RIGHT('00'   + CAST(DATEPART (mi, GETDATE(  ) ) AS CHAR(2)), 2) +
      RIGHT('00'   + CAST(DATEPART (ss, GETDATE(  ) ) AS CHAR(2)), 2) +
      RIGHT('000'  + CAST(DATEPART (ms, GETDATE(  ) ) AS CHAR(3)), 3)
    END
    GO

CREATE ROLE |
Mit CREATE ROLE können benannte Mengen von Privilegien erstellt werden, die Benutzern der Datenbank zugewiesen werden. Wenn einem Benutzer eine Rolle zugeteilt wird, erhält er alle Privilegien und Zugriffsrechte, die mit dieser Rolle verknüpft sind.
Hersteller | Befehl
--- | ---
SQL Server | Nicht unterstützt
MySQL | Nicht unterstützt
Oracle | Unterstützt, mit Variationen
PostgreSQL | Nicht unterstützt
Microsoft SQL Server unterstützt den Befehl CREATE ROLE nicht, stellt aber über die gespeicherte Systemprozedur sp_add_role eine ähnliche Funktionalität zur Verfügung..
SQL99: Syntax und Beschreibung
    CREATE ROLE role_name [WITH ADMIN {CURRENT_USER | CURRENT_ROLE}]
Diese Anweisung erzeugt eine neue Rolle und unterscheidet diese Rolle von einem Benutzer des Host-DBMS. Mit der Klausel WITH ADMIN wird dem gerade aktiven Benutzer oder der gerade aktiven Rolle unmittelbar eine Rolle zugewiesen. Standard bei dieser Anweisung ist WITH ADMIN CURRENT_USER.
Oracle: Syntax und Variationen
    CREATE ROLE role_name [NOT IDENTIFIED | IDENTIFIED
       {BY password | EXTERNALLY | GLOBALLY}]
In Oracle wird zuerst die Rolle erzeugt, und dann werden mit dem Befehl GRANT die Privilegien und Zugriffsrechte zugewiesen. Wenn der Benutzer Zugriff auf die Zugriffsrechte einer kennwortgeschützten Rolle haben möchte, muss er den Befehl SET ROLE verwenden. Bei einer Rolle mit Kennwortschutz muss der Benutzer, wenn er darauf zugreifen möchte, dieses Kennwort mit dem Befehl SET ROLE angeben.
Oracle wird mit verschiedenen vorkonfigurierten Rollen geliefert. CONNECT, DBA und RESOURCE sind in allen Oracle-Versionen verfügbar. EXP_FULL_DATABASE und IMP_FULL_DATABASE sind neuere Rollen, die für Import- und Exportoperationen verwendet werden.
Beispiel
Im folgenden Beispiel wird zunächst mit CREATE eine neue Rolle in Oracle definiert. Dann werden mit GRANT die Privilegien dieser Rolle zugewiesen, und mit ALTER ROLE wird ein Kennwort vergeben. Zum Schluss wird diese Rolle wiederum mit GRANT einer Reihe von Benutzern zugeteilt:
    CREATE ROLE boss;

    GRANT ALL ON employee TO boss;
    GRANT CREATE SESSION, CREATE DATABASE LINK TO boss;

    ALTER ROLE boss IDENTIFIED BY le_grande_fromage;

    GRANT boss TO nancy, dale;

CREATE SCHEMA |
Mit dieser Anweisung wird ein Schema, d. h. eine benannte Gruppe von zusammengehörenden Objekten, erzeugt. Ein Schema ist eine Sammlung von Tabellen, Views und den dazugehörigen Zugriffsrechten. Das Schema gehört einer bestehenden gültigen Benutzer-ID (dem Eigentümer).
Hersteller | Befehl
--- | ---
SQL Server | Unterstützt
MySQL | Nicht unterstützt
Oracle | Unterstützt, mit Variationen
PostgreSQL | Nicht unterstützt
SQL99: Syntax und Beschreibung
    CREATE SCHEMA [schema_name] [AUTHORIZATION owner_name]
    [DEFAULT CHARACTER SET char_set_name]
    [PATH schema_name [,...n] ]

       [ <create_table_statement1> [...n] ]
       [ <create_view_statement1>  [...n] ]
       [ <grant statement1> [...n] ]
Die Anweisung CREATE SCHEMA ist ein Container, in dem viele andere CREATE- und GRANT-Anweisungen Platz finden. Optional kann mit DEFAULT CHARACTER SET der Standardzeichensatz des Schemas festgelegt werden. Darüber hinaus kann PATH für alle Objekte angegeben werden, die sich im Dateisystem befinden.
Syntax in Microsoft SQL Server und Oracle
    CREATE SCHEMA AUTHORIZATION owner_name
       [ <create_table_statement1> [...n] ]
       [ <create_view_statement1>  [...n] ]
       [ <grant statement1> [...n] ]
Wenn eine der Anweisungen in der Anweisung CREATE SCHEMA fehlschlägt, schlägt die gesamte Anweisung fehl. Der Vorteil von CREATE SCHEMA ist, dass die Objekte nicht nach irgendwelchen Abhängigkeiten geordnet sein müssen. Zum Beispiel könnte eine GRANT-Anweisung normalerweise nicht für eine Tabelle ausgeführt werden, die noch nicht existiert. In einer CREATE SCHEMA-Anweisung könnten jedoch alle GRANT-Anweisungen zuerst stehen, gefolgt von den CREATE-Anweisungen.
Viele Implementierungen unterstützen den Befehl CREATE SCHEMA nicht explizit. Sie erstellen aber implizit ein Schema, wenn der Benutzer Datenbankobjekte erstellt. Auf der anderen Seite erzeugt Oracle immer dann ein Schema, wenn ein Benutzer angelegt wird. Mit dem Befehl CREATE SCHEMA können in einem Schritt alle Tabellen, Views und sonstigen Datenbankobjekte zusammen mit den jeweiligen Zugriffsrechten erstellt werden.
Beispiel
In Oracle wird mit CREATE SCHEMA kein Schema erstellt, dies ist nur mit CREATE USER möglich. CREATE SCHEMA ermöglicht es dem Benutzer, in einer einzigen SQL-Anweisung mehrere Schritte auszuführen. Im folgenden Beispiel aus Oracle werden die Zugriffsrechte in der Anweisung CREATE SCHEMA festgelegt, bevor die Objekte erstellt werden:
    CREATE SCHEMA AUTHORIZATION emily
       GRANT SELECT, INSERT ON view_1 TO sarah
       GRANT ALL ON table_1 TO sarah

       CREATE VIEW view_1 AS
          SELECT column_1, column_2
          FROM table_1
          ORDER BY column_2

       CREATE TABLE table_1(column_1 INT, column_2 CHAR(20));

CREATE TABLE |
Wie der Name schon sagt, wird mit der Anweisung CREATE TABLE eine Tabelle erstellt. Bei den meisten Herstellern können jedoch mit der Anweisung CREATE TABLE viele weitere Operationen ausgeführt werden, darunter das Zuweisen von Schlüsseln, kaskadierende referenzielle Integrität, Constraints und Standardwerte.
Hersteller | Befehl
--- | ---
SQL Server | Unterstützt, mit Variationen
MySQL | Unterstützt, mit Variationen
Oracle | Unterstützt, mit Variationen
PostgreSQL | Unterstützt, mit Variationen
Dieser Befehl definiert einen Tabellennamen, die Spalten der Tabelle und alle Eigenschaften der Spalten und/oder der Tabelle. Der Erstellung einer Tabelle gehen in der Regel zahlreiche Überlegungen im Hinblick auf den Aufbau voraus. Diesen Schritt bezeichnet man als Datenbankdesign . Die Phase, die sich mit der Analyse der Beziehungen einer Tabelle zu ihren eigenen Daten und zu anderen Tabellen in derselben Datenbank befasst, heißt Normalisierung.
Programmierern und Entwicklern sei dringend empfohlen, sich intensiv mit dem Datenbankdesign und der Normalisierung auseinanderzusetzen, bevor sie den Befehl CREATE TABLE zum ersten Mal ausführen.
Im Allgemeinen beginnt der Tabellenname immer mit einem Buchstaben. Die zulässige Länge des Namens hängt vom Hersteller ab. Oracle lässt nur 30 Zeichen zu, der Name kann jedoch um einiges länger sein als 30 Zeichen, wenn nötig. Im Tabellennamen können Zahlen verwendet werden, aber keine Symbole außer dem Unterstrich ( _ ). Manche Hersteller lassen noch viel mehr Symbole in Tabellennamen zu. Diese sollten jedoch nicht verwendet werden, weil das zu verwirrenden IDs führen kann.
Zur Definition von Spalteneigenschaften unterstützen alle Hersteller die Optionen NULL und NOT NULL. (Eine allein stehende NULL wird vom SQL99-Standard nicht verlangt.) Wenn eine Spalte als NULL definiert wird, kann diese unabhängig vom Datentyp Nullwerte enthalten. In der Regel belegen Spalten, die Nullwerte enthalten dürfen, ein weiteres Bit pro Datensatz. Wenn NOT NULL angegeben ist, darf die Spalte nie Nullwerte enthalten. Bei einer NOT NULL-Spalte schlägt jeder Versuch, mit INSERT einen Nullwert einzufügen und mit UPDATE einen Wert auf Null zu setzen, fehl und wird zurückgeführt.
Alle Hersteller unterstützen außerdem die Deklaration PRIMARY KEY, sowohl auf Spalten- als auch auf Tabellenebene. Ein Primärschlüssel ist eine besondere Bezeichnung, mit der sich jede Zeile einer Tabelle eindeutig identifizieren lässt. Der Primärschlüssel besteht aus einer oder mehreren Spalten in der Tabelle, die zusammengenommen eine eindeutige Identität für jede Zeile liefern. Eine Tabelle kann nur einen Primärschlüssel haben. Alle Werte im Primärschlüssel müssen eindeutig und dürfen nicht null sein. Es können anschließend Fremdschlüssel für die Tabelle deklariert werden, die eine direkte Beziehung zum Primärschlüssel einer anderen Tabelle herstellen. Auf diese Weise können Parent/Child- bzw. Master/Detail-Beziehungen zwischen Tabellen aufgebaut werden. Dies kann mit kaskadierenden Aktionen erweitert werden. Ein Benutzer möchte vielleicht verhindern, dass ein Datensatz aus der Tabelle customer gelöscht wird, wenn es für diesen Kunden noch Verkaufsdatensätze in der Tabelle sales gibt. Die Syntax zum Definieren von Fremdschlüsseln ist von Hersteller zu Hersteller unterschiedlich.
Die meisten Hersteller unterstützen auch DEFAULT-Werte für bestimmte Spalten. Jedes Mal, wenn ein Datensatz in eine Tabelle eingefügt wird und für die betreffende Spalte kein Wert angegeben ist, wird der Standardwert verwendet.
Die grundlegende Syntax für CREATE TABLE ist nachstehend dargestellt. Diese Informationen reichen aus, um mit dem Erstellen von Tabellen beginnen und die Tabellen dann mit Daten füllen zu können:
    CREATE TABLE table_name
       (
       column_name datatype[(length)] [NULL | NOT NULL],...n
       )
Dazu ein einfaches Beispiel:
    CREATE TABLE housing_construction
       (project_number      INT NOT NULL,
       project_date         DATETIME NOT NULL,
       project_name         VARCHAR(50) NOT NULL,
       construction_color   NCHAR(20) NULL,
       construction_height  DECIMAL(4,1) NULL,
       construction_length  DECIMAL(4,1) NULL,
       construction_width   DECIMAL(4,1) NULL,
       construction_volume  INT NULL)
    GO
In Microsoft SQL Server wird mit dieser Anweisung eine Tabelle namens housing_construction definiert, die acht Spalten enthält. Jede Spalte ist entweder als NULL oder NOT NULL definiert und hat einen zu den enthaltenen Informationen passenden Datentyp. Beachten Sie, dass die Liste der Spaltendefinitionen immer in runden Klammern stehen muss und und nach jeder Spaltendefinition ein Komma kommt, sofern noch eine weitere Definition folgt.
SQL99: Syntax und Beschreibung
    CREATE [GLOBAL TEMPORARY | LOCAL TEMPORARY] TABLE table_name
    [ON COMMIT {PRESERVE ROWS | DELETE ROWS}
    (column_name datatype attributes [,...n]
     | [LIKE  table_name]
     | [table_constraint][,...n] ]
Mit der SQL99-Anweisung CREATE TABLE werden temporäre Tabellen angelegt, die beim Erstellen der Tabelle instanziiert und am Ende der aktuellen Benutzersitzung automatisch gelöscht werden. Temporäre Tabellen vom Typ GLOBAL stehen allen aktiven Benutzersitzungen zur Verfügung, solche vom Typ LOCAL dagegen nur der Benutzersitzung, in der sie angelegt wurden. Es kann auch ein ON COMMIT-Wert für die temporäre Tabelle angegeben werden. Bei ON COMMIT PRESERVE ROWS bleiben alle Datenänderungen an einer temporären Tabelle bei einem COMMIT bestehen, während die Tabelle bei ON COMMIT DELETE ROWS bei einem COMMIT geleert wird.
Mit der Option LIKE table_name wird eine neue Tabelle mit denselben Spaltendefinitionen und Tabellen-Constraints wie eine bereits bestehende Tabelle erzeugt. Wenn Sie LIKE verwenden, müssen die Spalten- und Tabellen-Constraints nicht definiert werden.
Weil es keine einheitliche Implementierung von CREATE TABLE gibt, dieser Befehl aber sehr wichtig ist, werden alle Hersteller-Implementierungen einzeln und detailliert beschrieben.
Microsoft SQL Server: Syntax und Variationen
    CREATE TABLE [database_name.[owner]. | owner.] table_name
    ({column_name datatype [ [DEFAULT default_value]
       | {IDENTITY [(seed,increment) [NOT FOR REPLICATION]]]
       [ROWGIDCOL] ]
       [NULL | NOT NULL]
       | [{PRIMARY KEY | UNIQUE}
            [CLUSTERED | NONCLUSTERED]
            [WITH FILLFACTOR = int] [ON {filegroup | DEFAULT}] ]
       | [[FOREIGN KEY]
            REFERENCES reference_table[(reference_column[,...n])]
            [ON DELETE {CASCADE | NO ACTION}]
            [ON UPDATE {CASCADE | NO ACTION}]
            [NOT FOR REPLICATION]
       | [CHECK [NOT FOR REPLICATION] (expression)
       | [COLLATE collation_name]
    |column_name AS computed_column_expression
    [,...n]
    |[table_constraint][,...n] )
    [ON {filegroup | DEFAULT} ]
    [TEXTIMAGE_ON {filegroup | DEFAULT} ]
SQL Server bietet zahlreiche Optionen für die Definition einer Tabelle, ihrer Spalten und ihrer Contraints auf Tabellenebene. In SQL Server kann jeder Constraint auf Spaltenebene mit CONSTRAINT constraint_name. . ., gefolgt vom Text des Constraints, benannt werden. Für eine einzelne Spalte können mehrere Constraints festgelegt werden, solange diese sich nicht gegenseitig ausschließen (wie zum Beispiel PRIMARY KEY und NULL).
In SQL Server können auch lokale temporäre Tabellen erstellt werden, die dann in der Datenbank tempdb gespeichert werden. Dazu muss dem Tabellennamen ein Nummernzeichen (#) vorangestellt werden. Die lokale temporäre Tabelle kann nur von dem Benutzer oder dem Prozess, der sie erstellt hat, verwendet werden. Sie wird gelöscht, sobald sich die Person ausloggt oder der Prozess beendet ist. Eine globale temporäre Tabelle, die von allen aktuell angemeldeten Benutzern und Prozessen verwendet werden kann, wird erstellt, indem man dem Namen der Tabelle zwei Nummernzeichen (##) voranstellt. Die globale temporäre Tabelle wird gelöscht, sobald der Prozess beendet ist oder sich der Benutzer, der die Tabelle angelegt hat, ausloggt.
Weil SQL Server die integrierte Replikation unterstützt, können viele Eigenschaften einer Spalte als NOT FOR REPLICATION gekennzeichnet werden, was bedeutet, dass IDENTITY- und FOREIGN KEY-Werte nicht auf die beteiligten Server repliziert werden. Dies ist hilfreich in Situationen, in denen verschiedene Server dieselben Tabellenstrukturen, aber nicht genau dieselben Daten benötigen.
Ebenso nützlich für die Replikation ist ROWGUIDCOL. Damit wird eine Spalte als globaler eindeutiger Identifier ausgewiesen, was sicherstellt, dass keine zwei Werte über alle Server hinweg jemals doppelt vorkommen. Pro Tabelle kann nur eine solche Spalte identifiziert werden. Der eindeutige Wert selbst wird durch diese Operation jedoch nicht erzeugt. Dieser muss mit der Funktion NEWID eingefügt werden.
Wenn die Eigenschaft IDENTITY auf eine Integerspalte angewendet wird, ist sie vergleichbar mit AUTO_INCREMENT in MySQL, das die Spalten automatisch erstellt und mit monoton steigenden Zahlen füllt. IDENTITYist jedoch um einiges vielseitiger und flexibler. Während AUTO_INCREMENT immer bei 1 beginnt, beginnt IDENTITY mit dem Wert von seed. Während bei AUTO_INCREMENT der Wert jedes Mal um 1 erhöht wird, wenn eine neue Zeile eingefügt wird, wird bei IDENTITY der Wert jeweils um increment erhöht.
In SQL Server kann DEFAULT auf jede beliebige Spalte außer auf solche mit dem Datentyp "Timestamp" oder der Eigenschaft IDENTITY angewendet werden. DEFAULT muss ein konstanter Wert wie zum Beispiel eine Zeichenfolge oder eine Zahl sowie eine Systemfunktion wie GETDATE( ) oder NULL sein.
Pro Tabelle können darüber hinaus ein PRIMARY KEY namens "name per table" und mehrere Spalten vom Typ UNIQUE oder FOREIGN KEY angegeben werden. Diese können geclustert oder nicht-geclustert sein und mit einem anfänglichen Füllfaktor definiert werden. Nähere Informationen dazu finden Sie unter CREATE INDEX.
Wenn Sie einen FOREIGN KEY festlegen, können Sie die Tabelle und die Spalten, zu denen die referenzielle Integrität erhalten bleiben soll, mit der Klausel REFERENCES angeben. Es können nur Spalten referenziert werden, die als PRIMARY KEY- oder UNIQUE-Index auf der referenzierenden Tabelle definiert wurden. Es kann auch eine referenzielle Aktion angegeben werden, die in der reference_table ausgeführt werden soll, wenn ein Datensatz gelöscht oder aktualisiert wird. Bei Angabe von NO ACTION passiert mit der referenzierenden Tabelle nichts, wenn ein Datensatz gelöscht oder aktualisiert wird. Bei Angabe von CASCADE dagegen bezieht sich die Lösch- oder Aktualisierungsoperation auch auf die referenzierte Tabelle, und zwar auf alle Datensätze, die vom Wert des FOREIGN KEY abhängen.
Mit dem CHECK-Constraint wird sichergestellt, dass ein Wert, der in die angegebene Tabellenspalte eingefügt wird, laut CHECK-Ausdruck auch zulässig ist. Im folgenden Beispiel ist eine Tabelle mit mehreren Constraints auf Spaltenebene zu sehen:
    CREATE TABLE people
        (people_id     CHAR(4)
            CONSTRAINT pk_dist_id PRIMARY KEY CLUSTERED
            CONSTRAINT ck_dist_id CHECK (dist_id LIKE '[A-Z][A-Z][A-Z][A-Z]'),
         people_name   VARCHAR(40) NULL,
         people_addr1  VARCHAR(40) NULL,
         people_addr2  VARCHAR(40) NULL,
         city          VARCHAR(20) NULL,
         state         CHAR(2)     NULL
            CONSTRAINT def_st DEFAULT ("CA")
            CONSTRAINT chk_st REFERENCES states(state_ID),
         zip           CHAR(5)     NULL
            CONSTRAINT ck_dist_zip
            CHECK(zip LIKE '[0-9][0-9][0-9][0-9][0-9]'),
         phone         CHAR(12)    NULL,
         sales_rep     empid       NOT NULL DEFAULT USER)
    GO
Mit dem CHECK-Constraint für people_id wird sichergestellt, dass eine ID verwendet wird, die nur aus Buchstaben besteht, und mit dem Constraint für zip wird ein rein numerischer Wert gewährleistet. Mit dem REFERENCES-Constraint für state wird eine Nachschlageoperation in der Tabelle states ausgeführt. Der Constraint REFERENCES ist im Prinzip mit dem CHECK-Constraint vergleichbar, außer dass ersterer die Liste der zulässigen Werte aus den Werten holt, die in einer anderen Spalte gespeichert sind. Das Beispiel zeigt, wie Spalten-Constraints mit der Syntax CONSTRAINT constraint_name. . . angegeben werden.
Neu in SQL Server 2000 ist auch die Spalteneigenschaft COLLATE. Mit dieser Eigenschaft können Programmierer spaltenweise die Sortierreihenfolge und den Zeichensatz der Spalte festlegen. Da es sich hier um eine fortgeschrittene Technik handelt, sollten Sie in der Dokumentation des Herstellers nachschlagen, wenn die standardmäßige Sortierreihenfolge oder der Standardzeichensatz einer bestimmten Spalte geändert werden muss. Unter CREATE FUNCTION finden Sie ein Beispiel für diese Syntax.
SQL Server ermöglicht auch die Erstellung von Tabellen mit Spalten, die einen berechneten Wert enthalten. Die Spalte selbst enthält keine Daten. Vielmehr handelt es sich um eine virtuelle Spalte, die einen Ausdruck enthält, der auf andere Spalten in der Tabelle zurückgreift. So könnte zum Beispiel eine berechnete Spalte einen Ausdruck wie order_cost AS (price * qty) enthalten. Berechnete Spalten können auch Konstanten, Funktionen, Variablen, nicht-berechnete Spalten oder beliebige mit Operatoren verknüpfte Kombinationen aus diesen Spaltentypen sein.
Jede der oben beschriebenen Spalten-Constraints können auch auf Tabellenebene deklariert werden. PRIMARY KEY-Constraints, FOREIGN KEY-Constraints, CHECK-Constraints und sonstige Constraints können also nach der Definition aller Spalten in der Anweisung CREATE TABLE deklariert werden. Dies ist sehr nützlich für Constraints, die sich auf mehrere Spalte beziehen sollen. Wenn zum Beispiel auf Spaltenebene ein UNIQUE-Constraint deklariert wird, kann dieser nur auf diese Spalten angewendet werden. Wird der Constraint hingegen auf Tabellenebene deklariert, erstreckt er sich über mehrere Spalten. Nachfolgend ein Beispiel für Constraints auf Spalten- und auf Tabellenebene:
    -- Constraint auf Spaltenebene
    CREATE TABLE favorite_books
        (isbn          CHAR(100)    PRIMARY KEY NONCLUSTERED,
         book_name     VARCHAR(40)  UNIQUE,
         category      VARCHAR(40)  NULL,
         subcategory   VARCHAR(40)  NULL,
         pub_date      DATETIME     NOT NULL,
         purchase_date DATETIME     NOT NULL)
    GO

    -- Constraint auf Tabellenebene
    CREATE TABLE favorite_books
        (isbn          CHAR(100)    NOT NULL,
         book_name     VARCHAR(40)  NOT NULL,
         category      VARCHAR(40)  NULL,
         subcategory   VARCHAR(40)  NULL,
         pub_date      DATETIME     NOT NULL,
         purchase_date DATETIME     NOT NULL,
            CONSTRAINT pk_book_id   PRIMARY KEY NONCLUSTERED (isbn)
               WITH FILLFACTOR=70,
            CONSTRAINT unq_book     UNIQUE CLUSTERED (book_name,pub_date))
    GO
Die Ergebnisse dieser beiden Befehle sind nahezu gleich, außer dass sich der Tabellen-Constraint UNIQUEauf zwei Spalten bezieht, der Spalten-Constraint UNIQUE dagegen nur auf eine Spalte.
Microsoft SQL Server bietet außerdem zwei separate Klauseln, mit denen gesteuert werden kann, wie die Tabelle (oder die Primärschlüssel- oder eindeutigen Indizes) physisch abgelegt werden soll: [ON {filegroup | DEFAULT} ] und [TEXTIMAGE_ON {filegroup | DEFAULT}]. Mit der Klausel ON filegroup wird die Tabelle oder der Index in der angegebenen Dateigruppe gespeichert, solange diese in der Datenbank existiert. Wenn ON DEFAULT angegeben ist oder die Klausel ON gar nicht verwendet wird, wird die Tabelle oder der Index in der Standarddateigruppe der betreffenden Datenbank abgespeichert. Die Klausel TEXTIMAGE funktioniert ähnlich, außer dass mit ihr die Unterbringung von text-, ntext- und image-Spalten gesteuert wird. Diese Spalten werden normalerweise in der Standarddateigruppe zusammen mit allen anderen Tabellen und Datenbankobjekten gespeichert.
MySQL: Syntax und Variationen
    CREATE [TEMPORARY] TABLE [IF NOT EXISTS] table_name
    (column_name datatype [NULL | NOT NULL] [DEFAULT default_value]
       [AUTO_INCREMENT]
       [PRIMARY KEY] [reference_definition] |
       [CHECK (expression) |
       [INDEX [index_name] index_col_name1[(length)],...n)] |
       [UNIQUE [INDEX] [index_name] (index_col_name1,...n)] |
       [CONSTRAINT symbol] FOREIGN KEY index_name (index_col_name1,...n)
          [REFERENCES table_name [(index_col_name,...)]
          [MATCH FULL | MATCH PARTIAL]
          [ON DELETE {RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT}]
          [ON UPDATE {RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT}])
    {[TYPE = {ISAM | MYISAM | HEAP} |
       AUTO_INCREMENT = int |
       AVG_ROW_LENGTH = int |
       CHECKSUM = {0 | 1} |
       COMMENT = "string" |
       DELAY_KEY_WRITE = {0 | 1} |
       MAX_ROWS = int |
       MIN_ROWS = int |
       PACK_KEYS = {0 | 1} |
       PASSWORD = "string" |
       ROW_FORMAT= { default | dynamic | static | compressed }] }
    [[IGNORE | REPLACE] SELECT_statement]
MySQL bietet viele nützliche Optionen für das Erstellen von Tabellen. Mit der Option TEMPORARY wird eine Tabelle erstellt, die so lange bestehen bleibt, bis die Verbindung, während der sie angelegt wurde, getrennt wird. Sobald die Verbindung geschlossen wird, wird die temporäre Tabelle automatisch gelöscht. Die Option IF NOT EXISTS verhindert einen Fehler, wenn die Tabelle bereits existiert.
Wenn in MySQL eine Tabelle angelegt wird, werden in der Regel drei Betriebssystemdateien erstellt: eine Tabellendefinitionsdatei mit der Erweiterung .frm, eine Datendatei mit der Erweiterung .myd und eine Indexdatei mit der Erweiterung .myi.
Mit der Klausel AUTO_INCREMENT wird eine Integerspalte so konfiguriert, dass sich ihr Wert automatisch um 1 erhöht (beginnend mit dem Wert 1). MySQL erlaubt nur eine AUTO_INCREMENT-Spalte pro Tabelle zu. Wenn der höchste Wert gelöscht wird, wird der Wert wiederverwendet. Wenn alle Datensätze gelöscht werden, beginnt die Zählung der Werte von vorne.
Es können eine oder mehrere PRIMARY KEY-Spalten definiert werden, solange diese auch als NOT NULL definiert sind. Wenn eine Spalte die Eigenschaft INDEX aufweist, kann auch ein Name für den Index angegeben werden. (Ein Synonym für INDEX in MySQL ist KEY.) Wenn kein Name zugewiesen wird, verwendet MySQL den index_column_name und hängt ein numerisches Suffix an ( _2, _3,. . . ), um diesen Namen eindeutig zu machen. Nur der Tabellentyp "MyISAM" unterstützt Indizes für NULL-Spalten oder Spalten des Datentyps BLOB oder TEXT.
Die Klauseln FOREIGN KEY, CHECK und REFERENCES haben keine Funktion. Sie werden nur unterstützt, um die Kompatibilität mit anderen SQL-Datenbanken zu verbessern.
Mit den TYPE-Tabellenoptionen wird festgelegt, wie die Daten physisch gespeichert werden sollen. ISAM ist die ursprüngliche Tabellendefinition. MyISAM ist eine neuere, binäre, portablere Speicherstruktur. Mit HEAP wird die Tabelle im Speicher abgelegt. Es gibt noch weitere Optionen, mit denen die Leistung einer Tabelle optimiert werden kann:
AUTO_INCREMENT Legt den auto_increment-Wert für die Tabelle fest (nur bei MyISAM). AVG_ROW_LENGTH Legt die ungefähre durchschnittliche Zeilenlänge für Tabellen mit Datensätzen variabler Länge fest. MySQL verwendet avg_row_length * max_rows, um festzulegen, wie groß eine Tabelle sein darf. CHECKSUM Wenn dieser Wert auf 1 gesetzt ist, wird für alle Zeile in der Tabelle eine Prüfsumme geführt (nur MyISAM). Dadurch wird zwar die Verarbeitung langsamer, aber das Risiko einer Datenkorruption ist geringer. COMMENT Ermöglicht das Einfügen eines bis zu 60 Zeichen langen Kommentars. DELAY_KEY_WRITE Wenn dieser Wert auf 1 gesetzt ist, werden Aktualisierungen der Schlüsseltabellen verzögert, bis die Tabelle geschlossen wird (nur bei MyISAM). MAX_ROWS Legt die maximale Zeilenanzahl einer Tabelle fest. Der Standardwert ist 4 GB Festplattenspeicher. MIN_ROWS Legt die minimale Anzahl an Zeilen fest, die in der Tabelle gespeichert werden sollen. PACK_KEYS Wenn dieser Wert auf 1 gesetzt ist, werden die Indizes der Tabelle komprimiert, was das Lesen schneller, Aktualisierungen aber langsamer macht (nur bei MyISAM und ISAM). Standardmäßig werden nur Strings gepackt. Wenn der Wert auf 1 gesetzt ist, werden sowohl Strings als auch numerische Werte komprimiert. PASSWORD Verschlüsselt die .frm-Datei, aber nicht die Tabelle, mit einem Kennwort. ROW_FORMAT Legt fest, wie zukünftige Zeilen in der Tabelle gespeichert werden sollen.
Mit der Klausel SELECT_statement wird eine Tabelle erzeugt, deren Felder auf den Elementen in einer SELECT-Anweisung basieren. Sollte dies – wie bei manchen Implementierungen – nicht der Fall sein, kann die Tabelle mit den Ergebnissen der SELECT-Anweisung gefüllt werden. Beispiel:
    CREATE TABLE test_example
      (column_a INT NOT NULL AUTO_INCREMENT,
      PRIMARY KEY(column_a),
      INDEX(column_b))
    TYPE=HEAP
    SELECT column_b,column_c FROM samples;
Hiermit wird eine Heap-Tabelle mit drei Spalten erstellt: column_a, column_b und column_c.
Oracle: Syntax und Variationen
    CREATE [GLOBAL TEMPORARY] TABLE [schema.]table_name
    ( column_name datatype [DEFAULT] {column_constraint [...]} [,...n]
    | table_constraint [,...n] } )
    [ON COMMIT {DELETE | PRESERVE} ROWS]
    ( physical_characteristics )
    ( table_characteristics )
In diesem einfachen und kleinen Codeblock steckt mehr, als man denkt. Die extrem ausgefeilte Oracle-Implementierung der Anweisung CREATE TABLE hat das Potenzial, einer der komplexesten Einzelbefehle in irgendeiner Programmiersprache überhaupt zu werden.
Der Code der CREATE TABLE-Klausel in Oracle enthält viele Unterklauseln. Wir zeigen diese hier nicht alle in einem Befehl, sondern zerlegen diesen in Unterklauseln, die selbst wiederum Unterklauseln enthalten. Der normale SQL-Programmierer wird manche dieser Unterklauseln wahrscheinlich nie verwenden.
Beginnen wir mit den offensichtlichsten Unterschieden zwischen der SQL99-Version von CREATE TABLE und der Oracle-Version: Tabellen, die als GLOBAL TEMPORARY erzeugt werden, müssen einfache Tabellen sein. Globale temporäre Tabellen können die meisten von Oracle unterstützten Sondermerkmale wie Partitionierung, Indexorganisation oder geclusterte Tabellen nicht verwenden. Eine globale temporäre Tabelle steht allen Sitzungen zur Verfügung, aber die in dieser Tabelle gespeicherten Daten sind nur in der Sitzung sichtbar, in der sie eingefügt wurden. Mit der Klausel ON COMMIT, die nur bei der Erstellung temporärer Tabellen erlaubt ist, wird Oracle aufgefordert, die Tabelle entweder nach jedem Festschreiben der Tabelle (DELETE ROWS) oder beim Beenden der Sitzung (PRESERVE ROWS) abzuschneiden. Beispiel:
    CREATE GLOBAL TEMPORARY TABLE shipping_schedule
      (ship_date DATE,
       receipt_date DATE,
       received_by VARCHAR2(30),
       amt NUMBER)
    ON COMMIT PRESERVE ROWS;
Mit der oben gezeigten CREATE TABLE-Anweisung wird eine globale temporäre Tabelle namens shipping_schedule erstellt, bei der die eingefügten Zeilen über mehrere Sitzungen hinweg bestehen bleiben.
Die physischen Eigenschaften einer Oracle-Tabelle werden mit den folgenden Codeblöcken und deren Unterblöcken definiert:
    -- physical_characteristics
    {[{[physical_attributes]
    | TABLESPACE tablespace_name
    | {LOGGING | NOLOGGING} }]
    | {ORGANIZATION {HEAP [{[physical_attributes]
       | TABLESPACE tablespace_name
       | {LOGGING | NOLOGGING} }]
    | INDEX indexed_table_clause)}
    | CLUSTER cluster_name (column [,...n]) }
    [special_storage_clause]
Mit der Klausel physical_characteristics wird festgelegt, wie die Daten physisch im Festplattensubsystem gespeichert werden sollen.
Die Klausel TABLESPACE weist die Tabelle einem bestimmten, bereits vorhandenen Tablespace zu. Die Klausel TABLESPACE kann weggelassen werden, was zur Folge hat, dass der Index dem Standard-Tablespace zugeordnet wird. Das Gleiche erreicht man mit dem Schlüsselwort DEFAULT.
Mit den Klauseln LOGGING und NOLOGGING wird definiert, ob die Tabelle, große Objekte (LOB) oder Partitionen im Redo-Log gespeichert werden sollen.
Die Klausel ORGANIZATION HEAP teilt Oracle mit, dass die Zeilen in der Tabelle physisch in einer beliebigen Reihenfolge gespeichert werden können. Optional kann auch noch die Klausel segment_characteristic angegeben werden. Alternativ können die Zeilen der Tabelle mit ORGANIZATION INDEX index_name physisch nach einem benannten Index sortiert werden.
Mit der Klausel physical_attributes (siehe dazu den folgenden Codeblock) werden die Speichermerkmale der gesamten Tabelle oder, wenn die Tabelle partitioniert ist, einer bestimmten Partition definiert (dazu später mehr):
    -- physical_attributes
    [{PCTFREE int | PCTUSED int | INITRANS int | MAXTRANS int | storage_
        clause}]
PCTFREE definiert, wie viel freier Platz in Prozent für jeden Datenblock in der Tabelle reserviert wird. So werden zum Beispiel bei dem Wert 10 10 % des Datenplatzes für neu einzufügende Zeilen reserviert. Mit PCTUSED wird der minimale Prozentsatz an Speicherplatz definiert, der in einem Block zur Verfügung stehen muss, damit dort neue Zeilen aufgenommen werden können. So besagt zum Beispiel der Wert 90, dass dann neue Zeilen in den Datenblock eingefügt werden, wenn der verwendete Platz unter 90 % fällt. Die Summe von PCTFREE und PCTUSED darf nicht über 100 liegen. INITRANS wird selten verwendet; hier werden zwischen 1 und 255 anfängliche Transaktionen pro Datenblock definiert. MAXTRANS legt die maximale Anzahl gleichzeitiger Transaktionen in einem Datenblock fest.
Die Klausel storage_clause steuert eine Reihe von Attributen zur physischen Speicherung der Daten:
    -- storage_clause
    STORAGE ( [ {INITIAL int [K | M]
                | NEXT int [K | M]
                | MINEXTENTS int
                | MAXEXTENTS {int | UNLIMITED}
                | PCTINCREASE int
                | FREELISTS int
                | FREELIST GROUPS int
                | OPTIMAL [{int [K | M] | NULL}]
                | BUFFER_POOL {KEEP | RECYCLE | DEFAULT} ] [...] )
Wenn Sie diese Attribute in mehr als einer Zeile angeben, setzen Sie sie in runde Klammern und trennen Sie sie mit Leerzeichen wie in (INITIAL 32M NEXT8M). Mit INITIAL int [K | M] wird die anfängliche Bereichsgröße der Tabelle in Byte, Kilobyte (K) oder Megabyte (M) festgelegt. NEXT int [K | M] gibt an, wie viel zusätzlicher Speicherplatz alloziert wird, wenn INITIAL gefüllt ist. Mit PCTINCREASE int wird die Wachstumsrate des Objekts nach dem ersten Anwachsen festgelegt. Der anfängliche Bereich wird wie angegeben alloziert. Für den zweiten Bereich gilt die mit NEXT angegebene Größe. Der dritte Bereich hat die Größe NEXT + (NEXT * PCTINCREASE). Wenn PCTINCREASE auf 0 gesetzt ist, wird immer NEXT verwendet. Ansonsten ist jeder zusätzliche Speicherbereich um PCTINCREASE größer als der vorherige.
Mit MINEXTENTS int wird Oracle angewiesen, die minimale Anzahl von Speicherbereichen zu verwenden. Standardmäßig wird nur ein Speicherbereich erzeugt, es können aber beim Initialisieren des Objekts noch weitere erzeugt werden. MAXEXTENTS int teilt Oracle mit, wie viele Speicherbereiche maximal erlaubt sind. Dieser Wert kann auf UNLIMITED gesetzt werden. (Geben Sie vorsichtig mit UNLIMITED um. Es gibt Situationen, in denen damit Datenbankschäden verursacht werden können.) Mit FREELISTS int wird die Anzahl der freien Listen (Freelists) für jede Gruppe festgelegt, der Standardwert ist 1. FREELIST GROUPS int gibt die Anzahl der Gruppen von freien Listen an, der Standardwert ist 1. Beispiel:
    CREATE TABLE book_sales
      (qty NUMBER,
       period_end_date DATE,
       period_nbr NUMBER)
    TABLESPACE sales
    STORAGE (INITIAL 8M NEXT 8M MINEXTENTS 1 MAXEXTENTS 8);
Die Tabelle books_sales wird im Tablespace sales definiert, beansprucht anfänglich 8 MB und wächst um mindestens 8 MB, wenn der erste Speicherbereich voll ist. Die Tabelle hat mindestens 1 und maximal 8 Speicherbereiche, wodurch ihre Maximalgröße auf 64 MB beschränkt ist.
Die Klausel ORGANIZATION HEAP teilt Oracle mit, dass die Zeilen in der Tabelle physisch in einer beliebigen Reihenfolge gespeichert werden können. Optional kann zusätzlich noch die Klausel segment_characteristic angegeben werden. Alternativ können die Zeilen der Tabelle physisch nach einem benannten INDEX sortiert werden.
Mit der Klausel CLUSTER wird die Tabelle auf der Basis eines geclusterten Schlüssels in ein bestehendes Cluster aufgenommen. (Näheres dazu unter dem Oracle-Befehl CREATE CLUSTER.) Alle Tabellen im Cluster müssen Spalten enthalten, die den Spalten des geclusterten Schlüssels entsprechen.
Mit der Klausel special_storage_clause werden drei verschiedene Arten von Datenspeicher angegeben, die in einer Oracle-Tabelle möglich sind: LOB (große Objekte wie zum Beispiel Bilddateien), Varrays und verschachtelte Tabellen:
    {LOB { (LOB_item [,n]) STORE AS {ENABLE | DISABLE} STORAGE IN ROW
          | (LOB_item) STORE AS
               {LOB_segment_name ({ENABLE | DISABLE} STORAGE IN ROW)
               | LOB_segment_name
               | ({ENABLE | DISABLE} STORAGE IN ROW)}
      | VARRAY varray_item STORE AS
      | NESTED TABLE nested_item STORE AS storage_table
          [(physical_characteristics)]
          [RETURN AS {LOCATOR | VALUE}] }
Die Klausel LOB definiert die Speicherattribute des LOB-Datensegments. Das LOB-Element ist der Name der LOB-Spalte oder -Spalten, die in der Tabelle deklariert sind. Wird die Klausel ENABLE STORAGE IN ROW verwendet, werden die LOB-Objekte in der Zeile selbst gespeichert, sofern sie kleiner sind als 4000 Byte. Bei DISABLE STORAGE IN ROW erfolgt die Speicherung unabhängig von der Größe außerhalb der Zeile. Nähere Informationen über die Speicherung von LOB-Objekten mit LOB_storage_clause finden Sie in der Oracle-Dokumentation. Beispiel:
    CREATE TABLE large_objects
      (pretty_picture BLOB,
       interesting_text CLOB)
    STORAGE (INITIAL 256M NEXT 256M)
    LOG (pretty_picture, interesting_text)
       STORE AS (TABLESPACE large_object_segment
          STORAGE (INITIAL 512M NEXT 512M)
          NOCACHE LOGGING);
Die Tabelle large_objects wird verwendet, um Bilder und Text zu speichern. Die Speichermerkmale sowie die Protokoll- und Caching-Merkmale werden ebenfalls angegeben.
Ein Varray ist ein spezielles Oracle-Objekt. In Oracle kann man verschiedene Speicherparameter für LOBs, die in einem Varray gespeichert werden, angeben. Dabei wird im Prinzip dieselbe Syntax verwendet wie bei der Klausel LOB. Näheres zu Varrays finden Sie in der Dokumentation des Herstellers.
Oracle ermöglicht die Deklaration einer NESTED TABLE-Klausel, in der eine Tabelle virtuell in einer Spalte einer anderen Tabelle gespeichert wird. Mit der Klausel STORE AS kann ein Proxy-Name für die Tabelle in der Tabelle angegeben werden, aber die verschachtelte Tabelle muss zunächst als benutzerdefinierter Datentyp angelegt werden. Diese Möglichkeit ist sehr nützlich für spärlich besetzte Arrays, ist jedoch für den alltäglichen Gebrauch nicht zu empfehlen. Beispiel:
    CREATE TYPE prop_nested_tbl AS TABLE OF props_nt;

    CREATE TABLE proposal_types
       (proposal_category VARCHAR2(50),
       proposals          PROPS_NT)
    NESTED TABLE props_nt STORE AS props_nt_table;
In Oracle können für eine bestimmte Tabelle viele verschiedene Tabellenmerkmale definiert werden. Einige dieser Merkmale sind in der folgenden Liste aufgeführt:
    -- table_characteristics
    { PARTITION characteristics }
    [CACHE | NOCACHE] [MONITORING | NOMONITORING]
    [{NOPARALLEL | PARALLEL [int] }]
    [{ENABLE | DISABLE} [VALIDATE | NOVALIDATE]
      {UNIQUE (column [,...n] )
      | PRIMARY KEY
      | CONSTRAINT constraint_name}
    [index_clause]
    [EXCEPTION INTO [schema.]table_name]
    [CASCADE] ]
    [AS select_statement]
Oracle verwendet die Klausel PARTITION zur Verbesserung der Leistung, indem die Tabelle über mehrere Partitionen verteilt wird. Die vollständige Syntax aller Permutationen einer Tabellenpartition ist jedoch viel zu lang, um hier wiedergegeben zu werden. Außerdem wird sie von den meisten SQL-Programmierneulingen nicht verwendet. Nähere Informationen zur Tabellenpartitionierung finden Sie in der Oracle-Dokumentation.
Mit CACHE wird eine Tabelle für rasch aufeinanderfolgende Lesevorgänge gepuffert, mit NOCACHE wird genau dies verhindert. CACHE-Verhalten gibt es bei indexorganisierten Tabellen. Mit MONITORING werden zur Leistungsoptimierung Statistiken über die Tabelle zusammengestellt, mit NOMONITORING wird diese Funktion deaktiviert.
In der Anweisung CREATE TABLE steht die Klausel INDEX nur für den Primärschlüssel und die eindeutigen Indizes zur Verfügung, die zusammen mit der Tabelle erzeugt werden. In der Oracle-Dokumentation finden Sie umfassende Informationen über die Möglichkeiten zur Bearbeitung eines Index mit dem Befehl CREATE TABLE. In den meisten Fällen ist es am sinnvollsten, den Befehl CREATE INDEX zu verwenden. (Beachten Sie, dass Oracle für Tabellen mit einem Primärschlüssel-Constraint automatisch einen Index anlegt. In diesem Fall muss der Benutzer keinen Index erstellen.)
Die Klausel PARALLEL ermöglicht das parallele Erstellen von Tabellen auf verschiedenen CPUs, um die Operation zu beschleunigen. Mit dieser Klausel kann auch festgelegt werden, dass Abfragen und Datenmanipulationsoperationen in der Tabelle parallel ausgeführt werden. Es kann ein optionaler Integerwert angegeben werden, der bestimmt, wie viele parallele Threads in der aktuellen Operation und in Zukunft ausgeführt werden dürfen. (Oracle berechnet die optimale Anzahl an Threads für die betreffende parallele Operation selbst, dieses Merkmal ist somit optional.) Mit NOPARALLEL, dem Standard, werden die Tabellen seriell erstellt. Es sind somit auch in Zukunft keine parallelen Abfragen und Datenmanipulationsoperationen möglich.
Mit den Klauseln DISABLE und ENABLE können die Constraints für eine Tabelle deaktiviert bzw. aktiviert werden. Im Prinzip kann mit der Klausel DISABLE jeder beliebige aktive Integritäts-Contraint oder Trigger deaktiviert werden. Umgekehrt lässt sich mit ENABLE jeder deaktivierte Integritäts-Constraint oder Trigger aktivieren. Die Syntax für diese Klausel sieht folgendermaßen aus:
    DISABLE | ENABLE {{UNIQUE(column[,...n] |
       PRIMARY KEY |
       CONSTRAINT constraint_name}
          [CASCADE]}
          [EXCEPTIONS INTO [owner.]table_name]
          [USING INDEX [INITRANS int][MAXTRANS int]
             [TABLESPACE tablespace_name][storage_characteristics]
             [PCTFREE int] |
Das Schlüsselwort CASCADE, das nur bei DISABLE verwendet wird, deaktiviert einen kaskadierenden Constraint oder Trigger nicht, sondern kaskadiert das Deaktivieren/Aktivieren aller Integritäts-Constraints, die von dem in der Klausel genannten Constraint abhängen. Die Klausel EXCEPTIONS INTO, die nur bei ENABLE verwendet wird, fordert Oracle auf, Informationen über Verletzungen von Integritäts-Constraints in einer bestehenden Exceptions-Tabelle zu speichern. Die Klausel USING INDEX, die ebenfalls nur bei ENABLE verwendet wird, besitzt einen Mechanismus, mit dem verschiedene Speichermerkmale für den angegebenen Index festgelegt werden können, insbesondere für Primärschlüssel und eindeutige Schlüssel. Standardmäßig sind alle Constraints aktiviert.
Mit der Klausel AS SELECT_statement wird die neue Tabelle mit Datensätzen aus einer gültigen SELECT-Anweisung gefüllt. Im Gegensatz zur PostgreSQL-Implementierung von CREATE . . . AS SELECT müssen die Spalten der Anweisung CREATE TABLE zu denen in der Anweisung SELECT passen. Das Protokollieren von CREATE . . . AS SELECT kann mit dem Schlüsselwort NOLOGGING deaktiviert werden. Standardmäßig erfolgt eine Protokollierung im Redo-Log.
Oracle unterstützt eine Reihe objektorientierter Funktionsmerkmale, deren Beschreibung hier allerdings zu weit führen würde.
PostgreSQL: Syntax und Variationen
    CREATE [TEMPORARY | TEMP] TABLE table
    (column_name datatype [NULL | NOT NULL] [DEFAULT value]
      |[UNIQUE]
      | [PRIMARY KEY (column[,...n])]
       | [CHECK (expression) ]
       | REFERENCES reference_table (reference_column)
            [MATCH {FULL | PARTIAL | default}]
            [ON DELETE {CASCADE | NO ACTION | RESTRICT | SET NULL | SET
               DEFAULT}]
            [ON UPDATE {CASCADE | NO ACTION | RESTRICT | SET NULL | SET
               DEFAULT}]
            [[NOT] DEFERRABLE] [INITIALLY {DEFERRED | IMMEDIATE}] } [,...n]
    |[table_constraint][,...n]
    [INHERITS (inherited_table [,...n])]

    | [ON COMMIT {DELETE | PRESERVE} ROWS]

    | AS SELECT_statement
PostgreSQL verwendet eine ähnliche Syntax wie MySQL und erlaubt das Erstellen einer temporären Tabelle (TEMPORARY). Temporäre Tabellen bestehen nur während der Sitzung, in der sie angelegt wurden. Sie löschen sich automatisch selbst, wenn die Sitzung beendet ist.
Constraints wie UNIQUE, PRIMARY KEY und CHECK sind im Prinzip identisch mit denen in Microsoft SQL Server. Das Besondere bei PostgreSQL ist jedoch die Möglichkeit, Spalten-Constraints zu definieren, die sich über mehrere Spalten erstrecken. Da PostgreSQL auch normale Constraints auf Tabellenebene unterstützt, ist der ANSI-Standard-Ansatz nach wie vor zu empfehlen.
Der Constraint REFERENCES ähnelt einem CHECK-Constraint, außer dass ein Wert mit Werten in einer anderen Spalte einer anderen Tabelle verglichen wird. Er kann auch als Bestandteil einer FOREIGN KEY-Deklaration verwendet werden. Die MATCH-Optionen heißen FULL, PARTIAL und Default (wobei es bei MATCH kein anderes Schlüsselwort gibt). Bei einer vollständigen Übereinstimmung (FULL) müssen alle Spalten eines mehrspaltigen Fremdschlüssels entweder null sein oder einen zulässigen Wert enthalten. Standardmäßig sind Mischungen aus Nullwerten und anderen Werten zulässig. Teilweise Übereinstimmung (PARTIAL) ist zwar syntaktisch erlaubt, wird aber nicht unterstützt.
Mit der Klausel REFERENCES können auch verschiedene Verhalten hinsichtlich der referenziellen Integrität bei ON DELETE und/oder ON UPDATE deklariert werden:
NO ACTION Verursacht einen Fehler, wenn der Fremdschlüssel verletzt wird (= Standard). RESTRICT Ein Synonym für NO ACTION. CASCADE Setzt den Wert der referenzierenden Spalte auf den Wert der referenzierten Spalte. SET NULL Setzt den Wert der referenzierenden Spalte auf NULL. SET DEFAULT Setzt die referenzierende Spalte auf ihren deklarierten Standardwert oder auf null, wenn ein solcher nicht vorhanden ist.
Mit der Option DEFERRABLE der Klausel REFERENCES wird PostgreSQL angewiesen, alle Constraints bis zum Ende der Transaktion zurückzustellen. NOT DEFERRABLE ist das Standardverhalten der Klausel REFERENCES. Die Klausel INITIALLY ist der Klausel DEFERRABLE sehr ähnlich. Bei Angabe von INITIALLY DEFERRED werden die Constraints am Ende einer Transaktion überprüft, bei Angabe von INITIALLY IMMEDIATE dagegen nach jeder Anweisung (Standardwert).
Beachten Sie, dass wie bei Microsoft SQL Server alle Constraints auf Spaltenebene auch als Constraints auf Tabellenebene deklariert werden können. FOREIGN KEY-Constraints können aber nur auf Tabellenebene deklariert werden. Alle Optionen der Klausel REFERENCES werden auch als Bestandteil der Klausel FOREIGN KEYS unterstützt. Die Syntax sieht folgendermaßen aus:
    [FOREIGN KEY (column[,...n]) REFERENCES...]
Die Klausel INHERITS inherited_table gibt eine oder mehrere Tabellen an, von der die betreffende Tabelle alle Spalten erbt. Die neu erstellte Tabelle erbt auch Funktionen, die zu Tabellen gehören, die in der Hierarchie weiter oben stehen. Wenn eine vererbte Spalte mehrmals erscheint, schlägt die Anweisung fehl.
Wenn eine temporäre oder globale temporäre Tabelle in PostgreSQL angelegt wird, kann die Klausel ON COMMIT an den Befehl angehängt werden. Mit dieser Klausel wird das Verhalten der temporären Tabelle festgelegt, nachdem Datensätze in dieser festgeschrieben worden sind. Bei ON COMMIT DELETE ROWS werden nach dem Festschreiben alle Zeilen in der temporären Tabelle gelöscht. Dies ist die Standardeinstellung. Bei ON COMMIT PRESERVE ROWS bleiben die Zeilen in der temporären Tabelle auch nach dem Festschreiben der Transaktion erhalten.
Mit der Klausel AS SELECT_statement kann der Programmierer eine Tabelle erstellen und mit Daten aus einer zulässigen SELECT-Anweisung füllen. Es müssen keine Spalten, Datentypen oder Constraints definiert werden, da diese von der Abfrage geerbt werden. Diese Funktionalität ist vergleichbar mit der von SELECT . . . INTO, aber die Syntax scheint leichter lesbar zu sein.
Beispiele
Im folgenden Beispiel wird der Beispieltabelle ein Fremdschlüssel hinzugefügt:
    -- Constraint auf Spaltenebene
    CREATE TABLE favorite_books
       (isbn         CHAR(100)    PRIMARY KEY NONCLUSTERED,
       book_name     VARCHAR(40)  UNIQUE,
       category      VARCHAR(40)  NULL,
       subcategory   VARCHAR(40)  NULL,
       pub_date      DATETIME     NOT NULL,
       purchase_date DATETIME     NOT NULL,
          CONSTRAINT fk_categories FOREIGN KEY (category)
             REFERENCES category(cat_name));
Der Fremdschlüssel in der Spalte categories bezieht sich auf die Spalte cat_name in der Tabelle category. Diese Syntax wird von allen in diesem Buch behandelten Herstellern unterstützt. Der Fremdschlüssel hätte auch als mehrspaltiger Schlüssel deklariert werden können, der sowohl die Spalte category als auch die Spalte subcategory enthält:
    ...
    CONSTRAINT fk_categories FOREIGN KEY (category, subcategory)
             REFERENCES category(cat_name, subcat_name));
Nachfolgend zwei weitere vollständige Beispiele aus der Datenbank pubs (jobs und employee):
    -- Für eine Microsoft SQL Server-Datenbank
    CREATE TABLE jobs
       (job_id  SMALLINT IDENTITY(1,1) PRIMARY KEY CLUSTERED,
       job_desc VARCHAR(50) NOT NULL DEFAULT 'New Position',
       min_lvl  TINYINT NOT NULL CHECK (min_lvl >= 10),
       max_lvl  TINYINT NOT NULL CHECK (max_lvl <= 250))

    -- Für eine MySQL-Datenbank
    CREATE TABLE employee
       (emp_id INT AUTO_INCREMENT CONSTRAINT PK_emp_id PRIMARY KEY,
       fname VARCHAR(20) NOT NULL,
       minit CHAR(1) NULL,
       lname VARCHAR(30) NOT NULL,
       job_id SMALLINT NOT NULL DEFAULT 1
          REFERENCES jobs(job_id),
       job_lvl TINYINT DEFAULT 10,
       pub_id CHAR(4) NOT NULL DEFAULT ('9952')
          REFERENCES publishers(pub_id),
       hire_date DATETIME NOT NULL DEFAULT (CURRENT_DATE(  ));

    CREATE TABLE publishers
       (pub_id char(4) NOT NULL
          CONSTRAINT UPKCL_pubind PRIMARY KEY CLUSTERED
          CHECK (pub_id IN ('1389', '0736', '0877', '1622', '1756')
          OR pub_id LIKE '99[0-9][0-9]'),
       pub_name varchar(40) NULL,
       city varchar(20) NULL,
       state char(2) NULL,
       country varchar(30) NULL DEFAULT('USA'))
Nachfolgend ein Beispiel für eine CREATE TABLE-Anweisung in Oracle mit zahlreichen Speichereinstellungen:
    CREATE TABLE classical_music_cds
       (music_id        INT,
       composition      VARCHAR2(50),
       composer         VARCHAR2(50),
       performer        VARCHAR2(50),
       performance_date DATE DEFAULT SYSDATE,
       duration         INT,
       cd_name          VARCHAR2(100),
    CONSTRAINT pk_class_cds PRIMARY KEY (music_id)
       USING INDEX TABLESPACE index_ts
       STORAGE (INITIAL 100K NEXT 20K),
    CONSTRAINT uq_class_cds UNIQUE (composition, performer, performance_date)
       USING INDEX TABLESPACE index_ts
       STORAGE (INITIAL 100K NEXT 20K))
    TABLESPACE tabledata_ts;

CREATE TRIGGER |
Ein Trigger ist eine spezielle Art von gespeicherter Prozedur, die automatisch ausgelöst wird, wenn eine Datenmodifizierungsanweisung ausgeführt wird. Trigger gehören zu einer bestimmten Datenmodifizierungsanweisung (INSERT, UPDATE oder DELETE ) für eine bestimmte Tabelle.
Hersteller | Befehl
--- | ---
SQL Server | Unterstützt, mit Variationen
MySQL | Nicht unterstützt
Oracle | Unterstützt, mit Variationen
PostgreSQL | Unterstützt, mit Variationen
SQL99: Syntax und Beschreibung
    CREATE TRIGGER trigger_name
    {BEFORE | AFTER} {[DELETE] | [INSERT] | [UPDATE] [OF column [,...n]}
    ON table_name
    [REFERENCING {OLD [ROW] [AS] old_name | NEW [ROW] [AS] new_name
      OLD TABLE [AS] old_name | NEW TABLE [AS] new_name}]
    [FOR EACH { ROW | STATEMENT }]
    [WHEN (conditions)]
    code block
Trigger werden standardmäßig einmal auf Anweisungsebene ausgelöst. Mit einer einzigen INSERT-Anweisung könnten also 500 Zeilen in eine Tabelle eingefügt werden, ein Insert-Trigger für diese Tabelle wird aber trotzdem nur einmal ausgelöst. Manche Hersteller ermöglichen das Auslösen eines Triggers in jeder Zeile einer Datenmanipulationsoperation. In diesem Fall würde also eine Anweisung, die 500 Zeilen in eine Tabelle einfügt und einen Trigger auf Zeilenebene hat, den Trigger 500 Mal auslösen, d. h. einmal pro eingefügter Zeile.
Trigger sind nicht nur einer bestimmten Datenmodifizierungsanweisung (INSERT, UPDATE oder DELETE) für eine bestimmte Tabelle zugeordnet, sondern auch einem bestimmten Auslösezeitpunkt. Allgemein gesprochen können Trigger vor der Verarbeitung der Datenmanipulationsanweisung (BEFORE), danach (AFTER) oder (sofern dies vom Hersteller unterstützt wird) statt dessen (INSTEAD OF) ausgelöst werden. Trigger, die vor oder an Stelle der Datenmodifizierungsanweisung ausgelöst werden, sehen die Änderungen durch die Anweisung nicht, während Trigger, die danach ausgelöst werden, die Änderungen sehen und mit diesen arbeiten können.
Microsoft SQL Server: Syntax und Variationen
    CREATE TRIGGER trigger_name
    ON {table_name | view_name}
    [WITH ENCRYPTION]
    {FOR | AFTER | INSTEAD OF} {[DELETE] [,] [INSERT] [,] [UPDATE]}
    [WITH APPEND]
    [NOT FOR REPLICATION]
    AS
      {
      T-SQL_block
      |
      { IF UPDATE(column) [{AND | OR} UPDATE(column)] [...n]
        |
        IF (COLUMNS_UPDATED(  ) {bitwise_operator} updated_bitmask)
        { comparison_operator} column_bitmask [...n] }
        T-SQL_block [...n]
       }
Microsoft SQL Server unterstützt eine Reihe interessanter Funktionsmerkmale in der Anweisung CREATE TRIGGER. Zunächst einmal erlaubt SQL Server mehrere Trigger für eine bestimmte Datenmanipulationsoperation in einer Tabelle oder einem View. So sind zum Beispiel drei UPDATE-Trigger in einer Tabelle möglich.
Mit der Klausel WITH ENCRYPTION wird der Text des Triggers an der Stelle verschlüsselt, an der er in der syscomments-Systemtabelle gespeichert ist. Die Klausel WITH APPEND fügt einer Tabelle oder einem View einen weiteren Trigger eines vorhandenen Typs hinzu. Diese Klausel gibt es aus Gründen der Rückwärtskompatibilität mit früheren Versionen des Produkts; sie kann nur zusammen mit FOR-Triggern verwendet werden. Mit der Klausel NOT FOR REPLICATION werden Trigger für Datenmanipulationsoperationen, die über die integrierten Replikationsfunktionen von SQL Server aufgerufen werden, deaktiviert.
Die Klauseln FOR, AFTER und INSTEAD OF teilen SQL Server mit, wann der Trigger ausgelöst werden soll. Die Schlüsselwörter FOR und AFTER sind Synonyme und haben dieselbe Funktion. Sie geben an, dass der Trigger erst dann ausgelöst werden darf, wenn die auslösende Datenmodifizierungsanweisung (und alle kaskadierenden Aktionen und Constraint-Überprüfungen) erfolgreich ausgeführt wurde. Für eine Tabelle sind viele AFTER-Trigger möglich. Die Reihenfolge der Trigger ist nicht festgelegt, allerdings können der erste und der letzte Trigger mit der gespeicherten Systemprozedur sp_settriggerorder angegeben werden.
AFTER-Trigger können nicht für Views definiert werden.
Die Klausel INSTEAD OF funktioniert genauso wie der BEFORE-Trigger in Oracle. Sie gibt an, dass der Trigger vor (und somit an Stelle) der auslösenden Datenmodifizierungsanweisung ausgelöst werden soll. Es ist aber nur ein INSTEAD OF-Trigger pro INSERT-, UPDATE- oder DELETE-Anweisung in einer bestimmten Tabelle möglich (mehrere AFTER-Trigger sind jedoch erlaubt). Diese Art von Trigger kann bei Views eingesetzt werden, aber nur, wenn die Klausel WITH CHECK OPTION nicht verwendet wird. INSTEAD OF DELETE-Trigger können nicht verwendet werden, wenn die Löschoperation kaskadiert.
Mit den Spezifikationen DELETE, INSERT und UPDATE wird angegeben, welche Datenmodifizierungsanweisung den Trigger auslöst. In SQL Server können diese Spezifikationen beliebig kombiniert werden, wobei die einzelnen Optionen mit einem Komma voneinander zu trennen sind. (In diesem Fall wird der gleiche Code für jede angegebene Anweisung ausgeführt.)
Die Klausel AS T-SQL_block enthält den prozeduralen Code, den der Trigger auslöst, wenn die Datenmanipulationsoperation durchgeführt wird. Dieser Abschnitt sollte in die Transact-SQL-Klauseln BEGIN und END eingeschlossen werden. Traditionell enthält er Kontrollflussbefehle und fragt die Art und Menge der geänderten Daten ab.
SQL Server instanziiert zwei wichtige Pseudotabellen, wenn ein Trigger ausgelöst wird: deleted und inserted. Diese Tabellen sind von der Struktur her identisch mit der Tabelle, für die die Trigger definiert sind, außer dass sie die alten Daten vor dem Auslösen der Datenmodifizierungsanweisung enthalten (deleted) bzw. die neuen Werte nach dem Auslösen dieser Anweisung (inserted).
Nur INSTEAD OF-Trigger können auf text-, ntext- oder image-Spalten zugreifen.
Die Klausel AS IF UPDATE(column) sucht speziell nach INSERT- oder UPDATE-Aktionen für eine oder mehrere bestimmte Spalten. Mehrere Spalten können durch Hinzufügen weiterer UPDATE(column)-Klauseln nach der ersten Klausel angegeben werden; danach kommt der Transact-SQL-Block BEGIN . . . END mit den Operationen, die ausgelöst werden sollen, wenn die Bedingung erfüllt ist. Diese Klausel funktioniert genau wie die Operation IF . . . THEN . . . ELSE.
Die Klausel AS IF (COLUMNS_UPDATE( )) hat Ähnlichkeit mit der Klausel AS IF UPDATE( ), weil auch sie nur bei INSERT- oder UPDATE-Operationen in der angegebenen Spalte ausgelöst wird. Sie gibt ein varbinary-Bitmuster zurück, aus dem hervorgeht, welche Spalten eingefügt oder aktualisiert wurden. Darüber hinaus können mit Bitoperationen Spaltenwerte auf unterschiedliche Art und Weise verglichen werden. Die Vergleichsoperatoren sind das Gleichheitszeichen (=), mit dem überprüft wird, ob alle Spalten in der aktualisierten Bitmaske geändert wurden, und das Größer-als-Zeichen (>), mit dem überprüft wird, ob eine oder mehrere der Spalten geändert wurden.
Trigger werden oft zur Steuerung der deklarativen referenziellen Integrität verwendet. Primär- und Fremdschlüsseldeklarationen mit einer CREATE TABLE- oder ALTER TABLE-Anweisung sind jedoch vorzuziehen.
SQL Server lässt die folgenden Anweisungen im Transact-SQL-Block eines Triggers nicht zu: ALTER, CREATE, DROP, DENY, GRANT, REVOKE, LOAD, RESTORE, RECONFIGURE und TRUNCATE. Darüber hinaus werden weder DISK-Anweisungen noch der Befehl UPDATE STATISTICS unterstützt.
In SQL Server ist das rekursive Auslösen von Triggern mit der gespeicherten Systemprozedur sp_dboption möglich. Rekursive Trigger lösen sich durch ihren eigenen Code selbst erneut aus. Wenn zum Beispiel ein INSERT-Trigger für die Tabelle T1 eine INSERT-Operation in der Tabelle T1 ausführt, kann dies zu einer rekursiven Operation führen. Da rekursive Trigger gefährlich sind, ist diese Funktionalität standardmäßig deaktiviert.
SQL Server erlaubt außerdem verschachtelte Trigger bis zu einer Tiefe von 32 Ebenen. Wenn einer der verschachtelten Trigger eine ROLLBACK-Operation ausführt, werden keine weiteren Trigger ausgelöst. Ein Beispiel für verschachtelte Trigger ist ein Trigger für Tabelle T1, mit dem eine Operation in Tabelle T2 ausgelöst wird, für die wiederum ein Trigger definiert ist, der eine Operation in Tabelle T3 auslöst. Die Trigger werden abgebrochen, wenn sich eine Endlosschleife bildet. Verschachtelte Trigger werden durch eine Einstellung in der gespeicherten Systemprozedur sp_configure aktiviert. Wenn verschachtelte Trigger deaktiviert werden, werden rekursive Trigger ebenfalls deaktiviert, unabhängig davon, was in sp_dboption festgelegt ist.
CREATE-Anweisungen in SQL Server erlauben eine verzögerte Namensauflösung, was bedeutet, dass der Befehl auch dann verarbeitet wird, wenn er sich auf ein Datenbankobjekt bezieht, das noch nicht in der Datenbank vorhanden ist.
Oracle: Syntax und Variationen
    CREATE [OR REPLACE] TRIGGER [owner.]trigger_name
    {BEFORE | AFTER | INSTEAD OF}
    {[DELETE] [OR] [INSERT] [OR] [UPDATE [OF column [,...n] ]] [...n]}
    ON {table_name | view_name}
    [REFERENCING {OLD [AS] old_name | NEW [AS] new_name}]
    [FOR EACH { ROW | STATEMENT }]
    [WHEN (conditions)]
    PL/SQL block
Wie für die Anweisung CREATE TRIGGER typisch, wird mit dem Befehl die Datenmodifizierungsoperation (INSERT, UPDATE oder DELETE) angegeben, die den PL/SQL-Codeblock ausführt, und ob dies vor, nach oder an Stelle der Datenmodifizierungsoperation (BEFORE, AFTER oder INSTEAD OF) geschehen soll. Bei UPDATE-Operationen kann für eine oder mehrere Spalten UPDATE OF angegeben werden, um festzulegen, dass der Update-Trigger nur dann ausgelöst werden soll, wenn eine dieser Spalten geändert wird.
In Oracle sind INSTEAD OF-Trigger nur bei Views, aber nicht bei Tabellen möglich.
Oracle unterstützt auch das Auslösen von Triggern bei bestimmten Datenbankereignissen wie DROP TABLE oder SHUTDOWN.
Mit der Klausel REFERENCING wird ein Name für die Pseudotabellen angegeben, die die alten (OLD) und neuen (NEW) Versionen der Tabelle enthalten. (SQL Server nennt diese Pseudotabellen automatisch inserted und deleted.) In Oracle lauten die Standardnamen für diese Pseudotabellen OLDund NEW. Pseudotabellen vergleichen Datensatzwerte, bevor diese von der Datenmanipulationsoperation geändert werden (über die Pseudotabelle OLD) und danach (über die Pseudotabelle NEW). Pseudotabellen führen auch bedingte Operationen im PL/SQL_block aus.
Wenn Werte in den Pseudotabellen OLD und NEW referenziert werden, muss dem Wert ein Doppelpunkt (:) vorangestellt werden, außer in der WHEN-Klausel des Triggers, wo keine Doppelpunkte verwendet werden.
Mit der Klausel FOR EACH ROW wird der Trigger aufgefordert, jede einzelne Zeile zu bearbeiten (d. h. sich für jede von der Operation betroffene Zeile einmal auszulösen), und nicht als impliziter Anweisungstrigger zu fungieren (der einmal für die gesamte Transaktion ausgelöst wird). Die Klausel WHEN gibt eine SQL-Bedingung an, die besagt, dass ein Trigger nur dann ausgeführt werden darf, wenn die Bedingung erfüllt ist. Die Klausel WHEN bietet auch die Möglichkeit, die Tabellen OLD und NEW zu vergleichen, ohne dass dafür ein PL/SQL-Block erforderlich ist.
Mehrere Trigger können zu einem einzigen Triggerbefehl zusammengefasst werden, wenn sie sich auf dieselbe Ebene (Zeile oder Anweisung) und dieselbe Tabelle beziehen. Wenn Trigger in einer Einzelanweisung zusammengefasst werden, können im PL/SQL-Block die Klauseln IF INSERTING THEN, IF UPDATING THEN und IF DELETING THEN verwendet werden, um die Codelogik in verschiedene Segmente aufzuteilen. Eine ELSE-Klausel kann in dieser Struktur ebenfalls verwendet werden.
PostgreSQL: Syntax und Variationen
    CREATE TRIGGER trigger_name
    { BEFORE | AFTER }
    { {[DELETE] [OR | ,] [INSERT] [OR | ,] [UPDATE]} [OR ...] }
    ON table_name
    FOR EACH { ROW | STATEMENT }
    EXECUTE PROCEDURE function_name (parameters)
Die PostgreSQL-Implementierung von CREATE TRIGGER funktioniert ähnlich wie bei anderen Herstellern. Die Trigger können vor der Datenmodifizierungsoperation für den Datensatz (BEFORE) oder vor dem Auslösen von Constraints ausgelöst werden oder aber nachdem (AFTER) die Datenmanipulationsoperation verarbeitet wurde (und alle Constraints überprüft wurden), was die in der Transaktion ausgeführten Operationen für den Trigger sichtbar macht.
Statt einen prozeduralen Codeblock zu verarbeiten (wie bei Oracle und SQL Server), führt PostgreSQL über die Klausel EXECUTE PROCEDURE eine mit CREATE FUNCTION erstellte Funktion aus. Andere Hersteller verarbeiten den Trigger darüber hinaus implizit bei allen Zeilen, die von der Transaktion betroffen sind, während das bei PostgreSQL explizit für jede einzelne Zeile (FOR EACH ROW) oder einmal für die gesamte Transaktion (FOR EACH STATEMENT geschieht.
Beispiele
Nachfolgend ein Beispiel für einen BEFORE-Trigger in PostgreSQL, der auf Zeilenebene überprüft, ob der angegebene Distributorcode auch in der Tabelle distributors vorhanden ist, bevor eine Zeile in die Tabelle sales eingefügt oder dort aktualisiert wird:
    CREATE TRIGGER if_dist_exists
    BEFORE INSERT OR UPDATE ON sales
    FOR EACH ROW
    EXECUTE PROCEDURE check_primary_key ('did', 'distributors', 'did');
BEFORE-Trigger ändern die Werte, die durch eine Datenmodifizierungsoperation in der Tabelle festgeschrieben werden, da die Verarbeitung der betroffenen Datensätze stattfindet, bevor diese in der Tabelle verändert werden. AFTER-Trigger werden oft zum Auditing verwendet, weil sie erst dann ausgelöst werden können, wenn die Zeile in der Tabelle geändert wurde. Mit INSTEAD OF wird die Datenmodifizierungsoperation komplett übergangen, zu Gunsten des Codes, den der Benutzer für die Transaktion angegeben hat.
Das folgende Beispiel enthält einen BEFORE-Trigger in Oracle, der die Pseudotabellen OLD und NEW verwendet, um Werte zu vergleichen. (Zu demselben Zweck verwendet SQL Server die Pseudotabellen DELETED und INSERTED.) Dieser Trigger erzeugt einen Audit-Datensatz, bevor der Gehaltsdatensatz eines Mitarbeiters geändert wird:
    CREATE TRIGGER if_emp_changes
    BEFORE DELETE OR UPDATE ON employee
    FOR EACH ROW
    WHEN (new.emp_salary <> old.emp_salary)
    BEGIN
      INSERT INTO employee_audit
      VALUES ('old', :old.emp_id, :old.emp_salary, :old.emp_ssn);
    END;
Im folgenden Beispiel wird ein Insert- und Update-Trigger in Oracle erstellt, der die IF INSERTED THEN-Klauseln verwendet:
    CREATE TRIGGER if_emp_changes
    BEFORE DELETE OR UPDATE ON employee
    FOR EACH ROW
    BEGIN
      IF DELETING THEN
        INSERT INTO employee_audit
        VALUES ('DELETED', :old.emp_id, :old.emp_salary, :old.emp_ssn);
      ELSE
        INSERT INTO employee_audit
        VALUES ('UPDATED', :old.emp_id, :new.emp_salary, :old.emp_ssn);
      END IF;
    END;
Im folgenden Beispiel für SQL Server wird der Datenbank eine neue Tabelle namens contractor hinzugefügt. Alle Datensätze in der Tabelle employee, aus denen hervorgeht, dass der Mitarbeiter Freiberufler ist, werden in die Tabelle contractor kopiert. Jetzt landen alle neuen Mitarbeiter, die in die Tabelle employee eingefügt werden sollen, aufgrund des INSTEAD OF-Triggers statt dessen in der Tabelle contractor.
    CREATE TRIGGER if_emp_is_contractor
    INSTEAD OF INSERT ON employee
    BEGIN
      INSERT INTO contractor
      SELECT * FROM inserted WHERE status = 'CON'

      INSERT INTO employee
      SELECT * FROM inserted WHERE status = 'FTE'
    END
    GO

CREATE VIEW |
Mit dieser Anweisung wird ein View, auch virtuelle Tabelle genannt, erzeugt. Ein View verhält sich wie eine Tabelle, ist aber als Abfrage definiert. Nahezu jede zulässige SELECT-Anweisung kann den Inhalt eines Views definieren, aber ORDER BY-Klauseln sind in der Regel nicht zulässig.
Wenn ein View in einer Anweisung referenziert wird, wird die Ergebnismenge der Abfrage für die Dauer dieser Anweisung zum Inhalt des Views. In manchen Fällen können Views aktualisiert werden, was zur Folge hat, dass die Änderungen im View auf die zugrunde liegenden Daten in den Basistabellen übertragen werden.
Hersteller | Befehl
--- | ---
SQL Server | Unterstützt, mit Variationen
MySQL | Nicht unterstützt
Oracle | Unterstützt, mit Variationen
PostgreSQL | Unterstützt, mit Variationen
Views können auch auf andere Views aufgesetzt werden. Davon raten wir jedoch ab, weil dies als schlechter Stil betrachtet wird.
SQL99: Syntax und Beschreibung
    CREATE VIEW view_name [(column list)]
    AS
    (SELECT_statement
    [WITH [CASCADED | LOCAL] CHECK OPTION] )
Views sind normalerweise genauso effizient wie die Abfrage, auf der sie basieren. Aus diesem Grund muss die definierende SELECT-Anweisung schnell und gut geschrieben sein.
Nach dem Namen des Views kann auch eine Spaltenliste angegeben werden. Die optionale Spaltenliste enthält Aliasnamen für die einzelnen Elemente in der Ergebnismenge der SELECT-Anweisung.
Die Klausel WITH CHECK OPTION wird nur für Views verwendet, die Aktualisierungen der Basistabelle erlauben. Sie stellt sicher, dass nur Daten, die vom View gelesen werden können, von diesem eingefügt, aktualisiert oder gelöscht werden dürfen. Wenn zum Beispiel ein View von employees nur Mitarbeiter mit Monatsgehalt anzeigt, aber nicht die stundenweise bezahlten Mitarbeiter, ist es nicht möglich, stundenweise bezahlte Mitarbeiter über diesen View einzufügen, zu aktualisieren oder zu löschen. Die Optionen CASCADE und LOCAL der Klausel CHECK OPTION werden für verschachtelte Views verwendet. Bei Angabe von CASCADE wird CHECK OPTION für den aktuellen View und für alle Views, auf denen er basiert, ausgeführt. Bei Angabe von LOCAL wird CHECK OPTION nur für den aktuellen View ausgeführt, auch wenn dieser auf anderen Views basiert.
ANSI SQL99-Views können die Basistabelle oder Basistabellen, auf denen sie basieren, aktualisieren, wenn die folgenden Bedingungen erfüllt sind:
Die definierende SELECT-Anweisung basiert auf genau einer Tabelle. Der View verwendet nicht die Operatoren UNION, MINUS oder INTERSECT. Die definierende SELECT-Anweisung enthält keine GROUP BY- oder HAVING-Klausel. Die definierende SELECT-Anweisung enthält keine Referenzen auf Pseudospalten wie ROWNUM oder ROWGUIDCOL. Die definierende SELECT-Anweisung enthält keine Gruppierungsfunktionen. Die definierende SELECT-Anweisung enthält keine DISTINCT-Klausel.
Microsoft SQL Server: Syntax und Variationen
    CREATE [owner_name.]VIEW view_name [(column [,...n])]
    [WITH {ENCRYPTION | SCHEMABINDING | VIEW_METADATA} [,...n]]
    AS
    select_statement
    [WITH CHECK OPTION]
Microsoft SQL Server unterstützt zwei neue Optionen, die in SQL99 nicht vorgesehen sind: ENCRYPTION und SCHEMABINDING. Mit der Option ENCRYPTION wird der Text des Views in der Tabelle syscomments verschlüsselt. Mit der Option SCHEMABINDING wird der View an ein bestimmtes Schema gebunden, was bedeutet, dass alle Objekte in dem View mit ihrem vollständigen Namen (sowohl Name des Eigentümers als auch des Objekts) angegeben werden müssen. Wenn mit SCHEMABINDING erzeugte Views (und Tabellen, die diese Views referenzieren) gelöscht oder geändert werden sollen, muss vorher die Schemabindung (mit ALTER VIEW) gelöscht werden. Mit VIEW_METADATA wird festgelegt, dass SQL Server Metadaten über den View (und nicht über die Basistabelle) an Aufrufe aus den DBLIB- und OLEDB-APIs zurückgeben soll. In Views, die mit VIEW_METADATA erstellt oder geändert wurden, können die Spalten mit INSERT- und UPDATE INSTEAD OF-Triggern aktualisiert werden.
In SQL Server können Indizes für Views erstellt werden (siehe CREATE INDEX). Bei Erstellung eines eindeutigen, geclusterten Index für einen View speichert SQL Server praktisch eine physische Kopie des Datenbank-Views. Änderungen der Basistabelle werden im indizierten View automatisch aktualisiert.
Indizierte Views sollten nur mit der Klausel SCHEMABINDING auf Basistabellen aufgesetzt werden. Dies ist eine fortgeschrittene Technik, die nur von Experten angewendet werden sollte. Nähere Informationen zu dieser Technik finden Sie in der Dokumentation des Herstellers.
Oracle: Syntax und Variationen
    CREATE [OR REPLACE] [FORCE | NO FORCE] VIEW [owner_name.]view_name
      [(column [,...n])]
    AS
    SELECT_statement
    [WITH [READ ONLY | CHECK OPTION [CONSTRAINT constraint_name] ] ]
Mit der Klausel OR REPLACE wird Oracle angewiesen, einen bestehenden View mit demselben Namen durch den neuen View zu ersetzen. Mit der Klausel FORCE wird der View unabhängig davon, ob die Basistabellen existieren oder der Benutzer, der den View erzeugt, Zugriffsrechte auf die entsprechenden Basistabellen hat, erstellt. Mit der Klausel NO FORCE wird der View nur dann erstellt, wenn die Basistabellen und die Zugriffsrechte vorhanden sind.
Oracle erlaubt die Verwendung der Klausel CHECK OPTION; außerdem kann mit der Klausel CONSTRAINT ein Constraint benannt werden. Die Klausel CHECK OPTION kann für verschachtelte Views verwendet werden, allerdings nur, wenn CHECK OPTION auch beim obersten View in der Hierarchie verwendet wird. Wenn für den Constraint kein Name angegeben wird, verwendet Oracle den Namen SYS_C n, wobei n eine Ganzzahl ist.
Oracle ermöglicht Datenmodifizierungsoperationen über Views, sofern die Anforderungen des SQL99-Standards erfüllt und keine Ausdrücke enthalten sind. Die Klausel WITH READ ONLY stellt sicher, dass mit dem View Daten nur gelesen werden können.
PostgreSQL: Syntax und Variationen
    CREATE VIEW view_name AS SELECT_statement
Die CREATE VIEW-Implementierung von PostgreSQL unterstützt manche der komplexeren Optionen anderer Hersteller nicht. Es können aber Views für Tabellen und andere definierte Klassenobjekte aufgebaut werden. PostgreSQL-Views werden in der Regel nur auf Tabellen und nicht auf anderen Views aufgebaut und nicht für Datenmodifizierungsoperationen in den zugrunde liegenden Basistabellen verwendet.
Beispiele
Der einfachste View basiert auf dem gesamten Inhalt einer einzigen Tabelle:
    CREATE VIEW employees
    AS
    SELECT *
    FROM employee_tbl;
Das folgende Beispiel zeigt einen View namens california_authors, der Datenmodifzierungsoperationen ermöglicht, die nur Autoren in Kalifornien betreffen:
    CREATE VIEW california_authors
    AS
    SELECT au_lname, au_fname, city, state
    FROM authors
    WHERE state = 'CA'
    WITH CHECK OPTION
    GO

DECLARE CURSOR |
Der Befehl DECLARE CURSOR ermöglicht das zeilenweise Abrufen und Bearbeiten von Datensätzen in einer Tabelle. Damit ist eine zeilenbasierte Verarbeitung möglich, die im Gegensatz zur herkömmlichen mengenorientierten Verarbeitung in SQL steht. Wenn Sie dieses Verfahren anwenden möchten, sollten Sie Folgendes tun:
Den Cursor mit DECLARE deklarieren. Den Cursor mit OPEN öffnen. Zeilen mit FETCH aus dem Cursor abrufen. Zum Schluss den Cursor mit CLOSE schließen.
MySQL unterstützt keine serverseitigen Cursor im ANSI SQL-Stil, dafür aber umfangreiche C-Programmiererweiterungen, die dieselbe Funktionalität bieten.
Hersteller | Befehl
--- | ---
SQL Server | Unterstützt
MySQL | Nicht unterstützt
Oracle | Unterstützt
PostgreSQL | Unterstützt
SQL99: Syntax und Beschreibung
Beim Befehl DECLARE CURSOR wird eine SELECT-Anweisung angegeben. Jede Zeile, die von der SELECT-Anweisung zurückgegeben wird, kann individuell abgerufen und bearbeitet werden. Mit dem Befehl DECLARE CURSOR werden auch die Eigenschaften eines serverseitigen Cursors definiert. Dazu gehört, wie der Cursor scrollt und welche SELECT-Anweisung zum Abrufen der Ergebnismenge verwendet wird.
Microsoft SQL Server kennt auch die Optionen INSENSITIVE und SCROLL. Mit dem Schlüsselwort INSENSITIVE wird angegeben, dass der Cursor eine temporäre Kopie der vom Cursor verwendeten Ergebnismenge anlegen soll. Alle Anforderungen an den Cursor werden anhand der temporären Tabelle, und nicht anhand der Basistabelle, beantwortet. Der Cursor ermöglicht keine Modifizierungen. Spätere Abrufe durch den Cursor spiegeln keine durch den Cursor vorgenommenen Änderungen wider. Mit dem Schlüsselwort SCROLL werden alle FETCH-Optionen für den Cursor (FIRST, LAST, PRIOR, NEXT, RELATIVE und ABSOLUTE) aktiviert. Näheres dazu finden Sie unter dem Befehl FETCH. Wenn SCROLL nicht angegeben ist, steht nur NEXT als FETCH-Option zur Verfügung. Mit der Klausel FOR READ ONLY kann auch ein schreibgeschützter Cursor deklariert werden.
In Oracle sind keine Variablen in der WHERE-Klausel der SELECT-Anweisung zulässig, es sei denn, sie wurden vorher als Variablen deklariert. Die Parameter werden nicht von DECLARE, sondern von OPEN zugewiesen.
Die PostgreSQL-Implementierung ist der von Microsoft SQL Server sehr ähnlich, außer dass zusätzlich die Option BINARY unterstützt wird. BINARY zwingt den Cursor, binärformatierte statt textformatierte Daten abzurufen.
Syntax in Microsoft SQL Server
    DECLARE cursor_name [INSENSITIVE] [SCROLL] CURSOR
    FOR select_statement
    [FOR {READ ONLY | UPDATE [OF column_name [,...n]]}]
Syntax in Oracle
    DECLARE CURSOR cursor_name [parameter1 datatype1 [,...parameterN datatypeN]
    IS select_statement
    [FOR UPDATE [OF column_name [,...n]]}]
Syntax in PostgreSQL
    DECLARE cursor_name [BINARY] [INSENSITIVE] [SCROLL] CURSOR
    FOR select_statement
    [FOR {READ ONLY | UPDATE [OF column_name [,...n]]}]
Microsoft SQL Server: Syntax und Variationen
Microsoft SQL Server unterstützt das in diesem Kapitel bereits beschriebene Standardformat, bietet jedoch auch eine anspruchsvolle Erweiterung. Die Syntax dafür sieht folgendermaßen aus:
    DECLARE cursor_name CURSOR
    [LOCAL | GLOBAL] [FORWARD_ONLY | SCROLL]
    [STATIC | KEYSET | DYNAMIC | FAST_FORWARD]
    [READ_ONLY | SCROLL_LOCKS | OPTIMISTIC]
    [TYPE_WARNING]
    FOR select_statement
    [FOR UPDATE [OF column_name [,...n]]]
Diese Syntax funktioniert genauso wie die Cursor-Deklaration nach dem ANSI-Standard, beinhaltet jedoch viele neue Funktionsmerkmale. Zunächst einmal kann der Gültigkeitsbereich des Cursors als LOCAL oder GLOBAL deklariert werden. Bei LOCAL steht der Cursor nur im aktuellen Transact-SQL-Stapel, in der aktuellen gespeicherten Prozedur oder im aktuellen Trigger, in dem er deklariert wurde, zur Verfügung. Bei GLOBAL ist der Cursor während der Verbindungsdauer über OPEN und FETCH verfügbar.
Die Transact-SQL-Notation sollte nicht mit der Cursor-Deklaration nach dem ANSI-Standard in Microsoft SQL Server verwechselt werden.
Mit den nächsten Optionen wird festgelegt, wie der Cursor die Datensatzmenge durchsucht. Mit FORWARD_ONLY wird, im Gegensatz zu SCROLL, festgelegt, dass der Cursor nur vom ersten bis zum letzten Datensatz scrollen kann. Es ist keine Kombination mit STATIC, KEYSET oder DYNAMIC möglich. Der Cursor verhält sich wie ein DYNAMIC-Cursor.
STATIC funktioniert ähnlich wie das Schlüsselwort INSENSITIVE. KEYSET ist vergleichbar mit STATIC und INSENSITIVE, ermöglicht aber Änderungen der Ergebnismenge. Das Keyset kann die von anderen Benutzern nach dem Öffnen des Cursors eingefügten Datensätze nicht sehen. Datensätze, die von anderen Benutzern gelöscht wurden, haben den @@FETCH_STATUS –2 zur Folge. Neue Werte werden bei der Durchführung von Aktualisierungen mit WHERE CURRENT OF sichtbar gemacht. DYNAMIC spiegelt alle Datenänderungen an der Ergebnismenge wider, die während der Arbeit mit dem Cursor vorgenommen wurden. Die Ergebnismenge kann sich während jedem FETCH verändern. FETCH ABSOLUTE wird von DYNAMIC-Cursorn nicht unterstützt. FAST_FORWARD ist eine Abkürzung für FORWARD_ONLY, READ_ONLY, aktiviert aber auch zusätzliche Funktionen. FAST_FORWARD kann nicht in Verbindung mit SCROLL, FOR_UPDATE, SCROLL_LOCKS, OPTIMISTIC und FORWARD_ONLY verwendet werden.
Es können noch zwei weitere Optionen bei READ_ONLY verwendet werden: SCROLL_LOCKS und OPTIMISTIC. Mit SCROLL_LOCKS wird beim Abruf eines neues Datensatzes eine Datensatzsperre erzwungen. Auf diese Weise wird sichergestellt, dass Aktualisierungen und Löschungen durch den Cursor auch erfolgreich sind. Mit OPTIMISTIC wird angegeben, dass positionierte Aktualisierungen und Löschungen durch den Cursor fehlschlagen sollen, wenn die Zeile von einem anderen Benutzer geändert wurde.
Mit der Option TYPE_WARNING schließlich wird SQL Server mitgeteilt, dass eine Warnmeldung an den Client gesendet werden soll, wenn der Cursortyp geändert wird (zum Beispiel von KEYSET in DYNAMIC).
Beispiele
In diesem einfachen Beispiel aus Microsoft SQL Server wird ein Cursor auf der Tabelle publishers deklariert und geöffnet. Der Cursor ruft den ersten Datensatz aus der Tabelle publisher ab, der mit der SELECT-Anweisung übereinstimmt, und fügt diesen in eine andere Tabelle ein. Dann geht er zum nächsten Datensatz über usw., bis alle Datensätze verarbeitet sind. Abschließend wird der Cursor geschlossen und freigegeben (deallocate wird nur bei Microsoft SQL Server verwendet):
    DECLARE @publisher_name VARCHAR(20)

    DECLARE pub_cursor CURSOR
    FOR SELECT pub_name FROM publishers
        WHERE country <> 'USA'

    OPEN pub_cursor
    FETCH NEXT FROM pub_cursor INTO @publisher_name
    WHILE @@FETCH_STATUS = 0
    BEGIN
        INSERT INTO foreign_publishers VALUES(@publisher_name)
    END

    CLOSE pub_cursor
    DEALLOCATE pub_cursor
Im folgenden Oracle-Beispiel wird der Cursor zusammen mit anderen Variablen im Deklarationsblock definiert. Dann wird der Rest des Cursors verarbeitet:
    DECLARE
       new_price NUMBER(10,2);
       CURSOR title_price_cursor IS
          SELECT title, price
          FROM titles
          WHERE price IS NOT NULL;
       title_price_val title_price_cursor%ROWTYPE;
    BEGIN
       OPEN title_price_cursor;
       FETCH title_price_cursor INTO title_price_val;
       new_price := "title_price_val.price" * 1.25
       INSERT INTO new_title_price VALUES (title_price_val.title, new_price)
       CLOSE title_price_cursor;
    END;
Da in diesem Beispiel viel PL/SQL verwendet wird, würde eine detaillierte Beschreibung des Codes über den Umfang dieses Buches hinausgehen. Der DECLARE-Block zeigt jedoch deutlich, wie der Cursor deklariert wird. Im PL/SQL-Ausführungsblock wird der Cursor mit dem Befehl OPEN initialisiert. Die Werte werden mit dem Befehl FETCH abgerufen, und der Cursor wird zum Schluss mit dem Befehl CLOSE geschlossen.

DELETE |
Mit der Anweisung DELETE werden Datensätze aus einer oder mehreren Tabellen gelöscht. Es handelt sich dabei um eine protokollierte Operation, was bedeutet, dass sie mit dem Befehl ROLLBACK rückgängig gemacht werden kann.
Hersteller | Befehl
--- | ---
SQL Server | Unterstützt, mit Variationen
MySQL | Unterstützt, mit Variationen
Oracle | Unterstützt
PostgreSQL | Unterstützt
Eine DELETE-Anweisung wird selten ohne WHERE-Klausel verwendet, da ansonsten alle Zeilen aus der betreffenden Tabelle gelöscht werden.
SQL99: Syntax und Beschreibung
    DELETE [FROM] [owner.]table_name [WHERE clause]
Sollte es notwendig sein, alle Zeilen einer Tabelle zu entfernen, verwenden Sie am besten die Anweisung TRUNCATE TABLE . In Datenbanken, die diesen Befehl unterstützen, lassen sich alle Zeilen auf diesem Wege schneller physisch entfernen. Mit TRUNCATE TABLE geht es schneller als mit DELETE, weil TRUNCATE nicht protokolliert wird und somit ein Rückgängigmachen nicht möglich ist. Durch den Wegfall des Protokollierens wird Zeit gespart, was sich besonders beim Löschen vieler Datensätze positiv auswirkt.
Microsoft SQL Server: Syntax und Variationen
    DELETE [FROM] [owner.] {table_name | view_name}
    [WITH (query_hint[,...n]]
    [FROM table_source[,...n]]
    [WHERE clause | [CURRENT OF [GLOBAL] cursor_name]]
    [OPTION (query_hint[,...n])]
In Microsoft SQL Server können Datensätze sowohl aus Tabellen als auch aus Views, die auf einer einzelnen Tabelle basieren, gelöscht werden. (Es gibt einige andere Sonderregeln, die das Löschen aus einem Mehrfachtabellen-View ermöglichen, diese sind jedoch recht komplex und würden den Rahmen dieses Buches sprengen.) An zwei Stellen im Befehl, d. h. nach dem ersten FROM und am Ende der Anweisung, kann das Standardverhalten des Optimierers in SQL Server überschrieben werden. Dies sollte jedoch nur von Experten vorgenommen werden. Diese Hinweise gehören nicht zum ANSI-Standard, sind aber in der Dokumentation der meisten Hersteller zu finden.
SQL Server erlaubt darüber hinaus eine zweite FROM-Klausel. In dieser zweiten FROM-Klausel können JOIN-Anweisungen verwendet werden, so dass auf einfache Art und Weise Zeilen aus der Tabelle im ersten FROM (basierend auf den entsprechenden Zeilen in der im zweiten FROM deklarierten Tabelle) gelöscht werden können.
Die Klausel WHERE CURRENT OF wird für das positionierte Löschen mit Hilfe eines Cursors verwendet. In Verbindung mit einem Cursor löscht diese Form von DELETE nur die Zeile, die durch den Cursor geöffnet wurde.
MySQL: Syntax und Variationen
    DELETE [LOW_PRIORITY] FROM table_name [WHERE clause] [LIMIT rows]
MySQL ist für Geschwindigkeit optimiert. Es besteht die Möglichkeit, die Option LOW PRIORITY anzugeben, wodurch die Ausführung von DELETE verzögert wird, bis keine anderen Clients mehr aus der Tabelle lesen. In MySQL kann mit der Klausel LIMIT nbr_of_rows auch eine beliebige Obergrenze für die Anzahl der Datensätze festgelegt werden, die gelöscht werden, bevor die Kontrolle an den Client zurückgegeben wird.
Oracle: Syntax und Variationen
    DELETE FROM [schema.]{table_name | view_name | snapshot_name}
       {PARTITION (partition_name) | SUBPARTITION (subpartition_name)} |
    [WHERE clause]
    [subquery WITH {READ ONLY | CHECK OPTION [CONSTRAINT constraint_name]} ]
    [RETURNING expression[,...] INTO variable[,...]
In Oracle können Sie Zeilen aus Tabellen und Views sowie aus partitionierten Views und Tabellen löschen.
Mit PARTITION und SUBPARTITION wird der Name der Partition bzw. der Subpartition in der zu löschenden Tabelle angegeben.
Die Klausel WITH wird in Verbindung mit einer Unterabfrage verwendet. Sie beschränkt die Aktionen der DELETE-Anweisung. Mit der Option WITH READ ONLY wird festgelegt, dass keine der im Befehl verwendeten Unterabfragen aktualisiert werden kann. Mit WITH CHECK OPTION wird Oracle aufgefordert, alle Zeilen zu löschen, die nicht in der Unterabfrage enthalten sind.
Mit RETURNING werden die von dem Befehl betroffenen Zeilen abgerufen. Beim Löschen einer einzelnen Zeile werden die Werte der Zeile in PL/SQL-Variablen und Bindungsvariablen gespeichert. Beim Löschen mehrerer Zeilen werden die Werte der Zeilen dagegen in Bindungs-Arrays gespeichert. Mit dem Schlüsselwort INTO wird festgelegt, dass die gelöschten Werte in der Variablenliste gespeichert werden sollen.
PostgreSQL: Syntax und Variationen
    DELETE FROM [ONLY] table
    [WHERE {clause | CURRENT OF cursor_name}]
PostgreSQL verwendet den Befehl DELETE zur Entfernung von Zeilen und definierten Unterklassen aus der Tabelle. Wenn Sie Zeilen nur aus der angegebenen Tabelle löschen möchten, verwenden Sie die Klausel ONLY. Mit der Klausel WHERE CURRENT OF wird PostgreSQL aufgefordert, nur die aktuell geöffnete Zeile des benannten, offenen Cursors zu löschen.
Beispiele
So löschen Sie alle Datensätze aus der Tabelle titles:
    DELETE titles
So löschen Sie alle Datensätze aus der Tabelle authors, bei denen der Nachname mit "Mc" beginnt:
    DELETE FROM authors
    WHERE au_lname LIKE 'Mc%'
So löschen Sie alle Titel mit einer alten ID-Nummer:
    DELETE titles WHERE title_id >= 40
So löschen Sie alle Titel ohne Umsatz:
    DELETE titles WHERE ytd_sales IS NULL
So löschen Sie alle Datensätze aus einer Tabelle anhand der Ergebnisse einer Unterabfrage einer anderen Tabelle (in diesem Fall werden die Datensätze der Tabelle titleauthor gelöscht, zu denen es einen passenden Eintrag zum Thema "Computer" in der Tabelle titles gibt):
    DELETE FROM titleauthor
    WHERE title_id IN
      (SELECT title_id
      FROM titles
      WHERE title LIKE '%computers%')

DISCONNECT |
Mit der Anweisung DISCONNECT wird die Verbindung zu einem DBMS beendet.
Hersteller | Befehl
--- | ---
SQL Server | Unterstützt, mit Einschränkungen
MySQL | Nicht unterstützt
Oracle | Unterstützt, mit Variationen
PostgreSQL | Nicht unterstützt
SQL99: Syntax und Beschreibung
    DISCONNECT {CURRENT | ALL | connection_name}
Dieser Befehl sorgt für die Beendigung einer oder mehrere Verbindungen zwischen dem aktuellen SQL-Prozess und dem Datenbankserver. Mit der Klausel CURRENT wird die gegenwärtig aktive Benutzerverbindung geschlossen. Mit der Klausel ALL werden alle offenen Verbindungen des aktuellen Benutzers geschlossen. Es ist aber auch möglich, nur eine bestimmte Verbindung zu schließen.
Microsoft SQL Server: Syntax und Variationen
Microsoft SQL Server unterstützt DISCONNECT nur in Embedded-SQL (ESQL), nicht aber in dem Microsoft-Abfragetool SQL Query Analyzer. Es wird die volle SQL99-Syntax unterstützt. Beim Trennen der Verbindung zu Microsoft SQL Server in einem ESQL-Programm sollte der Befehl DISCONNECT ALL verwendet werden, um die Verbindung zum Datenbankserver sauber abzubauen.
Oracle: Syntax und Variationen
    DISC[ONNECT]
Im Gegensatz zu SQL Server erlaubt Oracle den Befehl DISCONNECT nur in seinem Abfragetool SQL*Plus. Hier wird mit dem Befehl die aktuelle Datenbankserversitzung beendet, ansonsten kann der Benutzer aber mit SQL*Plus weiterarbeiten. So kann ein Programmierer zum Beispiel weiter den Puffer bearbeiten, Protokolldateien speichern usw. Es muss jedoch eine neue Verbindung aufgebaut werden, wenn SQL-Befehle verwendet werden sollen. Mit dem Befehl EXIT verlassen Sie SQL*Plus und mit QUIT kehren Sie zu dem Dateisystem zurück.
Oracle unterstützt diese Funktionalität auch mit dem Befehl ALTER SYSTEM DISCONNECT SESSION. Es handelt sich dabei jedoch um einen privilegierten Befehl, der nur dem Datenbankadministrator zur Verfügung steht, um eine (in der Regel illegitime) Sitzung zwangsweise von der Datenbank zu trennen.
PostgreSQL
PostgreSQL unterstützt den Befehl DISCONNECT nicht explizit. Jede Programmierschnittstelle unterstützt jedoch eine Disconnect-Operation. So steht z. B. SPI_FINISH im Server Programming Interface und PG_CONNECT im PL/tcl-Programmierpaket zur Verfügung.
Beispiele
So beenden Sie die aktuelle Verbindung zu einem Oracle-Server:
    DISCONNECT;
Microsoft SQL Server unterstützt DISCONNECT nur in ESQL-Programmen:
    EXEC SQL DISCONNECT new_york;

DROP DATABASE |
DROP DATABASE macht alle Änderungen durch den Befehl CREATE DATABASE rückgängig. Es werden alle bestehenden Datenbankobjekte gelöscht und der von ihnen beanspruchte Speicherplatz freigegeben. Bei den meisten Herstellern kann dieser Befehl nicht ausgeführt werden, wenn noch Benutzer (einschließlich Eigentümer) in der Datenbank aktiv sind.
Hersteller | Befehl
--- | ---
SQL Server | Unterstützt
MySQL | Unterstützt
Oracle | Nicht unterstützt
PostgreSQL | Unterstützt
SQL99: Syntax und Beschreibung
    DROP DATABASE database_name
Genau wie CREATE DATABASE wird auch DROP DATABASE von ANSI SQL nur als Erweiterung und nicht als Kernbefehl unterstützt. SQL99 bevorzugt Befehle im Zusammenhang mit SCHEMA und DOMAIN, um Bereiche abzudecken, die in den meisten Implementierungen grob als "Datenbankangelegenheiten" gelten.
Die vom Datenbankhersteller erstellten Systemdatenbanken dürfen nie gelöscht werden. Das Löschen einer Datenbank erfordert explizite Zugriffsrechte, es sei denn, diese Operation wird vom Eigentümer der Datenbank oder dem Systemadministrator durchgeführt.
Microsoft SQL Server: Syntax und Variationen
    DROP DATABASE database_name [,...n]
In SQL Server können mehrere Datenbanken mit demselben Befehl gelöscht werden, wobei die einzelnen Datenbanknamen mit einem Komma voneinander zu trennen sind. Eine Datenbank kann nur von einem Benutzer in der Master-Datenbank, einem Benutzer mit Administratorrechten oder dem Datenbankeigentümer gelöscht werden. Die Datenbank muss ONLINE sein, damit sie gelöscht werden kann.
MySQL und PostgreSQL: Syntax und Variationen
In MySQL und PostgreSQL wird mit diesem Befehl eine gesamte Datenbank mit allen dazugehörigen Dateien entfernt. Die Datenbank sendet eine Meldung, die angibt, wie viele Dateien gelöscht wurden. In PostgreSQL kann eine Datenbank, die geöffnet ist und gerade verwendet wird, nicht gelöscht werden.
Oracle: Syntax und Variationen
Oracle unterstützt DROP DATABASE nicht. Eine Datenbank kann mit dem Befehl CREATE DATABASE database_name (ohne Parameter) gelöscht werden. Dabei wird derselbe Name verwendet wie derjenige der zu löschenden Datenbank.

DROP FUNCTION |
Mit diesem Befehl wird eine benutzerdefinierte Funktion aus der aktuellen Datenbank gelöscht.
Hersteller | Befehl
--- | ---
SQL Server | Unterstützt, mit Variationen
MySQL | Unterstützt, mit Variationen
Oracle | Unterstützt, mit Variationen
PostgreSQL | Unterstützt, mit Variationen
SQL99: Syntax und Beschreibung
    DROP FUNCTION function_name {RESTRICT | CASCADE}
Mit diesem Befehl wird eine Funktion dauerhaft gelöscht. Die Klausel RESTRICT sorgt dafür, dass der Befehl fehlschlägt, wenn andere Datenbankobjekte wie z. B. ein View von der Funktion abhängig sind. Mit der Option CASCADE hingegen werden die Funktion, alle auf der Funktion basierenden Zugriffsrechte und alle abhängigen Datenbankobjekte gelöscht.
Microsoft SQL Server: Syntax und Variationen
    DROP FUNCTION [owner_name.]function_name [,...n]
Wie auch bei anderen DROP-Befehlen in SQL Server kann mehr als ein Datenbankobjekt desselben Typs gelöscht werden, indem die Namen der einzelnen Datenbankobjekte durch Kommas getrennt werden.
MySQL: Syntax und Variationen
Mit diesem Befehl wird nicht die Datei gelöscht, die die Funktion enthält. Vielmehr wird die Funktionsreferenz aus der Systemtabelle gelöscht, die später mit der Anweisung CREATE FUNCTION erneut hinzugefügt werden kann.
Oracle: Syntax und Variationen
    DROP FUNCTION [owner_name.]function_name
Wie bei anderen DROP-Befehlen in Oracle kann auch hier der Name des Funktionseigentümers angegeben werden. Andernfalls geht Oracle vom Kontext des aktuellen Benutzers aus und sorgt dafür, dass nur Funktionen gelöscht werden, die dem aktuellen Eigentümer gehören. Alternativ haben Benutzer mit dem Systemprivileg DROP ANY FUNCTION die Möglichkeit, jede beliebige Funktion an jeder beliebigen Stelle zu löschen.
PostgreSQL: Syntax und Variationen
    DROP FUNCTION name ( [ type [,...n] ] )
In PostgreSQL können Funktionen unabhängig von der Programmiersprache, in der sie deklariert wurden, gelöscht werden. Type ist das Eingabeargument der zu löschenden Funktion. Dieses Argument muss angegeben werden, da nur die Funktion mit dem angegebenen Namen und den angegebenen Parametertypen gelöscht wird.

DROP INDEX |
Mit dem Befehl DROP INDEX werden ein oder mehrere Indizes in der aktuellen Datenbank gelöscht. Wenn ein Index gelöscht wird, wird sofort der gesamte vorher belegte Speicherplatz freigegeben. Mit DROP INDEX werden jedoch nicht die PRIMARY KEY- oder UNIQUE-Constraints gelöscht. Dies muss mit dem Befehl ALTER TABLE . . . DROP geschehen. Nähere Informationen zu diesen Constraints finden Sie unter dem Befehl CREATE TABLE.
Hersteller | Befehl
--- | ---
SQL Server | Unterstützt, mit Variationen
MySQL | Unterstützt, mit Variationen
Oracle | Unterstützt, mit Variationen
PostgreSQL | Unterstützt, mit Variationen
SQL99: Syntax und Beschreibung
    DROP INDEX table_name.index_name
PostgreSQL folgt dem SQL99-Standard mit Variationen.
Microsoft SQL Server: Syntax und Variationen
    DROP INDEX {table_name | view_name}.index_name [,...n]
In Microsoft SQL Server können sowohl Indizes für Tabellen als auch für Views gelöscht werden. Wenn ein geclusterter Index für eine Tabelle, die nicht-geclusterte Indizes enthält, gelöscht wird, werden alle nicht-geclusterten Indizes neu aufgebaut und erhalten neue Zeiger.
MySQL: Syntax und Variationen
    DROP INDEX table_name.index_name [,...n]
In älteren MySQL-Versionen ist dieser Befehl nur aus Gründen der Kompatibilität enthalten. In neueren Versionen wird der angegebene Index tatsächlich gelöscht. Diese Anweisung entspricht von der Funktionsweise her der MySQL-Anweisung ALTER TABLE . . . DROP INDEX.
In MySQL können mehrere Indizes gleichzeitig gelöscht werden; dazu müssen die einzelnen Tabellen- und Indexnamen durch Kommas voneinander getrennt werden.
Oracle: Syntax und Variationen
    DROP INDEX [owner_name.]index_name
In Oracle können Indizes direkt unter Angabe ihres Namens gelöscht werden, ohne dass der Tabellenname angegeben werden muss. Oracle bietet auch die Möglichkeit, den Index anhand des Eigentümernamens zu löschen.

DROP PROCEDURE |
Mit diesem Befehl wird eine bestehende gespeicherte Prozedur aus der aktuellen Benutzerdatenbank gelöscht.
Hersteller | Befehl
--- | ---
SQL Server | Unterstützt
MySQL | Nicht unterstützt
Oracle | Unterstützt
PostgreSQL | Nicht unterstützt
SQL99: Syntax und Beschreibung
    DROP PROCEDURE procedure_name {RESTRICT | CASCADE}
Dieser Befehl entspricht im Wesentlichen DROP FUNCTION, wirkt sich aber auf gespeicherte Prozeduren aus statt auf Funktionen.
Microsoft SQL Server: Syntax und Variationen
    DROP PROCEDURE [owner_name.]procedure_name [,...n]
Microsoft SQL Server ermöglicht das Löschen mehrerer gespeicherter Prozeduren gleichzeitig. Dazu müssen die einzelnen Namen durch Kommas voneinander getrennt werden. Individuelle Versionen von gespeicherten Prozeduren können nicht gelöscht werden. Es muss stets die gesamte Gruppe von Versionen einer gespeicherten Prozedur gelöscht werden.
Oracle: Syntax und Variationen
    DROP PROCEDURE [owner_name.]procedure_name
Oracle bietet auch die Möglichkeit, Prozeduren anhand des Eigentümernamens zu löschen. Benutzer mit dem Systemprivileg DROP ANY PROCEDURE dürfen Prozeduren anderer Benutzer löschen.

DROP ROLE |
Mit diesem Befehl wird eine benannte Gruppe von Benutzerprivilegien aus der aktuellen Benutzerdatenbank gelöscht.
Hersteller | Befehl
--- | ---
SQL Server | Nicht unterstützt
MySQL | Nicht unterstützt
Oracle | Unterstützt, mit Variationen
PostgreSQL | Nicht unterstützt
SQL99: Syntax und Beschreibung
    DROP ROLE role_name
Mit dem Befehl DROP ROLE wird die angegebene Rolle gelöscht. Nur Benutzer mit WITH ADMIN OPTION dürfen Rollen löschen.
Oracle: Syntax
    DROP ROLE [owner_name.]role_name;
Mit dem Befehl DROP ROLE wird die Rolle aus der aktuellen Benutzerdatenbank gelöscht. Sie kann dann nicht mehr von Benutzern oder anderen Rollen verwendet werden, denen die Rolle zugewiesen war.

DROP TABLE |
Mit diesem Befehl können Sie eine Tabellendefinition und alle mit der Tabelle zusammenhängenden Daten, Indizes, Trigger, Constraints und Zugriffsrechte löschen. In Views und gespeicherten Prozeduren, die die gelöschte Tabelle referenzieren, entstehen Probleme, wenn diese nicht explizit geändert oder ebenfalls gelöscht werden.
Manche Hersteller lassen es nicht zu, dass eine Tabelle gelöscht wird, wenn nicht zuerst bestimmte Eigenschaften der Tabelle gelöscht werden. So muss die Tabelle in Microsoft SQL Server zunächst von der Replikation ausgeschlossen werden, und die FOREIGN KEY-Referenzen müssen gelöscht werden, bevor die Tabelle selbst gelöscht werden kann.
Hersteller | Befehl
--- | ---
SQL Server | Unterstützt, mit Variationen
MySQL | Unterstützt, mit Variationen
Oracle | Unterstützt, mit Variationen
PostgreSQL | Unterstützt, mit Variationen
SQL99: Syntax und Beschreibung
    DROP TABLE table_name RESTRICT | CASCADE
In der SQL99-Syntax wird mit RESTRICT verhindert, dass das DBMS den Befehl ausführt, wenn die Tabelle noch von Views oder Constraints referenziert wird. Die Klausel CASCADE sorgt dafür, dass zusammen mit der Tabelle auch alle referenzierenden Objekte gelöscht werden.
Microsoft SQL Server: Syntax und Variationen
    DROP TABLE [database_name.][owner_name.]table_name [,...n]
    GO
In Microsoft SQL Server können mehrere Tabellen auf einmal gelöscht werden. Dazu müssen die einzelnen Tabellennamen durch Kommas voneinander getrennt werden. Tabellen können auch in Datenbanken außerhalb des aktuellen Kontexts gelöscht werden, indem der Datenbankname angegeben wird (vorausgesetzt, der Benutzer verfügt über die erforderlichen Zugriffsrechte). Zusammen mit der Tabelle werden alle Constraints und Trigger gelöscht. Explizit deklarierte Regeln und Standardwerte verlieren ihre Bindungen, wenn die zugrunde liegende Tabelle gelöscht wird. Views und gespeicherte Prozeduren, die auf eine gelöschte Tabelle verweisen, verursachen einen Fehler, wenn sie ausgeführt werden und die Tabelle nicht mehr vorhanden ist.
MySQL: Syntax und Variationen
    DROP TABLE [IF EXISTS] table_name;
Wenn dieser Befehl ausgeführt wird, löscht MySQL die Tabelle und alle dazugehörigen Dateien vollständig und dauerhaft. Die Klausel IF EXISTS kann angegeben werden, um bei dem Versuch, eine nicht vorhandene Tabelle zu löschen, die Rückgabe von Fehlern zu verhindern.
Oracle: Syntax und Variationen
    DROP TABLE [owner_name.]table_name [CASCADE CONSTRAINTS];
Beim Löschen einer Tabelle in Oracle wird der von der Tabelle beanspruchte Speicherplatz freigegeben, und alle noch ausstehenden Änderungen werden in der Datenbank festgeschrieben. Wenn eine Tabelle gelöscht wird, wird sofort der gesamte vorher belegte Speicherplatz frei. Alle mit der Tabelle verbundenen Indizes und Zugriffsrechte gehen verloren. Objekte wie Views, gespeicherte Prozeduren und Synonyme, die auf der Tabelle basieren, werden als ungültig gekennzeichnet und funktionieren nicht mehr.
Beachten Sie, dass in Oracle bei Ausführung eines ALTER-, CREATE- oder DROP-Befehls alle noch ausstehenden Transaktionen festgeschrieben werden.
Mit der Klausel CASCADE CONSTRAINTS werden alle Integritäts-Contraints, die sich auf Schlüssel in der gelöschten Tabelle beziehen, gelöscht.
PostgreSQL: Syntax und Variationen
    DROP TABLE table_name;
PostgreSQL unterstützt nur die Basisfunktionalität des Befehls DROP TABLE.

DROP TRIGGER |
Mit dem Befehl DROP TRIGGER wird ein Trigger für eine Tabelle in der aktuellen Datenbank gelöscht.
Hersteller | Befehl
--- | ---
SQL Server | Unterstützt, mit Variationen
MySQL | Nicht unterstützt
Oracle | Unterstützt, mit Variationen
PostgreSQL | Unterstützt, mit Variationen
SQL99: Syntax und Beschreibung
    DROP TRIGGER trigger_name
Mit DROP TRIGGER wird ein Trigger aus der aktuellen Datenbank gelöscht. MySQL unterstützt diesen Befehl nicht.
Microsoft SQL Server: Syntax und Variationen
    DROP TRIGGER [owner_name.]trigger_name [,...n]
    GO
In Microsoft SQL Server können mehrere Trigger auf einmal gelöscht werden, indem die einzelnen Triggernamen durch Kommas voneinander getrennt werden.
Oracle: Syntax und Variationen
    DROP TRIGGER [owner_name.]trigger_name;
Oracle löscht den angegebenen Trigger und schreibt noch ausstehende Änderungen in der Datenbank fest, wenn dieser Befehl ausgeführt wird.
PostgreSQL: Syntax und Variationen
    DROP TRIGGER trigger_name ON table_name;
PostgreSQL schreibt vor, dass die Tabelle, in der sich der Trigger befindet, angegeben wird. Wenn dieser Befehl ausgeführt wird, werden alle Referenzen auf einen vorhandenen Trigger gelöscht.

DROP VIEW |
Mit diesem Befehl wird ein View dauerhaft aus der aktuellen Datenbank gelöscht.
Hersteller | Befehl
--- | ---
SQL Server | Unterstützt
MySQL | Nicht unterstützt
Oracle | Unterstützt
PostgreSQL | Unterstützt
SQL99: Syntax und Beschreibung
    DROP VIEW view_name RESTRICT | CASCADE
In der SQL99-Syntax wird dem DBMS mit RESTRICT mitgeteilt, dass der View nicht gelöscht werden darf, wenn andere Views oder Assertions, die gegenwärtig auf die Tabelle verweisen, gelöscht werden sollen. Die Klausel CASCADE sorgt dafür, dass zusammen mit dem View auch alle referenzierenden Objekte gelöscht werden.
Dieser Befehl wird von MySQL derzeit nicht unterstützt.
Microsoft SQL Server: Syntax und Variationen
    DROP VIEW [owner_name.]view_name [,...n]
    GO
In Microsoft SQL Server können mehrere Views auf einmal gelöscht werden, indem die einzelnen Viewnamen durch Kommas voneinander getrennt werden. Die Views müssen sich in derselben Datenbank befinden. Informationen über den View werden aus allen Systemtabellen entfernt.
Oracle: Syntax und Variationen
    DROP VIEW [owner_name.]view_name;
Wie bei anderen DROP-Befehlen in Oracle kann zusammen mit dem Namen des Views der Eigentümer angegeben werden. Benutzer mit dem Systemprivileg DROP ANY VIEW dürfen Views anderer Benutzer löschen.
PostgreSQL: Syntax und Variationen
    DROP VIEW view_name;
In PostgreSQL können mit dem Befehl DROP VIEW Views aus der aktuellen Datenbank gelöscht werden. Nur der Eigentümer des Views darf diesen löschen. Mit dem PostgreSQL-Befehl DROP TABLE können ebenfalls Views gelöscht werden.

FETCH |
Der Befehl FETCH ist einer von vier Befehlen, die im Zusammenhang mit Cursorn verwendet werden. Mit FETCH wird eine bestimmte Zeile aus einem serverseitigen Server abgerufen.
Hersteller | Befehl
--- | ---
SQL Server | Unterstützt
MySQL | Nicht unterstützt
Oracle | Unterstützt, mit Variationen
PostgreSQL | Unterstützt, mit Variationen
SQL99: Syntax und Beschreibung
Mit dem Befehl FETCH wird ein Datensatz aus dem cursor_name (der mit der Anweisung DECLARE CURSOR erstellt wurde) abgerufen, basierend auf dem Schlüsselwort NEXT, PRIOR, FIRST, LAST, ABSOLUTE oder RELATIVE. Die mit der Anweisung FETCH abgerufenen Werte können optional in Variablen gespeichert werden. Es gibt folgende FETCH-Operationen:
NEXT Teilt dem Cursor mit, den Datensatz abzurufen, der unmittelbar auf die aktuelle Zeile folgt, und setzt die aktuelle Zeile auf die zurückgegebene Zeile. FETCH NEXT ist das Standardverhalten von FETCH. Hier wird der erste Datensatz abgerufen, wenn es sich um die erste FETCH-Operation bei dem Cursor handelt. (PostgreSQL verwendet das Schlüsselwort FORWARD oder den String FETCH RELATIVE NEXT.) PRIOR Fordert den Cursor auf, den Datensatz abzurufen, der der aktuellen Zeile unmittelbar vorangeht, und setzt die aktuelle Zeile auf die zurückgegebene Zeile. FETCH PRIOR gibt keinen Datensatz zurück, wenn es sich um die erste FETCH-Operation bei dem Cursor handelt. (PostgreSQL verwendet das Schlüsselwort BACKWARD oder den String FETCH RELATIVE PRIOR.) FIRST Fordert den Cursor auf, den ersten Datensatz im Cursor zurückzugeben, und macht ihn zur aktuellen Zeile. (Wird von PostgreSQL nicht unterstützt.) LAST Fordert den Cursor auf, den letzten Datensatz im Cursor zurückzugeben, und macht ihn zur aktuellen Zeile. (Wird von PostgreSQL nicht unterstützt.) ABSOLUTE { n } Fordert den Cursor auf, den n-ten Datensatz aus der Ergebnismenge des Cursors vom Anfang her gesehen (wenn n positiv ist) oder vom Ende her gesehen (wenn n negativ ist) zurückzugeben. Der zurückgegebene Datensatz wird zum neuen aktuellen Datensatz des Cursors. Wenn n = 0 ist, werden keine Zeilen zurückgegeben. (Wird von PostgreSQL nicht unterstützt.) RELATIVE { n } Fordert den Cursor auf, den Datensatz zurückzugeben, der sich n Zeilen nach dem aktuellen Datensatz (wenn n positiv ist) oder n Zeilen vor dem aktuellen Datensatz (wenn n negativ ist) befindet. Der zurückgegebene Datensatz wird zur neuen aktuellen Zeile des Cursors. Wenn n = 0 ist, wird die aktuelle Zeile zurückgegeben. (Wird wie beschrieben von PostgreSQL unterstützt, sofern nicht n = 0 ist.)
Mit dem Schlüsselwort INTO können Daten aus jeder Spalte im FETCH-Befehl in lokale Variablen eingelesen werden. Für jede Spalte im FETCH-Befehl muss es eine entsprechende Variable mit einem passenden Datentyp in der INTO-Klausel geben. (INTO wird von PostgreSQL nicht unterstützt.)
PostgreSQL-Cursor können nur in explizit deklarierten Transaktionen mit Hilfe von BEGIN, COMMIT oder ROLLBACK verwendet werden. In PostgreSQL kann der Benutzer entweder eine bestimmte Anzahl an Datensätzen durch Angabe der entsprechenden Zahl oder alle Datensätze durch Angabe des Schlüsselworts ALL abrufen.
Oracle: Syntax und Variationen
    FETCH cursor_name
    {INTO variable_name1 [,...n] ]
    | BULK COLLECT INTO [collection_name [,...n] }
Oracle-Cursor sind vorwärts scrollende Cursor. Sie müssen die abgerufenen Werte entweder in passende Variablen schreiben oder mit der Klausel BULK COLLECT die gesamte Ausgabe binden, bevor sie an den PL/SQL-Parser zurückgegeben wird. FETCH wird oftmals mit einer PL/SQL-FOR-Schleife kombiniert, um alle Zeilen im Cursor zu verarbeiten.
PostgreSQL: Syntax und Variationen
    FETCH [ FORWARD | BACKWARD | RELATIVE [ { [ # | ALL | NEXT | PRIOR ] } ]  ]
    [ count ]
    FROM cursor_name
PostgreSQL-Cursor können nur in explizit deklarierten Transaktionen mit Hilfe von BEGIN, COMMIT oder ROLLBACK verwendet werden.
Der Cursor kann vorwärts (FORWARD), rückwärts (BACKWARD) oder relativ (RELATIVE) scrollend sein. Die Klausel RELATIVE kann entweder die Anzahl der zurückzugebenden Datensätze oder das Schlüsselwort ALL (alle Datensätze) enthalten.
Beispiele
Im folgenden Oracle-Beispiel werden verschiedene Elemente aus dem Cursor employee_new_hires_cursor abgerufen (siehe dazu das Beispiel unter DECLARE CURSOR) und in lokale Variablen gestellt:
    FETCH FROM employee_new_hires_cursor
    INTO : emp_id, :fname, :lname, :job_id
Mit dem folgenden PostgreSQL-Befehl werden fünf Datensätze aus der Tabelle employee abgerufen:
    FETCH FORWARD 5 IN employee_new_hires_cursor;

GRANT |
In SQL99 werden Benutzern und Rollen mit der Anweisung GRANT die entsprechenden Rechte zugewiesen, um auf Datenbankobjekte zugreifen und diese verwenden zu können. Die meisten Datenbankhersteller verwenden die Anweisung GRANT auch, um Benutzern und Rollen Berechtigungen zur Erstellung von Datenbankobjekten und zur Ausführung gespeicherter Prozeduren, Funktionen usw. zu erteilen.
Hersteller | Befehl
--- | ---
SQL Server | Unterstützt, mit Variationen
MySQL | Unterstützt, mit Variationen
Oracle | Unterstützt, mit Variationen
PostgreSQL | Unterstützt, mit Variationen
SQL99: Syntax und Beschreibung
    GRANT { ALL [PRIVILEGES] }
    | SELECT
    | INSERT [ (column_name [,...n]) ]
    | DELETE
    | UPDATE [ (column_name [,...n]) ]
    | REFERENCES [ (column_name [,...n]) ]
    | USAGE }[,...n]
    ON { [TABLE] table_name
    | DOMAIN domain_name
    | COLLATION collation_name
    | CHARACTER SET character_set_name
    | TRANSLATION translation_name }
    TO {grantee_name |  PUBLIC}
    [WITH GRANT OPTION]
Mit der Anweisung GRANT können einem Benutzer von einer dazu berechtigten Person ein oder mehrere Privilegien Privilegien – SELECT, INSERT, UPDATE, DELETE, REFERENCES oder USAGE – eingeräumt werden. Jedes Privileg ermöglicht es dem Benutzer, den angegebenen Befehl auszuführen; mit REFERENCES und USAGE hingegen werden andere Privilegien erteilt. Sie haben die Möglichkeit, mehrere Zugriffsprivilegien anzugeben, wobei die einzelnen Privilegien durch Kommas voneinander zu trennen sind. Sie können auch mit ALL sämtliche Zugriffsrechte übertragen. Das Schlüsselwort PRIVILEGES ist optional.
Das Privileg USAGE bezieht sich neben einer Tabelle auch auf alle Datenbankobjekte, während die anderen Privilegien nur für Tabellen gelten. Mit dem Privileg USAGE kann der Benutzer Datenbankobjekte unter Verwendung der Definition eines anderen Objekts erstellen und zum Beispiel eine Übersetzung zur Erzeugung einer Sortierung verwenden. Mit dem Privileg REFERENCES kann eine Tabelle in einem Constraint oder einem Fremdschlüssel verwendet werden.
Die Privilegien INSERT, UPDATEund REFERENCES können bestimmten Spalten in einer Tabelle zugewiesen werden. Wenn keine Spalten angegeben sind, beziehen sie sich auf alle Spalten.
Mit der Klausel ON wird die Tabelle oder das Datenbankobjekt deklariert, für die bzw. das der Benutzer Privilegien erhält.
Die Klausel TO gibt genau an, welcher Benutzer oder welche Rolle ein bestimmtes Zugriffsrecht erhält. Mit PUBLIChingegen wird das angegebene Privileg allen gegenwärtigen und zukünftigen Benutzern zugewiesen. Andere Benutzer können mit WITH GRANT OPTION autorisiert werden. Diese Klausel teilt der Datenbank mit, dass Benutzer, die ein Zugriffsrecht erhalten, dieses auch an andere Benutzer weitergeben dürfen.
Je nach Datenbankimplementierung können sich die Zugriffsrechte für Views von denen für die zugrunde liegenden Basistabellen unterscheiden.
Microsoft SQL Server: Syntax und Variationen
    GRANT { ALL [PRIVILEGES] }
    | SELECT
    | INSERT
    | DELETE
    | UPDATE
    | REFERENCES
    | EXECUTE
    | CREATE {DATABASE | DEFAULT | FUNCTION | PROCEDURE | RULE | TABLE | VIEW}
    | BACKUP {DATABASE | LOG} } [,...n]
    ON { {table_name | view_name} [(column [,...n])]
    | stored_procedure_name
    | extended_stored_procedure_name
    | user_defined_function_name
    | [(column [,...n] ON {table_name | view_name} }
    TO {grantee_name | PUBLIC} [,...n]
    [WITH GRANT OPTION]
    [AS {group | role}]
Microsoft SQL Server bietet die Möglichkeit, einer Tabelle die Zugriffsrechte SELECT, INSERT, UPDATE, DELETE und REFERENCES zuzuweisen. Eine Spaltenliste kann nur für die Zugriffsberechtigungen SELECT und UPDATE angegeben werden. Standardmäßig werden allen Spalten die Zugriffsrechte SELECT und UPDATE gewährt.
Das Privileg EXECUTE kann nur für gespeicherte Prozeduren, erweiterte gespeicherte Prozeduren und benutzerdefinierte Funktionen gewährt werden. Um einen FOREIGN KEY-Constraint erstellen zu können, muss der Benutzer über das Privileg REFERENCES verfügen. Dieses Recht ist auch erforderlich, wenn eine Funktion oder ein View erstellt werden soll, die bzw. der von einem Objekt mit SCHEMABINDING abhängig ist.
Mit der Klausel AS werden Privilegien wie in einem anderen Gruppen- oder Rollenkontext gewährt. Da Gruppen und Rollen den Befehl GRANT nicht ausführen können, lassen sich auf diese Art und Weise schnell und einfach Privilegien an Personen außerhalb der Gruppe oder Rolle zuweisen. Privilegien dürfen nicht in einer anderen Datenbank als dem aktuellen Datenbankkontext gewährt werden.
Beispiel
Zunächst werden den Benutzern Emily und Sarah mit CREATE DATABASE und CREATE TABLE Zugriffsrechte erteilt. Als nächstes werden der Gruppe "editors" verschiedene Zugriffsrechte für die Tabelle titles gewährt. Die Mitglieder dieser Gruppe können diese Rechte dann an andere weitergeben:
    GRANT CREATE DATABASE, CREATE TABLE TO emily, sarah
    GO

    GRANT SELECT, INSERT, UPDATE, DELETE ON titles
    TO editors
    WITH GRANT OPTION
    GO
MySQL: Syntax und Variationen
    GRANT { ALL PRIVILEGES
    | SELECT
    | INSERT [ (column_name [,...n]) ]
    | DELETE
    | UPDATE [ (column_name [,...n]) ]
    | REFERENCES [ (column_name [,...n]) ]
    | USAGE
    | ALTER
    | CREATE
    | DROP
    | FILE
    | INDEX
    | PROCESS
    | RELOAD
    | SHUTDOWN }[,...n]
    ON {table_name | * | *.* | database_name.*}
    TO grantee_name [IDENTIFIED BY 'password'] [,...n]
    [WITH GRANT OPTION]
MySQL bietet noch weitere Zugriffsprivilegien, insbesondere im Zusammenhang mit der Bearbeitung von Objekten in einer Datenbank. Wie bei den anderen Privilegien dürfen die Benutzer den gleichnamigen Befehl (wie ALTER, CREATE, INDEX oder RELOAD) ausführen. REFERENCES wird unterstützt, hat aber keine Funktionalität. Mit USAGE werden die Privilegien eines Benutzers deaktiviert.
Die folgenden Zugriffsrechte können bei Tabellen verwendet werden: SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, GRANT, INDEX und ALTER. INSERT, UPDATE und SELECT können auch auf Spaltenebene eingesetzt werden.
Die MySQL-Implementierung der Klausel ON kennt einige interessante Optionen. Mit ON *.* können globale Privilegien eingestellt werden, die dann für alle Datenbanken auf dem Server gelten. Datenbankweite Privilegien können Sie mit ON database_name.* bzw. ON * für die aktuelle Datenbank festlegen. Host-, Tabellen-, Datenbank- und Spaltennamen dürfen aus maximal 60 Zeichen bestehen.
MySQL erlaubt es, einem bestimmten Benutzer auf einem bestimmten Host Rechte zu gewähren, wenn der grantee_name das Format USER@HOST aufweist. In einem grantee_name können Wildcards verwendet werden, um mehreren Benutzer auf einmal Zugriffsrechte zu erteilen. Der grantee_name darf aus maximal 16 Zeichen bestehen. Wenn Sie den Benutzer angeben, können Sie mit der Klausel IDENTIFIED BY einen Kennwortschutz erzwingen.
Beispiel
Im folgenden Beispiel werden zwei Benutzern mit Kennwörtern Zugriffsrechte gewährt:
    GRANT SELECT ON employee TO Dylan IDENTIFIED BY 'porsche',
      kelly IDENTIFIED BY 'mercedes',
      emily IDENTIFIED BY 'saab';
Oracle: Syntax und Variationen
    GRANT { ALL [PRIVILEGES] }
    {| GRANT ANY PRIVILEGE }
    {| SELECT | INSERT  | DELETE | UPDATE | REFERENCES }
    {| CREATE [ANY] {CLUSTER | CONTEXT | DATABASE| DATABASE LINK | DIMENSION
       | DIRECTORY | INDEXTYPE | INDEX | LIBRARY | OPERATOR | OUTLINE
       | PROCEDURE | PROFILE | ROLE | ROLLBACK SEGMENT | SEQUENCE | SESSION
       | SNAPSHOT | SYNONYM | TABLE | TABLESPACE | TRIGGER | TYPE |
       | USER | [MATERIALIZED] VIEW}
    | DROP [ANY] {...as CREATE...}
    | ALTER [ANYh] {...as CREATE...}
    | AUDIT SYSTEM
    | EXECUTE [ANY] {INDEXTYPE | OPERATOR | PROCEDURE | TYPE
    | BACKUP [ANY] {TABLE | DATABASE | LOG} } [,...n] }
    ON { [schema_name.]
    {table_name | view_name} [ (column [,...n]) ]
    | stored_procedure_name
    | extended_stored_procedure_name
    | user_defined_function_name
    | DIRECTORY directory_name
    | JAVA {SOURCE | RESOURCE} [schema_name.]object_name }
    TO {{grantee_name | role_name} [,...n] | PUBLIC}
    [WITH ADMIN OPTION];
Hier sieht man ganz deutlich, dass der Befehl GRANT in Oracle sehr umfangreich ist. Dabei zeigt die Syntax oben noch nicht einmal alle Permutationen dieser Anweisung. Beachten Sie, dass es beiGRANT zwei allgemeine Klassen von Privilegien gibt: Objektprivilegien (wie das Privileg, in einer bestimmten Tabelle SELECT- oder DELETE-Operationen auszuführen) und Systemprivilegien (wie CREATE CLUSTER oder DROP ANY TABLE).
In Oracle können Objekt- und Systemprivilegien nicht in einem GRANT-Befehl kombiniert werden. Es ist zwar möglich, in einem GRANT-Befehl einem einzelnen Benutzer oder einer Rolle mehrere Objektprivilegien oder Systemprivilegien zuzuweisen, aber mit einem GRANT-Befehl können nicht Objekt- und Systemprivilegien gleichzeitig erteilt werden.
In einem GRANT-Befehl ist nahezu jedes von Oracle unterstützte Funktionsmerkmal zulässig. Privilegien können nicht nur für Datenbankobjekte (wie Tabellen und Views) und Systembefehle (wie CREATE ANY TABLE) gewährt werden, sondern auch für Schemaobjekte (wie DIRECTORY, JAVA SOURCE und RESOURCE).
Mit der Option ANY wird das Privileg zur Ausführung einer bestimmten Anweisung für Objekte eines bestimmten Typs erteilt, die einem beliebigen Benutzer im Schema gehören. Eine umfassendere Liste der Systemprivilegien in Oracle finden Sie in Tabelle 3.2.
Kategorie | Systemprivileg | Beschreibung
--- | --- | ---
CLUSTER | CREATE CLUSTER | Gewährt das Privileg, ein Cluster im eigenen Schema erstellen.
| CREATE ANY CLUSTER | Gewährt das Privileg, ein Cluster in einem beliebigen Schema zu erstellen.
| ALTER ANY CLUSTER | Gewährt das Privileg, Cluster in einem beliebigen Schema zu ändern.
| DROP ANY CLUSTER | Gewährt das Privileg, Cluster in einem beliebigen Schema zu löschen.
CONTEXT | CREATE ANY CONTEXT | Gewährt das Privileg, beliebige Kontext-Namespaces zu erstellen.
| DROP ANY CONTEXT | Gewährt das Privileg, beliebige Kontext-Namespaces zu löschen.
DATABASE | ALTER DATABASE | Gewährt das Privileg, die Datenbank zu ändern.
| ALTER SYSTEM | Führt ALTER SYSTEM-Anweisungen aus.
| AUDIT SYSTEM | Führt AUDIT sql_statements-Anweisungen aus.
DATABASE LINKS | CREATE DATABASE LINK | Gewährt das Privileg, private Datenbankverknüpfungen im eigenen Schema zu erstellen.
| CREATE PUBLICDATABASE LINK | Gewährt das Privileg, öffentlicheDatenbankverknüpfungen zu erstellen.
| DROP PUBLICDATABASE LINK | Gewährt das Privileg, öffentlicheDatenbankverknüpfungen zu löschen.
DIMENSIONS | CREATE DIMENSION | Gewährt das Privileg, Dimensionen im eigenen Schema zu erstellen.
| CREATE ANYDIMENSION | Gewährt das Privileg, Dimensionen in einem beliebigen Schema zu erstellen.
| ALTER ANYDIMENSION | Gewährt das Privileg, Dimensionen in einem beliebigen Schema zu ändern.
| DROP ANYDIMENSION | Gewährt das Privileg, Dimensionen in einem beliebigen Schema zu löschen.
DIRECTORIES | CREATE ANYDIRECTORY | Gewährt das Privileg, Verzeichnisdatenbankobjekte zu erstellen.
| DROP ANYDIRECTORY | Gewährt das Privileg, Verzeichnis-datenbankobj ekte zu löschen.
INDEXTYPES | CREATE INDEXTYPE | Gewährt das Privileg, einen Indextyp im eigenen Schema zu erstellen.
| CREATE ANYINDEXTYPE | Gewährt das Privileg, einen Indextyp in einem beliebigen Schema zu erstellen.
| ALTER ANYINDEXTYPE | Ändert Indextypen in einem beliebigen Schema.
| DROP ANYINDEXTYPE | Gewährt das Privileg, einen Indextyp in einem beliebigen Schema zu löschen.
| EXECUTE ANYINDEXTYPE | Referenziert einen Indextyp in einem beliebigen Schema.
INDEXES | CREATE ANY INDEX | Gewährt das Privileg, einen Domain-Index in einem beliebigen Schema oder einen Index für eine beliebige Tabelle in einem beliebigen Schema zu erstellen.
| ALTER ANY INDEX | Gewährt das Privileg, Indizes in einem beliebigen Schema zu ändern.
| DROP ANY INDEX | Gewährt das Privileg, Indizes in einem beliebigen Schema zu löschen.
| QUERY REWRITE | Aktiviert das Neuschreiben mit einem materialisierten View oder erstellt einen funktionsbasierten Index, wenn der materialisierte View oder Index auf Tabellen und Views im eigenen Schema des Benutzers verweist.
| GLOBAL QUERY REWRITE | Aktiviert das Neuschreiben mit einem materialisierten View oder erstellt einen funktionsbasierten Index, wenn der materialisierte View oder Index auf Tabellen oder Views in einem beliebigen Schema verweist.
LIBRARIES | CREATE LIBRARY | Gewährt das Privileg, externe Prozedur- oder Funktionsbibliotheken im eigenen Schema zu erstellen.
| CREATE ANY LIBRARY | Gewährt das Privileg, externe Prozedur- oder Funktionsbibliotheken in einem beliebigen Schema zu erstellen.
| DROP LIBRARY | Gewährt das Privileg, externe Prozedur- oder Funktionsbibliotheken im eigenen Schema zu löschen.
| DROP ANY LIBRARY | Gewährt das Privileg, externe Prozedur- oder Funktionsbibliotheken in einem beliebigen Schema zu löschen.
MATERIALIZED VIEWS (identisch mit SNAPSHOTS) | CREATE MATERIALIZED VIEW | Gewährt das Privileg, einen materialisierten View im eigenen Schema zu erstellen.
| CREATE ANY MATERIALIZED VIEW | Gewährt das Privileg, materialisierte Views in einem beliebigen Schema zu erstellen.
| ALTER ANY MATERIALIZED VIEW | Gewährt das Privileg, materialisierte Views in einem beliebigen Schema zu ändern.
| DROP ANY MATERIALIZED VIEW | Gewährt das Privileg, materialisierte Views in einem beliebigen Schema zu löschen.
| GLOBAL QUERY REWRITE | Aktiviert das Neuschreiben mit einem materialisierten View oder erstellt einen funktionsbasierten Index, wenn der materialisierte View oder Index auf Tabellen oder Views in einem beliebigen Schema verweist.
| QUERY REWRITE | Aktiviert das Neuschreiben mit einem materialisierten View oder erstellt einen funktionsbasierten Index, wenn der materialisierte View oder Index auf Tabellen und Views im eigenen Schema verweist.
OPERATORS | CREATE OPERATOR | Gewährt das Privileg, einen Operator und dessen Bindungen im eigenen Schema zu erstellen.
| CREATE ANYOPERATOR | Gewährt das Privileg, einen Operator und dessen Bindungen in einem beliebigen Schema zu erstellen.
| DROP ANY OPERATOR | Gewährt das Privileg, einen Operator in einem beliebigen Schema zu löschen.
| EXECUTE ANYOPERATOR | Referenziert einen Operator in einem beliebigen Schema.
OUTLINES | CREATE ANY OUTLINE | Gewährt das Privileg, Outlines zu erstellen, die in einem beliebigen Schema, das Outlines benutzt, verwendet werden können.
| ALTER ANY OUTLINE | Modifiziert Outlines.
| DROP ANY OUTLINE | Gewährt das Privileg, Outlines zu löschen.
PROCEDURES | CREATE PROCEDURE | Gewährt das Privileg, gespeicherte Prozeduren, Funktionen und Packages im eigenen Schema zu erstellen.
| CREATE ANYPROCEDURE | Gewährt das Privileg, gespeicherte Prozeduren, Funktionen und Packages in einem beliebigen Schema zu erstellen.
| ALTER ANYPROCEDURE | Gewährt das Privileg, gespeicherte Prozeduren, Funktionen oder Packages in einem beliebigen Schema zu ändern.
| DROP ANYPROCEDURE | Gewährt das Privileg, gespeicherte Prozeduren, Funktionen oder Packages in einem beliebigen Schema zu löschen.
| EXECUTE ANYPROCEDURE | Führt Prozeduren oder Funktionen (alleine oder in einem Paket) aus.
PROFILES | CREATE PROFILE | Gewährt das Privileg, Profile zu erstellen.
| ALTER PROFILE | Gewährt das Privileg, Profile zu ändern.
| DROP PROFILE | Gewährt das Privileg, Profile zu löschen.
ROLES | CREATE ROLE | Gewährt das Privileg, Rollen zu erstellen.
| ALTER ANY ROLE | Gewährt das Privileg, eine beliebige Rolle in der Datenbank zu ändern.
| DROP ANY ROLE | Gewährt das Privileg, Rollen zu löschen.
| GRANT ANY ROLE | Gewährt eine beliebige Rolle in der Datenbank.
ROLLBACK SEGMENTS | CREATE ROLLBACK SEGMENT | Gewährt das Privileg, Rollback-Segmente zu erstellen.
| ALTER ROLLBACK SEGMENT | Gewährt das Privileg, Rollback-Segmente zu ändern.
| DROP ROLLBACK SEGMENT | Gewährt das Privileg, Rollback-Segmente zu löschen.
SEQUENCES | CREATE SEQUENCE | Gewährt das Privileg, Sequenzen im eigenen Schema zu erstellen.
| CREATE ANY SEQUENCE | Gewährt das Privileg, Sequenzen in einem beliebigen Schema zu erstellen.
| ALTER ANY SEQUENCE | Gewährt das Privileg, eine beliebige Sequenz in der Datenbank zu ändern.
| DROP ANY SEQUENCE | Gewährt das Privileg, Sequenzen in einem beliebigen Schema zu löschen.
| SELECT ANY SEQUENCE | Referenziert Sequenzen in einem beliebigen Schema.
SESSIONS | CREATE SESSION | Stellt eine Verbindung zur Datenbank her.
| ALTER RESOURCE COST | Legt die Kosten für Sitzungsressourcen fest.
| ALTER SESSION | Führt ALTER SESSION-Anweisungen aus.
| RESTRICTED SESSION | Führt eine Anmeldung durch, sobald die Instanz mit der SQL*Plus-Anweisung STARTUP RESTRICT gestartet wurde.
SNAPSHOTS (identisch mit MATERIALIZED VIEWS) | CREATE SNAPSHOT | Gewährt das Privileg, Snapshots im eigenen Schema zu erstellen.
| CREATE ANYSNAPSHOT | Gewährt das Privileg, Snapshots in einem beliebigen Schema zu erstellen.
| ALTER ANY SNAPSHOT | Gewährt das Privileg, einen beliebigen Snapshot in der Datenbank zu ändern.
| DROP ANY SNAPSHOT | Gewährt das Privileg, Snapshots in einem beliebigen Schema zu löschen.
| GLOBAL QUERY REWRITE | Aktiviert das Neuschreiben mit einem Snapshot oder erstellt einen funktionsbasierten Index, wenn der Snapshot oder Index auf Tabellen oder Views in einem beliebigen Schema verweist.
| QUERY REWRITE | Aktiviert das Neuschreiben mit einem Snapshot oder erstellt einen funktionsbasierten Index, wenn der Snapshot oder Index auf Tabellen und Views im eigenen Schema verweist.
SYNONYMS | CREATE SYNONYM | Gewährt das Privileg, Synonyme im eigenen Schema zu erstellen.
| CREATE ANY SYNONYM | Gewährt das Privileg, Synonyme in einem beliebigen Schema zu erstellen.
| CREATE PUBLIC SYNONYM | Gewährt das Privileg, öffentliche Synonyme zu erstellen.
| DROP ANY SYNONYM | Gewährt das Privileg, private Synonyme in einem beliebigen Schema zu löschen.
| DROP PUBLIC SYNONYM | Gewährt das Privileg, öffentliche Synonyme zu löschen.
TABLES | CREATE ANY TABLE | Gewährt das Privileg, Tabellen in einem beliebigen Schema zu erstellen. Der Eigentümer des Schemas, das die Tabelle enthält, muss über genügend Tablespace verfügen, damit die Tabelle erstellt werden kann.
| ALTER ANY TABLE | Gewährt das Privileg, eine beliebige Tabelle oder einen View im Schema zu ändern.
| BACKUP ANY TABLE | Verwendet das Export-Dienstprogramm, um Objekte aus dem Schema anderer Benutzer zu exportieren.
| DELETE ANY TABLE | Löscht Zeilen aus Tabellen, Tabellenpartitionen oder Views in einem beliebigen Schema.
| DROP ANY TABLE | Gewährt das Privileg, Tabellen oder Tabellenpartitionen in einem beliebigen Schema zu löschen oder zu leeren.
| INSERT ANY TABLE | Fügt Zeilen in Tabellen und Views in einem beliebigen Schema ein.
| LOCK ANY TABLE | Sperrt Tabellen und Views in einem beliebigen Schema.
| UPDATE ANY TABLE | Aktualisiert Zeilen in Tabellen und Views in einem beliebigen Schema.
| SELECT ANY TABLE | Fragt Tabellen, Views oder Snapshots in einem beliebigen Schema ab.
TABLESPACES | CREATE TABLESPACE | Gewährt das Privileg, Tablespaces zu erstellen.
| ALTER TABLESPACE | Gewährt das Privileg, Tablespaces zu ändern.
| DROP TABLESPACE | Gewährt das Privileg, Tablespaces zu löschen.
| MANAGE TABLESPACE | Arbeitet mit Tablespaces offline und online und startet und beendet die Sicherung (Backup) von Tablespaces.
| UNLIMITED TABLESPACE | Ermöglicht die Verwendung beliebig großer Tablespaces. Dieses Privileg hat Vorrang vor eventuell zugewiesenen Speicherplatzquoten. Wenn Sie einem Benutzer dieses Privileg entziehen, bleiben die Schemaobjekte des Benutzers zwar bestehen, aber es wird nur dann zusätzlicher Tablespace zur Verfügung gestellt, wenn dies durch die Tablespace-Quoten zugelassen wird. Rollen kann dieses Systemprivileg nicht zugeteilt werden.
TRIGGERS | CREATE TRIGGER | Gewährt das Privileg, einen Datenbanktrigger im eigenen Schema zu erstellen.
| CREATE ANY TRIGGER | Gewährt das Privileg, Datenbanktrigger in einem beliebigen Schema zu erstellen.
| ALTER ANY TRIGGER | Aktiviert, deaktiviert oder kompiliert Datenbanktrigger in einem beliebigen Schema.
| DROP ANY TRIGGER | Gewährt das Privileg, Datenbanktrigger in einem beliebigen Schema zu löschen.
| ADMINISTER DATABASE TRIGGER | Gewährt das Privileg, einen Trigger für DATABASE zu erstellen. (Dazu müssen Sie auch über das Privileg CREATE TRIGGER oder CREATE ANY TRIGGER verfügen.)
TYPES | CREATE TYPE | Gewährt das Privileg, Objekttypen und deren Rümpfe im eigenen Schema zu erstellen.
| CREATE ANY TYPE | Gewährt das Privileg, Objekttypen und deren Rümpfe in einem beliebigen Schema zu erstellen.
| ALTER ANY TYPE | Gewährt das Privileg, Objekttypen in einem beliebigen Schema zu ändern.
| DROP ANY TYPE | Gewährt das Privileg, Objekttypen und deren Rümpfe in einem beliebigen Schema zu löschen.
| EXECUTE ANY TYPE | Verwendet und referenziert Objekt- und Sammlungstypen in einem beliebigen Schema und ruft Methoden eines Objekttyps in einem beliebigen Schema auf, wenn Sie dieses Privileg einem bestimmten Benutzer gewähren. Wenn Sie einer Rolle das Privileg EXECUTE ANY TYPE zuweisen, können Benutzer, die über diese Rolle verfügen, keine Methoden eines Objekttyps in einem beliebigen Schema aufrufen.
USERS | CREATE USER | Gewährt das Privileg, Benutzer zu erstellen. Dieses Privileg gibt dem Ersteller auch die Möglichkeit: Quoten für beliebige Tablespaces zuzuweisen, Standard- und temporäre Tablespaces festzulegen, ein Profil als Bestandteil einer CREATE USER -Anweisung zuzuweisen.
| ALTER USER | Gewährt das Privileg, einen beliebigen Benutzer zu ändern. Mit diesem Privileg hat der Inhaber auch das Recht: das Kennwort oder die Authentifizierungsmethode eines anderen Benutzers zu ändern, Quoten für beliebige Tablespaces zuzuweisen, Standard- und temporäre Tablespaces festzulegen, ein Profil und Standardrollen zuzuweisen.
| BECOME USER | Sorgt dafür, dass ein Benutzer zu einem anderen Benutzer wird (dies ist erforderlich, wenn ein Benutzer einen vollständigen Datenbankimport durchführen möchte).
| DROP USER | Gewährt das Privileg, Benutzer zu löschen.
VIEWS | CREATE VIEW | Gewährt das Privileg, Views im eigenen Schema zu erstellen.
| CREATE ANY VIEW | Gewährt das Privileg, Views in einem beliebigen Schema zu erstellen.
| DROP ANY VIEW | Gewährt das Privileg, Views in einem beliebigen Schema zu löschen.
MISCELLANEOUS | ANALYZE ANY | Analysiert beliebige Tabellen, Cluster oder Indizes in einem beliebigen Schema.
| AUDIT ANY | Führt einen Audit für ein beliebiges Objekt in einem beliebigen Schema mit der Anweisung AUDIT schema_objects durch.
| COMMENT ANY TABLE | Kommentiert eine beliebige Tabelle, einen View oder eine Spalte in einem beliebigen Schema.
| FORCE ANYTRANSACTION | Erzwingt das Festschreiben (COMMIT) oder Zurückführen (ROLLBACK) einer beliebigen zweifelhaften verteilten Transaktion in der lokalen Datenbank; sorgt dafür, dass die verteilte Transaktion fehlschlägt.
| FORCE TRANSACTION | Erzwingt das Festschreiben (COMMIT) oder Zurückführen (ROLLBACK) der eigenen zweifelhaften verteilten Transaktionen in der lokalen Datenbank.
| GRANT ANYPRIVILEGE | Gewährt beliebige Systemprivilegien.
| SYSDBA | Ermöglicht es dem Benutzer: STARTUP- und SHUTDOWN-Operationen durchzuführen, ALTER DATABASE auszuführen: Öffnen, Einhängen, Sichern oder Ändern des Zeichensatzes, CREATE DATABASE auszuführen, ARCHIVELOG und RECOVERY auszuführen. Beinhaltet das Privileg RESTRICTED SESSION.
| SYSOPER | Ermöglicht es dem Benutzer: STARTUP- und SHUTDOWN-Operationen durchzuführen, ALTER DATABASE OPEN/MOUNT/BACKUP – ARCHIVELOG und RECOVERY auszuführen. Beinhaltet das Privileg RESTRICTED SESSION.
PostgreSQL: Syntax und Variationen
    GRANT { ALL
    | SELECT
    | INSERT
    | DELETE
    | UPDATE
    | RULE } [,...n]
    ON { object_name }
    TO {grantee_name | PUBLIC | GROUP group_name}
PostgreSQL unterstützt weder die Klausel WITH GRANT OPTION noch Zugriffsrechte auf Spaltenebene. Die PostgreSQL-Implementierung von GRANT verhält sich so, als sei WITH GRANT OPTION immer aktiviert. Jeder Benutzer, dem ein Zugriffsrecht gewährt wird, kann dieses Privileg an andere Benutzer übertragen. In PostgreSQL haben Sie die Möglichkeit, einer GROUP Zugriffsrechte zuzuweisen, sofern es sich um einen gültigen, bereits bestehenden group_name handelt.
Im Gegensatz zu verschiedenen anderen Herstellern unterstützt PostgreSQL GRANT nicht in Verbindung mit Systembefehlen.
Beispiel
Die PostgreSQL-Unterstützung für die Anweisung GRANT geht nicht über die Grundfunktionalität hinaus:
    GRANT INSERT ON publishers TO PUBLIC;

    GRANT SELECT, UPDATE ON sales TO emily;

INSERT |
Mit der Anweisung INSERT können Sie einer Tabelle oder einem View Datenzeilen hinzufügen. Die Anweisung INSERT bietet mehrere Möglichkeiten, Datensätze in eine Tabelle einzugeben:
Die erste Methode besteht darin, Datensätze mit den DEFAULT-Werten hinzuzufügen, die den Spalten mit der CREATE TABLE- oder ALTER TABLE-Anweisung zugewiesen wurden. (Diese Methode wird von Oracle nicht unterstützt.) Bei der zweiten und gebräuchlichsten Methode werden die Werte, die in die einzelnen Spalten des Datensatzes eingefügt werden sollen, explizit angegeben. Die dritte Methode, die ein schnelles Füllen einer Tabelle mit zahlreichen Datensätzen ermöglicht, besteht darin, die Ergebnismenge einer SELECT-Anweisung in eine Tabelle einzufügen.
Hersteller | Befehl
--- | ---
SQL Server | Unterstützt, mit Variationen
MySQL | Unterstützt, mit Variationen
Oracle | Unterstützt, mit Variationen
PostgreSQL | Unterstützt
SQL99: Syntax und Beschreibung
    INSERT [INTO] [[database_name.]owner.] {table_name | view_name} [(column_
        list)]
    {[DEFAULT] VALUES | VALUES (value[,...]) | SELECT_statement }
Um die Anweisung INSERT verwenden zu können, müssen Sie zunächst die Tabelle (oder den View) deklarieren, in die (bzw. den) die Daten eingefügt werden sollen. Das Schlüsselwort INTO ist optional. Geben Sie die Spalten der Tabelle, in die die Daten kopiert werden sollen, in der column_list an, indem Sie sie in runde Klammern setzen und die Namen durch Kommas voneinander trennen. Die column_list kann auch weggelassen werden, dann werden aber alle für die Tabelle definierten Spalten übernommen.
Die Methode DEFAULT VALUES kann nicht mit den Methoden list_of_values und SELECT_statement-kombiniert werden.
Mit der Anweisung INSERT . . . VALUES wird einer Tabelle eine einzelne Datenzeile hinzugefügt, die aus den in der Anweisung angegebenen Literalwerten besteht. Wenn die INSERT-Anweisung zusammen mit einer verschachtelten SELECT-Anweisung verwendet wird, lassen sich in eine Tabelle schnell mehrere Zeilen einfügen. Wenn Sie INSERT . . . SELECT über zwei Tabellen hinweg verwenden, müssen Sie darauf achten, dass die Tabellen kompatible Datentypen und Strukturen besitzen, auch wenn eventuelle Inkompatibilitäten zwischen den beiden Tabellen mit der SELECT-Anweisung ausgeglichen werden. INSERT . . . SELECT wird auch von PostgreSQL unterstützt.
Microsoft SQL Server: Syntax und Beschreibung
    INSERT [INTO] [[database_name.]owner.]
        {table_name | view_name} [(column_list)]
    {[DEFAULT] VALUES | list_of_values | SELECT_statement |
     EXEC[UTE] { procedure_name }
        [[@parameter_name=] {value [OUTPUT] | DEFAULT}[,...]}
Die Implementierung des Befehls INSERT in Microsoft SQL Server unterscheidet sich dadurch, dass sie das Schlüsselwort DEFAULT unterstützt. Mit DEFAULT kann der Anweisung INSERT mitgeteilt werden, dass einfach ein neuer Datensatz mit allen für die Tabelle deklarierten Standardwerten erstellt werden soll.
Der wichtigste Unterschied zu den Implementierungen anderer Hersteller besteht im Schlüsselwort EXECUTE. Mit der Klausel EXECUTE wird SQL Server aufgefordert, die von einer dynamischen Transact-SQL-Anweisung, einer vom System oder vom Benutzer gespeicherten Prozedur, einem Remote Procedure Call (RPC) oder einer erweiterten gespeicherten Prozedur zurückgegebene Ergebnismenge in einer lokalen Tabelle zu speichern.
So wird zum Beispiel mit der nachfolgenden INSERT-Anweisung das Verzeichnis C:\temp ausgelesen und in der temporären Tabelle #ins_exec_container gespeichert:
    INSERT INTO #ins_exec_container
    EXEC master..xp_cmdshell "dir c:\temp"
    GO
MySQL: Syntax und Variationen
    INSERT [LOW_PRIORITY | DELAYED] [IGNORE]
    [INTO] [[database_name.]owner.] {table_name | view_name} [(column_list)]
    {VALUES (value[,...]) | SELECT_statement | SET column=value[,...n]}
Mit der Option LOW_PRIORITY wird MySQL angewiesen, die Ausführung von INSERT so lange hinauszuzögern, bis keine anderen Clients mehr aus der Tabelle lesen. Das kann zu langen Wartezeiten führen. Mit der Option DELAYED kann der Client sofort fortfahren, selbst wenn die INSERT-Anweisung noch nicht abgeschlossen ist. Das Schlüsselwort IGNORE bedeutet, dass MySQL keine Datensätze einfügen darf, die zu einem doppelten Wert in einem Primär- oder eindeutigen Schlüssel führen würden. Ohne diese Klausel würde die INSERT-Anweisung fehlschlagen. Mit der Syntax SET column=value können die Spalten der Tabelle deklariert und Werte in diese eingefügt werden.
Oracle: Syntax und Beschreibung
    INSERT [INTO] [[database_name.]owner.] {table_name | view_name}
       [PARTITION partition_name | SUBPARTITION subpartition_name]
    [(column_list)]
    {VALUES (value1[,...n]) RETURNING expression1 [,...n] INTO variable1
       [,...n]
     |
    SELECT_statement
    [WITH {READ ONLY | CHECK OPTION [CONSTRAINT constraint_name]} }
Die Oracle-spezifische Implementierung der Anweisung INSERT unterstützt die Schlüsselwörter PARTITION und SUBPARTITION und ermöglicht so das Einfügen von Daten nicht nur in eine Tabelle, einen View oder einen Snapshot, sondern auch in eine Partition oder Subpartition in einer Tabelle.
Wenn die Anweisung INSERT mit einer SELECT-Klausel in Beziehung steht, gelten einige zusätzliche Regeln. Wenn die SELECT-Klausel mit einer VALUES-Klausel verbunden ist, wird nur eine Zeile in die Tabelle eingefügt, nämlich die erste Zeile, die von der SELECT-Klausel zurückgegeben wird. Wenn SELECT ohne VALUES verwendet wird, werden alle Zeilen, die von der Abfrage zurückgegeben werden, in die Tabelle eingefügt.
Mit der Klausel RETURNING werden die Werte nicht in eine Tabelle, sondern in Variablen eingefügt. Zwischen den Ausdrücken und Variablen der RETURNING-Klausel muss es eine Eins-zu-Eins-Übereinstimmung geben. Die von der Klausel zurückgegebenen Ausdrücke müssen nicht zwangsläufig diejenigen sein, die in der VALUES-Klausel genannt sind. Mit der folgenden INSERT-Anweisung wird beispielsweise ein Datensatz in die Tabelle sales eingefügt, wobei jedoch ein völlig anderer Wert in einer Bindungsvariablen abgelegt wird:
    INSERT authors (au_id, au_lname, au_fname, contract )
    VALUES ('111-11-1111', 'Rabbit', 'Jessica', 1)
    RETURNING hire_date INTO :temp_hr_dt;
Beachten Sie, dass die RETURNING-Klausel den hire_date-Wert zurückgibt, auch wenn hire_date nicht zu den Werten gehört, die in der VALUES-Klausel angegeben sind. (In diesem Beispiel kann man davon ausgehen, dass ein Standardwert für die Spalte hire_date festgelegt wurde.) LONG-Datentypen können mit RETURNING nicht bearbeitet werden. RETURNING kann nicht auf Views mit INSTEAD OF-Triggern angewendet werden.
Zusätzlich kann die SELECT-Klausel die Option WITH verwenden. Mit WITH READ ONLY wird angegeben, dass die von der SELECT-Klausel zurückgegebene Ergebnismenge nicht mit der Anweisung INSERT geändert werden kann. Mit der Klausel WITH CHECK OPTION wird Oracle aufgefordert, Datenänderungen zu unterbinden, die zu Zeilen führen würden, die nicht in der Ergebnismenge der SELECT-Klausel enthalten sind.
PostgreSQL: Syntax und Beschreibung
PostgreSQL unterstützt den SQL99-Standard der Anweisung INSERT. Im Abschnitt vorher finden Sie nähere Informationen zur Syntax und Verwendung nach dem SQL99-Standard.
Beispiele
Im folgenden Beispiel wird für die Autorin Jessica Rabbit eine neue Zeile in die Tabelle authors in einer Microsoft SQL Server-Datenbank eingefügt:
    INSERT INTO authors (au_id, au_lname, au_fname, phone, address, city,
         state, zip, contract )
    VALUES ('111-11-1111', 'Rabbit', 'Jessica', DEFAULT, '1717 Main St', NULL,
        'CA', '90675', 1)
Jeder Spalte wird ein bestimmter Literalwert zugewiesen. Dies gilt jedoch nicht für die Spalten phone und city – erstere erhält den Standardwert (entsprechend der Anweisung CREATE TABLE oder ALTER TABLE), letztere den Wert Null.
Im folgenden Beispiel sehen Sie eine teilweise INSERT-Operation in einer Microsoft SQL Server-Datenbank mit denselben Daten:
    INSERT authors (au_id, au_lname, au_fname,  phone, contract )
    VALUES ('111-11-1111', 'Rabbit', 'Jessica', DEFAULT, 1)
Um Daten aus der Tabelle sales in die Tabelle new_sales zu laden, können Sie die Anweisung INSERT . . . SELECT verwenden:
    INSERT sales
        (stor_id,
        ord_num,
        ord_date,
        qty,
        payterms,
        title_id)
    SELECT
        CAST(store_nbr AS CHAR(4)),
        CAST(order_nbr AS VARCHAR(20)),
        order_date,
        quantity,
        SUBSTRING(payment_terms,1,12),
        CAST(title_nbr AS CHAR(1))
    FROM new_sales
    WHERE order_date >= '01/01/2000'         -- retrieve only the newer records

LIKE-Operator |
Mit dem LIKE-Operator können bestimmte Stringmuster in SELECT- , INSERT-, UPDATE- und DELETE-Anweisungen verglichen werden. Die angegebenen Suchmuster können sogar spezielle Wildcard-Zeichen enthalten.
Hersteller | Befehl
--- | ---
SQL Server | Unterstützt, mit Variationen
MySQL | Unterstützt, mit Variationen
Oracle | Unterstützt, mit Variationen
PostgreSQL | Unterstützt, mit Variationen
SQL99: Syntax und Beschreibung
    WHERE expression [NOT] LIKE string_pattern
Der LIKE-Operator ist gerade wegen den unterstützten Wildcards so nützlich. LIKE gibt den Booleschen Wert TRUE zurück, wenn der Vergleich einen oder mehrere passende Werte ergibt. Beachten Sie, dass die standardmäßige Groß-/Kleinschreibung des DBMS große Auswirkungen auf das Verhalten von LIKE hat. In Microsoft SQL Server wird die Groß-/Kleinschreibung normalerweise nicht berücksichtigt, auch wenn dies so eingestellt werden kann. Mit der Abfrage
    SELECT *
    FROM authors
    WHERE lname LIKE 'LARS%'
würde man daher nur Autoren finden, deren Nachnamen als "larson" or "lars" gespeichert sind, auch wenn eigentlich nach "LARS%" in Großbuchstaben gesucht wurde. Oracle berücksichtigt die Groß-/Kleinschreibung bei den Wildcards "%" und "_" und verfügt über weitere Operatoren außer LIKE für Mustervergleiche mit regulären Ausdrücken. Die Wildcard-Operatoren sind in Tabelle 3.3 zusammengefasst.
Wildcard-Operator | Beispiel | Beschreibung
--- | --- | ---
% | Ruft alle Datensätze mit Städtenamen ab, die die Zeichenfolge "ville" enthalten (von allen Herstellern unterstützt).
    SELECT * FROM authors
    WHERE city LIKE '%ville%'
| Ist ein Platzhalter für jeden beliebigen String, ähnelt dem * in DOS-Operationen.
[ ] | Ruft alle Autoren mit einem ähnlich klingenden Nachnamen wie Carson, Carsen, Karson oder Karsen ab (von Oracle nicht unterstützt; von Microsoft SQL Server unterstützt.)
    SELECT * FROM authors
    WHERE au_lname LIKE '[CK]ars[eo]n'
| Sucht nach Zeichen, die mit den Werten in der angegebenen Menge (z. B. [abc]) oder im angegebenen Bereich (z. B. [k-n]) übereinstimmen.
[^ ] | Ruft alle Autoren mit Nachnamen ab, die auf "arson" oder "arsen" enden, aber nicht Larsen oder Larson (von Microsoft SQL Server unterstützt).
    SELECT * FROM authors
    WHERE au_lname LIKE '[A-Z^L]ars[eo]n'
| Sucht nach Zeichen, die nicht in der angegebenen Menge oder im angegebenen Bereich vorkommen.
_ (Unterstrich) | Ruft alle Autoren ab, deren Vorname weder Sheryl noch Cheryl ist (von allen Herstellern unterstützt).
    SELECT * FROM authors
    WHERE au_fname NOT LIKE '_heryl'
| Steht für ein beliebiges einzelnes Zeichen.
Wenn Sie Stringvergleiche mit LIKE durchführen, sind alle Zeichen in dem Suchmuster entscheidend, einschließlich aller führenden oder folgenden Leerzeichen.

OPEN |
Mit dem Befehl OPEN wird ein serverseitiger Cursor geöffnet, der mit einer DECLARE CURSOR-Anweisung erstellt wurde. MySQL unterstützt keine serverseitigen Cursor vom Typ ANSI.
Hersteller | Befehl
--- | ---
SQL Server | Unterstützt
MySQL | Nicht unterstützt
Oracle | Unterstützt
PostgreSQL | Unterstützt
SQL99: Syntax und Beschreibung
    OPEN { cursor_name }
Mit cursor_name ist der Name des Cursors gemeint, der mit dem Befehl DECLARE CURSOR erstellt wurde.
Neben den Standard-Servercursorn erlaubt Microsoft SQL Server auch die Deklaration globaler Cursor (im Format OPEN GLOBAL cursor_name), die von mehreren Benutzern verwendet werden können. Darüber hinaus können in Oracle Parameter direkt an den Cursor übergeben werden, wenn dieser geöffnet ist (im Format OPEN cursor_name parameter1 [,...n]).
Beispiel
Im folgenden Beispiel für Microsoft SQL Server wird ein Cursor geöffnet und anschließend werden alle Zeilen ausgelesen. Dasselbe erreichen Sie in Oracle und PostgreSQL ohne die abschließende DEALLOCATAE-Klausel:
    DECLARE employee_cursor CURSOR FOR
      SELECT lname, fname
      FROM pubs.dbo.authors
      WHERE lname LIKE 'K%'

    OPEN employee_cursor

    FETCH NEXT FROM employee_cursor

    WHILE @@FETCH_STATUS = 0
    BEGIN
      FETCH NEXT FROM Employee_Cursor
    END

    CLOSE employee_cursor

    DEALLOCATE employee_cursor
    -- DEALLOCATE is specific to Microsoft SQL Server and non-ANSI
    -- standard.

Operatoren |
Ein Operator ist ein Symbol, das eine Aktion für einen oder mehrere Ausdrücke angibt. Operatoren werden meistens in DELETE- , INSERT-, SELECT- oder UPDATE-Anweisungen verwendet, können aber auch bei der Erstellung von Datenbankobjekten wie gespeicherten Prozeduren, Funktionen, Triggern und Views eingesetzt werden.
Hersteller | Befehl
--- | ---
SQL Server | Unterstützt, mit Variationen
MySQL | Unterstützt, mit Variationen
Oracle | Unterstützt, mit Variationen
PostgreSQL | Unterstützt, mit Variationen
Operatoren werden in der Regel in folgende logische Kategorien eingeteilt:
Arithmetische Operatoren in allen Datenbanken unterstützt Zuweisungsoperatoren in allen Datenbanken unterstützt Bitweise Operatoren unterstützt in Microsoft SQL Server Vergleichs operatoren in allen Datenbanken unterstützt Logische Operatoren unterstützt in Oracle, Microsoft SQL Server und PostgreSQL Unäre Operatoren unterstützt in Oracle
Arithmetische Operatoren
Arithmetische Operatoren führen mathematische Operationen für zwei Ausdrücke aus, die aus beliebigen numerischen Datentypen bestehen. Die arithmetischen Operatoren sind in Tabelle 3.4 zusammengefasst.
Arithmetischer Operator | Bedeutung
--- | ---
+ | Addition
- | Subtraktion
* | Multiplikation
/ | Division
% | Modula (nur in SQL Server); gibt den Rest einer Divisionsoperation als Ganzzahl zurück.
In Oracle und SQL Server können die Operatoren + und – auch für arithmetische Operationen mit Datumswerten verwendet werden.
Zuweisungsoperatoren
Außer in Oracle wird mit dem Zuweisungsoperator (=) der Wert einer Variablen oder dem Alias einer Spaltenüberschrift zugewiesen. In Microsoft SQL Server kann das Schlüsselwort AS als Operator für Aliasnamen in Tabellen- oder Spaltenüberschriften verwendet werden.
Bitweise Operatoren
Microsoft SQL Server stellt bitweise Operatoren als Schnellverfahren für die Bitmanipulation zwischen Ausdrücken mit zwei Integerwerten zur Verfügung (siehe Tabelle 3.5). Zu den Datentypen, die mit bitweisen Operatoren verwendet werden können, gehören binary, bit, int, smallint, tinyint und varbinary.
Bitweise Operatoren | Bedeutung
--- | ---
& | Bitweises UND (zwei Operanden)
| | Bitweises ODER (zwei Operanden)
^ | Bitweises Exklusiv-ODER (zwei Operanden)
Vergleichsoperatoren
Vergleichsoperatoren prüfen, ob zwei Ausdrücke gleich oder ungleich sind. Das Ergebnis einer Vergleichsoperation ist ein Boolescher Wert: TRUE, FALSE oder UNKNOWN. Der ANSI-Standard sieht vor, dass das Ergebnis eines Vergleichs, bei dem einer der beiden Ausdrücke NULL ist, ebenfalls NULL ist. So gibt zum Beispiel der Ausdruck 23 + NULL NULL zurück, ebenso der Ausdruck Feb 23, 2002 + NULL. Die Vergleichsoperatoren sind in Tabelle 3.6 zusammengefasst.
Vergleichsoperatoren | Bedeutung
--- | ---
= | Gleich
> | Größer als
< | Kleiner als
>= | Größer oder gleich
<= | Kleiner oder gleich
<> | Ungleich
!= | Ungleich (nicht im ANSI-Standard)
!< | Nicht kleiner als (nicht im ANSI-Standard)
!> | Nicht größer als (nicht im ANSI-Standard)
Boolesche Vergleichsoperatoren werden meistens in einer WHERE-Klausel verwendet, um die Zeilen herauszufiltern, die die Suchbedingungen erfüllen. Im folgenden Beispiel für Microsoft SQL Server ist ein Größer-oder-Gleich-Vergleich enthalten:
    SELECT *
       FROM Products
       WHERE ProductID >= @MyProduct
Logische Operatoren
Logische Operatoren werden häufig in WHERE-Klauseln verwendet, um zu überprüfen, ob eine Bedingung wahr ist. Logische Operatoren geben einen Booleschen Wert zurück, d. h. entweder TRUE oder FALSE. Logische Operatoren werden unter der Anweisung SELECT näher erläutert. Nicht alle RDBMS unterstützen alle Operatoren. Die logischen Operatoren sind in Tabelle 3.7 zusammengefasst.
Logische Operatoren | Bedeutung
--- | ---
ALL | TRUE, wenn alle Vergleiche aus einer Menge TRUE sind
AND | TRUE, wenn beide Boolesche Ausdrücke TRUE sind
ANY | TRUE, wenn alle Vergleiche aus einer Menge TRUE sind
BETWEEN | TRUE, wenn der Operand im angegebenen Bereich liegt
EXISTS | TRUE, wenn eine Unterabfrage Zeilen enthält
IN | TRUE, wenn der Operand gleich einem Ausdruck in einer Liste von Ausdrücken ist
LIKE | TRUE, wenn der Operand mit dem Muster übereinstimmt
NOT | Kehrt den Wert jedes anderen Booleschen Operators um
OR | TRUE, wenn einer der beiden Booleschen Ausdrücke TRUE ist
SOME | TRUE, wenn einige Vergleiche aus einer Menge TRUE sind
Unäre Operatoren
Unäre Operatoren führen eine Operation für einen einzigen Ausdruck eines beliebigen numerischen Datentyps aus. Unäre Operatoren können bei Integerdatentypen verwendet werden, + und - dagegen bei jedem beliebigen numerischen Datentyp (siehe Tabelle 3.8).
Unäre Operatoren | Bedeutung
--- | ---
+ | Numerischer Wert ist positiv
- | Numerischer Wert ist negativ
~ | Bitweises NICHT, gibt das Komplement einer Zahl zurück (nicht in Oracle)
Rangfolge von Operatoren
Manchmal sind Operatorausdrücke ziemlich komplex. Wenn in einem Ausdruck mehrere Operatoren enthalten sind, bestimmt die Rangfolge, in welcher Reihenfolge die Operationen ausgeführt werden. Die Ausführungsreihenfolge kann sich entscheidend auf den Ergebniswert auswirken.
Für Operatoren gelten die nachstehend genannten Rangstufen. Ein Operator einer höheren Stufe wird vor einem Operator einer niedrigeren Stufe ausgewertet:
( ) (Ausdrücke in Klammern) +, -, ~ (unäre Operatoren) *, /, % (mathematische Operatoren) +, - (arithmetische Operatoren) =, >, <, >=, <=, <>, !=, !>, !< (Vergleichsoperatoren) ^ (bitweises Exklusiv-ODER), & (bitweises UND), | (bitweises ODER) NOT AND ALL, ANY, BETWEEN, IN, LIKE, OR, SOME = (Variablenzuweisung)
Operatoren mit gleicher Rangstufe werden von links nach rechts ausgewertet. Die Rangstufe eines Operators in einem Ausdruck kann jedoch geändert werden, indem dieser in runde Klammern gesetzt wird. Ausdrücke in Klammern werden zuerst ausgewertet, dann erst kommen die Operatoren außerhalb der Klammern.
Die folgenden Ausdrücke in einer Oracle-Abfrage geben beispielsweise sehr unterschiedliche Ergebnisse zurück:
    SELECT 2 * 4 + 5 FROM dual
    -- Evaluates to 8 + 5 which yields an expression result of 13.

    SELECT 2 * (4 + 5) FROM dual
    -- Evaluates to 2 * 9 which yields an expression result of 18.
In Ausdrücken mit verschachtelten Klammern wird der am tiefsten verschachtelte Ausdruck zuerst ausgewertet.
Das folgende Beispiel enthält verschachtelte Klammern, wobei der Ausdruck 5 -3 am tiefsten verschachtelt ist. Dieser Ausdruck ergibt den Wert 2. Der Additionsoperator (+) addiert dieses Ergebnis zu 4 hinzu, was 6 ergibt. Zum Schluss wird 6 mit 2 multipliziert, so dass das Ergebnis des Ausdrucks 12 ist:
    SELECT 2 * (4 + (5 - 3) ) FROM dual
    -- Evaluates to 2 * (4 + 2) which further evaluates to 2 * 6, and
    -- yields an expression result of 12.

RETURN |
Mit der Anweisung RETURN wird die Verarbeitung einer von SQL (also nicht vom Host) aufgerufenen Funktion beendet und der Ergebniswert der Funktion zurückgegeben.
Hersteller | Befehl
--- | ---
SQL Server | Unterstützt
MySQL | Unterstützt
Oracle | Unterstützt
PostgreSQL | Unterstützt
SQL99: Syntax und Beschreibung
    RETURNS return_parameter_value | NULL
Die Funktion RETURN wird in einer Funktion verwendet, um deren Verarbeitung zu beenden. Mit der Klausel NULL wird die Funktion ohne Rückgabe eines Wertes beendet. Ansonsten wird der angegebene Parameterwert entweder als Variable oder als Literalausdruck zurückgegeben.
Obwohl die Anweisung RETURN als eigenständiger SQL-Befehl betrachtet wird, steht sie in engem Zusammenhang mit der Anweisung CREATE FUNCTION . Nähere Informationen über die herstellerspezifischen Implementierungen von RETURN finden Sie unter der Anweisung CREATE FUNCTION.
Beispiele
Im folgenden Beispiel wird eine Funktion erstellt. Die Funktion gibt den in der Variablen proj_rev gespeicherten Wert an die aufrufende Sitzung zurück:
    CREATE FUNCTION project_revenue (project IN varchar2)
    RETURN NUMBER
    AS
       proj_rev NUMBER(10,2);
    BEGIN
       SELECT SUM(DECODE(action,'COMPLETED',amount,0) -
              SUM(DECODE(action,'STARTED',amount,0)   +
              SUM(DECODE(action,'PAYMENT',amount,0)
       INTO proj_rev
       FROM construction_actions
       WHERE project_name = project;
       RETURN (proj_rev);
    END;
Im folgenden Beispiel wird eine Funktion erstellt, die einen berechneten Wert an die aufrufende Sitzung zurückgibt:
    CREATE FUNCTION metric_volume -- Input dimensions in centimeters.
       (@length decimal(4,1),
       @width decimal(4,1),
       @height decimal(4,1) )
    RETURNS decimal(12,3) -- Cubic Centimeters.
    AS
    BEGIN
       RETURN ( @length * @width * @height )
    END
    GO

REVOKE |
Mit der Anweisung REVOKE werden einem Benutzer, einer Gruppe oder einer Rolle die Zugriffsrechte für ein bestimmtes Datenbankobjekt oder einen Systembefehl entzogen.
Hersteller | Befehl
--- | ---
SQL Server | Unterstützt, mit Variationen
MySQL | Unterstützt, mit Variationen
Oracle | Unterstützt, mit Variationen
PostgreSQL | Unterstützt, mit Variationen
SQL99: Syntax und Beschreibung
    REVOKE [GRANT OPTION FOR]
    { ALL PRIVILEGES }
    | SELECT
    | INSERT
    | DELETE
    | UPDATE
    | REFERENCES
    | USAGE }[,...n]
    ON { [TABLE] table_name
    | DOMAIN domain_name
    | COLLATION collation_name
    | CHARACTER SET character_set_name
    | TRANSLATION translation_name }
    FROM {grantee_name | PUBLIC} [,...n]
    {CASCADE | RESTRICT}
Ein bestimmtes Zugriffsrecht für ein bestimmtes Datenbankobjekt kann einem einzelnen Benutzer mit REVOKE privilege_name ON object_name FROM grantee_name entzogen werden. Ein bestimmtes Zugriffsrecht für ein bestimmtes Objekt können Sie sämtlichen Benutzern mit der Klausel PUBLIC entziehen. Alternativ dazu kann WITH GRANT OPTION verwendet werden, um Zugriffsrechte mit der Klausel REVOKE GRANT OPTION FOR zu entziehen.
Mit der Option RESTRICT wird nur das angegebene Zugriffsrecht entzogen. Mit der Option CASCADE werden das angegebene Zugriffsrecht sowie alle davon anhängigen Zugriffsrechte entzogen. Der kaskadierende Entzug von Zugriffsrechten kann von Datenbankplattform zu Datenbankplattform unterschiedlich sein. Sie sollte daher vorher in der Herstellerdokumentation nachlesen, wie diese Option richtig implementiert wird.
Microsoft SQL Server: Syntax und Variationen
    REVOKE [GRANT OPTION FOR]
    {ALL [ PRIVILEGES ]
    | SELECT
    | INSERT
    | DELETE
    | UPDATE
    | REFERENCES
    | EXECUTE
    | CREATE {DATABASE | DEFAULT | FUNCTION | PROCEDURE | RULE | TABLE | VIEW}
    | BACKUP {DATABASE | LOG} } [,...n]
    ON { {table_name | view_name} [(column [,...n])]
    | stored_procedure_name
    | extended_stored_procedure_name
    | user_defined_function_name
    | [(column [,...n] ON {table_name | view_name} }
    {TO | FROM} {grantee_name} [,...n]
    [CASCADE]
    [AS {group_name | role_name} ]
Dieser Befehl ist im Wesentlichen SQL99-kompatibel, mit Ausnahme der mit dem Befehl GRANT eingeführten Erweiterungen.
Wenn einem Benutzer mit WITH GRANT OPTION die Ausführung von Befehlen gewährt wurde, sollte dieses Privileg sowohl mit WITH GRANT OPTION als auch CASCADE entzogen werden.
REVOKE kann nur in der aktuellen Datenbank verwendet werden. REVOKE wird auch verwendet, um DENY-Einstellungen zu deaktivieren.
Microsoft SQL Server unterstützt zusätzlich die Anweisung DENY. DENY ist REVOKE syntaktisch ähnlich, unterscheidet sich aber konzeptionell dahingehend, dass REVOKE die Zugriffsrechte eines Benutzers neutralisiert, während diese mit DENY explizit verboten werden. Mit der Anweisung DENY können Sie einen Benutzer oder eine Rolle von der Nutzung eines Privilegs ausschließen.
Beispiel
    REVOKE CREATE DATABASE, CREATE TABLE FROM emily, sarah
    GO

    REVOKE GRANT OPTION FOR
    SELECT, INSERT, UPDATE, DELETE ON titles
    TO editors
    GO
MySQL: Syntax und Variationen
    REVOKE { ALL PRIVILEGES
    | SELECT
    | INSERT [ (column_name [,...n]) ]
    | UPDATE [ (column_name [,...n]) ]
    | REFERENCES [ (column_name [,...n]) ]
    | DELETE
    | USAGE
    | ALTER
    | CREATE
    | DROP
    | FILE
    | INDEX
    | PROCESS
    | RELOAD
    | SHUTDOWN } [,...n]
    ON {table_name | * | *.* | database_name.*}
    FROM user_name [,...n]
Mit der Anweisung REVOKE werden Zugriffsrechte, die einem oder mehreren Benutzern zuvor eingeräumt wurden, wieder entzogen. Zugriffsrechte können wie unter der Anweisung GRANT beschrieben global zurückgenommen werden. Außerdem werden bei der MySQL-Implementierung von REVOKE nicht automatisch Zugriffsrechte für gelöschte Objekte entzogen. Aus diesem Grunde müssen Zugriffsrechte für eine gelöscht Tabelle explizit zurückgenommen werden. Ansonsten entspricht der MySQL-Befehl REVOKE dem SQL99-Standard.
Beispiel
Mit dem ersten Befehl werden Emily und Dylan alle Zugriffsrechte für die Tabelle sales entzogen, mit dem zweiten Befehl dagegen alle Rechte des Benutzers Kelly in der aktuellen Datenbank:
    REVOKE ALL PRIVILEGES ON sales FROM emily, dylan;

    REVOKE * employee FROM kelly;
Oracle: Syntax und Variationen
    REVOKE {ALL [PRIVILEGES] | [object_privilege] }
    ON { [schema_name.][object] | [DIRECTORY directory_object_name] }
    FROM {grantee_name | role | PUBLIC} [,...n]
    [CASCADE [CONSTRAINTS] ] [FORCE];

    REVOKE {system_privilege | role}
    FROM {grantee_name | role | PUBLIC} [,...n];
Mit dem Befehl REVOKE können nicht nur Objekt- und Systemprivilegien zurückgenommen werden, sondern die Rolle eines bestimmten Benutzers oder einer anderen Rolle. Nähere Informationen über Objekt- und Systemprivilegien, die der Befehl REVOKE unterstützt, finden Sie unter der Anweisung GRANT.
Die beiden Formen des REVOKE-Befehls, REVOKE object_privilege und REVOKE system_privilege schließen sich gegenseitig aus. Versuchen Sie nicht, beide Operationen in einer einzigen Anweisung zu verwenden.
Wenn einem Benutzer Zugriffsrechte entzogen werden, werden gleichzeitig auch die Zugriffsrechte aller anderen Benutzer, die ihre Rechte von diesem Benutzer erhalten haben, entzogen.
Benutzer mit dem Systemprivileg GRANT ANY ROLE können auch beliebige Rollen entziehen. Mit dem Befehl REVOKE können nur Privilegien entzogen werden, die explizit mit dem Befehl GRANT gewährt wurden, nicht solche, die über Rollen oder das Betriebssystem zur Verfügung stehen.
Mit der Klausel ON DIRECTORY wird ein Verzeichnisobjekt angegeben, bei dem Zugriffsrechte entzogen werden. Mit der Klausel CASCADE CONSTRAINTS werden alle von Benutzern erstellten referenziellen Integritäts-Constraints gelöscht, wenn deren REFERENCES-Privileg entzogen wird. Mit der Klausel FORCE werden EXECUTE-Rechte für abhängige benutzerdefinierte Tabellen und Typobjekte entzogen. In der Folge werden diese Objekte so lange als ungültig und nicht verwendbar gekennzeichnet, bis sie neu kompiliert werden.
Beispiele
So entziehen Sie einem Benutzer eine Rolle:
    REVOKE read-only FROM sarah;
So entziehen Sie das Zugriffsrecht für Systembefehle:
    REVOKE CREATE ANY SEQUENCE, CREATE ANY DIRECTORY FROM read_only;
So entziehen Sie ein REFERENCES-Privileg:
    REVOKE REFERENCES
    ON pubs_new_york.emp
    FROM dylan
    CASCADE CONSTRAINTS;
PostgreSQL: Syntax und Variationen
    REVOKE { ALL
    | SELECT
    | INSERT
    | DELETE
    | UPDATE
    | RULE
    | REFERENCES
    | USAGE} [,...n]
    ON {object_name}
    TO {grantee_name | PUBLIC | GROUP group_name}
    {CASCADE | RESTRICT}
In PostgreSQL können Sie Zugriffsrechte für Tabellen, Views und Sequenzen entziehen. Ansonsten ist der Befehl identisch mit dem SQL99-Befehl. Nähere Informationen dazu finden Sie in der Beschreibung der SQL99-Syntax von REVOKE und GRANT.

ROLLBACK |
Mit der Anweisung ROLLBACK wird eine Transaktion an ihren Anfang oder einen zuvor deklarierten SAVEPOINT zurückgeführt. Sie schließt geöffnete Cursor und gibt genau wie COMMIT Sperren frei.
Hersteller | Befehl
--- | ---
SQL Server | Unterstützt, mit Variationen
MySQL | Nicht unterstützt
Oracle | Unterstützt
PostgreSQL | Unterstützt
SQL99: Syntax und Beschreibung
    ROLLBACK [WORK]
    [TO SAVEPOINT savepoint_name]
Neben dem Abschluss einer einzelnen oder mehrerer Datenmanipulationsoperationen können Sie mit der Anweisung ROLLBACK Transaktionen bis zur letzten ausgeführten BEGIN- oder SAVEPOINT-Anweisung rückgängig machen.
SQL99 umfasst die neuen optionalen Schlüsselwörter AND CHAIN. Bislang wird dieser Befehl noch von keinem der vier Hersteller unterstützt. Diese neue Syntax sieht folgendermaßen aus:
    ROLLBACK [WORK] [AND [NO] CHAIN]
Mit der Option AND CHAIN wird das DBMS aufgefordert, die aktuelle Transaktion zu beenden, aber die gemeinsame Transaktionsumgebung (wie z. B. die Isolationsebene der Transaktion) in der nächsten Transaktion weiter zu nutzen. Mit der Option AND NO CHAIN wird einfach eine einzelne Transaktion beendet. Der Befehl ROLLBACK ist von der Funktion dem Befehl ROLLBACK WORK AND NO CHAIN gleichwertig.
Microsoft SQL Server: Syntax und Variationen
    ROLLBACK [TRAN[SACTION] [transaction_name |
     @tran_name_variable |
    savepoint_name | @savepoint_variable] ]
Mit ROLLBACK werden alle Datenänderungen rückgängig gemacht, die in der gerade geöffneten Transaktion oder ab einem bestimmten Savepoint vorgenommen wurden. Wenn ROLLBACK ohne sonstige Angaben ausgeführt wird, wird die aktuelle offene Transaktion zurückgeführt. Mit ROLLBACK werden normalerweise Sperren aufgehoben. Dies ist jedoch nicht der Fall, wenn bis zu einem Savepoint zurückgegangen wird. ROLLBACK verhält sich ähnlich wie COMMIT, was verschachtelte Trigger anbelangt, und verringert den Wert der Systemvariablen @@TRANCOUNT um eins.
Wenn ROLLBACK TRANSACTION in einem Trigger verwendet wird, werden alle Datenänderungen, einschließlich der vom Trigger vorgenommenen, bis zur ROLLBACK-Anweisung zurückgenommen. Verschachtelte Trigger werden nicht ausgeführt, wenn sie auf eine ROLLBACK-Anweisung in einem Trigger folgen. Anweisungen im selben Trigger, die auf die ROLLBACK-Anweisung folgen, sind von dieser aber nicht betroffen.
Oracle: Syntax und Variationen
    ROLLBACK [WORK] [TO savepoint_name] [FORCE text];
Mit ROLLBACK werden alle Datenänderungen rückgängig gemacht, die in der gerade geöffneten Transaktion oder ab einem bestimmten Savepoint vorgenommen wurden. Die Implementierung in Oracle hält sich eng an den SQL-Standard, mit Ausnahme der Option FORCE. Mit ROLLBACK FORCE können Sie zu einer zweifelhaften verteilten Transaktion zurückgehen. Diese Transaktionen sind in dem Oracle-Systemview DBA_2PC_PENDING beschrieben.
PostgreSQL: Syntax und Variationen
    {ROLLBACK | ABORT} [WORK | TRANSACTION];
Mit ROLLBACK werden alle Datenänderungen rückgängig gemacht, die in der gerade geöffneten Transaktion oder ab einem bestimmten Savepoint vorgenommen wurden. PostgreSQL unterstützt die SQL99-Optionen WORK und TRANSACTION. Nicht unterstützt wird das Zurückführen auf einen Savepoint. Die Option ABORT ist ein Synonym für ROLLBACK.
Beispiel
Nachfolgend sehen Sie einen Transact-SQL-Batch für Microsoft SQL Server, in dem COMMIT und ROLLBACK verwendet werden. Damit wird ein Datensatz in die Tabelle sales eingefügt. Schlägt dieser Vorgang fehl, wird die Transaktion zurückgeführt, ansonsten wird sie festgeschrieben:
    BEGIN TRAN -- initializes a transaction

    -- the transaction itself
    INSERT INTO sales
    VALUES('7896','JR3435','Oct 28 1997',25,'Net 60','BU7832')

    -- some error-handling in the event of a failure
    IF @@ERROR <> 0
    BEGIN
        -- raises an error in the event log and skips to the end
        RAISERROR 50000 'Insert of sales record failed'
        ROLLBACK WORK
        GOTO end_of_batch
    END

    -- the transaction is committed if no errors are detected
    COMMIT TRAN

    -- the GOTO label that enables the batch to skip to the end without
    -- committing
    end_of_batch:
    GO

SAVEPOINT |
Mit diesem Befehl wird ein Savepoint in die aktuelle Transaktion eingefügt. Transaktionen können mit dem Befehl SAVEPOINT in logische Abschnitte (Breakpoints) aufgeteilt werden. Sie können mehrere Savepoints in einer einzelnen Transaktion festlegen. Der Hauptvorteil des Befehls SAVEPOINT besteht darin, dass Transaktionen mit dem Befehl ROLLBACK teilweise auf einen eindeutigen Savepoint zurückgeführt werden können.
Hersteller | Befehl
--- | ---
SQL Server | Unterstützt, mit Variationen
MySQL | Nicht unterstützt
Oracle | Unterstützt
PostgreSQL | Nicht unterstützt
SQL99: Syntax und Beschreibung
    SAVEPOINT savepoint_name
Einige Hersteller ermöglichen die Mehrfachvergabe von Savepoint-Namen in einer Transaktion, davon sei jedoch abgeraten. Ersatz-Savepoint-Identifier (im Format :X) können ebenfalls verwendet werden, damit das DBMS die Savepoints anhand einer Ganzzahl anstatt eines Namens verwalten kann. Nicht alle Hersteller unterstützen dies, und besonders guter Stil ist es auch nicht.
Beachten Sie, dass SQL99 die Anweisung RELEASE SAVEPOINT savepoint_name unterstützt, mit der ein Savepoint gelöscht werden kann. Diese Anweisung wird jedoch von keinem der in diesem Buch behandelten Hersteller unterstützt.
Microsoft SQL Server: Syntax und Variationen
    SAVE TRAN[SACTION] {savepoint_name | @savepoint_variable}
Microsoft SQL Server unterstützt den Befehl SAVEPOINT nicht. Statt dessen können Sie den Befehl SAVE verwenden. Statt einen Literalnamen für den Savepoint zu deklarieren, können Sie eine Variable referenzieren, die den Namen des Savepoints enthält.
Wenn der Befehl ROLLBACK TRAN savepoint_name ausgeführt wird, führt SQL Server die Transaktion zu dem entsprechenden Savepoint zurück und macht mit der Verarbeitung des nächsten gültigen Transact-SQL-Befehls nach der Anweisung ROLLBACK weiter. Zum Schluss muss die Transaktion mit einer COMMIT- oder einer abschließenden ROLLBACK-Anweisung beendet werden.
Oracle: Syntax und Variationen
    SAVEPOINT savepoint_name
Oracle unterstützt die SQL99-Implementierung vollständig.
Beispiel
Im folgenden Beispiel werden zunächst verschiedene Datenmodifizierungen ausgeführt. Dann wird zu einem Savepoint zurückgegangen und anschließend die Transaktion vollständig zurückgeführt:
    INSERT INTO sales VALUES('7896','JR3435','Oct 28 1997',25,'Net
    60','BU7832');

    SAVEPOINT after_insert;

    UPDATE sales SET terms = 'Net 90'
    WHERE sales_id = '7896';

    SAVEPOINT after_update;

    DELETE sales;

    ROLLBACK TO after_insert;
    ROLLBACK;

SELECT |
Mit der Anweisung SELECT werden Zeilen, Spalten und abgeleitete Werte aus einer oder mehreren Tabellen einer Datenbank abgerufen.
Hersteller | Befehl
--- | ---
SQL Server | Unterstützt, mit Variationen (ANSI-Joins werden unterstützt)
MySQL | Unterstützt, mit Variationen (ANSI-Joins werden teilweise unterstützt)
Oracle | Unterstützt, mit Variationen (ANSI-Joins werden nicht unterstützt)
PostgreSQL | Unterstützt, mit Variationen (ANSI-Joins werden teilweise unterstützt)
SQL99: Syntax und Beschreibung
Die vollständige Syntax der Anweisung SELECT ist mächtig und komplex, lässt sich aber in folgende Hauptklauseln aufteilen:
    SELECT [ALL | DISTINCT] select_list
    FROM table_name1 [,..., table_nameN]
    [JOIN join_condition]
    [WHERE search_condition]
    [GROUP BY group_by_expression]
    [HAVING search_condition]
    [ORDER BY order_expression [ASC | DESC] ]
Jede Klausel der Anweisung SELECT hat eine bestimmte Aufgabe. Man kann daher die Klauseln FROM, WHERE und GROUP BY getrennt voneinander betrachten. Allerdings ist nicht für jede Abfrage jede Klausel erforderlich. Zu einer Abfrage gehören als Mindestanforderung eine SELECT-Liste und eine FROM-Klausel. (Microsoft SQL Server und PostgreSQL unterstützen bestimmte Abfragetypen, bei denen keine FROM-Klausel erforderlich ist. Näheres dazu in den Beispielen unten.)
SELECT-Liste
Die SELECT-Liste enthält im Wesentlichen alle Informationen, die ein Benutzer vom Server abrufen möchte. In der SELECT-Liste können verschiedene Arten von Elementen vorkommen, wie zum Beispiel Literalstrings, Aggregatfunktionen und mathematische Berechnungen. In Microsoft SQL Server kann die SELECT-Liste auch eine Unterabfrage enthalten.
Die Vorgabe ist ALL, d. h. es werden alle Datensätze, einschließlich der Standardwerte, zurückgegeben. DISTINCT ist ein Schlüsselwort, das dafür sorgt, dass die Abfrage alle doppelten Datensätze herausfiltert. Die Ergebnismenge enthält somit nur jeweils eine Instanz identischer Datensätze.
Es gibt noch weitere Regeln, die bestimmen, was in der SELECT-Liste enthalten sein darf:
Die einzelnen Spalten sollten mit einem Komma voneinander getrennt werden. Ein Sternchen (*) bezeichnet alle Spalten in allen Tabellen in der Klausel FROM, so wie sie in der Anweisung CREATE TABLE stehen. Spalten-Aliasnamen können hinzugefügt werden, um die voreingestellten Spaltenüberschriften in den Ergebnissen zu ersetzen. Verwenden Sie das Format spalte AS "alias" oder spalte alias. Dies ist besonders nützlich, wenn eine Spaltenüberschrift zu kryptisch oder zu lang ist, um leicht verstanden zu werden. Beispiel: Sofern dies unterstützt wird, können auch lokale und globale Variablen in der SELECT-Liste stehen. In der gesamten SQL- oder Transact-SQL-Anweisung können Kommentare stehen, die mit einem doppelten Gedankenstrich (—) oder einer Schrägstrich-Sternchen-Folge ( /* ... */ ) markiert werden müssen. Der doppelte Gedankenstrich sorgt dafür, dass die Abfrage sämtlichen Text nach dem doppelten Gedankenstrich bis zum Zeilenende ignoriert. Bei der Schrägstrich-Sternchen-Folge wird sämtlicher Text zwischen der Schrägstrich-Sternchen-Folge und der Sternchen-Schrägstrich-Folge ignoriert. In einer Abfrage über mehrere Tabellen hinweg sollte dem Spaltennamen der Tabellenname vorangestellt werden. Genaugenommen muss sich der Tabellenname auf alle Spalten in beiden Tabellen beziehen. Es gilt jedoch als guter Stil, diese Angabe immer zu machen. Im folgenden Beispiel ist die Spalte job_id sowohl in der Tabelle jobs als auch employee enthalten: Wenn eine Spalte aus einem Kontext außerhalb des aktuellen Benutzers stammt, sollte der Spalte der Name des Schemas oder des Eigentümers vorangestellt werden. Gehört die Tabelle einem anderen Benutzer, muss der Benutzername in der Spaltenreferenz angegeben werden. Angenommen, die folgende Beispielabfrage läuft in der Datenbank PUBS, ruft gleichzeitig aber auch Daten aus der Datenbank SALES ab: In der SELECT-Liste können auch Literalausdrücke verwendet werden. Mathematische Berechnungen können in der SELECT-Liste ebenfalls eingegeben werden. In Microsoft SQL Server ist dafür keine FROM-Anweisung erforderlich. In Oracle sollte die Berechnung unter Verwendung der Systemtabelle DUAL ausgeführt werden. Diese Tabelle ermöglicht es dem SELECT-Befehl, auch dann Werte abzurufen, wenn keine Tabelle vorhanden ist. Beispiel:
FROM-Klausel
Die FROM-Klausel dient im Wesentlichen zwei Zwecken: Auflistung der Tabellen und Views (durch Kommas voneinander getrennt), aus denen Daten abgerufen werden, und Zuweisung eines Aliasnamens für lange Tabellennamen, was das Programmieren langer Abfragen um einiges leichter macht. Ein Aliasname kann in der FROM-Klausel auf zwei verschiedene Arten zugewiesen werden: entweder durch Eingabe des Tabellennamens, eines Leerzeichens und des Aliasnamens oder durch Eingabe des Tabellennamens, AS und des Aliasnamens. Im Beispiel unten werden beide Techniken gezeigt. Dieses Beispiel zeigt eine Abfrage, mit der Daten aus mehreren Tabellen abgerufen werden. Achten Sie dabei vor allem auf die Klauseln FROM und WHERE:
    SELECT   e.emp_id,
             e.fname,
             e.lname,
             j.job_desc
    FROM     employee e,
             jobs AS  j
    WHERE    e.job_id = j.job_id
    ORDER BY e.fname,
             e.lname
Wenn in einer Abfrage ein Aliasnamen zugewiesen wurde, sollten Sie nur diesen für Tabellenreferenzen in dieser Abfrage verwenden. Benutzen Sie nicht sowohl den vollständigen Tabellennamen als auch den Aliasnamen in einer Abfrage.
Mit dieser Abfrage wird die emp_id (Vor- und Nachname der in der Tabelle employee gespeicherten Mitarbeiter) abgerufen, und die job_id des Mitarbeiters, eine Codenummer, mit der vollständigen Jobbeschreibung in der Tabelle JOBS verknüpft.
JOIN-Klausel
In Implementierungen, die nicht dem ANSI-Standard folgen, wird die Join-Operation in der WHERE-Klausel ausgeführt (siehe Beschreibung im Abschnitt über WHERE-Klauseln). Im ANSI SQL-92-Standard werden Joins in der JOIN-Klausel der Abfrage durchgeführt. Diese beiden Join-Methoden werden als Theta-Joins bzw. ANSI-Joins bezeichnet.
Um korrelierte Daten aus zwei oder mehreren Tabellen abrufen zu können, müssen die Tabellen eine sinnvolle Beziehung zueinander haben. Die zu verbindenden Tabellen müssen eine oder mehrere Spalten besitzen, die eine gemeinsame Menge von Werten enthalten. Nur dann können die Tabellen sinnvoll verknüpft werden. Diese Spalte oder Spalten werden Join-Schlüssel oder gemeinsame Schlüssel genannt. Meistens, wenn auch nicht immer, ist der Join-Schlüssel der Primärschlüssel der einen Tabelle und ein Fremdschlüssel in der anderen Tabelle. Wenn die Daten in den Spalten zueinander passen, kann eine Verknüpfung erfolgen.
In der Datenbank PUBS enthält sowohl die Tabelle employee als auch die Tabelle jobs eine Spalte namens job_id. Somit ist die Spalte job_id der gemeinsame Schlüssel der Tabellen employee und jobs.
Um eine Abfrage mit einem ANSI-Join durchzuführen, geben Sie die erste Tabelle und das Schlüsselwort JOIN an, gefolgt von der zu verknüpfenden Tabelle. Geben Sie anschließend das Schlüsselwort ON und die Join-Bedingung an, die Sie auch in der traditionellen Abfrage verwendet hätten. Das folgende Beispiel zeigt die obige Abfrage nun im ANSI-Stil:
    SELECT   e.emp_id,
             e.fname,
             e.lname,
             j.job_desc
    FROM     employee AS e
    JOIN     jobs AS j ON e.job_id = j.job_id
    ORDER BY e.fname,
             e.lname
Join-Typen
Die Unterscheidung zwischen verschiedenen Joins erfolgt durch die Join-Typen im ANSI-Stil und die Gleichheitszeichen-Sternchen-Kombination ("=*") in Microsoft SQL Server bzw. Pluszeichen-Sternchen ("+*") in Oracle für Theta-Joins. Nachfolgend sind die einzelnen Join-Typen und ihr Verhalten beschrieben:
Cross Join Vollständiges Kreuzprodukt zweier Tabellen. Für jeden Datensatz in der ersten Tabelle werden alle Datensätze der zweiten Tabelle verknüpft, was zu einer riesigen Ergebnismenge führt. Dieser Befehl hat dieselben Auswirkungen wie das Weglassen der Join-Bedingungen und wird auch "Kartesisches Produkt" genannt. Die Verwendung von Cross Joins ist weder ratsam noch empfehlenswert (wird derzeit von Microsoft SQL Server unterstützt): Inner Join Legt fest, dass nicht zusammenpassende Zeilen aus beiden Tabellen verworfen werden. Wenn kein Join-Typ im ANSI-Stil angegeben wird, sieht der Standard folgendermaßen aus (wird derzeit von Microsoft SQL Server, PostgreSQL und MySQL unterstützt): Left [Outer] Join Hier werden alle Datensätze aus der Tabelle auf der linken Seite der Join-Anweisung zurückgegeben. Wenn es zu einem Datensatz aus der linken Tabelle kein passendes Gegenstück in der rechten Tabelle gibt, wird dieser trotzdem zurückgegeben. Die Spalten aus der rechten Tabelle erhalten dann NULL-Werte. (In diesem Fall werden alle Mitarbeiter zurückgegeben, unabhängig davon, ob es für diese eine Jobbeschreibung gibt oder nicht.) Viele Programmierprofis raten, Outer Joins aus Konsistenzgründen als Left Joins zu konfigurieren, sofern dies möglich ist (wird derzeit von Microsoft SQL Server unterstützt): Right [Outer] Join Alle Datensätze aus der Tabelle auf der rechten Seite der Join-Anweisung werden zurückgegeben, auch wenn es in der Tabelle auf der linken Seite keinen passenden Datensatz gibt. Die Spalten aus der linken Tabelle erhalten dann NULL-Werte. Im Beispiel werden alle Datensätze aus der Tabelle jobs zurückgegeben, unabhängig davon, ob es in der Tabelle employee einen entsprechenden Datensatz gibt (wird derzeit von Microsoft SQL Server unterstützt): Full Join Alle Zeilen aus allen Tabellen werden zurückgegeben, unabhängig davon, ob es in der anderen Tabelle dazu passende Datensätze gibt. In den Fällen, in denen die Verknüpfung keine Daten enthält, besteht die Ergebnismenge aus NULL-Werten (wird derzeit von Microsoft SQL Server unterstützt):
Joins im ANSI-Format sind leichter verständlich als Theta-Joins, weil in der Abfrage selbst genau angegeben ist, welche Tabelle bei einem LEFT JOIN auf der linken Seite steht und welche bei einem RIGHT JOIN auf der rechten Seite.
Die Syntax zur Durchführung einer ähnlichen Abfrage mit mehrteiligen Schlüsseln und mehreren verknüpften Tabellen ist im Wesentlichen eine Erweiterung derselben Technik.
Beispiel für einen Join mit mehreren Tabellen
    --Theta-Abfrage mit mehreren Tabellen
    SELECT   a.au_lname,
             a.au_fname,
             t2.title
    FROM     authors a,
             titleauthor t1,
             titles t2
    WHERE    a.au_id     = t1.au_id
      AND    t1.title_id = t2.title_id
    ORDER BY t2.title

    -- ANSI-Abfrage mit mehreren Tabellen
    SELECT   a.au_lname,
             a.au_fname,
             t2.title
    FROM     authors a
    JOIN     titleauthor AS t1 ON a.au_id     = t1.au_id
    JOIN     titles      AS t2 ON t1.title_id = t2.title_id
    ORDER BY t2.title
Beispiel für einen Join mit mehrteiligem Schlüssel
    --Theta-Abfrage mit mehrteiligem Schlüssel
    SELECT   s1.store_id,
             s1.title_id,
             s2.qty
    FROM     sales s1,
             sales_projections s2
    WHERE    s1.store_id = s2.store_id
      AND  s1.title_id = s2.title_id
    ORDER BY s1.store_id, s2.title_id

    -- ANSI-Abfrage mit mehrteiligem Schlüssel
    SELECT   s1.store_id,
             s1.title_id,
             s2.qty
    FROM     sales s1
    JOIN     sales_projections s2 ON s1.store_id = s2.store_id
       AND   s1.title_id = s2.title_id
    ORDER BY s1.store_id, s2.title_id
WHERE-Klausel
Die WHERE-Klausel ist ein extrem mächtiger Bestandteil der SELECT-Anweisung. Sie enthält die meisten der Suchbedingungen, mit denen unerwünschte Daten aus der Abfrage entfernt werden. Die restlichen Suchbedingungen sind dann Gegenstand der weiter unten erläuterten HAVING-Klausel.
Eine schlecht geschriebene WHERE-Klausel kann eine ansonsten schöne SELECT-Anweisung ruinieren. Setzen Sie sich daher eingehend mit der WHERE-Klausel auseinander. Nachfolgend ein Beispiel für eine typische Abfrage und eine mehrteilige WHERE-Klausel:
    SELECT   a.au_lname,
             a.au_fname,
             t2.title,
             convert(char,t2.pubdate)
    FROM     authors a
    JOIN     titleauthor t1 ON a.au_id = t1.au_id
    JOIN     titles t2 ON t1.title_id = t2.title_id
    WHERE    (t2.type = 'business' OR t2.type = 'popular_comp')
      AND    t2.advance > $5500
    ORDER BY t2.title
Beachten Sie, dass die runden Klammern die Reihenfolge beeinflussen, in der die WHERE-Kriterien verarbeitet werden (Rangfolge der Operatoren).
Mit der Standard-Sortierreihenfolge wird festgelegt, wie die WHERE-Klausel die Ergebnismengen für eine Abfrage abruft. In Microsoft SQL Server zum Beispiel ist standardmäßig dictionary-order und case-insensitive eingestellt, was bewirkt, dass keine Unterscheidung zwischen "Smith", "smith" und "SMITH" getroffen wird. In Oracle dagegen wird dictionary-order und case-sensitive verwendet, so dass die Werte "Smith", "smith" und "SMITH" nicht gleich sind.
Die WHERE-Klausel bietet noch weitere spezielle Funktionen, die über dieses Beispiel hinausgehen. In Tabelle 3.9 finden Sie eine Zusammenfassung der gebräuchlichsten Funktionen der WHERE-Klausel.
Suchbedingung in Kurzform | Syntax | Beispiel | Verwendung und Beschreibung
--- | --- | --- | ---
Einfache Boolesche Abfrage |
    WHERE [NOT] expression
    comparison_operator  expression
    SELECT au_id
    FROM   authors
    WHERE  au_id = '172-32-1176'

    SELECT au_id
    FROM   authors
    WHERE  au_lname NOT LIKE 'John%'
| Die Operatoren <, >, <>, >=, <= und = können für den Vergleich von Ausdrücken verwendet werden. Es gibt auch eine Reihe speziellerer Vergleichsoperatoren wie LIKE, die weiter unten in dieser Tabelle beschrieben sind. Mit dem Schlüsselwort NOT wird das Gegenteil jeder Booleschen Bedingung abgefragt, basierend auf den normalen Operatoren <, >, <>, >=, <= und = sowie den speziellen Operatoren wie LIKE, NULL, BETWEEN, IN, EXISTS, ANY und ALL.
Mehrfache Suchbedingungen |
    WHERE [NOT] expression
    comparison_operator expression
    {AND | OR}
    expression comparison_operator
    expression
    SELECT au_id
    FROM   authors
    WHERE  au_id = '172-32-1176'
      AND  au_lname = 'White'
| AND fasst mehrere Suchbedingungen zusammen und gibt Ergebnisse zurück, wenn beide Bedingungen wahr sind. AND hat Vorrang vor anderen Operatoren.Darüber hinaus lässt sich mit runden Klammern in der WHERE-Klausel die Rangfolge der Operatoren beeinflussen. OR fasst mehrere Bedingungen zusammen und gibt Ergebnisse zurück, wenn mindestens eine der beiden Bedingungen wahr ist. OR hat eine niedrigere Priorität als AND.
NULL-Abfrage |
    WHERE [NOT] column_name IS [NOT]
    NULL
    SELECT *
    FROM   titles
    WHERE  price IS NULL
| Mit IS NULL und IS NOT NULL wird der Abfrage mitgeteilt, dass sie Nullwerte (bzw. alle Werte außer Null) suchen soll.
JOIN-Abfrage |
    WHERE [NOT] column_value(s)
    [(+)]=[(+)] column_value(s)
Oder
    WHERE [NOT] column_value(s)
    [*]=[*] column_value(s)
    SELECT a.au_lname,
           a.au_fname,
           t2.title
    FROM  authors a,
          titleauthor t1,
          titles t2
    WHERE a.au_id = t1.au_id
      AND t1.title_id = t2.title_id
    ORDER BY t2.title
| JOIN-Abfragen können durch Auswerten des gemeinsamen Schlüssels zweier oder mehrerer Tabellen durchgeführt werden. Outer Joins werden in PostgreSQL durchgeführt, indem die Seite, auf der alle Datensätze abgerufen werden sollen, mit einem Sternchen gekennzeichnet wird. In Oracle geschieht dies durch Hinzufügen des eingeklammerten Pluszeichens (+) auf der Seite, auf der Nullwerte zulässig sind (ist also im Prinzip das Gegenteil der Sternchen-Methode). Nähere Informationen dazu finden Sie im vorherigen Abschnitt über JOINs.
LIKE-Abfrage |
    WHERE [NOT] column_name [NOT]
    LIKE 'match_string'
    /* get any phone number starting with 415 */
    SELECT * FROM authors
    WHERE phone LIKE '415%'
| Bei Angabe von LIKE wird eine Mustersuche anhand des Strings in Anführungszeichen durchgeführt. Die Wildcard-Symbole sind unter LIKE beschrieben.
EXISTS-Abfrage |
    WHERE [NOT] EXISTS (subquery)
    SELECT p1.pub_name
    FROM publishers p1
    WHERE EXISTS
        (SELECT *
        FROM titles t1
        WHERE pub_id =p1.pub_id
          AND type =
          'psychology')
| EXISTS wird immer zusammen mit einer Unterabfrage verwendet; anstatt Daten zurückzugeben, ist die Unterabfrage ein Boolescher Test, ob die Daten existieren. In diesem Beispiel werden alle Herausgeber von Psychologiebüchern zurückgegeben.
BETWEEN-Bereichsabfrage |
    WHERE [NOT] expression [NOT] BETWEEN expression AND expression
    SELECT *
    FROM titles
    WHERE ytd_sales BETWEEN 4000 AND 9000
| Mit BETWEEN wird eine inklusive Bereichsüberprüfung durchgeführt. Dies ist das gleiche wie WHERE (ausdruck>= x AND ausdruck<= y).
IN-Bereichsabfrage |
    WHERE [NOT] expression [NOT] IN
    (value_list | subquery)
    SELECT *
    FROM stores
    WHERE state IN ('WA','IL','NY')

    SELECT *
    FROM stores
    WHERE stor_id IN
      (SELECT stor_id
      FROM sales
      WHERE ord_date LIKE
      'Oct%')
| IN gibt eine Ergebnismenge zurück, die entweder mit einer Liste von Werten übereinstimmt oder der Ergebnismenge der äußeren Abfrage entspricht, deren Wert mit den von der Unterabfrage zurückgegebenen Werten übereinstimmt. Die value_list bzw. Unterabfrage sollte in Klammern gesetzt werden.
SOME | ALL-Bereichsabfrage |
    WHERE [NOT] expression
    comparison_operator
    {[ANY | SOME] | ALL} (subquery)
    -- Duplizierung der Funktionalität von IN
    SELECT au_lname,
           au_fname
    FROM   authors
    WHERE city = ANY
        (SELECT city
         FROM   publishers)
    -- Duplizierung der Funktionalität von NOT IN
    SELECT au_lname,
           au_fname
    FROM authors
    WHERE city <> ALL
        (SELECT city
         FROM   publishers)
    /* to find the titles that got an
    advance larger than the minimum
    advance amount paid New Moon Books*/
    SELECT title
    FROM   titles
    WHERE  advance > ANY
        (SELECT  advance
         FROM publishers,
          titles
         WHERE titles.pub_id =
           publishers.pub_id
         AND pub_name = 'New
           Moon Books')
| ALL und SOME werden immer zusammen mit einer Unterabfrage und einem Vergleichsoperator wie <, >, <>, >=, or <= verwendet. Eine Abfrage vom Typ ALL ergibt entweder TRUE oder FALSE, wenn alle von der Unterabfrage abgerufenen Werte mit dem Wert der WHERE-Klausel (oder der HAVING-Klausel) übereinstimmen oder wenn die Unterabfrage keine Zeilen der äußeren Anweisung zurückgibt.SOME hat dieselbe Funktion wie EXISTS. Dieser Operator funktioniert wie ALL, ergibt allerdings TRUE, wenn mindestens einer der von der Unterabfrage zurückgegebenen Werte die Vergleichsbedingungen in der WHERE-Klausel der äußeren Anweisung erfüllt.
Wie in Tabelle 3.9, erwähnt, können mit Wildcard-Zeichen die Suchoptionen erweitert werden, insbesondere mit dem LIKE-Operator. Unter LIKE finden Sie nähere Informationen über die einzelnen Wildcard-Operationen.
Aggregate und die GROUP BY-Klausel
Die GROUP BY-Klausel (und die HAVING-Klausel) wird nur in Abfragen gebraucht, die Aggregatfunktionen verwenden (siehe oben in diesem Kapitel). Abfragen mit Aggregatfunktionen liefern vielfältige zusammenfassende Informationen. Zu den gebräuchlichsten Aggregatfunktionen gehören:
AVG gibt den Durchschnitt aller Nicht-NULL-Werte in der oder den angegebenen Spalten zurück. COUNT zählt, wie oft Nicht-NULL-Werte in der oder den angegebenen Spalten vorkommen. COUNT DISTINCT zählt, wie oft unterschiedliche Nicht-NULL-Werte in der oder den angegebenen Spalten vorkommen. COUNT(*) zählt alle Datensätze in der Tabelle. MAX gibt den höchsten Nicht-NULL-Wert in der oder den angegebenen Spalten zurück. MIN gibt den niedrigsten Nicht-NULL-Wert in der oder den angegebenen Spalten zurück. SUM summiert alle Nicht-NULL-Werte in der oder den angegebenen Spalten.
Die Aggregatfunktionen können nicht bei allen Datentypen eingesetzt werden. Nur COUNT und COUNT DISTINCT können in Spalten eines beliebigen Datentyps verwendet werden. MIN und MAX funktionieren bei numerischen Spalten (beliebigen Typs) sowie bei Datums- und Zeichenspalten. SUM und AVG können nur bei numerischen Spaltentypen angewendet werden.
Wenn Aggregatfunktionen für Spalten mit Nullwerten ausgeführt werden müssen, verwenden Sie die Funktion ISNULL( ) in SQL Server bzw. die Funktion NVL in Oracle, um den Nullspalten einen Wert zuzuweisen.
Abfragen, die einen einzelnen Wert zurückgeben, heißen skalare Aggregate . Bei skalaren Aggregaten ist keine GROUP BY-Klausel erforderlich. Beispiel:
    --Abfrage
    SELECT AVG(price)
    FROM titles

    --Ergebnisse
    14.77
Abfragen, die sowohl reguläre Spaltenwerte als auch Aggregatfunktionen zurückgeben, werden häufig als Vektoraggregate bezeichnet. Vektoraggregate verwenden die GROUP BY-Klausel und geben eine oder mehrere Zeilen zurück. Es gibt einige Regeln, die bei der Verwendung von GROUP BY beachtet werden sollten:
Positionieren Sie die GROUP BY-Klausel an der richtigen Stelle – nach der WHERE-Klausel und vor der ORDER BY-Klausel. Beziehen Sie alle Nichtaggregatspalten in die GROUP BY-Klausel mit ein. Verwenden Sie keine Spaltenaliasnamen in der GROUP BY-Klausel; Tabellenaliasnamen dagegen sind erlaubt.
Angenommen, Sie möchten wissen, wie viele Mitarbeiter im Unternehmen eine bestimmte Arbeit verrichten:
    --Abfrage
    SELECT   j.job_desc AS "Job Description",
             COUNT(e.job_id) AS "Nbr in Job"
    FROM     employee e
    JOIN     jobs j ON e.job_id = j.job_id
    GROUP BY j.job_desc

    --Ergebnisse
    Job Description                                    Nbr in Job
    -------------------------------------------------- -----------
    Acquisitions Manager                               4
    Business Operations Manager                        1
    Chief Executive Officer                            1
    Chief Financial Officer                            1
    Designer                                           3
    Editor                                             3
    Managing Editor                                    4
    Marketing Manager                                  4
    Operations Manager                                 4
    Productions Manager                                4
    Public Relations Manager                           4
    Publisher                                          7
    Sales Representative                               3
HAVING-Klausel
Mit der HAVING-Klausel werden nach dem Ergebnis der GROUP BY-Klausel Suchbedingungen hinzugefügt. HAVING hat keine Auswirkung auf die Zeilen, aus denen die Aggregate berechnet werden, sondern nur auf die Zeilen, die von der Abfrage zurückgegeben werden.
HAVING funktioniert in ähnlicher Weise wie die WHERE-Klausel. Die HAVING-Klausel verwendet genau dieselben Suchbedingungen wie die WHERE-Klausel, die in Tabelle 3.9näher beschrieben ist.
Im folgenden Beispiel soll herausgefunden werden, welche Arbeit von mehr als drei Personen verrichtet wird:
    --Abfrage
    SELECT   j.job_desc "Job Description",
             COUNT(e.job_id) "Nbr in Job"
    FROM     employee e
    JOIN     jobs j ON e.job_id = j.job_id
    GROUP BY j.job_desc
    HAVING   COUNT(e.job_id) > 3

    --Ergebnisse
    Job Description                                    Nbr in Job
    -------------------------------------------------- -----------
    Acquisitions Manager                               4
    Managing Editor                                    4
    Marketing Manager                                  4
    Operations Manager                                 4
    Productions Manager                                4
    Public Relations Manager                           4
    Publisher                                          7
HAVING sollte nicht zum Löschen von Zeilen verwendet werden, die auch mit der WHERE-Klausel entfernt werden können. HAVING-Bedingungen sollten sich immer nur auf aggregierte Werte beziehen.
ORDER BY-Klausel
Eine Ergebnismenge kann mit der ORDER BY-Klausel entsprechend der Sortierreihenfolge der Datenbank sortiert werden. Die Ergebnismenge kann in aufsteigender (ASC) oder absteigender (DESC) Reihenfolge sortiert werden. (Standard ist die aufsteigende Reihenfolge.) Beispiel:
    --ABFRAGE
    SELECT   e.emp_id "Emp ID",
             rtrim(e.fname) || " " || rtrim(e.lname) "Name",
             j.job_desc "Job Desc"
    FROM     employee e,
             jobs j
    WHERE    e.job_id = j.job_id
      AND    j.job_desc = 'Acquisitions Manager'
    ORDER BY e.fname DESC,
             e.lname ASC

    --ERGEBNISSE
    Emp ID    Name                           Job Desc
    --------- ------------------------------ --------------------
    M-R38834F Martine Rancé                  Acquisitions Manager
    MAS70474F Margaret Smith                 Acquisitions Manager
    KJJ92907F Karla Jablonski                Acquisitions Manager
    GHT50241M Gary Thomas                    Acquisitions Manager
Sobald die Ergebnismenge anhand der Suchbedingungen verringert wurde, wird sie nach den Nachnamen der Autoren in absteigender Reihenfolge sortiert. Bei gleichen Nachnamen werden die Vornamen der Autoren in aufsteigender Reihenfolge sortiert.
Alle hier besprochenen Implementierungen ermöglichen auch die Verwendung von Ordinalpositionen in der ORDER_BY-Klausel. Die Reihenfolge der Ergebnismenge kann durch Angabe der Nummer der Spaltenposition statt dem Spalten- oder Aliasnamen festgelegt werden. So können Sie beispielsweise die Reihenfolge nach au_id, au_ fname und schließlich nach au_lname sortieren:
    SELECT au_fname, au_lname, au_id
    FROM authors
    ORDER BY 3, 1, 2
Im Allgemeinen wird die ORDER BY-Klausel verwendet, um die Sortierreihenfolge der Ergebnismenge einer Abfrage zu bestimmen. Wenn keine ORDER BY-Klausel angegeben ist, geben die meisten Implementierungen die Daten entsprechend ihrer physischen Anordnung in der Tabelle oder entsprechend der Sortierreihenfolge des von der Abfrage verwendeten Index zurück. Das kann zu Problemen führen, wenn der Index oder die physische Sortierreihenfolge der Daten einmal geändert werden sollte. Geben Sie daher immer explizit die Reihenfolge an.
Microsoft SQL Server: Syntax und Variationen
Microsoft bietet verschiedene Varianten der SELECT-Anweisung; dazu gehören Optimiererhinweise, die INTO-Klausel, die TOP-Klausel, GROUP BY-Variationen, COMPUTE und WITH OPTIONS.
SELECT . . . INTO
    SELECT select_list
    INTO   new_table_name
    FROM   table_source
    WHERE  clause
SELECT . . . INTO ist eine heftig diskutierte Befehlsoption, die es nur in SQL Server gibt. Mit dem Befehl SELECT . . . INTO lassen sich schnell aus anderen Tabellen abgefragte Zeilen und Spalten in einer nicht protokollierten Operation in eine neue Tabelle kopieren.
Im folgenden Beispiel wird mit Hilfe von SELECT . . . INTO eine Tabelle namens non_mgr_employees erstellt. Die Tabelle enthält die emp_id, den Vornamen und den Nachnamen aller Mitarbeiter aus der Tabelle employee, die keine Führungsposition innehaben, zusammen mit den jeweiligen Jobbeschreibungen aus der Tabelle jobs:
    --ABFRAGE
    SELECT   e.emp_id "emp_id",
             convert(char(25),rtrim(e.fname) + " " + rtrim(e.lname)) "name",
             substring(j.job_desc,1,30) "job_desc"
    INTO     non_mgr_employee
    FROM     employee e
        JOIN jobs AS j ON e.job_id = j.job_id
    WHERE    j.job_desc NOT LIKE '%MANAG%'
    ORDER BY 2,3,1
Die neu erstellte und geladene Tabelle non_mgr_employee kann nun abgefragt werden. Mit einer einfachen Abfrage werden folgende Daten zurückgegeben:
    --ABFRAGE
    SELECT   emp_id,
             name,
             job_desc
    FROM     non_mgr_emp
    ORDER BY 3,2,1

    --ERGEBNISSE
    emp_id    name                      job_desc
    --------- ------------------------- ------------------------------
    PTC11962M Philip Cramer             Chief Executive Officer
    F-C16315M Francisco Chang           Chief Financial Officer
    <...edited for brevity...>
    PMA42628M Paolo Accorti             Sales Representative
    TPO55093M Timothy O'Rourke          Sales Representative
SELECT . . . INTO sollte nur in Entwicklungscode und Nicht-Produktionscode verwendet werden.
TOP-Klausel
Die Syntax der TOP-Klausel sieht folgendermaßen aus:
    SELECT [TOP n [PERCENT] [WITH TIES]] select list
    FROM table_name
Dieser Befehl gibt an, dass nur die ersten n Zeilen in der Ergebnismenge der Abfrage berücksichtigt werden sollen. Wenn zusätzlich PERCENT angegeben wird, werden nur die ersten n Prozent der Zeilen abgerufen. Das Schlüsselwort WITH TIES kann nur bei Abfragen mit der ORDER BY-Klausel verwendet werden. Es gibt an, dass zusätzliche Zeilen aus der Basisergebnismenge mit demselben Wert in der ORDER BY-Klausel zurückgegeben werden und als letzte in den TOP-Zeilen erscheinen.
GROUP BY-Variationen
GROUP BY in Microsoft SQL Server unterstützt die Variationen ALL, WITH CUBE und WITH ROLLUP:
    [ GROUP BY [ALL] group_by_expression [,...n]
    [ WITH { CUBE | ROLLUP } ] ]
Mit ALL werden alle Gruppen in die Ergebnismenge aufgenommen, auch diejenigen, in denen es keine Zeilen gibt, die mit den Filtern in der WHERE-Klausel übereinstimmen. ALL kann nicht zusammen mit CUBE oder ROLLUP verwendet werden. CUBE gibt an, dass für jede Kombination aus Gruppe und Untergruppe zusätzliche Zusammenfassungszeilen in die Ergebnismenge aufgenommen werden sollen. ROLLUP funktioniert ähnlich wie CUBE, allerdings werden hier Gruppen in zusammengefasster hierarchischer Reihenfolge zurückgegeben, jeweils von der niedrigsten zur höchsten Ebene in der Gruppe.
COMPUTE-Klausel
Mit der COMPUTE-Klausel werden Summen erzeugt, die als zusätzliche Zusammenfassungsspalten am Ende der Ergebnismenge erscheinen. Mit der Klausel COMPUTE BY werden Gruppenwechsel und Zwischensummen in der Ergebnismenge erzeugt. COMPUTE BY und COMPUTE können beide in derselben Abfrage verwendet werden:
    [ COMPUTE { { AVG | COUNT | MAX | MIN | STDEV | STDEVP |VAR | VARP | SUM }
    (expression) } [,...n]
    [ BY expression [,...n] ] ]
Die Argumente (AVG, COUNT, MAX, MIN, STDEV, STDEVP, VAR, VARP, SUM) geben die von der COMPUTE-Klausel durchzuführende Aggregation an. Der Wert expression ist in der Regel ein Spaltenname. Der Wert BY expression kann eine oder mehrere Spalten enthalten, die in der ORDER BY-Klausel der Abfragen stehen. COMPUTE erscheint in der Abfrage nach der ORDER BY-Klausel.
OPTION-Klausel
Die OPTION-Klausel ist die letzte Klausel, die in einer Microsoft SQL Server-Abfrage steht. Sie gibt an, dass in der gesamten Abfrage ein Abfragehinweis verwendet werden soll. Abfragehinweise stellen eine nicht im ANSI-Standard festgelegte Methode dar, mit der Sie die Standardverarbeitung einer Abfrage ändern können. Abfragehinweise und die vollständige Syntax und Verwendung von OPTION gehen über den Umfang dieses Buches hinaus. Nähere Informationen dazu finden Sie in der SQL Server-Dokumentation.
MySQL: Syntax und Variationen
    SELECT [STRAIGHT_JOIN][SQL_SMALL_RESULT][SQL_BIG_RESULT][HIGH_PRIORITY]
    [INTO {OUTFILE | DUMPFILE} 'file_name' options]
    FROM...
    JOIN...
    [LIMIT [[offset_record,] number_of_rows]];
Zu den MySQL-Erweiterungen gehören Änderungen am Standard-SELECT-Schlüsselwort, teilweise JOIN-Unterstützung, die LIMIT-Klausel und die PROCEDURE-Klausel.
Die erste Erweiterung der Standard-SELECT-Klausel ist STRAIGHT_ JOIN. STRAIGHT_JOIN zwingt den Optimierer, Tabellen in der Reihenfolge, in der sie in der FROM-Klausel erscheinen, zu verknüpfen. SQL_SMALL_RESULT und SQL_BIG_RESULT können verwendet werden, wenn die Abfrage eine GROUP BY-oder DISTINCT-Klausel enthält. Sie teilen dem Optimierer mit, dass eine kleinere bzw. eine größere Ergebnismenge erzeugt werden soll. Da MySQL eine temporäre Tabelle anlegt, wenn eine Abfrage eine DISTINCT- oder GROUP BY-Klausel enthält, wird MySQL mit diesen optionalen Klauseln aufgefordert, entweder eine schnelle temporäre Tabelle im Arbeitsspeicher (bei SQL_SMALL_RESULT) oder eine langsamere, festplattenbasierte temporäre Tabelle (bei SQL_BIG_RESULT) zu erstellen, um die Arbeitstabelle zu verarbeiten. HIGH_PRIORITY gibt der Abfrage eine höhere Priorität als Anweisungen, die Daten in der Tabelle modifizieren. Diese Option sollte nur bei speziellen Abfragen, die schnell durchgeführt werden müssen, verwendet werden. Mit der LIMIT-Klausel wird die Anzahl der Zeilen, die von der Abfrage zurückgegeben werden, wie angegeben beschränkt (Beginn: offset_record; Anzahl von Datensätzen: returning number_of_rows). Wenn nur ein Wert angegeben wird, wird dieser als Anzahl der zurückzugebenden Datensätze interpretiert, und für offset_record wird vom Standardwert 0 ausgegangen.
Mit der Klausel SELECT . . . INTO OUTFILE 'file_name' wird die Ergebnismenge der Abfrage in eine Datei im Dateisystem des Hosts geschrieben. Es darf noch keine Datei mit diesem Namen geben. Mit der Syntax SELECT . . . INTO DUMPFILE wird eine einzelne lange Datenzeile ohne Spaltenenden, Zeilenenden oder Steuerzeichen geschrieben. Diese Option wird meistens für BLOB-Dateien verwendet.
MySQL unterstützt nur die folgenden Typen der JOIN-Syntax:
    [CROSS JOIN]
    INNER JOIN
    STRAIGHT_JOIN
    LEFT [OUTER] JOIN
    NATURAL LEFT [OUTER] JOIN
Oracle: Syntax und Variationen
    SELECT {[ALL] [DISTINCT] | [UNIQUE]}...
    {columns_and_expressions_list} [,...n] AS alias
    [INTO {variable[,...n] | record}]
    FROM {[table_name [@database_link]| view_name | snapshot_name]
       | subquery [WITH {READ ONLY | CHECK OPTION [CONSTRAINT constraint_name]}]
       | TABLE {(nested_tbl_column)}
          [PARTITION {partition_name}]
          [SUBPARTITION {subpartition_name}
             [SAMPLE [BLOCK] [sample_percentage]}
    WHERE
    [[START WITH clause] CONNECT BY clause]
    GROUP BY...
    [ORDER BY... [NULLS FIRST | NULLS LAST] |
     FOR UPDATE [OF [schema.]table[,...n]] [NOWAIT] ]
Oracle bietet verschiedene Erweiterungen der SELECT-Anweisung, mit denen zusätzliche Serverfunktionalitäten unterstützt werden. Da zum Beispiel sowohl verschachtelte als auch partitionierte Tabellen erstellt werden können (siehe CREATE TABLE), ermöglicht die SELECT-Anweisung Abfragen aus diesen speziell benannten Strukturen. (Die Klausel PARTITION ist nicht erforderlich, wenn die Abfrage von der Standardpartition aus erfolgt.)
Mit der Klausel SAMPLE wird Oracle aufgefordert, Datensätze aus einer zufälligen Auswahl von Zeilen in der Ergebnismenge und nicht aus der gesamten Tabelle auszuwählen. Die Klausel SAMPLE BLOCK fordert Oracle auf, Block-Sampling an Stelle von Zeilen-Sampling zu verwenden. Mit dem Sampling-Prozentsatz wird Oracle die gesamte Block- oder Zeilenzahl mitgeteilt, die in der Ausgangsmenge berücksichtigt werden soll. Dieser Wert kann zwischen 0,000001 und 99 liegen. Sampling kann nur bei Abfragen verwendet werden, die auf einer einzigen Tabelle basieren.
Die Syntax SELECT . . . INTO kann nur in PL/SQL-Code verwendet werden und ermöglicht es der SELECT-Anweisung, Variablen Werte zuzuweisen.
Bei der Abfrage einer verschachtelten Tabelle muss die Klausel FROM TABLE nested_table_column verwendet werden. Die Klausel @database_link ermöglicht der Abfrage den Zugriff auf Tabellen, die in anderen Datenbanken oder auf anderen Servern gespeichert sind, sofern diese Datenbanken und Server als db_link deklariert wurden (nähere Informationen zu db_link finden Sie in der Dokumentation des Herstellers).
Mit den Optionen NULL FIRST und NULL LAST der Klausel ORDER BY wird angegeben, dass Zeilen, die Nullwerte enthalten, in der Ergebnismenge an den Anfang bzw. an das Ende gestellt werden sollen.
Oracle ermöglicht die Angabe von Ergebnismengen in einer hierarchischen Reihenfolge. Diese so genannten hierarchischen Abfragen enthalten eine Reihe von Regeln und besondere Verhaltensweisen. Eine vollständige Beschreibung der Regeln für diesen Abfragetyp finden Sie in der Dokumentation des Herstellers. Die Klausel START WITH ist elementarer Bestandteil von hierarchischen Abfragen und gibt die Root-Zeilen einer Hierarchie an. Mit der Klausel CONNECT BY wird die Beziehung zwischen Parent- und Child-Zeilen in der Hierarchie beschrieben.
Mit der Klausel FOR UPDATE OF wird ausschließlich die von der Abfrage zurückgegebene Zeile gesperrt. Unmittelbar danach sollte ein UPDATE . . . WHERE-, COMMIT- oder ROLLBACK-Befehl kommen. Bei Angabe der Option NOWAIT wartet Oracle nicht, wenn der Datensatz bereits gesperrt ist, sondern beendet die Abfrage und kehrt sofort zum Benutzer zurück.
PostgreSQL: Syntax und Variationen
    SELECT...
    [INTO [TEMPORARY | TEMP] [TABLE] new_table_name]
    FROM...
    WHERE...
    [FOR UPDATE [OF class_name[,...n]]
    [LIMIT {count | ALL} [offset [,number_of_records]] ]
PostgreSQL ermöglicht die Erstellung einer neuen Tabelle mit der Syntax SELECT . . . INTO, die im Prinzip genauso funktioniert wie die gleichnamige Syntax in Microsoft SQL Server. Mit der Klausel FOR UPDATE können von der Abfrage zurückgegebene Zeilen exklusiv gesperrt werden. Darüber hinaus wird ähnlich wie bei MySQL die Klausel LIMIT unterstützt, mit der die Anzahl der von der Abfrage zurückgegebenen Zeilen beschränkt werden kann.

SET CONNECTION |
Die Anweisung SET CONNECTION bietet dem Benutzer die Möglichkeit, zwischen verschiedenen offenen Verbindungen zu einem oder mehreren Datenbankservern umzuschalten.
Hersteller | Befehl
--- | ---
SQL Server | Unterstützt, mit Einschränkungen
MySQL | Nicht unterstützt
Oracle | Nicht unterstützt
PostgreSQL | Nicht unterstützt
SQL99: Syntax und Beschreibung
    SET CONNECTION {DEFAULT | connection_name}
Dieser Befehl beendet keine Verbindung, sondern schaltet von der aktuellen Verbindung zu der in dem Befehl angegebenen Verbindung bzw. bei Verwendung der DEFAULT-Klausel zur aktuellen Verbindung um. Beim Umschalten zwischen Verbindungen ruht die alte Verbindung (ohne dass Änderungen festgeschrieben werden), während die neue Verbindung aktiviert wird.
Der Befehl CONNECT muss zum Herstellen einer neuen Verbindung, der Befehl DISCONNECT zum Trennen einer Verbindung verwendet werden.
Microsoft SQL Server: Syntax und Variationen
Microsoft SQL Server unterstützt SET CONNECTION nur in Embedded-SQL (ESQL), nicht aber im interaktiven Microsoft-Abfragewerkzeug SQL Query Analyzer. Es wird die volle SQL99-Syntax unterstützt.
Beispiel
Nachfolgend ein vollständiges ESQL-Programm in SQL Server, in dem CONNECT, DISCONNECT und SET CONNECTIONverwendet werden:
    EXEC SQL CONNECT TO chicago.pubs AS chicago1 USER sa;
    EXEC SQL CONNECT TO new_york.pubs AS new_york1 USER read-only;
    // opens connections to the servers named "chicago" //
    //   and "new_york"//

    EXEC SQL SET CONNECTION chicago1;
    EXEC SQL SELECT name FROM employee INTO :name;
    // sets the chicago1 connection as active and performs work //
    //   within that session //

    EXEC SQL SET CONNECTION new_york1;
    EXEC SQL SELECT name FROM employee INTO :name;
    // sets the new_york1 connection as active and performs work //
    //   within that session //

    EXEC SQL DISCONNECT ALL;
    // Terminates all sessions.  You could alternately use two //
    //   DISCONNECT commands, one for each named connection. //

SET ROLE |
Mit dem Befehl SET ROLE werden bestimmte Sicherheitsrollen für die aktuelle Sitzung aktiviert oder deaktiviert. Sitzungen werden mit der Anweisung CONNECT erstellt, Rollen dagegen mit der Anweisung CREATE ROLE.
Hersteller | Befehl
--- | ---
SQL Server | Nicht unterstützt
MySQL | Nicht unterstützt
Oracle | Unterstützt, mit Variationen
PostgreSQL | Nicht unterstützt
SQL99: Syntax und Beschreibung
    SET ROLE {NONE | role_name}
Die Sitzung wird mit der Anweisung CONNECT geöffnet. Nach Initiierung einer Benutzersitzung wird dieser Sitzung mit der Anweisung SET ROLE eine Reihe von rollenbezogenen Privilegien zugewiesen. Der Befehl SET ROLE kann nur außerhalb einer Transaktion ausgeführt werden.
Mit SET ROLE NONE wird der aktuellen Sitzung eine NULL-Rolle zugewiesen.
Wenn der gerade aktiven Benutzersitzung eine Rolle zugewiesen werden soll, kann ein Zeichenstring, eine Datenbankvariable oder eine Systemfunktion wie CURRENT_ROLE oder SYSTEM_ROLE verwendet werden. In allen Fällen muss der angegebene Wert ein gültiger Rollenname sein.
Oracle: Syntax und Variationen
    SET ROLE {role_name [IDENTIFIED BY password] [,...n]
    | [ALL [EXCEPT role_name [,...]]
    |  NONE;
Wenn ein Benutzer eine Verbindung aufbaut, weist Oracle ihm explizit rollenspezifische Zugriffsrechte zu. Die für die Sitzung geltende(n) Rolle(n) können mit dem Befehl SET ROLE geändert werden. Oracle verwendet den Initialisierungsparameter MAX_ENABLED_ROLES, um die maximale Anzahl an Rollen, die gleichzeitig geöffnet sein können, festzulegen.
Der angegebene role_name muss ein gültiger Rollenname sein, der bereits in Oracle vorhanden ist. Nicht angegebene Rollen stehen für die aktuelle Sitzung nicht zur Verfügung. Wenn der role_name über ein Kennwort verfügt, muss dieses in der Klausel IDENTIFIED BY password angegeben werden. Wenn Sie mehrere Rollen angeben möchten, müssen diese durch Kommas voneinander getrennt werden.
Mit der Anweisung SET ROLE ALL werden alle Rollen aktiviert, die der aktuellen Sitzung zugewiesen wurden, einschließlich der Rollen, die über andere Rollen gewährt wurden. Mit der Klausel EXCEPT können Sie bestimmte Rollen ausschließen. SET ROLE ALL kann nicht verwendet werden, wenn ein Kennwort angegeben werden muss. Auf Rollen mit Kennwörtern kann nur über die Anweisung SET ROLE role_name IDENTIFIED BY password zugegriffen werden.
Mit der Anweisung SET ROLE NONE werden alle Rollen deaktiviert, auch die Standardrolle.
Beispiele
So aktivieren Sie die Rollen read_only und updater mit dem Kennwort editor bzw. red_marker für die aktuelle Sitzung:
    SET ROLE read_only IDENTIFIED BY editor, updater IDENTIFIED BY red_marker;
So aktivieren Sie alle Rollen außer read_write:
    SET ROLE ALL EXCEPT read_write;

SET TIME ZONE |
Mit der Anweisung SET TIME ZONE wird die Zeitzone der aktuellen Sitzung geändert, wenn eine andere als die Standardzeitzone erforderlich ist.
Hersteller | Befehl
--- | ---
SQL Server | Nicht unterstützt
MySQL | Nicht unterstützt
Oracle | Nicht unterstützt
PostgreSQL | Unterstützt, mit Variationen
SQL99: Syntax und Beschreibung
    SET TIME ZONE {LOCAL | INTERVAL {+ | -}'00:00' HOUR TO MINUTE}
Wie die meisten SET-Befehle kann auch SET TIME ZONE nur außerhalb einer expliziten Transaktion verwendet werden. Mit der Klausel LOCAL wird die Zeitzone der aktuellen Sitzung auf die Standardzeitzone des Servers zurückgesetzt. Ansonsten kann auch ein Intervallwert angegeben werden, mit dem von der Standardzeit nach oben (mit +) oder unten (mit -) abgewichen wird.
PostgreSQL: Syntax und Variationen
    SET TIME ZONE {'timezone' | LOCAL | DEFAULT
    | INTERVAL {+ | -}'00:00' HOUR TO MINUTE};
In PostgreSQL kann die Zeitzone einer Sitzung mit LOCAL oder DEFAULT auf den Standardwert des Servers gesetzt werden.
Der für die Zeitzone anzugebende Wert hängt vom Betriebssystem ab. "PST8PDT" ist beispielsweise eine gültige Zeitzone für Kalifornien auf Linux-Systemen, während "Europe/Rome" eine gültige Zeitzone für Italien auf Linux- und anderen Systemen ist. Wenn eine ungültige Zeitzone angegeben wird, setzt der Befehl die Zeitzone auf Greenwich Mean Time (GMT).
Die Zeitzone kann auch als Intervall der Standardzeitzone des Servers angegeben werden.
Beispiele
Im folgenden Beispiel wird die Zeitzone gegenüber der aktuellen Standardzeitzone um drei Stunden nach vorne gesetzt:
    SET TIME ZONE INTERVAL +'03:00' HOUR TO MINUTE;
Als Nächstes wird die Zeitzone für die aktuelle Sitzung um viereinhalb Stunden zurück gesetzt:
    SET TIME ZONE INTERVAL -'04:30' HOUR TO MINUTE;
Zum Schluss wird die Zeitzone für die aktuelle Sitzung auf den Standardwert zurückgesetzt:
    SET TIME ZONE LOCAL;

SET TRANSACTION |
Mit der Anweisung SET TRANSACTION werden zahlreiche Eigenschaften einer Datenmodifikation wie Lesen/Schreiben oder die Isolationsebene gesteuert.
Hersteller | Befehl
--- | ---
SQL Server | Unterstützt, mit Variationen
MySQL | Nicht unterstützt
Oracle | Unterstützt, mit Einschränkungen
PostgreSQL | Unterstützt
SQL99: Syntax und Beschreibung
    SET [LOCAL] TRANSACTION { {READ ONLY | READ WRITE}[,...]
    | ISOLATION LEVEL
      {READ COMMITTED
      | READ UNCOMMITTED
      | REPEATABLE READ
      | SERIALIZABLE}[,...]
    | DIAGNOSTIC SIZE INT};
Dieser Befehl befindet sich außerhalb des Kontexts eines Transaktion und gilt für die nächste gültige Transaktion. Er kann mehr als eine Option enthalten, wobei die einzelnen Optionen durch Kommas voneinander zu trennen sind.
Mit dem Befehl LOCAL können die Transaktionseinstellungen nur auf den lokalen Server angewendet werden. Ansonsten gelten die Einstellungen unabhängig davon, wo die Transaktion ausgeführt wird. Dies ist eine neue Option in SQL99.
Eine Transaktion kann auch als READ ONLY oder READ WRITE konfiguriert werden. Die Klausel DIAGNOSTIC SIZE, gefolgt von einer Ganzzahl, gibt die Anzahl der Fehlermeldungen an, die für eine Transaktion aufgezeichnet werden sollen. Mit der Anweisung GET DIAGNOSTICS können diese Informationen abgerufen werden.
Mit der Klausel ISOLATION LEVEL werden verschiedene Eigenschaften des Transaktionsverhaltens im Hinblick auf gleichzeitig stattfindende Transaktionen gesteuert. Mit Isolationsebenen wird gesteuert, wie sich Transaktionen bei Dirty Reads, Non-Repeatable Reads und Phantom Records verhalten:
Dirty Reads Treten auf, wenn eine Transaktion die geänderten Datensätze einer anderen Transaktion liest, bevor diese beendet ist. Damit kann auch ein Datensatz modifiziert werden, der noch nicht in der Datenbank festgeschrieben wurde. Non-Repeatable Reads Treten auf, wenn eine Transaktion einen Datensatz liest, während eine andere ihn ändert. Wenn die erste Transaktion also versucht, den Datensatz nochmals zu lesen, findet sie diesen nicht. Phantom Records Treten auf, wenn eine Transaktion eine Gruppe von Datensätzen liest, die Daten durch eine Datenmodifikation aber so geändert werden, dass mehr Datensätze als zuvor zur ersten Transaktion gehören.
Die Einstellung der Isolationsebene hat Auswirkungen auf diese Anomalien, wie in Tabelle 3.10näher beschrieben.
Isolationsebene | Dirty Reads | Non-Repeatable Reads | Phantom Records
--- | --- | --- | ---
READ COMMITTED | Nein | Ja | Ja
READ UNCOMMITTED | Ja | Ja | Ja
REPEATABLE READ | Nein | Nein | Ja
SERIALIZABLE | Nein | Nein | Nein
In SQL99 ist SERIALIZABLE die Standardisolationsebene. READ WRITE-Transaktionen dürfen nicht READ UNCOMMITTED sein.
Microsoft SQL Server: Syntax und Variationen
    SET TRANSACTION ISOLATION LEVEL
    {READ COMMITTED
    | READ UNCOMMITTED
    | REPEATABLE READ
    | SERIALIZABLE}
READ COMMITTED ist die Standardeinstellung in SQL Server, im Gegensatz zu SERIALIZABLE in SQL99. Die Isolationsebene bleibt während der gesamten Dauer der Sitzung bestehen, und nicht nur für eine Transaktion wie in SQL99.
Oracle SQL Server: Syntax und Variationen
    SET TRANSACTION READ ONLY;
Oracle unterstützt nicht die gesamte Syntax der Anweisung SET TRANSACTION, und die Implementierung von READ ONLY weicht ebenfalls ab. Oracle unterstützt nur READ COMMITTED und SERIALIZABLE. READ COMMITTED ist das Standardverhalten. In Oracle wird mit diesem Befehl eine Transaktion auf der Isolationsebene SERIALIZABLE gestartet. Oracle lässt SELECT-Befehle nur zu, wenn die folgenden Befehle gesetzt sind: READ ONLY, ALTER SESSION, ALTER SYSTEM, LOCK TABLE und SET ROLE.
PostgreSQL: Syntax und Variationen
    SET TRANSACTION ISOLATION LEVEL {READ COMMITTED | SERIALIZABLE};
PostgreSQL unterstützt nicht die vollständige Syntax der Anweisung SET TRANSACTION. In PostgreSQL gibt SET TRANSACTION ISOLATION LEVEL READ COMMITTED an, dass die schreibgeschützten Zeilen der aktuellen Transaktion vor Beginn der Transaktion festgeschrieben wurden. Dies ist die Standardeinstellung. SERIALIZABLE, die ANSI-Standardisolationsebene, gibt an, dass die schreibgeschützten Zeilen der aktuellen Transaktion vor der ersten erste Datenmodifikation im Batch festgeschrieben wurden.

START TRANSACTION |
Neu in SQL99 ist die Anweisung START TRANSACTION, die alle Funktionen von SET TRANSACTION unterstützt und darüber hinaus auch eine neue Transaktion startet.
Hersteller | Befehl
--- | ---
SQL Server | Nicht unterstützt; siehe BEGIN TRAN weiter unten
MySQL | Nicht unterstützt
Oracle | Nicht unterstützt
PostgreSQL | Nicht unterstützt; siehe BEGIN TRAN weiter unten
SQL99: Syntax und Beschreibung
    START TRANSACTION { {READ ONLY | READ WRITE}[,...]
    | ISOLATION LEVEL
      {READ COMMITTED
      | READ UNCOMMITTED
      | REPEATABLE READ
      | SERIALIZABLE}[,...]
    | DIAGNOSTIC SIZE INT};
Der einzige Unterschied zwischen SET und START besteht darin, dass SET außerhalb der aktuellen Transaktion liegt, während START den Beginn einer neuen Transaktion kennzeichnet.
BEGIN TRANSACTION
Der Befehl BEGIN TRANSACTION hat eine ähnliche Funktion wie START TRANSACTION. Sowohl Microsoft SQL Server als auch PostgreSQL unterstützen BEGIN TRANSACTION, auch wenn sie sich hinsichtlich der Syntax ein wenig unterscheiden. Oracle unterstützt implizite, aber keine expliziten Transaktionen. MySQL unterstützt atomare Transaktionen überhaupt nicht. BEGIN TRANSACTION deklariert eine explizite Transaktion, legt aber keine Isolationsebenen fest.
Die Syntax in Microsoft SQL Server sieht folgendermaßen aus:
    BEGIN TRAN[SACTION] [transaction_name | @transaction_variable
    [WITH MARK [ 'log_description' ] ] ]
In Microsoft SQL Server können einer Transaktion Namen zugewiesen und Transaktionen mittels einer Variablen referenziert werden. Dies hat jedoch keine Auswirkungen auf die Funktionalität und erweitert diese auch nicht. Beim Verschachteln von Transaktionen sollte nur das äußerste BEGIN . . . COMMIT- oder BEGIN . . . ROLLBACK-Paar den Transaktionsnamen angeben (sofern ein solcher vorhanden ist).
Die Option WITH MARK sorgt dafür, dass die Transaktion im Ereignisprotokoll von SQL Server protokolliert wird. Mit WITH MARK 'log_description' können Sie einen zusätzlichen Beschreibungstext für das zu protokollierende Ereignis angeben.
Die Syntax in PostgreSQL sieht folgendermaßen aus:
    BEGIN [ WORK | TRANSACTION ]
PostgreSQL läuft normalerweise im Autocommit-Modus, in dem jede Datenmodifikation oder Abfrage eine eigene Transaktion bildet. PostgreSQL führt normalerweise am Ende der Transaktion ein implizites COMMIT oder ROLLBACK aus. Mit der Anweisung BEGIN kann das nächste COMMIT oder ROLLBACK explizit deklariert werden.
Verwenden Sie BEGIN immer zusammen mit COMMIT oder ROLLBACK. Ansonsten führt das DBMS den oder die Befehle erst dann aus, wenn es auf COMMIT oder ROLLBACK stößt. Dies kann möglicherweise zu riesigen Transaktionen mit unvorhersehbaren Auswirkungen auf die Daten führen.
Manuell kodierte Transaktionen sind in PostgreSQL wesentlich schneller als Autocommit-Transaktionen. SET TRANSACTION ISOLATION LEVEL sollte direkt nach der Anweisung BEGIN auf SERIALIZABLE gesetzt werden, um die Transaktionsisolation zu optimieren. Ein BEGIN . . . COMMIT -Block kann zahlreiche Datenmodifizierungsanweisungen enthalten (INSERT, UPDATE, DELETE). Bei Ausführung des Befehls COMMIT finden entweder alle Transaktionen oder überhaupt keine statt, je nachdem, ob der Befehl erfolgreich war oder fehlgeschlagen ist.
Beispiel
Im folgenden Beispiel werden die drei INSERT-Anweisungen als einzige Transaktion behandelt:
    BEGIN TRANSACTION
       INSERT INTO sales VALUES('7896','JR3435','Oct 28 2001',25,
       'Net 60','BU7832')

       INSERT INTO sales VALUES('7901','JR3435','Oct 28 2001',17,
       'Net 60','BU7832')

       INSERT INTO sales VALUES('7907','JR3435','Oct 28 2001',6,
       'Net 60','BU7832')

    COMMIT
    GO
Die gesamte Transaktionsgruppe würde jedoch fehlschlagen, wenn in einer der INSERT-Anweisungen eine Verletzung des Primärschlüssels auftreten würde.

TRUNCATE TABLE |
TRUNCATE TABLE ist eine Anweisung, die nicht zum ANSI-Standard gehört und mit der Sie alle Zeilen aus einer Tabelle löschen können, ohne dass das Löschen der einzelnen Zeilen protokolliert wird. Es handelt sich hierbei um einen sehr praktischen Befehl, mit dem schnell alle Datensätze einer Tabelle gelöscht werden können, ohne die Tabellenstruktur zu verändern und zu viel Platz in den Redo- oder Transaktionsprotokollen zu beanspruchen. Nachteil ist, dass dieser Befehl nicht rückgängig werden kann, da keine Protokollierung stattfindet.
Hersteller | Befehl
--- | ---
SQL Server | Unterstützt
MySQL | Nicht unterstützt
Oracle | Unterstützt
PostgreSQL | Unterstützt
SQL99: Syntax und Beschreibung
    TRUNCATE TABLE name
Die Anweisung TRUNCATE TABLE hat dieselbe Wirkung wie eine DELETE-Anweisung ohne WHERE-Klause. In beiden Fällen werden alle Zeilen einer Tabelle gelöscht. Es gibt jedoch zwei wichtige Unterschiede. TRUNCATE TABLE ist schneller und wird nicht protokolliert, kann also beim Auftreten eines Fehlers nicht rückgängig gemacht werden.
TRUNCATE TABLE aktiviert normalerweise keine Trigger und funktioniert nicht, wenn die betreffende Tabelle Fremdschlüssel enthält.
Beispiel
Im folgenden Beispiel werden alle Daten aus der Tabelle publishers gelöscht:
    TRUNCATE TABLE publishers
Oracle: Syntax und Variationen
    TRUNCATE { CLUSTER [owner.]cluster
       | TABLE [owner.]table [{PRESERVE | PURGE} SNAPSHOT LOG]}
    [{DROP | REUSE} STORAGE]
In Oracle kann eine Tabelle oder ein indizierter Cluster (aber kein Hash-Cluster) geleert werden.
Oracle bietet die Möglichkeit, beim Leeren einer Tabelle das Snapshot-Protokoll beizubehalten oder zu löschen, sofern für die Tabelle eines definiert ist. Bei Angabe von PRESERVE wird das Snapshot-Protokoll beibehalten, wenn die Master-Tabelle geleert wird, bei Angabe von PURGE wird es gelöscht.
Bei Verwendung der Klausel DROP STORAGE wird der von den gelöschten Zeilen zuvor beanspruchte Festplattenspeicher freigegeben. Bei Verwendung der Klausel REUSE STORAGE bleibt der Speicherplatz im Cluster oder in der Tabelle erhalten.
Hinweis zu Microsoft SQL Server und PostgreSQL
Beide Implementierungen unterstützen die SQL99-Standardsyntax.

UPDATE |
Mit dem Befehl UPDATE werden in einer Tabelle vorhandene Daten geändert.
Hersteller | Befehl
--- | ---
SQL Server | Unterstützt, mit Variationen
MySQL | Unterstützt, mit Variationen
Oracle | Unterstützt, mit Variationen
PostgreSQL | Unterstützt
SQL99: Syntax und Beschreibung
    UPDATE {table_name | view_name}
    SET {column_name | variable_name} = {DEFAULT | expression} [,...n]
    WHERE conditions
Wie die Anweisung DELETE wird auch der Befehl UPDATE selten ohne die Klausel WHERE verwendet, da sich die Anweisung sonst auf jede Zeile in der gesamten Tabelle auswirkt.
Es gilt als guter Stil, zuerst einen SELECT-Befehl mit der gleichen WHERE-Klausel und dann die eigentliche UPDATE-Anweisung anzugeben. Auf diese Weise werden alle Zeilen in der Ergebnismenge überprüft, bevor die UPDATE-Operation ausgeführt wird. Alle von SELECT zurückgegebenen Zeilen werden durch UPDATE modifiziert.
Beispiele
Eine einfache UPDATE-Anweisung ohne WHERE-Klausel sieht folgendermaßen aus:
    UPDATE authors
    SET contract = 0
Ohne WHERE-Klausel wird bei allen Autoren in der Tabelle authors der Vertragsstatus auf 0 gesetzt, was bedeutet, dass sie keinen Vertrag mehr haben. Werte können auch mathematisch mit einer UPDATE-Anweisung geändert werden:
    UPDATE titles
    SET price = price * 1.1
Mit dieser UPDATE-Anweisung würden alle Buchpreise um 10 % erhöht werden.
Wird einer UPDATE-Anweisung eine WHERE-Klausel hinzugefügt, werden nur bestimmte Datensätze in der Tabelle geändert:
    UPDATE titles
    SET    type  = 'pers_comp',
           price = (price * 1.15)
    WHERE  type  = 'popular_com'
Mit dieser Abfrage werden an jedem Datensatz des Typs 'popular_com' zwei Änderungen vorgenommen. Durch den Befehl wird der Preise um 15 % erhöht und der Typ in 'pers_comp' geändert.
Manchmal müssen Werte in einer Tabelle anhand von Werten in einer anderen Tabelle aktualisiert werden. Wenn zum Beispiel das Erscheinungsdatum aller Titel eines bestimmten Autors aktualisiert werden muss, muss zunächst mit Unterabfragen nach dem Autor und der Liste der Titel gesucht werden:
    UPDATE titles
    SET    pubdate = 'Jan 01 2002'
    WHERE  title_id IN
        (SELECT title_id
         FROM   titleauthor
         WHERE  au_id IN
             (SELECT au_id
              FROM   authors
              WHERE  au_lname = 'White'))
Microsoft: Syntax und Variationen
    UPDATE {table_name | view_name} [WITH (table_hint [,...n])]
    SET {column_name | variable_name} = {DEFAULT | expression | NULL} [,...n]
    [FROM {table [,...n]}]
    WHERE {conditions | CURRENT OF [GLOBAL] cursor_name}
    [OPTION (query_hint [,...n])]
Microsoft SQL Server ist in der Lage, sowohl Views als auch Tabellen zu aktualisieren. Mit den Klauseln WITH table_hint und OPTION können Optimiererhinweise auf Tabellen- und Abfrageebene deklariert werden. Optimiererhinweise ändern die Standardfunktionalität des Abfrageoptimierers. In der Herstellerdokumentation finden Sie eine umfassende Beschreibung der Optimiererhinweise.
Microsoft SQL Server unterstützt die Klausel FROM in einer UPDATE-Anweisung. Der Hauptvorteil dieser Variante besteht darin, dass sich mehrere Tabellen viel einfacher verknüpfen lassen. Im folgenden Beispiel werden Tabelle mit beiden Syntaxformaten verknüpft:
    -- ANSI-Format
    UPDATE titles
    SET    pubdate = GETDATE(  )
    WHERE  title_id IN
        (SELECT title_id
         FROM   titleauthor
         WHERE  au_id IN
             (SELECT au_id
              FROM   authors
              WHERE  au_lname = 'White'))

    -- Microsoft Transact-SQL-Format
    UPDATE  titles
    SET     pubdate = GETDATE(  )
    FROM    authors a,
            titleauthor t2
    WHERE   a.au_id     = t2.au_id
        AND t2.title_id = titles.title_id
        AND a.au_lname  = 'White'
Im Transact-SQL-Format müssen schlicht und einfach die drei Tabellen authors, titles und titleauthor miteinander verknüpft werden. Um dieselbe Operation im ANSI-Format auszuführen, muss zunächst die au_id in der Tabelle author gesucht und an die Tabelle titleauthors übergeben werden, wo die title_id identifiziert und dann an die Haupt-UPDATE-Anweisung weitergegeben werden muss.
Die Klausel WHERE CURRENT OF cursor_name teilt SQL Server bei Verwendung mit einem Cursor mit, dass nur der Datensatz, auf dem der Cursor gerade steht, aktualisiert werden soll. Der Cursor kann global oder lokal sein; darüber gibt das Schlüsselwort GLOBAL Auskunft.
Im folgenden Beispiel wird die Spalte state der ersten 10 Autoren in der Tabelle authors aktualisiert:
    UPDATE authors
    SET state = 'ZZ'
    FROM (SELECT TOP 10 * FROM authors ORDER BY au_lname) AS t1
    WHERE authors.au_id = t1.au_id
MySQL: Syntax und Variationen
    UPDATE [LOW PRIORITY] table_name
    SET {column_name | variable_name} = {DEFAULT | expression}
    WHERE conditions
    [LIMIT integer]
MySQL unterstützt den SQL99-Standard mit zwei Variationen: der Klausel LOW PRIORITY und der Klausel LIMIT. Die Klausel LOW PRIORITY fordert MySQL auf, die Ausführung der Anweisung UPDATE so lange hinauszuzögern, bis kein anderer Client mehr aus der Tabelle liest. Mit der Klausel LIMIT wird die UPDATE-Aktion auf die durch den Integerwert angegebene Anzahl an Zeilen beschränkt.
Oracle: Syntax und Variationen
    UPDATE [schema.]{view_name | snapshot_name
       | table_name [@database_link]
          {[PARTITION partition_name] | [SUBPARTITION subpartition_name]}
       | subquery [WITH {[READ ONLY]
          | [CHECK OPTION [CONSTRAINT constraint_name] ]
    SET {column [,...] = {expression [,...n] | subquery} | VALUE value}
    WHERE conditions | CURRENT OF cursor_name}
    RETURNING expression [,...n] INTO variable [,...n];
Die Oracle-Implementierung von UPDATE ermöglicht Aktualisierungen von Views, Snapshots und Tabellen in einem Schema, in dem dies erlaubt ist. Zu aktualisierende Tabellen können lokal sein oder über @dblink zur Verfügung stehen. Aktualisierungen werden immer in der Partition ausgeführt; der Befehl UPDATE unterstützt aber auch Updates in einer benannten PARTITION oder SUBPARTITION.
Bei der Aktualisierung anhand einer Unterabfrage steht auch die Klausel WITH zur Verfügung. Mit der Klausel WITH READ ONLY wird angegeben, dass die Unterabfrage nicht aktualisiert werden kann. Mit WITH CHECK OPTION wird Oracle aufgefordert, sämtliche Änderungen an der aktualisierten Tabelle zu verwerfen, die nicht in der Ergebnismenge der Unterabfrage erscheinen. Die Unterklausel CONSTRAINT weist Oracle an, Änderungen auf der Grundlage eines bestimmten Constraints weiter einzuschränken.
Die Klausel SET VALUE bietet dem Benutzer die Möglichkeit, für beliebige Tabellendatentypen den gesamten Zeilenwert festzulegen.
In Oracle gibt die Klausel WHERE CURRENT OF an, dass die UPDATE-Operation nur für den aktuellen Datensatz im Cursorkontext ausgeführt werden soll.
Mit RETURNING werden die von dem Befehl betroffenen Zeilen abgerufen. Beim Aktualisieren einer einzelnen Zeile werden die Werte der Zeile in PL/SQL-Variablen und Bindungsvariablen gespeichert. Beim Aktualisieren mehrerer Zeilen dagegen werden die Werte der Zeilen in Bindungs-Arrays gespeichert. Mit dem Schlüsselwort INTO wird festgelegt, dass die aktualisieren Werte in der Variablenliste gespeichert werden sollen.
Hinweise zu PostgreSQL
PostgreSQL unterstützt den SQL99-Standard. Eine umfassende Beschreibung des Befehls UPDATEfinden Sie oben.