<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de-x-formal">
	<id>https://glossar.hs-augsburg.de/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Jrdesign</id>
	<title>GlossarWiki - Benutzerbeiträge [de-formal]</title>
	<link rel="self" type="application/atom+xml" href="https://glossar.hs-augsburg.de/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Jrdesign"/>
	<link rel="alternate" type="text/html" href="https://glossar.hs-augsburg.de/Spezial:Beitr%C3%A4ge/Jrdesign"/>
	<updated>2026-07-17T15:05:10Z</updated>
	<subtitle>Benutzerbeiträge</subtitle>
	<generator>MediaWiki 1.43.3</generator>
	<entry>
		<id>https://glossar.hs-augsburg.de/w/index.php?title=SQLite_Foreign_Keys_erzwingen&amp;diff=12135</id>
		<title>SQLite Foreign Keys erzwingen</title>
		<link rel="alternate" type="text/html" href="https://glossar.hs-augsburg.de/w/index.php?title=SQLite_Foreign_Keys_erzwingen&amp;diff=12135"/>
		<updated>2008-07-14T22:26:01Z</updated>

		<summary type="html">&lt;p&gt;Jrdesign: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{In Bearbeitung}}&lt;br /&gt;
&lt;br /&gt;
=Problem =&lt;br /&gt;
SQLite unterstützt standartmäßig keine FOREIGN KEYS (Fremdschlüssel). Man kann diese zwar bei erstellen von Tabellen definieren, jedoch werden diese, wie gesagt, ignoriert.&lt;br /&gt;
&lt;br /&gt;
=Lösung =&lt;br /&gt;
Es ist möglich, SQLite dazu zu zwingen, Fremdschlüssel zu akzeptieren. Um das zu erreichen werden TRIGGER verwendet.&lt;br /&gt;
TRIGGER werden zum Einfügen, Löschen oder Ändern von Referenzdaten eingesetzt. Der TRIGGER wird ausgeführt, entweder bevor Änderungen an der Tabelle vorgenommen werden oder danach. TRIGGER können selbst Datensätze einfügen, ändern oder löschen und durch seine Ausführung weitere TRIGGER auslösen.&lt;br /&gt;
Nun zum Beispiel:&lt;br /&gt;
Nehmen wir an wie haben 2 Tabellen-Deklarationen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TABLE kontakt (&lt;br /&gt;
  id INTEGER NOT NULL PRIMARY KEY&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
CREATE TABLE termin (&lt;br /&gt;
  id INTEGER NOT NULL PRIMARY KEY,&lt;br /&gt;
  kontakt_id INTEGER NOT NULL&lt;br /&gt;
         CONSTRAINT fk_kontakt_id REFERENCES a(id) ON DELETE CASCADE&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Die Tabelle termin hat einen Fremdschlüssel, der auf die Primär-Schlüssel-Spalte in der kontakt-Tabelle verweist. Obwohl SQLite diese Syntax unterstützt, wird sie einfach ignoriert. Wenn man also eine Referenz erzwingen will, muss man TRIGGER erstellen, die das erledigen. Jede Bedingung muss einen eigenen TRIGGER haben, also einen für INSERT, DELETE und UPDATE.&lt;br /&gt;
Der INSERT-TRIGGER sieht folgendermaßen aus:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TRIGGER fki_termin_kontakt_id&lt;br /&gt;
BEFORE INSERT ON termin&lt;br /&gt;
FOR EACH ROW BEGIN &lt;br /&gt;
  SELECT CASE&lt;br /&gt;
     WHEN ((SELECT id FROM kontakt WHERE id = NEW.kontakt_id) IS NULL)&lt;br /&gt;
     THEN RAISE(ABORT, ‘insert on table &amp;quot;termin&amp;quot; violates foreign key‘ || ‘constraint &amp;quot;fk_kontakt_id&amp;quot;’)&lt;br /&gt;
  END;&lt;br /&gt;
END;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Wenn man die Fremdschlüssel-Spalte als NOT NULL definiert haben will/sollte, muss der INSERT-TRIGGER SELECT CASE ein wenig anders aussehen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TRIGGER fki_termin_kontakt_id&lt;br /&gt;
BEFORE INSERT ON termin&lt;br /&gt;
FOR EACH ROW BEGIN &lt;br /&gt;
   SELECT CASE&lt;br /&gt;
     WHEN ((new.kontakt_id IS NOT NULL)&lt;br /&gt;
           AND ((SELECT id FROM kontakt WHERE id = new.kontakt_id) IS NULL))&lt;br /&gt;
     THEN RAISE(ABORT, ‘insert on table &amp;quot;termin&amp;quot; violates foreign key‘ || ‘constraint &amp;quot;fk_kontakt_id&amp;quot;’)&lt;br /&gt;
  END;&lt;br /&gt;
END;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Das UPDATE-Statement ist fast identisch, wenn die Fremdschlüssel-Spalte NOT NULL ist:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TRIGGER fku_termin_kontakt_id&lt;br /&gt;
BEFORE UPDATE ON termin&lt;br /&gt;
FOR EACH ROW BEGIN &lt;br /&gt;
   SELECT CASE&lt;br /&gt;
     WHEN ((SELECT id FROM kontakt WHERE id = new.kontakt_id) IS NULL))&lt;br /&gt;
     THEN RAISE(ABORT, ‘update on table &amp;quot;termin&amp;quot; violates foreign key‘ || ‘constraint &amp;quot;fk_kontakt_id&amp;quot;’)&lt;br /&gt;
  END;&lt;br /&gt;
END;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
und wenn NULL erlaubt ist:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TRIGGER fku_termin_kontakt_id&lt;br /&gt;
BEFORE UPDATE ON termin&lt;br /&gt;
FOR EACH ROW BEGIN &lt;br /&gt;
   SELECT CASE&lt;br /&gt;
     WHEN ((new.kontakt_id IS NOT NULL)&lt;br /&gt;
           AND ((SELECT id FROM kontakt WHERE id = new.kontakt_id) IS NULL))&lt;br /&gt;
     THEN RAISE(ABORT, ‘update on table &amp;quot;termin&amp;quot; violates foreign key‘ || ‘constraint &amp;quot;fk_kontakt_id&amp;quot;’)&lt;br /&gt;
  END;&lt;br /&gt;
END;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Der DELETE TRIGGER wird zur Primär-Sclüssel-Tabelle hinzugefügt und überwacht DELETEs auf der kontakt-Tabelle:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TRIGGER fkd_termin_kontakt_id&lt;br /&gt;
BEFORE DELETE ON kontakt&lt;br /&gt;
FOR EACH ROW BEGIN &lt;br /&gt;
  SELECT CASE&lt;br /&gt;
    WHEN ((SELECT kontakt_id FROM termin WHERE kontakt_id = OLD.id) IS NOT NULL)&lt;br /&gt;
    THEN RAISE(ABORT, ‘delete on table &amp;quot;kontakt&amp;quot; violates foreign key‘ || ‘constraint &amp;quot;fk_kontakt_id&amp;quot;’)&lt;br /&gt;
  END;&lt;br /&gt;
END;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Dieser TRIGGER verhindert Löschvorgänge in der kontakt-Tabelle, wenn es Fremdschlüssel gibt, die auf die termin-Tabelle verweisen.&lt;br /&gt;
Eine weitere, etwas übersichtlichere Lösung:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TABLE departments (&lt;br /&gt;
    dept_id   INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,&lt;br /&gt;
    dept_name TEXT NOT NULL UNIQUE&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
CREATE TABLE employees (&lt;br /&gt;
    emp_id   INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,&lt;br /&gt;
    emp_name TEXT NOT NULL UNIQUE,&lt;br /&gt;
    dept_id  INTEGER NOT NULL,&lt;br /&gt;
    CONSTRAINT fkey_dept_id FOREIGN KEY (dept_id) REFERENCES departments (dept_id)&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
und die zugehörigen TRIGGER:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TRIGGER fkey_dept_id_ins BEFORE INSERT ON employees&lt;br /&gt;
  FOR EACH ROW&lt;br /&gt;
    BEGIN&lt;br /&gt;
      SELECT&lt;br /&gt;
        RAISE(ABORT, &lt;br /&gt;
             &#039;insert on table &amp;quot;employees&amp;quot; violates foreign key constraint &amp;quot;fkey_dept_id&amp;quot;&#039;)&lt;br /&gt;
          WHERE (SELECT dept_id FROM departments &lt;br /&gt;
                   WHERE dept_id = new.dept_id) IS NULL;&lt;br /&gt;
    END;&lt;br /&gt;
&lt;br /&gt;
CREATE TRIGGER fkey_dept_id_upd BEFORE UPDATE ON employees&lt;br /&gt;
  FOR EACH ROW&lt;br /&gt;
    BEGIN&lt;br /&gt;
      SELECT&lt;br /&gt;
        RAISE(ABORT,&lt;br /&gt;
             &#039;update on table &amp;quot;employees&amp;quot; violates foreign key constraint &amp;quot;fkey_dept_id&amp;quot;&#039;)&lt;br /&gt;
          WHERE (SELECT dept_id FROM departments &lt;br /&gt;
                   WHERE dept_id = new.dept_id) IS NULL;&lt;br /&gt;
    END;&lt;br /&gt;
&lt;br /&gt;
CREATE TRIGGER fkey_dept_id_del BEFORE DELETE ON departments&lt;br /&gt;
  FOR EACH ROW&lt;br /&gt;
    BEGIN&lt;br /&gt;
      SELECT&lt;br /&gt;
        RAISE(ABORT,&lt;br /&gt;
             &#039;delete on table &amp;quot;departments&amp;quot; violates foreign key constraint &amp;quot;fkey_dept_id&amp;quot; on &amp;quot;employees&amp;quot;&#039;)&lt;br /&gt;
          WHERE (SELECT dept_id from employees &lt;br /&gt;
                   WHERE dept_id = old.dept_id) IS NOT NULL;&lt;br /&gt;
    END;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Die INSERT-Befehle und SELECT-Ausgaben sehen dann so aus:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
INSERT INTO departments (dept_name) VALUES (&#039;Marketing&#039;);&lt;br /&gt;
INSERT INTO departments (dept_name) VALUES (&#039;MIS&#039;);&lt;br /&gt;
INSERT INTO departments (dept_name) VALUES (&#039;Accounting&#039;);&lt;br /&gt;
&lt;br /&gt;
SELECT * FROM departments;&lt;br /&gt;
&lt;br /&gt;
1|Marketing&lt;br /&gt;
2|MIS&lt;br /&gt;
3|Accounting&lt;br /&gt;
&lt;br /&gt;
INSERT INTO employees (emp_name, dept_id) VALUES (&#039;John&#039;, 1);&lt;br /&gt;
INSERT INTO employees (emp_name, dept_id) VALUES (&#039;Tim&#039;, 2);&lt;br /&gt;
INSERT INTO employees (emp_name, dept_id) VALUES (&#039;Gene&#039;, 3);&lt;br /&gt;
&lt;br /&gt;
SELECT emp_id, emp_name, dept_id FROM employees;&lt;br /&gt;
&lt;br /&gt;
1|John|1&lt;br /&gt;
2|Tim|2&lt;br /&gt;
3|Gene|3&lt;br /&gt;
&lt;br /&gt;
UPDATE employees set dept_id = 2 WHERE emp_id = 1;&lt;br /&gt;
UPDATE employees set dept_id = 3 WHERE emp_id = 2;&lt;br /&gt;
&lt;br /&gt;
SELECT emp_id, emp_name, dept_id FROM employees;&lt;br /&gt;
&lt;br /&gt;
1|John|2&lt;br /&gt;
2|Tim|3&lt;br /&gt;
3|Gene|3&lt;br /&gt;
&lt;br /&gt;
DELETE FROM departments WHERE dept_id = 1;&lt;br /&gt;
DELETE FROM departments WHERE dept_id = 2;&lt;br /&gt;
// hier müsste nach dem 2. Statement ein Fehler auftreten, weil Department mit ID=2 noch von einem Mitarbeiter belegt ist&lt;br /&gt;
// das ist völlig OK&lt;br /&gt;
&lt;br /&gt;
SELECT * FROM departments;&lt;br /&gt;
&lt;br /&gt;
2|MIS&lt;br /&gt;
3|Accounting&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Online Generator für Fremdschlüssel =&lt;br /&gt;
Für SQLite gibt es einen Online-Fremdschlüssel-Generator, der  die eingegebnenen Tabellen-Deklarationen, wie im obrigen Beispiel erklärt, automatisch mitsamt dem dazugehörigen TRIGGER ausgibt.&lt;br /&gt;
Zu finden ist der Generator unter [http://www.rcs-comp.com/site/index.php/view/Utilities-SQLite_foreign_key_trigger_generator RCS Computers].&lt;br /&gt;
&lt;br /&gt;
=Quellen =&lt;br /&gt;
&lt;br /&gt;
*[http://www.sqlite.org/cvstrac/wiki?p=ForeignKeyTriggers SQLite Homepage]&lt;br /&gt;
*[http://de.wikipedia.org/wiki/Datenbanktrigger Wikipedia: Datenbanktrigger]&lt;br /&gt;
*[http://www.rcs-comp.com/site/index.php/view/Utilities-SQLite_foreign_key_trigger_generator Online FOREIGN KEY Generator]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Glossar]]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Informatik]]&lt;/div&gt;</summary>
		<author><name>Jrdesign</name></author>
	</entry>
	<entry>
		<id>https://glossar.hs-augsburg.de/w/index.php?title=SQLite_Foreign_Keys_erzwingen&amp;diff=12134</id>
		<title>SQLite Foreign Keys erzwingen</title>
		<link rel="alternate" type="text/html" href="https://glossar.hs-augsburg.de/w/index.php?title=SQLite_Foreign_Keys_erzwingen&amp;diff=12134"/>
		<updated>2008-07-14T22:21:06Z</updated>

		<summary type="html">&lt;p&gt;Jrdesign: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{In Bearbeitung}}&lt;br /&gt;
&lt;br /&gt;
=Problem =&lt;br /&gt;
SQLite unterstützt standartmäßig keine FOREIGN KEYS (Fremdschlüssel). Man kann diese zwar bei erstellen von Tabellen definieren, jedoch werden diese, wie gesagt, ignoriert.&lt;br /&gt;
&lt;br /&gt;
=Lösung =&lt;br /&gt;
Es ist möglich, SQLite dazu zu zwingen, Fremdschlüssel zu akzeptieren. Um das zu erreichen werden TRIGGER verwendet.&lt;br /&gt;
TRIGGER werden zum Einfügen, Löschen oder Ändern von Referenzdaten eingesetzt. Der TRIGGER wird ausgeführt, entweder bevor Änderungen an der Tabelle vorgenommen werden oder danach. TRIGGER können selbst Datensätze einfügen, ändern oder löschen und durch seine Ausführung weitere TRIGGER auslösen.&lt;br /&gt;
Nun zum Beispiel:&lt;br /&gt;
Nehmen wir an wie haben 2 Tabellen-Deklarationen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TABLE kontakt (&lt;br /&gt;
  id INTEGER NOT NULL PRIMARY KEY&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
CREATE TABLE termin (&lt;br /&gt;
  id INTEGER NOT NULL PRIMARY KEY,&lt;br /&gt;
  kontakt_id INTEGER NOT NULL&lt;br /&gt;
         CONSTRAINT fk_kontakt_id REFERENCES a(id) ON DELETE CASCADE&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Die Tabelle termin hat einen Fremdschlüssel, der auf die Primär-Schlüssel-Spalte in der kontakt-Tabelle verweist. Obwohl SQLite diese Syntax unterstützt, wird sie einfach ignoriert. Wenn man also eine Referenz erzwingen will, muss man TRIGGER erstellen, die das erledigen. Jede Bedingung muss einen eigenen TRIGGER haben, also einen für INSERT, DELETE und UPDATE.&lt;br /&gt;
Der INSERT-TRIGGER sieht folgendermaßen aus:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TRIGGER fki_termin_kontakt_id&lt;br /&gt;
BEFORE INSERT ON termin&lt;br /&gt;
FOR EACH ROW BEGIN &lt;br /&gt;
  SELECT CASE&lt;br /&gt;
     WHEN ((SELECT id FROM kontakt WHERE id = NEW.kontakt_id) IS NULL)&lt;br /&gt;
     THEN RAISE(ABORT, ‘insert on table &amp;quot;termin&amp;quot; violates foreign key‘ || ‘constraint &amp;quot;fk_kontakt_id&amp;quot;’)&lt;br /&gt;
  END;&lt;br /&gt;
END;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Wenn man die Fremdschlüssel-Spalte als NOT NULL definiert haben will/sollte, muss der INSERT-TRIGGER SELECT CASE ein wenig anders aussehen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TRIGGER fki_termin_kontakt_id&lt;br /&gt;
BEFORE INSERT ON termin&lt;br /&gt;
FOR EACH ROW BEGIN &lt;br /&gt;
   SELECT CASE&lt;br /&gt;
     WHEN ((new.kontakt_id IS NOT NULL)&lt;br /&gt;
           AND ((SELECT id FROM kontakt WHERE id = new.kontakt_id) IS NULL))&lt;br /&gt;
     THEN RAISE(ABORT, ‘insert on table &amp;quot;termin&amp;quot; violates foreign key‘ || ‘constraint &amp;quot;fk_kontakt_id&amp;quot;’)&lt;br /&gt;
  END;&lt;br /&gt;
END;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Das UPDATE-Statement ist fast identisch, wenn die Fremdschlüssel-Spalte NOT NULL ist:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TRIGGER fku_termin_kontakt_id&lt;br /&gt;
BEFORE UPDATE ON termin&lt;br /&gt;
FOR EACH ROW BEGIN &lt;br /&gt;
   SELECT CASE&lt;br /&gt;
     WHEN ((SELECT id FROM kontakt WHERE id = new.kontakt_id) IS NULL))&lt;br /&gt;
     THEN RAISE(ABORT, ‘update on table &amp;quot;termin&amp;quot; violates foreign key‘ || ‘constraint &amp;quot;fk_kontakt_id&amp;quot;’)&lt;br /&gt;
  END;&lt;br /&gt;
END;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
und wenn NULL erlaubt ist:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TRIGGER fku_termin_kontakt_id&lt;br /&gt;
BEFORE UPDATE ON termin&lt;br /&gt;
FOR EACH ROW BEGIN &lt;br /&gt;
   SELECT CASE&lt;br /&gt;
     WHEN ((new.kontakt_id IS NOT NULL)&lt;br /&gt;
           AND ((SELECT id FROM kontakt WHERE id = new.kontakt_id) IS NULL))&lt;br /&gt;
     THEN RAISE(ABORT, ‘update on table &amp;quot;termin&amp;quot; violates foreign key‘ || ‘constraint &amp;quot;fk_kontakt_id&amp;quot;’)&lt;br /&gt;
  END;&lt;br /&gt;
END;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Der DELETE TRIGGER wird zur Primär-Sclüssel-Tabelle hinzugefügt und überwacht DELETEs auf der kontakt-Tabelle:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TRIGGER fkd_termin_kontakt_id&lt;br /&gt;
BEFORE DELETE ON kontakt&lt;br /&gt;
FOR EACH ROW BEGIN &lt;br /&gt;
  SELECT CASE&lt;br /&gt;
    WHEN ((SELECT kontakt_id FROM termin WHERE kontakt_id = OLD.id) IS NOT NULL)&lt;br /&gt;
    THEN RAISE(ABORT, ‘delete on table &amp;quot;kontakt&amp;quot; violates foreign key‘ || ‘constraint &amp;quot;fk_kontakt_id&amp;quot;’)&lt;br /&gt;
  END;&lt;br /&gt;
END;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Dieser TRIGGER verhindert Löschvorgänge in der kontakt-Tabelle, wenn es Fremdschlüssel gibt, die auf die termin-Tabelle verweisen.&lt;br /&gt;
Eine weitere, etwas übersichtlichere Lösung:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TABLE departments (&lt;br /&gt;
    dept_id   INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,&lt;br /&gt;
    dept_name TEXT NOT NULL UNIQUE&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
CREATE TABLE employees (&lt;br /&gt;
    emp_id   INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,&lt;br /&gt;
    emp_name TEXT NOT NULL UNIQUE,&lt;br /&gt;
    dept_id  INTEGER NOT NULL,&lt;br /&gt;
    CONSTRAINT fkey_dept_id FOREIGN KEY (dept_id) REFERENCES departments (dept_id)&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
und die zugehörigen TRIGGER:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TRIGGER fkey_dept_id_ins BEFORE INSERT ON employees&lt;br /&gt;
  FOR EACH ROW&lt;br /&gt;
    BEGIN&lt;br /&gt;
      SELECT&lt;br /&gt;
        RAISE(ABORT, &lt;br /&gt;
             &#039;insert on table &amp;quot;employees&amp;quot; violates foreign key constraint &amp;quot;fkey_dept_id&amp;quot;&#039;)&lt;br /&gt;
          WHERE (SELECT dept_id FROM departments &lt;br /&gt;
                   WHERE dept_id = new.dept_id) IS NULL;&lt;br /&gt;
    END;&lt;br /&gt;
&lt;br /&gt;
CREATE TRIGGER fkey_dept_id_upd BEFORE UPDATE ON employees&lt;br /&gt;
  FOR EACH ROW&lt;br /&gt;
    BEGIN&lt;br /&gt;
      SELECT&lt;br /&gt;
        RAISE(ABORT,&lt;br /&gt;
             &#039;update on table &amp;quot;employees&amp;quot; violates foreign key constraint &amp;quot;fkey_dept_id&amp;quot;&#039;)&lt;br /&gt;
          WHERE (SELECT dept_id FROM departments &lt;br /&gt;
                   WHERE dept_id = new.dept_id) IS NULL;&lt;br /&gt;
    END;&lt;br /&gt;
&lt;br /&gt;
CREATE TRIGGER fkey_dept_id_del BEFORE DELETE ON departments&lt;br /&gt;
  FOR EACH ROW&lt;br /&gt;
    BEGIN&lt;br /&gt;
      SELECT&lt;br /&gt;
        RAISE(ABORT,&lt;br /&gt;
             &#039;delete on table &amp;quot;departments&amp;quot; violates foreign key constraint &amp;quot;fkey_dept_id&amp;quot; on &amp;quot;employees&amp;quot;&#039;)&lt;br /&gt;
          WHERE (SELECT dept_id from employees &lt;br /&gt;
                   WHERE dept_id = old.dept_id) IS NOT NULL;&lt;br /&gt;
    END;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Die INSERT-Befehle und SELECT-Ausgaben sehen dann so aus:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
INSERT INTO departments (dept_name) VALUES (&#039;Marketing&#039;);&lt;br /&gt;
INSERT INTO departments (dept_name) VALUES (&#039;MIS&#039;);&lt;br /&gt;
INSERT INTO departments (dept_name) VALUES (&#039;Accounting&#039;);&lt;br /&gt;
&lt;br /&gt;
SELECT * FROM departments;&lt;br /&gt;
&lt;br /&gt;
1|Marketing&lt;br /&gt;
2|MIS&lt;br /&gt;
3|Accounting&lt;br /&gt;
&lt;br /&gt;
INSERT INTO employees (emp_name, dept_id) VALUES (&#039;John&#039;, 1);&lt;br /&gt;
INSERT INTO employees (emp_name, dept_id) VALUES (&#039;Tim&#039;, 2);&lt;br /&gt;
INSERT INTO employees (emp_name, dept_id) VALUES (&#039;Gene&#039;, 3);&lt;br /&gt;
&lt;br /&gt;
SELECT emp_id, emp_name, dept_id FROM employees;&lt;br /&gt;
&lt;br /&gt;
1|John|1&lt;br /&gt;
2|Tim|2&lt;br /&gt;
3|Gene|3&lt;br /&gt;
&lt;br /&gt;
UPDATE employees set dept_id = 2 WHERE emp_id = 1;&lt;br /&gt;
UPDATE employees set dept_id = 3 WHERE emp_id = 2;&lt;br /&gt;
&lt;br /&gt;
SELECT emp_id, emp_name, dept_id FROM employees;&lt;br /&gt;
&lt;br /&gt;
1|John|2&lt;br /&gt;
2|Tim|3&lt;br /&gt;
3|Gene|3&lt;br /&gt;
&lt;br /&gt;
DELETE FROM departments WHERE dept_id = 1;&lt;br /&gt;
DELETE FROM departments WHERE dept_id = 2;&lt;br /&gt;
// hier müsste nach dem 2. Statement ein Fehler auftreten, weil Department mit ID=2 noch von einem Mitarbeiter belegt ist&lt;br /&gt;
// das ist völlig OK&lt;br /&gt;
&lt;br /&gt;
SELECT * FROM departments;&lt;br /&gt;
&lt;br /&gt;
2|MIS&lt;br /&gt;
3|Accounting&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
=Quellen =&lt;br /&gt;
&lt;br /&gt;
*[http://www.sqlite.org/cvstrac/wiki?p=ForeignKeyTriggers SQLite Homepage]&lt;br /&gt;
*[http://de.wikipedia.org/wiki/Datenbanktrigger Wikipedia: Datenbanktrigger]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Glossar]]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Informatik]]&lt;/div&gt;</summary>
		<author><name>Jrdesign</name></author>
	</entry>
	<entry>
		<id>https://glossar.hs-augsburg.de/w/index.php?title=SQLite_Foreign_Keys_erzwingen&amp;diff=12133</id>
		<title>SQLite Foreign Keys erzwingen</title>
		<link rel="alternate" type="text/html" href="https://glossar.hs-augsburg.de/w/index.php?title=SQLite_Foreign_Keys_erzwingen&amp;diff=12133"/>
		<updated>2008-07-14T22:19:49Z</updated>

		<summary type="html">&lt;p&gt;Jrdesign: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{In Bearbeitung}}&lt;br /&gt;
&lt;br /&gt;
== Problem ==&lt;br /&gt;
SQLite unterstützt standartmäßig keine FOREIGN KEYS (Fremdschlüssel). Man kann diese zwar bei erstellen von Tabellen definieren, jedoch werden diese, wie gesagt, ignoriert.&lt;br /&gt;
&lt;br /&gt;
== Lösung ==&lt;br /&gt;
Es ist möglich, SQLite dazu zu zwingen, Fremdschlüssel zu akzeptieren. Um das zu erreichen werden TRIGGER verwendet.&lt;br /&gt;
TRIGGER werden zum Einfügen, Löschen oder Ändern von Referenzdaten eingesetzt. Der TRIGGER wird ausgeführt, entweder bevor Änderungen an der Tabelle vorgenommen werden oder danach. TRIGGER können selbst Datensätze einfügen, ändern oder löschen und durch seine Ausführung weitere TRIGGER auslösen.&lt;br /&gt;
Nun zum Beispiel:&lt;br /&gt;
Nehmen wir an wie haben 2 Tabellen-Deklarationen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TABLE kontakt (&lt;br /&gt;
  id INTEGER NOT NULL PRIMARY KEY&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
CREATE TABLE termin (&lt;br /&gt;
  id INTEGER NOT NULL PRIMARY KEY,&lt;br /&gt;
  kontakt_id INTEGER NOT NULL&lt;br /&gt;
         CONSTRAINT fk_kontakt_id REFERENCES a(id) ON DELETE CASCADE&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Die Tabelle termin hat einen Fremdschlüssel, der auf die Primär-Schlüssel-Spalte in der kontakt-Tabelle verweist. Obwohl SQLite diese Syntax unterstützt, wird sie einfach ignoriert. Wenn man also eine Referenz erzwingen will, muss man TRIGGER erstellen, die das erledigen. Jede Bedingung muss einen eigenen TRIGGER haben, also einen für INSERT, DELETE und UPDATE.&lt;br /&gt;
Der INSERT-TRIGGER sieht folgendermaßen aus:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TRIGGER fki_termin_kontakt_id&lt;br /&gt;
BEFORE INSERT ON termin&lt;br /&gt;
FOR EACH ROW BEGIN &lt;br /&gt;
  SELECT CASE&lt;br /&gt;
     WHEN ((SELECT id FROM kontakt WHERE id = NEW.kontakt_id) IS NULL)&lt;br /&gt;
     THEN RAISE(ABORT, ‘insert on table &amp;quot;termin&amp;quot; violates foreign key‘ || ‘constraint &amp;quot;fk_kontakt_id&amp;quot;’)&lt;br /&gt;
  END;&lt;br /&gt;
END;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Wenn man die Fremdschlüssel-Spalte als NOT NULL definiert haben will/sollte, muss der INSERT-TRIGGER SELECT CASE ein wenig anders aussehen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TRIGGER fki_termin_kontakt_id&lt;br /&gt;
BEFORE INSERT ON termin&lt;br /&gt;
FOR EACH ROW BEGIN &lt;br /&gt;
   SELECT CASE&lt;br /&gt;
     WHEN ((new.kontakt_id IS NOT NULL)&lt;br /&gt;
           AND ((SELECT id FROM kontakt WHERE id = new.kontakt_id) IS NULL))&lt;br /&gt;
     THEN RAISE(ABORT, ‘insert on table &amp;quot;termin&amp;quot; violates foreign key‘ || ‘constraint &amp;quot;fk_kontakt_id&amp;quot;’)&lt;br /&gt;
  END;&lt;br /&gt;
END;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Das UPDATE-Statement ist fast identisch, wenn die Fremdschlüssel-Spalte NOT NULL ist:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TRIGGER fku_termin_kontakt_id&lt;br /&gt;
BEFORE UPDATE ON termin&lt;br /&gt;
FOR EACH ROW BEGIN &lt;br /&gt;
   SELECT CASE&lt;br /&gt;
     WHEN ((SELECT id FROM kontakt WHERE id = new.kontakt_id) IS NULL))&lt;br /&gt;
     THEN RAISE(ABORT, ‘update on table &amp;quot;termin&amp;quot; violates foreign key‘ || ‘constraint &amp;quot;fk_kontakt_id&amp;quot;’)&lt;br /&gt;
  END;&lt;br /&gt;
END;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
und wenn NULL erlaubt ist:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TRIGGER fku_termin_kontakt_id&lt;br /&gt;
BEFORE UPDATE ON termin&lt;br /&gt;
FOR EACH ROW BEGIN &lt;br /&gt;
   SELECT CASE&lt;br /&gt;
     WHEN ((new.kontakt_id IS NOT NULL)&lt;br /&gt;
           AND ((SELECT id FROM kontakt WHERE id = new.kontakt_id) IS NULL))&lt;br /&gt;
     THEN RAISE(ABORT, ‘update on table &amp;quot;termin&amp;quot; violates foreign key‘ || ‘constraint &amp;quot;fk_kontakt_id&amp;quot;’)&lt;br /&gt;
  END;&lt;br /&gt;
END;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Der DELETE TRIGGER wird zur Primär-Sclüssel-Tabelle hinzugefügt und überwacht DELETEs auf der kontakt-Tabelle:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TRIGGER fkd_termin_kontakt_id&lt;br /&gt;
BEFORE DELETE ON kontakt&lt;br /&gt;
FOR EACH ROW BEGIN &lt;br /&gt;
  SELECT CASE&lt;br /&gt;
    WHEN ((SELECT kontakt_id FROM termin WHERE kontakt_id = OLD.id) IS NOT NULL)&lt;br /&gt;
    THEN RAISE(ABORT, ‘delete on table &amp;quot;kontakt&amp;quot; violates foreign key‘ || ‘constraint &amp;quot;fk_kontakt_id&amp;quot;’)&lt;br /&gt;
  END;&lt;br /&gt;
END;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Dieser TRIGGER verhindert Löschvorgänge in der kontakt-Tabelle, wenn es Fremdschlüssel gibt, die auf die termin-Tabelle verweisen.&lt;br /&gt;
Eine weitere, etwas übersichtlichere Lösung:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TABLE departments (&lt;br /&gt;
    dept_id   INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,&lt;br /&gt;
    dept_name TEXT NOT NULL UNIQUE&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
CREATE TABLE employees (&lt;br /&gt;
    emp_id   INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,&lt;br /&gt;
    emp_name TEXT NOT NULL UNIQUE,&lt;br /&gt;
    dept_id  INTEGER NOT NULL,&lt;br /&gt;
    CONSTRAINT fkey_dept_id FOREIGN KEY (dept_id) REFERENCES departments (dept_id)&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
und die zugehörigen TRIGGER:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TRIGGER fkey_dept_id_ins BEFORE INSERT ON employees&lt;br /&gt;
  FOR EACH ROW&lt;br /&gt;
    BEGIN&lt;br /&gt;
      SELECT&lt;br /&gt;
        RAISE(ABORT, &lt;br /&gt;
             &#039;insert on table &amp;quot;employees&amp;quot; violates foreign key constraint &amp;quot;fkey_dept_id&amp;quot;&#039;)&lt;br /&gt;
          WHERE (SELECT dept_id FROM departments &lt;br /&gt;
                   WHERE dept_id = new.dept_id) IS NULL;&lt;br /&gt;
    END;&lt;br /&gt;
&lt;br /&gt;
CREATE TRIGGER fkey_dept_id_upd BEFORE UPDATE ON employees&lt;br /&gt;
  FOR EACH ROW&lt;br /&gt;
    BEGIN&lt;br /&gt;
      SELECT&lt;br /&gt;
        RAISE(ABORT,&lt;br /&gt;
             &#039;update on table &amp;quot;employees&amp;quot; violates foreign key constraint &amp;quot;fkey_dept_id&amp;quot;&#039;)&lt;br /&gt;
          WHERE (SELECT dept_id FROM departments &lt;br /&gt;
                   WHERE dept_id = new.dept_id) IS NULL;&lt;br /&gt;
    END;&lt;br /&gt;
&lt;br /&gt;
CREATE TRIGGER fkey_dept_id_del BEFORE DELETE ON departments&lt;br /&gt;
  FOR EACH ROW&lt;br /&gt;
    BEGIN&lt;br /&gt;
      SELECT&lt;br /&gt;
        RAISE(ABORT,&lt;br /&gt;
             &#039;delete on table &amp;quot;departments&amp;quot; violates foreign key constraint &amp;quot;fkey_dept_id&amp;quot; on &amp;quot;employees&amp;quot;&#039;)&lt;br /&gt;
          WHERE (SELECT dept_id from employees &lt;br /&gt;
                   WHERE dept_id = old.dept_id) IS NOT NULL;&lt;br /&gt;
    END;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Die INSERT-Befehle und SELECT-Ausgaben sehen dann so aus:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
INSERT INTO departments (dept_name) VALUES (&#039;Marketing&#039;);&lt;br /&gt;
INSERT INTO departments (dept_name) VALUES (&#039;MIS&#039;);&lt;br /&gt;
INSERT INTO departments (dept_name) VALUES (&#039;Accounting&#039;);&lt;br /&gt;
&lt;br /&gt;
SELECT * FROM departments;&lt;br /&gt;
&lt;br /&gt;
1|Marketing&lt;br /&gt;
2|MIS&lt;br /&gt;
3|Accounting&lt;br /&gt;
&lt;br /&gt;
INSERT INTO employees (emp_name, dept_id) VALUES (&#039;John&#039;, 1);&lt;br /&gt;
INSERT INTO employees (emp_name, dept_id) VALUES (&#039;Tim&#039;, 2);&lt;br /&gt;
INSERT INTO employees (emp_name, dept_id) VALUES (&#039;Gene&#039;, 3);&lt;br /&gt;
&lt;br /&gt;
SELECT emp_id, emp_name, dept_id FROM employees;&lt;br /&gt;
&lt;br /&gt;
1|John|1&lt;br /&gt;
2|Tim|2&lt;br /&gt;
3|Gene|3&lt;br /&gt;
&lt;br /&gt;
UPDATE employees set dept_id = 2 WHERE emp_id = 1;&lt;br /&gt;
UPDATE employees set dept_id = 3 WHERE emp_id = 2;&lt;br /&gt;
&lt;br /&gt;
SELECT emp_id, emp_name, dept_id FROM employees;&lt;br /&gt;
&lt;br /&gt;
1|John|2&lt;br /&gt;
2|Tim|3&lt;br /&gt;
3|Gene|3&lt;br /&gt;
&lt;br /&gt;
DELETE FROM departments WHERE dept_id = 1;&lt;br /&gt;
DELETE FROM departments WHERE dept_id = 2;&lt;br /&gt;
// hier müsste nach dem 2. Statement ein Fehler auftreten, weil Department mit ID=2 noch von einem Mitarbeiter belegt ist&lt;br /&gt;
// das ist völlig OK&lt;br /&gt;
&lt;br /&gt;
SELECT * FROM departments;&lt;br /&gt;
&lt;br /&gt;
2|MIS&lt;br /&gt;
3|Accounting&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
==Quellen==&lt;br /&gt;
&lt;br /&gt;
*[http://www.sqlite.org/cvstrac/wiki?p=ForeignKeyTriggers SQLite Homepage]&lt;br /&gt;
*[http://de.wikipedia.org/wiki/Datenbanktrigger Wikipedia: Datenbanktrigger]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Glossar]]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Informatik]]&lt;/div&gt;</summary>
		<author><name>Jrdesign</name></author>
	</entry>
	<entry>
		<id>https://glossar.hs-augsburg.de/w/index.php?title=SQLite_Foreign_Keys_erzwingen&amp;diff=12127</id>
		<title>SQLite Foreign Keys erzwingen</title>
		<link rel="alternate" type="text/html" href="https://glossar.hs-augsburg.de/w/index.php?title=SQLite_Foreign_Keys_erzwingen&amp;diff=12127"/>
		<updated>2008-07-14T21:51:09Z</updated>

		<summary type="html">&lt;p&gt;Jrdesign: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{In Bearbeitung}}&lt;br /&gt;
&lt;br /&gt;
= Problem =&lt;br /&gt;
SQLite unterstützt standartmäßig keine FOREIGN KEYS (Fremdschlüssel). Man kann diese zwar bei erstellen von Tabellen definieren, jedoch werden diese, wie gesagt, ignoriert.&lt;br /&gt;
&lt;br /&gt;
= Lösung =&lt;br /&gt;
Es ist möglich, SQLite dazu zu zwingen, Fremdschlüssel zu akzeptieren. Um das zu erreichen werden TRIGGER verwendet.&lt;br /&gt;
TRIGGER werden zum Einfügen, Löschen oder Ändern von Referenzdaten eingesetzt. Der TRIGGER wird ausgeführt, entweder bevor Änderungen an der Tabelle vorgenommen werden oder danach. TRIGGER können selbst Datensätze einfügen, ändern oder löschen und durch seine Ausführung weitere TRIGGER auslösen.&lt;br /&gt;
Nun zum Beispiel:&lt;br /&gt;
Nehmen wir an wie haben 2 Tabellen-Deklarationen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TABLE kontakt (&lt;br /&gt;
  id INTEGER NOT NULL PRIMARY KEY&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
CREATE TABLE termin (&lt;br /&gt;
  id INTEGER NOT NULL PRIMARY KEY,&lt;br /&gt;
  kontakt_id INTEGER NOT NULL&lt;br /&gt;
         CONSTRAINT fk_kontakt_id REFERENCES a(id) ON DELETE CASCADE&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Die Tabelle termin hat einen Fremdschlüssel, der auf die Primär-Schlüssel-Spalte in der kontakt-Tabelle verweist. Obwohl SQLite diese Syntax unterstützt, wird sie einfach ignoriert. Wenn man also eine Referenz erzwingen will, muss man TRIGGER erstellen, die das erledigen. Jede Bedingung muss einen eigenen TRIGGER haben, also einen für INSERT, DELETE und UPDATE.&lt;br /&gt;
Der INSERT-TRIGGER sieht folgendermaßen aus:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TRIGGER fki_termin_kontakt_id&lt;br /&gt;
BEFORE INSERT ON termin&lt;br /&gt;
FOR EACH ROW BEGIN &lt;br /&gt;
  SELECT CASE&lt;br /&gt;
     WHEN ((SELECT id FROM kontakt WHERE id = NEW.kontakt_id) IS NULL)&lt;br /&gt;
     THEN RAISE(ABORT, ‘insert on table &amp;quot;termin&amp;quot; violates foreign key‘ || ‘constraint &amp;quot;fk_kontakt_id&amp;quot;’)&lt;br /&gt;
  END;&lt;br /&gt;
END;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Wenn man die Fremdschlüssel-Spalte als NOT NULL definiert haben will/sollte, muss der INSERT-TRIGGER SELECT CASE ein wenig anders aussehen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TRIGGER fki_termin_kontakt_id&lt;br /&gt;
BEFORE INSERT ON termin&lt;br /&gt;
FOR EACH ROW BEGIN &lt;br /&gt;
   SELECT CASE&lt;br /&gt;
     WHEN ((new.kontakt_id IS NOT NULL)&lt;br /&gt;
           AND ((SELECT id FROM kontakt WHERE id = new.kontakt_id) IS NULL))&lt;br /&gt;
     THEN RAISE(ABORT, ‘insert on table &amp;quot;termin&amp;quot; violates foreign key‘ || ‘constraint &amp;quot;fk_kontakt_id&amp;quot;’)&lt;br /&gt;
  END;&lt;br /&gt;
END;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Das UPDATE-Statement ist fast identisch, wenn die Fremdschlüssel-Spalte NOT NULL ist:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TRIGGER fku_termin_kontakt_id&lt;br /&gt;
BEFORE UPDATE ON termin&lt;br /&gt;
FOR EACH ROW BEGIN &lt;br /&gt;
   SELECT CASE&lt;br /&gt;
     WHEN ((SELECT id FROM kontakt WHERE id = new.kontakt_id) IS NULL))&lt;br /&gt;
     THEN RAISE(ABORT, ‘update on table &amp;quot;termin&amp;quot; violates foreign key‘ || ‘constraint &amp;quot;fk_kontakt_id&amp;quot;’)&lt;br /&gt;
  END;&lt;br /&gt;
END;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
und wenn NULL erlaubt ist:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TRIGGER fku_termin_kontakt_id&lt;br /&gt;
BEFORE UPDATE ON termin&lt;br /&gt;
FOR EACH ROW BEGIN &lt;br /&gt;
   SELECT CASE&lt;br /&gt;
     WHEN ((new.kontakt_id IS NOT NULL)&lt;br /&gt;
           AND ((SELECT id FROM kontakt WHERE id = new.kontakt_id) IS NULL))&lt;br /&gt;
     THEN RAISE(ABORT, ‘update on table &amp;quot;termin&amp;quot; violates foreign key‘ || ‘constraint &amp;quot;fk_kontakt_id&amp;quot;’)&lt;br /&gt;
  END;&lt;br /&gt;
END;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Der DELETE TRIGGER wird zur Primär-Sclüssel-Tabelle hinzugefügt und überwacht DELETEs auf der kontakt-Tabelle:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TRIGGER fkd_termin_kontakt_id&lt;br /&gt;
BEFORE DELETE ON kontakt&lt;br /&gt;
FOR EACH ROW BEGIN &lt;br /&gt;
  SELECT CASE&lt;br /&gt;
    WHEN ((SELECT kontakt_id FROM termin WHERE kontakt_id = OLD.id) IS NOT NULL)&lt;br /&gt;
    THEN RAISE(ABORT, ‘delete on table &amp;quot;kontakt&amp;quot; violates foreign key‘ || ‘constraint &amp;quot;fk_kontakt_id&amp;quot;’)&lt;br /&gt;
  END;&lt;br /&gt;
END;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Dieser TRIGGER verhindert Löschvorgänge in der kontakt-Tabelle, wenn es Fremdschlüssel gibt, die auf die termin-Tabelle verweisen.&lt;br /&gt;
Eine weitere, etwas übersichtlichere Lösung:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TABLE departments (&lt;br /&gt;
    dept_id   INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,&lt;br /&gt;
    dept_name TEXT NOT NULL UNIQUE&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
CREATE TABLE employees (&lt;br /&gt;
    emp_id   INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,&lt;br /&gt;
    emp_name TEXT NOT NULL UNIQUE,&lt;br /&gt;
    dept_id  INTEGER NOT NULL,&lt;br /&gt;
    CONSTRAINT fkey_dept_id FOREIGN KEY (dept_id) REFERENCES departments (dept_id)&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
und die zugehörigen TRIGGER:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TRIGGER fkey_dept_id_ins BEFORE INSERT ON employees&lt;br /&gt;
  FOR EACH ROW&lt;br /&gt;
    BEGIN&lt;br /&gt;
      SELECT&lt;br /&gt;
        RAISE(ABORT, &lt;br /&gt;
             &#039;insert on table &amp;quot;employees&amp;quot; violates foreign key constraint &amp;quot;fkey_dept_id&amp;quot;&#039;)&lt;br /&gt;
          WHERE (SELECT dept_id FROM departments &lt;br /&gt;
                   WHERE dept_id = new.dept_id) IS NULL;&lt;br /&gt;
    END;&lt;br /&gt;
&lt;br /&gt;
CREATE TRIGGER fkey_dept_id_upd BEFORE UPDATE ON employees&lt;br /&gt;
  FOR EACH ROW&lt;br /&gt;
    BEGIN&lt;br /&gt;
      SELECT&lt;br /&gt;
        RAISE(ABORT,&lt;br /&gt;
             &#039;update on table &amp;quot;employees&amp;quot; violates foreign key constraint &amp;quot;fkey_dept_id&amp;quot;&#039;)&lt;br /&gt;
          WHERE (SELECT dept_id FROM departments &lt;br /&gt;
                   WHERE dept_id = new.dept_id) IS NULL;&lt;br /&gt;
    END;&lt;br /&gt;
&lt;br /&gt;
CREATE TRIGGER fkey_dept_id_del BEFORE DELETE ON departments&lt;br /&gt;
  FOR EACH ROW&lt;br /&gt;
    BEGIN&lt;br /&gt;
      SELECT&lt;br /&gt;
        RAISE(ABORT,&lt;br /&gt;
             &#039;delete on table &amp;quot;departments&amp;quot; violates foreign key constraint &amp;quot;fkey_dept_id&amp;quot; on &amp;quot;employees&amp;quot;&#039;)&lt;br /&gt;
          WHERE (SELECT dept_id from employees &lt;br /&gt;
                   WHERE dept_id = old.dept_id) IS NOT NULL;&lt;br /&gt;
    END;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Die INSERT-Befehle und SELECT-Ausgaben sehen dann so aus:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
INSERT INTO departments (dept_name) VALUES (&#039;Marketing&#039;);&lt;br /&gt;
INSERT INTO departments (dept_name) VALUES (&#039;MIS&#039;);&lt;br /&gt;
INSERT INTO departments (dept_name) VALUES (&#039;Accounting&#039;);&lt;br /&gt;
&lt;br /&gt;
SELECT * FROM departments;&lt;br /&gt;
&lt;br /&gt;
1|Marketing&lt;br /&gt;
2|MIS&lt;br /&gt;
3|Accounting&lt;br /&gt;
&lt;br /&gt;
INSERT INTO employees (emp_name, dept_id) VALUES (&#039;John&#039;, 1);&lt;br /&gt;
INSERT INTO employees (emp_name, dept_id) VALUES (&#039;Tim&#039;, 2);&lt;br /&gt;
INSERT INTO employees (emp_name, dept_id) VALUES (&#039;Gene&#039;, 3);&lt;br /&gt;
&lt;br /&gt;
SELECT emp_id, emp_name, dept_id FROM employees;&lt;br /&gt;
&lt;br /&gt;
1|John|1&lt;br /&gt;
2|Tim|2&lt;br /&gt;
3|Gene|3&lt;br /&gt;
&lt;br /&gt;
UPDATE employees set dept_id = 2 WHERE emp_id = 1;&lt;br /&gt;
UPDATE employees set dept_id = 3 WHERE emp_id = 2;&lt;br /&gt;
&lt;br /&gt;
SELECT emp_id, emp_name, dept_id FROM employees;&lt;br /&gt;
&lt;br /&gt;
1|John|2&lt;br /&gt;
2|Tim|3&lt;br /&gt;
3|Gene|3&lt;br /&gt;
&lt;br /&gt;
DELETE FROM departments WHERE dept_id = 1;&lt;br /&gt;
DELETE FROM departments WHERE dept_id = 2;&lt;br /&gt;
// hier müsste nach dem 2. Statement ein Fehler auftreten, weil Department mit ID=2 noch von einem Mitarbeiter belegt ist&lt;br /&gt;
// das ist völlig OK&lt;br /&gt;
&lt;br /&gt;
SELECT * FROM departments;&lt;br /&gt;
&lt;br /&gt;
2|MIS&lt;br /&gt;
3|Accounting&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
=Quellen=&lt;br /&gt;
&lt;br /&gt;
*[http://www.sqlite.org/cvstrac/wiki?p=ForeignKeyTriggers SQLite Homepage]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Glossar]]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Informatik]]&lt;/div&gt;</summary>
		<author><name>Jrdesign</name></author>
	</entry>
	<entry>
		<id>https://glossar.hs-augsburg.de/w/index.php?title=SQLite_Foreign_Keys_erzwingen&amp;diff=12122</id>
		<title>SQLite Foreign Keys erzwingen</title>
		<link rel="alternate" type="text/html" href="https://glossar.hs-augsburg.de/w/index.php?title=SQLite_Foreign_Keys_erzwingen&amp;diff=12122"/>
		<updated>2008-07-14T21:43:38Z</updated>

		<summary type="html">&lt;p&gt;Jrdesign: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{In Bearbeitung}}&lt;br /&gt;
&lt;br /&gt;
= Problem =&lt;br /&gt;
SQLite unterstützt standartmäßig keine FOREIGN KEYS (Fremdschlüssel). Man kann diese zwar bei erstellen von Tabellen definieren, jedoch werden diese, wie gesagt, ignoriert.&lt;br /&gt;
&lt;br /&gt;
= Lösung =&lt;br /&gt;
Es ist möglich, SQLite dazu zu zwingen, Fremdschlüssel zu akzeptieren. Um das zu erreichen werden TRIGGER verwendet.&lt;br /&gt;
TRIGGER werden zum Einfügen, Löschen oder Ändern von Referenzdaten eingesetzt. Der TRIGGER wird ausgeführt, entweder bevor Änderungen an der Tabelle vorgenommen werden oder danach. TRIGGER können selbst Datensätze einfügen, ändern oder löschen und durch seine Ausführung weitere TRIGGER auslösen.&lt;br /&gt;
Nun zum Beispiel:&lt;br /&gt;
Nehmen wir an wie haben 2 Tabellen-Deklarationen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
create table kontakt (&lt;br /&gt;
  id INTEGER NOT NULL PRIMARY KEY&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
CREATE TABLE termin (&lt;br /&gt;
  id INTEGER NOT NULL PRIMARY KEY,&lt;br /&gt;
  kontakt_id INTEGER NOT NULL&lt;br /&gt;
         CONSTRAINT fk_kontakt_id REFERENCES a(id) ON DELETE CASCADE&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Die Tabelle termin hat einen Fremdschlüssel, der auf die Primär-Schlüssel-Spalte in der kontakt-Tabelle verweist. Obwohl SQLite diese Syntax unterstützt, wird sie einfach ignoriert. Wenn man also eine Referenz erzwingen will, muss man TRIGGER erstellen, die das erledigen. Jede Bedingung muss einen eigenen TRIGGER haben, also einen für INSERT, DELETE und UPDATE.&lt;br /&gt;
Der INSERT-TRIGGER sieht folgendermaßen aus:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TRIGGER fki_termin_kontakt_id&lt;br /&gt;
BEFORE INSERT ON termin&lt;br /&gt;
FOR EACH ROW BEGIN &lt;br /&gt;
  SELECT CASE&lt;br /&gt;
     WHEN ((SELECT id FROM kontakt WHERE id = NEW.kontakt_id) IS NULL)&lt;br /&gt;
     THEN RAISE(ABORT, ‘insert on table &amp;quot;termin&amp;quot; violates foreign key‘ || ‘constraint &amp;quot;fk_kontakt_id&amp;quot;’)&lt;br /&gt;
  END;&lt;br /&gt;
END;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Wenn man die Fremdschlüssel-Spalte als NOT NULL definiert haben will/sollte, muss der INSERT-TRIGGER SELECT CASE ein wenig anders aussehen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TRIGGER fki_termin_kontakt_id&lt;br /&gt;
BEFORE INSERT ON termin&lt;br /&gt;
FOR EACH ROW BEGIN &lt;br /&gt;
   SELECT CASE&lt;br /&gt;
     WHEN ((new.kontakt_id IS NOT NULL)&lt;br /&gt;
           AND ((SELECT id FROM kontakt WHERE id = new.kontakt_id) IS NULL))&lt;br /&gt;
     THEN RAISE(ABORT, ‘insert on table &amp;quot;termin&amp;quot; violates foreign key‘ || ‘constraint &amp;quot;fk_kontakt_id&amp;quot;’)&lt;br /&gt;
  END;&lt;br /&gt;
END;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
DaS UPDATE-Statement ist fast identisch, wenn die Fremdschlüssel-Spalte NOT NULL ist:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TRIGGER fku_termin_kontakt_id&lt;br /&gt;
BEFORE UPDATE ON termin&lt;br /&gt;
FOR EACH ROW BEGIN &lt;br /&gt;
   SELECT CASE&lt;br /&gt;
     WHEN ((SELECT id FROM kontakt WHERE id = new.kontakt_id) IS NULL))&lt;br /&gt;
     THEN RAISE(ABORT, ‘update on table &amp;quot;termin&amp;quot; violates foreign key‘ || ‘constraint &amp;quot;fk_kontakt_id&amp;quot;’)&lt;br /&gt;
  END;&lt;br /&gt;
END;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
und wenn NULL erlaubt ist:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TRIGGER fku_termin_kontakt_id&lt;br /&gt;
BEFORE UPDATE ON termin&lt;br /&gt;
FOR EACH ROW BEGIN &lt;br /&gt;
   SELECT CASE&lt;br /&gt;
     WHEN ((new.kontakt_id IS NOT NULL)&lt;br /&gt;
           AND ((SELECT id FROM kontakt WHERE id = new.kontakt_id) IS NULL))&lt;br /&gt;
     THEN RAISE(ABORT, ‘update on table &amp;quot;termin&amp;quot; violates foreign key‘ || ‘constraint &amp;quot;fk_kontakt_id&amp;quot;’)&lt;br /&gt;
  END;&lt;br /&gt;
END;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Der DELETE TRIGGER wird zur Primär-Sclüssel-Tabelle hinzugefügt und überwacht DELETEs auf der kontakt-Tabelle:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TRIGGER fkd_termin_kontakt_id&lt;br /&gt;
BEFORE DELETE ON kontakt&lt;br /&gt;
FOR EACH ROW BEGIN &lt;br /&gt;
  SELECT CASE&lt;br /&gt;
    WHEN ((SELECT kontakt_id FROM termin WHERE kontakt_id = OLD.id) IS NOT NULL)&lt;br /&gt;
    THEN RAISE(ABORT, ‘delete on table &amp;quot;kontakt&amp;quot; violates foreign key‘ || ‘constraint &amp;quot;fk_kontakt_id&amp;quot;’)&lt;br /&gt;
  END;&lt;br /&gt;
END;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Dieser TRIGGER verhindert Löschvorgänge in der kontakt-Tabelle, wenn es Fremdschlüssel gibt, die auf die termin-Tabelle verweisen.&lt;br /&gt;
Eine weitere, etwas übersichtlichere Lösung:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TABLE departments (&lt;br /&gt;
    dept_id   INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,&lt;br /&gt;
    dept_name TEXT NOT NULL UNIQUE&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
CREATE TABLE employees (&lt;br /&gt;
    emp_id   INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,&lt;br /&gt;
    emp_name TEXT NOT NULL UNIQUE,&lt;br /&gt;
    dept_id  INTEGER NOT NULL,&lt;br /&gt;
    CONSTRAINT fkey_dept_id FOREIGN KEY (dept_id) REFERENCES departments (dept_id)&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
und die zugehörigen TRIGGER:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TRIGGER fkey_dept_id_ins BEFORE INSERT ON employees&lt;br /&gt;
  FOR EACH ROW&lt;br /&gt;
    BEGIN&lt;br /&gt;
      SELECT&lt;br /&gt;
        RAISE(ABORT, &lt;br /&gt;
             &#039;insert on table &amp;quot;employees&amp;quot; violates foreign key constraint &amp;quot;fkey_dept_id&amp;quot;&#039;)&lt;br /&gt;
          WHERE (SELECT dept_id FROM departments &lt;br /&gt;
                   WHERE dept_id = new.dept_id) IS NULL;&lt;br /&gt;
    END;&lt;br /&gt;
&lt;br /&gt;
CREATE TRIGGER fkey_dept_id_upd BEFORE UPDATE ON employees&lt;br /&gt;
  FOR EACH ROW&lt;br /&gt;
    BEGIN&lt;br /&gt;
      SELECT&lt;br /&gt;
        RAISE(ABORT,&lt;br /&gt;
             &#039;update on table &amp;quot;employees&amp;quot; violates foreign key constraint &amp;quot;fkey_dept_id&amp;quot;&#039;)&lt;br /&gt;
          WHERE (SELECT dept_id FROM departments &lt;br /&gt;
                   WHERE dept_id = new.dept_id) IS NULL;&lt;br /&gt;
    END;&lt;br /&gt;
&lt;br /&gt;
CREATE TRIGGER fkey_dept_id_del BEFORE DELETE ON departments&lt;br /&gt;
  FOR EACH ROW&lt;br /&gt;
    BEGIN&lt;br /&gt;
      SELECT&lt;br /&gt;
        RAISE(ABORT,&lt;br /&gt;
             &#039;delete on table &amp;quot;departments&amp;quot; violates foreign key constraint &amp;quot;fkey_dept_id&amp;quot; on &amp;quot;employees&amp;quot;&#039;)&lt;br /&gt;
          WHERE (SELECT dept_id from employees &lt;br /&gt;
                   WHERE dept_id = old.dept_id) IS NOT NULL;&lt;br /&gt;
    END;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Die INSERT-Befehle und SELECT-Ausgaben sehen dann so aus:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
INSERT INTO departments (dept_name) VALUES (&#039;Marketing&#039;);&lt;br /&gt;
INSERT INTO departments (dept_name) VALUES (&#039;MIS&#039;);&lt;br /&gt;
INSERT INTO departments (dept_name) VALUES (&#039;Accounting&#039;);&lt;br /&gt;
&lt;br /&gt;
SELECT * FROM departments;&lt;br /&gt;
&lt;br /&gt;
1|Marketing&lt;br /&gt;
2|MIS&lt;br /&gt;
3|Accounting&lt;br /&gt;
&lt;br /&gt;
INSERT INTO employees (emp_name, dept_id) VALUES (&#039;John&#039;, 1);&lt;br /&gt;
INSERT INTO employees (emp_name, dept_id) VALUES (&#039;Tim&#039;, 2);&lt;br /&gt;
INSERT INTO employees (emp_name, dept_id) VALUES (&#039;Gene&#039;, 3);&lt;br /&gt;
&lt;br /&gt;
SELECT emp_id, emp_name, dept_id FROM employees;&lt;br /&gt;
&lt;br /&gt;
1|John|1&lt;br /&gt;
2|Tim|2&lt;br /&gt;
3|Gene|3&lt;br /&gt;
&lt;br /&gt;
UPDATE employees set dept_id = 2 WHERE emp_id = 1;&lt;br /&gt;
UPDATE employees set dept_id = 3 WHERE emp_id = 2;&lt;br /&gt;
&lt;br /&gt;
SELECT emp_id, emp_name, dept_id FROM employees;&lt;br /&gt;
&lt;br /&gt;
1|John|2&lt;br /&gt;
2|Tim|3&lt;br /&gt;
3|Gene|3&lt;br /&gt;
&lt;br /&gt;
DELETE FROM departments WHERE dept_id = 1;&lt;br /&gt;
DELETE FROM departments WHERE dept_id = 2;&lt;br /&gt;
// hier müsste nach dem 2. Statement ein Fehler auftreten, weil Department mit ID=2 noch von einem Mitarbeiter belegt ist&lt;br /&gt;
// das ist völlig OK&lt;br /&gt;
&lt;br /&gt;
SELECT * FROM departments;&lt;br /&gt;
&lt;br /&gt;
2|MIS&lt;br /&gt;
3|Accounting&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
=Quellen=&lt;br /&gt;
&lt;br /&gt;
*[http://www.sqlite.org/cvstrac/wiki?p=ForeignKeyTriggers SQLite Homepage]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Glossar]]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Informatik]]&lt;/div&gt;</summary>
		<author><name>Jrdesign</name></author>
	</entry>
	<entry>
		<id>https://glossar.hs-augsburg.de/w/index.php?title=SQLite_Foreign_Keys_erzwingen&amp;diff=12121</id>
		<title>SQLite Foreign Keys erzwingen</title>
		<link rel="alternate" type="text/html" href="https://glossar.hs-augsburg.de/w/index.php?title=SQLite_Foreign_Keys_erzwingen&amp;diff=12121"/>
		<updated>2008-07-14T21:42:08Z</updated>

		<summary type="html">&lt;p&gt;Jrdesign: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{In Bearbeitung}}&lt;br /&gt;
&lt;br /&gt;
= Problem =&lt;br /&gt;
SQLite unterstützt standartmäßig keine FOREIGN KEYS (Fremdschlüssel). Man kann diese zwar bei erstellen von Tabellen definieren, jedoch werden diese, wie gesagt, ignoriert.&lt;br /&gt;
&lt;br /&gt;
= Lösung =&lt;br /&gt;
Es ist möglich, SQLite dazu zu zwingen, Fremdschlüssel zu akzeptieren. Um das zu erreichen werden TRIGGER verwendet.&lt;br /&gt;
TRIGGER werden zum Einfügen, Löschen oder Ändern von Referenzdaten eingesetzt. Der TRIGGER wird ausgeführt, entweder bevor Änderungen an der Tabelle vorgenommen werden oder danach. TRIGGER können selbst Datensätze einfügen, ändern oder löschen und durch seine Ausführung weitere TRIGGER auslösen.&lt;br /&gt;
Nun zum Beispiel:&lt;br /&gt;
Nehmen wir an wie haben 2 Tabellen-Deklarationen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
create table kontakt (&lt;br /&gt;
  id INTEGER NOT NULL PRIMARY KEY&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
CREATE TABLE termin (&lt;br /&gt;
  id INTEGER NOT NULL PRIMARY KEY,&lt;br /&gt;
  kontakt_id INTEGER NOT NULL&lt;br /&gt;
         CONSTRAINT fk_kontakt_id REFERENCES a(id) ON DELETE CASCADE&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Die Tabelle termin hat einen Fremdschlüssel, der auf die Primär-Schlüssel-Spalte in der kontakt-Tabelle verweist. Obwohl SQLite diese Syntax unterstützt, wird sie einfach ignoriert. Wenn man also eine Referenz erzwingen will, muss man TRIGGER erstellen, die das erledigen. Jede Bedingung muss einen eigenen TRIGGER haben, also einen für INSERT, DELETE und UPDATE.&lt;br /&gt;
Der INSERT-TRIGGER sieht folgendermaßen aus:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TRIGGER fki_termin_kontakt_id&lt;br /&gt;
BEFORE INSERT ON termin&lt;br /&gt;
FOR EACH ROW BEGIN &lt;br /&gt;
  SELECT CASE&lt;br /&gt;
     WHEN ((SELECT id FROM kontakt WHERE id = NEW.kontakt_id) IS NULL)&lt;br /&gt;
     THEN RAISE(ABORT, ‘insert on table &amp;quot;termin&amp;quot; violates foreign key‘ || ‘constraint &amp;quot;fk_kontakt_id&amp;quot;’)&lt;br /&gt;
  END;&lt;br /&gt;
END;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Wenn man die Fremdschlüssel-Spalte als NOT NULL definiert haben will/sollte, muss der INSERT-TRIGGER SELECT CASE ein wenig anders aussehen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TRIGGER fki_termin_kontakt_id&lt;br /&gt;
BEFORE INSERT ON termin&lt;br /&gt;
FOR EACH ROW BEGIN &lt;br /&gt;
   SELECT CASE&lt;br /&gt;
     WHEN ((new.kontakt_id IS NOT NULL)&lt;br /&gt;
           AND ((SELECT id FROM kontakt WHERE id = new.kontakt_id) IS NULL))&lt;br /&gt;
     THEN RAISE(ABORT, ‘insert on table &amp;quot;termin&amp;quot; violates foreign key‘ || ‘constraint &amp;quot;fk_kontakt_id&amp;quot;’)&lt;br /&gt;
  END;&lt;br /&gt;
END;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
DaS UPDATE-Statement ist fast identisch, wenn die Fremdschlüssel-Spalte NOT NULL ist:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TRIGGER fku_termin_kontakt_id&lt;br /&gt;
BEFORE UPDATE ON termin&lt;br /&gt;
FOR EACH ROW BEGIN &lt;br /&gt;
   SELECT CASE&lt;br /&gt;
     WHEN ((SELECT id FROM kontakt WHERE id = new.kontakt_id) IS NULL))&lt;br /&gt;
     THEN RAISE(ABORT, ‘update on table &amp;quot;termin&amp;quot; violates foreign key‘ || ‘constraint &amp;quot;fk_kontakt_id&amp;quot;’)&lt;br /&gt;
  END;&lt;br /&gt;
END;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
und wenn NULL erlaubt ist:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TRIGGER fku_termin_kontakt_id&lt;br /&gt;
BEFORE UPDATE ON termin&lt;br /&gt;
FOR EACH ROW BEGIN &lt;br /&gt;
   SELECT CASE&lt;br /&gt;
     WHEN ((new.kontakt_id IS NOT NULL)&lt;br /&gt;
           AND ((SELECT id FROM kontakt WHERE id = new.kontakt_id) IS NULL))&lt;br /&gt;
     THEN RAISE(ABORT, ‘update on table &amp;quot;termin&amp;quot; violates foreign key‘ || ‘constraint &amp;quot;fk_kontakt_id&amp;quot;’)&lt;br /&gt;
  END;&lt;br /&gt;
END;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Der DELETE TRIGGER wird zur Primär-Sclüssel-Tabelle hinzugefügt und überwacht DELETEs auf der kontakt-Tabelle:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TRIGGER fkd_termin_kontakt_id&lt;br /&gt;
BEFORE DELETE ON kontakt&lt;br /&gt;
FOR EACH ROW BEGIN &lt;br /&gt;
  SELECT CASE&lt;br /&gt;
    WHEN ((SELECT kontakt_id FROM termin WHERE kontakt_id = OLD.id) IS NOT NULL)&lt;br /&gt;
    THEN RAISE(ABORT, ‘delete on table &amp;quot;kontakt&amp;quot; violates foreign key‘ || ‘constraint &amp;quot;fk_kontakt_id&amp;quot;’)&lt;br /&gt;
  END;&lt;br /&gt;
END;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Dieser TRIGGER verhindert Löschvorgänge in der kontakt-Tabelle, wenn es Fremdschlüssel gibt, die auf die termin-Tabelle verweisen.&lt;br /&gt;
Eine weitere, etwas übersichtlichere Lösung:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TABLE departments (&lt;br /&gt;
    dept_id   INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,&lt;br /&gt;
    dept_name TEXT NOT NULL UNIQUE&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
CREATE TABLE employees (&lt;br /&gt;
    emp_id   INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,&lt;br /&gt;
    emp_name TEXT NOT NULL UNIQUE,&lt;br /&gt;
    dept_id  INTEGER NOT NULL,&lt;br /&gt;
    CONSTRAINT fkey_dept_id FOREIGN KEY (dept_id) REFERENCES departments (dept_id)&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
und die zugehörigen TRIGGER:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TRIGGER fkey_dept_id_ins BEFORE INSERT ON employees&lt;br /&gt;
  FOR EACH ROW&lt;br /&gt;
    BEGIN&lt;br /&gt;
      SELECT&lt;br /&gt;
        RAISE(ABORT, &lt;br /&gt;
             &#039;insert on table &amp;quot;employees&amp;quot; violates foreign key constraint &amp;quot;fkey_dept_id&amp;quot;&#039;)&lt;br /&gt;
          WHERE (SELECT dept_id FROM departments &lt;br /&gt;
                   WHERE dept_id = new.dept_id) IS NULL;&lt;br /&gt;
    END;&lt;br /&gt;
&lt;br /&gt;
CREATE TRIGGER fkey_dept_id_upd BEFORE UPDATE ON employees&lt;br /&gt;
  FOR EACH ROW&lt;br /&gt;
    BEGIN&lt;br /&gt;
      SELECT&lt;br /&gt;
        RAISE(ABORT,&lt;br /&gt;
             &#039;update on table &amp;quot;employees&amp;quot; violates foreign key constraint &amp;quot;fkey_dept_id&amp;quot;&#039;)&lt;br /&gt;
          WHERE (SELECT dept_id FROM departments &lt;br /&gt;
                   WHERE dept_id = new.dept_id) IS NULL;&lt;br /&gt;
    END;&lt;br /&gt;
&lt;br /&gt;
CREATE TRIGGER fkey_dept_id_del BEFORE DELETE ON departments&lt;br /&gt;
  FOR EACH ROW&lt;br /&gt;
    BEGIN&lt;br /&gt;
      SELECT&lt;br /&gt;
        RAISE(ABORT,&lt;br /&gt;
             &#039;delete on table &amp;quot;departments&amp;quot; violates foreign key constraint &amp;quot;fkey_dept_id&amp;quot; on &amp;quot;employees&amp;quot;&#039;)&lt;br /&gt;
          WHERE (SELECT dept_id from employees &lt;br /&gt;
                   WHERE dept_id = old.dept_id) IS NOT NULL;&lt;br /&gt;
    END;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Die INSERT-Befehle und SELECT-Ausgaben sehen dann so aus:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
INSERT INTO departments (dept_name) VALUES (&#039;Marketing&#039;);&lt;br /&gt;
INSERT INTO departments (dept_name) VALUES (&#039;MIS&#039;);&lt;br /&gt;
INSERT INTO departments (dept_name) VALUES (&#039;Accounting&#039;);&lt;br /&gt;
&lt;br /&gt;
SELECT * FROM departments;&lt;br /&gt;
&lt;br /&gt;
1|Marketing&lt;br /&gt;
2|MIS&lt;br /&gt;
3|Accounting&lt;br /&gt;
&lt;br /&gt;
INSERT INTO employees (emp_name, dept_id) VALUES (&#039;John&#039;, 1);&lt;br /&gt;
INSERT INTO employees (emp_name, dept_id) VALUES (&#039;Tim&#039;, 2);&lt;br /&gt;
INSERT INTO employees (emp_name, dept_id) VALUES (&#039;Gene&#039;, 3);&lt;br /&gt;
&lt;br /&gt;
SELECT emp_id, emp_name, dept_id FROM employees;&lt;br /&gt;
&lt;br /&gt;
1|John|1&lt;br /&gt;
2|Tim|2&lt;br /&gt;
3|Gene|3&lt;br /&gt;
&lt;br /&gt;
UPDATE employees set dept_id = 2 WHERE emp_id = 1;&lt;br /&gt;
UPDATE employees set dept_id = 3 WHERE emp_id = 2;&lt;br /&gt;
&lt;br /&gt;
SELECT emp_id, emp_name, dept_id FROM employees;&lt;br /&gt;
&lt;br /&gt;
1|John|2&lt;br /&gt;
2|Tim|3&lt;br /&gt;
3|Gene|3&lt;br /&gt;
&lt;br /&gt;
DELETE FROM departments WHERE dept_id = 1;&lt;br /&gt;
DELETE FROM departments WHERE dept_id = 2;&lt;br /&gt;
// hier müsste nach dem 2. Statement ein Fehler auftreten, weil Department mit ID=2 noch von einem Mitarbeiter belegt ist&lt;br /&gt;
// das ist völlig OK&lt;br /&gt;
&lt;br /&gt;
SELECT * FROM departments;&lt;br /&gt;
&lt;br /&gt;
2|MIS&lt;br /&gt;
3|Accounting&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
=Quellen=&lt;br /&gt;
&lt;br /&gt;
*[http://www.sqlite.org/cvstrac/wiki?p=ForeignKeyTriggers SQLite Homepage]&lt;br /&gt;
&lt;br /&gt;
=Siehe auch=&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Glossar]]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Informatik]]&lt;/div&gt;</summary>
		<author><name>Jrdesign</name></author>
	</entry>
	<entry>
		<id>https://glossar.hs-augsburg.de/w/index.php?title=SQLite_Manager_f%C3%BCr_Firefox&amp;diff=11753</id>
		<title>SQLite Manager für Firefox</title>
		<link rel="alternate" type="text/html" href="https://glossar.hs-augsburg.de/w/index.php?title=SQLite_Manager_f%C3%BCr_Firefox&amp;diff=11753"/>
		<updated>2008-06-09T19:56:15Z</updated>

		<summary type="html">&lt;p&gt;Jrdesign: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{In Bearbeitung}}&lt;br /&gt;
&lt;br /&gt;
=Einleitung =&lt;br /&gt;
SQLite Manager ist eine von zahlreichen freien Erweiterungen für den Webbrowser Firefox. Mit diesem Tool ist es möglich, SQLite Datenbanken auf dem lokalen Rechner, zu managen. Das Tool ist unter [http://code.google.com/p/sqlite-manager/downloads/list Google Code] erhältlich.&lt;br /&gt;
&lt;br /&gt;
=Download und Installation =&lt;br /&gt;
Unter Google Code die Datei SQLiteManager_0.2.43.xpi anklicken und downloaden. Danach im Firefox unter &amp;quot;Extras&amp;quot; -&amp;gt; &amp;quot;Add-ons&amp;quot; auswählen. Per Drag&amp;amp;Drop die zuvor heruntergeladene *.xpi-Datei ins Add-on Fenster ziehen. Es erscheint ein Dialogfenster, welches man bestätigen sollte, um das Add-on zu installieren.&lt;br /&gt;
&lt;br /&gt;
[[Medium:SQLlite-Manager-Dialog.png]]&lt;br /&gt;
&lt;br /&gt;
Nach erfolgreicher Installation muss man Firefox neustarten. Den erscheinenden Dialog einfach bestätigen, Firefox startet automatisch neu.&lt;br /&gt;
Nachdem Firefox neugestartet wurde, findet man unter Extras den SQLite Manager.&lt;br /&gt;
&lt;br /&gt;
=Programmfunktionen =&lt;br /&gt;
==kurzer Überblick==&lt;br /&gt;
Nachdem man den SQLite Manager gestartet hat, öffnet sich automatisch ein neues Browserfenster.&lt;br /&gt;
&lt;br /&gt;
[[Medium:SQLiteManager-Window.png]]&lt;br /&gt;
&lt;br /&gt;
Nun kann man eine neue SQLite-Datenbank anlegen, eine bereits angelegte Datenbank öffnen und andere Funktionen ausführen.&lt;br /&gt;
Die Buttons und Menüeinträge sind selbsterklärend. Um eine neue Datenbank anzulegen klickt man einfach auf den Button &amp;quot;New Database&amp;quot;. Im darauffolgenden Fenster gibt man den neuen Datenbanknamen, bestätigt mit OK und wählt nachfolgend den Speicherort für die Datenbank aus. Wie man SQLite Statements ausführt, um zum Beispel Tabellen anzulegen wird im Artikel [[SQLite]] erklärt.&lt;br /&gt;
&lt;br /&gt;
==Datenbank öffnen und managen==&lt;br /&gt;
Im Beispiel [[Lokale Datenbank erstellen (Flex und AIR)]] wurde bereits eine Test-Datenbank angelegt. Diese Datenbank öffnet man jetzt im SQLite Manager über den Button &amp;quot;Connect Database&amp;quot; oder über das Menü Database -&amp;gt; Connect Database. Über den Dialog navigiert man nun zur auf dem Desktop liegenden Testdatenbank &amp;quot;DB_Test.db&amp;quot; und öffnet diese. ACHTUNG: sollte der Manager die Dateiendung .db nicht finden, muss man über das Hauptmenü den Punkt &amp;quot;Tools&amp;quot; -&amp;gt; &amp;quot;Options&amp;quot; auswählen und in das Feld &amp;quot;Default file Extension for SQLite files&amp;quot; anstelle von &amp;quot;sqlite&amp;quot;, &amp;quot;db&amp;quot; eintragen.&lt;br /&gt;
&lt;br /&gt;
[[Medium:SQLlite-Manager-Options.png]]&lt;br /&gt;
&lt;br /&gt;
Die geöffnete Datenbank sieht wie folgt im SQLite Manager aus:&lt;br /&gt;
&lt;br /&gt;
[[Medium:Datenbank_geoeffnet.png]]&lt;br /&gt;
&lt;br /&gt;
Im linken Teil des Programms sieht man die angelegte Tabelle &amp;quot;person&amp;quot; sowie eine Zweite, die intern verwendet wird. Der rechte Fensterbereich zeigt, bei Klick auf die &amp;quot;person&amp;quot;-Tabelle, die Struktur dieser an. Interessant ist auch, das man zusätzlich Informationen angezeigt bekommt, wie man z.B. über ein Statement diese Tabelle anlegen kann. Wenn man nun den Reiter &amp;quot;Browse &amp;amp; Search&amp;quot; anklickt (bei vorher ausgewählter &amp;quot;person&amp;quot;-Tabelle) erhält man einen Überblick der Einträge in dieser Tabelle.&lt;br /&gt;
&lt;br /&gt;
[[Medium:Tabelle_ausgewaehlt.png]]&lt;br /&gt;
&lt;br /&gt;
Um SQL-Statements auszuführen, wählt man den Reiter &amp;quot;Execute SQL&amp;quot; und kann im nun im kleinen Fenster SQL-Befehle ausführen.&lt;br /&gt;
Zum Beispiel einen Insert in die Tabelle: Den Reiter &amp;quot;Data Manipulation&amp;quot; auswählen und dann &amp;quot;Insert values&amp;quot;, das Statement eintragen und über den Button &amp;quot;Run SQL&amp;quot; ausführen. Fertig. Ein Klick auf &amp;quot;Browse &amp;amp; Search&amp;quot; zeigt nun auch den neuen Eintrag an.&lt;br /&gt;
&lt;br /&gt;
[[Medium:SQL-Insert.png]]&lt;br /&gt;
&lt;br /&gt;
=Quellen=&lt;br /&gt;
&lt;br /&gt;
*[http://code.google.com/p/sqlite-manager/ Google Code]&lt;br /&gt;
&lt;br /&gt;
=Siehe auch=&lt;br /&gt;
&lt;br /&gt;
*[[SQLite]]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Glossar]]&lt;/div&gt;</summary>
		<author><name>Jrdesign</name></author>
	</entry>
	<entry>
		<id>https://glossar.hs-augsburg.de/w/index.php?title=Datei:SQL-Insert.png&amp;diff=11752</id>
		<title>Datei:SQL-Insert.png</title>
		<link rel="alternate" type="text/html" href="https://glossar.hs-augsburg.de/w/index.php?title=Datei:SQL-Insert.png&amp;diff=11752"/>
		<updated>2008-06-09T19:51:09Z</updated>

		<summary type="html">&lt;p&gt;Jrdesign: Insertbefehl im SQLite Manager&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Insertbefehl im SQLite Manager&lt;/div&gt;</summary>
		<author><name>Jrdesign</name></author>
	</entry>
	<entry>
		<id>https://glossar.hs-augsburg.de/w/index.php?title=Datei:Tabelle_ausgewaehlt.png&amp;diff=11751</id>
		<title>Datei:Tabelle ausgewaehlt.png</title>
		<link rel="alternate" type="text/html" href="https://glossar.hs-augsburg.de/w/index.php?title=Datei:Tabelle_ausgewaehlt.png&amp;diff=11751"/>
		<updated>2008-06-09T19:35:40Z</updated>

		<summary type="html">&lt;p&gt;Jrdesign: ausgewählte Tabelle im SQLite Manager&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;ausgewählte Tabelle im SQLite Manager&lt;/div&gt;</summary>
		<author><name>Jrdesign</name></author>
	</entry>
	<entry>
		<id>https://glossar.hs-augsburg.de/w/index.php?title=Datei:Datenbank_geoeffnet.png&amp;diff=11750</id>
		<title>Datei:Datenbank geoeffnet.png</title>
		<link rel="alternate" type="text/html" href="https://glossar.hs-augsburg.de/w/index.php?title=Datei:Datenbank_geoeffnet.png&amp;diff=11750"/>
		<updated>2008-06-09T19:17:06Z</updated>

		<summary type="html">&lt;p&gt;Jrdesign: eine geöffnete Datenbank im SQLite Manager&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;eine geöffnete Datenbank im SQLite Manager&lt;/div&gt;</summary>
		<author><name>Jrdesign</name></author>
	</entry>
	<entry>
		<id>https://glossar.hs-augsburg.de/w/index.php?title=Datei:SQLlite-Manager-Options.png&amp;diff=11749</id>
		<title>Datei:SQLlite-Manager-Options.png</title>
		<link rel="alternate" type="text/html" href="https://glossar.hs-augsburg.de/w/index.php?title=Datei:SQLlite-Manager-Options.png&amp;diff=11749"/>
		<updated>2008-06-09T19:07:44Z</updated>

		<summary type="html">&lt;p&gt;Jrdesign: Optionsdialog des SQLite Managers&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Optionsdialog des SQLite Managers&lt;/div&gt;</summary>
		<author><name>Jrdesign</name></author>
	</entry>
	<entry>
		<id>https://glossar.hs-augsburg.de/w/index.php?title=Datei:SQLiteManager-Window.png&amp;diff=11748</id>
		<title>Datei:SQLiteManager-Window.png</title>
		<link rel="alternate" type="text/html" href="https://glossar.hs-augsburg.de/w/index.php?title=Datei:SQLiteManager-Window.png&amp;diff=11748"/>
		<updated>2008-06-09T18:14:54Z</updated>

		<summary type="html">&lt;p&gt;Jrdesign: Programmoberfläche des SQLite Managers&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Programmoberfläche des SQLite Managers&lt;/div&gt;</summary>
		<author><name>Jrdesign</name></author>
	</entry>
	<entry>
		<id>https://glossar.hs-augsburg.de/w/index.php?title=Datei:SQLlite-Manager-Dialog.png&amp;diff=11747</id>
		<title>Datei:SQLlite-Manager-Dialog.png</title>
		<link rel="alternate" type="text/html" href="https://glossar.hs-augsburg.de/w/index.php?title=Datei:SQLlite-Manager-Dialog.png&amp;diff=11747"/>
		<updated>2008-06-09T17:35:03Z</updated>

		<summary type="html">&lt;p&gt;Jrdesign: Installationsdialog für die Installation des SQLite Manager Addons für Firefox.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Installationsdialog für die Installation des SQLite Manager Addons für Firefox.&lt;/div&gt;</summary>
		<author><name>Jrdesign</name></author>
	</entry>
	<entry>
		<id>https://glossar.hs-augsburg.de/w/index.php?title=Datei:New_Flex_Project_2.png&amp;diff=11549</id>
		<title>Datei:New Flex Project 2.png</title>
		<link rel="alternate" type="text/html" href="https://glossar.hs-augsburg.de/w/index.php?title=Datei:New_Flex_Project_2.png&amp;diff=11549"/>
		<updated>2008-04-30T19:35:43Z</updated>

		<summary type="html">&lt;p&gt;Jrdesign: Tutorial zum Erstellen eines neuen Flex Projektes (Bild 2)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Tutorial zum Erstellen eines neuen Flex Projektes (Bild 2)&lt;/div&gt;</summary>
		<author><name>Jrdesign</name></author>
	</entry>
	<entry>
		<id>https://glossar.hs-augsburg.de/w/index.php?title=Datei:New_Flex_Project_1.png&amp;diff=11548</id>
		<title>Datei:New Flex Project 1.png</title>
		<link rel="alternate" type="text/html" href="https://glossar.hs-augsburg.de/w/index.php?title=Datei:New_Flex_Project_1.png&amp;diff=11548"/>
		<updated>2008-04-30T19:27:11Z</updated>

		<summary type="html">&lt;p&gt;Jrdesign: Tutorial zum Erstellen eines neuen Flex-Projektes (Bild1)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Tutorial zum Erstellen eines neuen Flex-Projektes (Bild1)&lt;/div&gt;</summary>
		<author><name>Jrdesign</name></author>
	</entry>
</feed>