· 6 years ago · Sep 05, 2019, 01:48 PM
1
2<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3<html xmlns="http://www.w3.org/1999/xhtml">
4<head>
5 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
6 <meta http-equiv="Content-Style-Type" content="text/css" />
7 <meta name="generator" content="pandoc" />
8 <meta name="author" content="2019-09-05" />
9 <title>Datenbanken</title>
10 <style type="text/css">code{white-space: pre;}</style>
11 <style type="text/css">
12div.sourceCode { overflow-x: auto; }
13table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode {
14 margin: 0; padding: 0; vertical-align: baseline; border: none; }
15table.sourceCode { width: 100%; line-height: 100%; }
16td.lineNumbers { text-align: right; padding-right: 4px; padding-left: 4px; color: #aaaaaa; border-right: 1px solid #aaaaaa; }
17td.sourceCode { padding-left: 5px; }
18code > span.kw { color: #0000ff; } /* Keyword */
19code > span.ch { color: #008080; } /* Char */
20code > span.st { color: #008080; } /* String */
21code > span.co { color: #008000; } /* Comment */
22code > span.ot { color: #ff4000; } /* Other */
23code > span.al { color: #ff0000; } /* Alert */
24code > span.er { color: #ff0000; font-weight: bold; } /* Error */
25code > span.wa { color: #008000; font-weight: bold; } /* Warning */
26code > span.cn { } /* Constant */
27code > span.sc { color: #008080; } /* SpecialChar */
28code > span.vs { color: #008080; } /* VerbatimString */
29code > span.ss { color: #008080; } /* SpecialString */
30code > span.im { } /* Import */
31code > span.va { } /* Variable */
32code > span.cf { color: #0000ff; } /* ControlFlow */
33code > span.op { } /* Operator */
34code > span.bu { } /* BuiltIn */
35code > span.ex { } /* Extension */
36code > span.pp { color: #ff4000; } /* Preprocessor */
37code > span.do { color: #008000; } /* Documentation */
38code > span.an { color: #008000; } /* Annotation */
39code > span.cv { color: #008000; } /* CommentVar */
40code > span.at { } /* Attribute */
41code > span.in { color: #008000; } /* Information */
42 </style>
43</head>
44<body>
45<div id="header">
46<h1 class="title">Datenbanken</h1>
47<h2 class="author">2019-09-05</h2>
48</div>
49<div id="TOC">
50<ul>
51<li><a href="#a.-eigenschaften-und-architekturen-von-datenbanksystemen-..."><span class="toc-section-number">1</span> A. Eigenschaften und Architekturen von Datenbanksystemen <a href="#TOC">...</a></a><ul>
52<li><a href="#big-data-cap-theorem-..."><span class="toc-section-number">1.1</span> Big-Data, CAP-Theorem <a href="#TOC">...</a></a></li>
53<li><a href="#acid-vs.-base-..."><span class="toc-section-number">1.2</span> ACID vs. BASE <a href="#TOC">...</a></a></li>
54</ul></li>
55<li><a href="#b.-grundlagen-datenmodelle-..."><span class="toc-section-number">2</span> B. Grundlagen Datenmodelle <a href="#TOC">...</a></a><ul>
56<li><a href="#attributwerte-schlüssel-..."><span class="toc-section-number">2.1</span> Attributwerte, Schlüssel <a href="#TOC">...</a></a></li>
57<li><a href="#datentypen-..."><span class="toc-section-number">2.2</span> Datentypen <a href="#TOC">...</a></a></li>
58<li><a href="#normalformen-..."><span class="toc-section-number">2.3</span> Normalformen <a href="#TOC">...</a></a></li>
59</ul></li>
60<li><a href="#c.-datenmodellierung-systemanalyse-..."><span class="toc-section-number">3</span> C. Datenmodellierung / Systemanalyse <a href="#TOC">...</a></a><ul>
61<li><a href="#assoziationen-..."><span class="toc-section-number">3.1</span> Assoziationen <a href="#TOC">...</a></a></li>
62<li><a href="#vererbung-attribute-..."><span class="toc-section-number">3.2</span> Vererbung, Attribute <a href="#TOC">...</a></a></li>
63</ul></li>
64<li><a href="#d.-datenbankabfrage-sql-..."><span class="toc-section-number">4</span> D. Datenbankabfrage (SQL) <a href="#TOC">...</a></a><ul>
65<li><a href="#joins-..."><span class="toc-section-number">4.1</span> Joins <a href="#TOC">...</a></a></li>
66<li><a href="#index-..."><span class="toc-section-number">4.2</span> Index <a href="#TOC">...</a></a></li>
67<li><a href="#aufgaben-..."><span class="toc-section-number">4.3</span> Aufgaben <a href="#TOC">...</a></a></li>
68<li><a href="#aufgaben-nordwind-..."><span class="toc-section-number">4.4</span> Aufgaben Nordwind <a href="#TOC">...</a></a></li>
69</ul></li>
70<li><a href="#e.-datenbankdefinition-ddl-..."><span class="toc-section-number">5</span> E. Datenbankdefinition (DDL) <a href="#TOC">...</a></a><ul>
71<li><a href="#constraints-..."><span class="toc-section-number">5.1</span> Constraints <a href="#TOC">...</a></a></li>
72<li><a href="#views-collections-..."><span class="toc-section-number">5.2</span> Views, Collections <a href="#TOC">...</a></a></li>
73</ul></li>
74<li><a href="#f.-datenbankmanipulation-dml-..."><span class="toc-section-number">6</span> F. Datenbankmanipulation (DML) <a href="#TOC">...</a></a><ul>
75<li><a href="#grundlagen-..."><span class="toc-section-number">6.1</span> Grundlagen <a href="#TOC">...</a></a></li>
76<li><a href="#dml-mongodb-..."><span class="toc-section-number">6.2</span> DML MongoDB <a href="#TOC">...</a></a></li>
77<li><a href="#dml-mongodb2-..."><span class="toc-section-number">6.3</span> DML MongoDB2 <a href="#TOC">...</a></a></li>
78</ul></li>
79<li><a href="#g.-datenbankanwendungen-..."><span class="toc-section-number">7</span> G. Datenbankanwendungen <a href="#TOC">...</a></a><ul>
80<li><a href="#trigger-..."><span class="toc-section-number">7.1</span> Trigger <a href="#TOC">...</a></a></li>
81<li><a href="#skriptsprachen-..."><span class="toc-section-number">7.2</span> Skriptsprachen <a href="#TOC">...</a></a></li>
82</ul></li>
83<li><a href="#h.-administration-von-datenbanksystemen-..."><span class="toc-section-number">8</span> H. Administration von Datenbanksystemen <a href="#TOC">...</a></a><ul>
84<li><a href="#installation-konfiguration-..."><span class="toc-section-number">8.1</span> Installation, Konfiguration <a href="#TOC">...</a></a></li>
85<li><a href="#export-backup-..."><span class="toc-section-number">8.2</span> Export, Backup <a href="#TOC">...</a></a></li>
86</ul></li>
87</ul>
88</div>
89<h1 id="a.-eigenschaften-und-architekturen-von-datenbanksystemen-..."><span class="header-section-number">1</span> A. Eigenschaften und Architekturen von Datenbanksystemen <a href="#TOC">...</a></h1>
90<h2 id="big-data-cap-theorem-..."><span class="header-section-number">1.1</span> Big-Data, CAP-Theorem <a href="#TOC">...</a></h2>
91<p>Ein technischer Berater möchte seinem Kunden die wesentlichen Merkmale von NoSQL-Datenbanken präsentieren.</p>
92<ol class="example" style="list-style-type: decimal">
93<li>Nennen und beschreiben Sie die grundlegenden technischen Herausforderungen im Big-Data-Umfeld.</li>
94</ol>
95<hr />
96<ul>
97<li>Volume</li>
98<li>Velocity</li>
99<li>Variety</li>
100</ul>
101<p>Bei <em>Volume</em> geht es um die schiere Menge an Daten, die pro Zeiteinheit gespeichert werden muss.</p>
102<p><em>Velocity</em> adressiert die Geschwindigkeit, mit der die Daten gespeichert, aber auch verarbeitet werden.</p>
103<p>Der Aspekt <em>Variety</em> bezieht sich auf die unterschiedlichen Grade von Strukturiertheit der Daten, das reicht von völlig unstrukturiert über semistrukturiert bis hin zu stark strukturiert.</p>
104<p>Daneben machen zwei weitere Dinge den Begriff Big Data aus:</p>
105<ul>
106<li>Kostenersparnis durch elastische Skalierung und die</li>
107<li>Gewinnung neuer Informationen aus den Daten.</li>
108</ul>
109<hr />
110<hr />
111<ol start="2" class="example" style="list-style-type: decimal">
112<li>Begründen Sie den Einsatz von NoSQL-Datenbanken.</li>
113</ol>
114<hr />
115<ul>
116<li>Der Begriff NoSQL leitet sich ab von <em>not only SQL</em>, wobei SQL als Synonym für relationale Datenbankensysteme verwendet wird.</li>
117<li>Die Grundidee ist die, dass man sich beim Umsetzen seiner konkreten Anforderungen (ob nun Big Data oder nicht) nicht im Vorhinein auf relationale Datenbanksysteme (RDBMS) beschränkt.</li>
118<li>Entstanden sind die NoSQL-Datenbanken in der <strong>Web-2.0-Welt</strong>. Soziale Netzwerke wie Facebook, Twitter und Co. haben mit vielen Millionen, über den ganzen Globus verteilten Benutzern ganz andere Anforderungen an die Datenhaltung als das Bestandsführungssystem eines Versicherungsunternehmens. Es müssen sehr viele Daten sehr schnell gespeichert und abgerufen können. Dabei stoßen relationale Datenbanksysteme durchaus an ihre Grenzen.</li>
119</ul>
120<hr />
121<hr />
122<ol start="3" class="example" style="list-style-type: decimal">
123<li>Nennen und beschreiben Sie die wichtigsten Kategorien von NoSQL-Datenbanken.</li>
124</ol>
125<hr />
126<ul>
127<li><em>Key-Value</em>-Datenbanken verwalten Tupel bestehend aus einem Schlüssel und einem Wert. Abfragen sind nur über den einen Schlüssel möglich. Der Wert des Datensatzes ist in der Regel ein Byte-Array, ist also im Sinne des Variety-Aspekts völlig unstrukturiert.</li>
128<li><em>Spaltenorientierte</em> Datenbanken, im Englischen <em>Wide Column Stores</em>, verwenden Tabellen, bei denen ein Datensatz allerdings eine dynamische Anzahl an Spalten haben kann. Indizes sind frei definierbar und ermöglichen die Abfrage über beliebige Spalten.</li>
129<li><em>Graphen</em>-Datenbanken spezialisieren sich auf die Verwaltung von Knoten und Kanten zwischen diesen Knoten.</li>
130<li><em>Dokumentenorientierte</em> Datenbanken</li>
131</ul>
132<dl>
133<dt>.</dt>
134<dd><img src="/home/user/acha/www-img/mongodb/f01-01.jpg" />
135</dd>
136</dl>
137<hr />
138<hr />
139<ol start="4" class="example" style="list-style-type: decimal">
140<li>Nennen und beschreiben Sie die wesentlichsten Eigenschaften von MongoDB.</li>
141</ol>
142<hr />
143<ul>
144<li>MongoDB gehört zur Kategorie der sogenannten dokumentenorientierten Datenbanken.</li>
145<li>Der Begriff <em>Mongo</em> leitet sich vom Englischen <em>hu<strong>mongo</strong>us</em> ab, was so viel wie <em>gigantisch</em> oder <em>wahnsinnig groß</em> bedeutet, was dann zu einem versteckten Hinweis auf den <em>Volume</em>-Aspekt von Big Data interpretiert werden kann.</li>
146<li>MongoDB ist Open Source (Gnu AGPL), es gibt allerdings auch kommerziellen Support von der Firma <em>MongoDB Inc</em>.</li>
147<li>Auch für Volume und Velocity bietet MongoDB Lösungen an: Den Big-Data-Aspekten <em>Volume</em> und <em>Velocity</em> ist in der Regel nur mit dem Einsatz von verteilten Systemen zu begegnen, in denen die Last und die Daten auf viele einzelne Rechnerknoten verteilt werden.</li>
148</ul>
149<hr />
150<hr />
151<ol start="5" class="example" style="list-style-type: decimal">
152<li>Beschreiben Sie das CAP-Theorem.</li>
153</ol>
154<hr />
155<p>Bei der Implementierung eines verteilten (Datenbank-)Systems können nicht alle Anforderungen an Konsistenz, Verfügbarkeit und Toleranz gegenüber Ausfällen gleichzeitig in vollem Maße erreichen kann.</p>
156<p>Das <em>CAP-Theorem</em> besagt, dass in verteilten Systemen maximal zwei der drei folgenden Eigenschaften gleichzeitig gelten können:</p>
157<ul>
158<li><p>Consistency (C):</p>
159<p>Alle Knoten haben jederzeit den gleichen Datenbestand.</p></li>
160<li><p>Availability (A):</p>
161<p>Das System steht für Lese- und Schreibzugriffe zur Verfügung.</p></li>
162<li><p>Partition Tolerance (P):</p>
163<p>Toleranz gegenüber dem Ausfall einzelner Knoten und/oder Netzwerkstrecken.</p></li>
164</ul>
165<p>Die Eigenschaften sind dabei als graduelle Größen zu verstehen, d. h., sie können irgendwo zwischen gar nicht und voll erfüllt liegen.</p>
166<hr />
167<hr />
168<ol start="6" class="example" style="list-style-type: decimal">
169<li><p>Erörtern Sie das CAP-Theorem mit einem System, das aus zwei Knoten besteht.</p>
170<p>Das Netzwerk zwischen diesen Knoten soll gestört sein, sodass eine Partition des Systems in zwei Teile vorliegt, die sich gegenseitig nicht mehr erreichen können.</p></li>
171</ol>
172<dl>
173<dt>.</dt>
174<dd><img src="/home/user/my/acha/www-img/mongodb/f01-02.jpg" />
175</dd>
176</dl>
177<!--  -->
178<hr />
179<ol style="list-style-type: lower-alpha">
180<li>Erlaubt man nun einem der Knoten, seinen Zustand zu ändern (also im Falle eines Datenbanksystems schreibende Operationen auszuführen), wird das Gesamtsystem inkonsistent, man gibt also <em>C</em> auf.</li>
181<li>Will man die Konsistenz erhalten, muss der Knoten, dessen Zustand sich nicht ändert, sich als nicht verfügbar »abmelden« (da er sonst gegenüber den Clients einen nicht aktuellen Datenbestand ausliefern würde), womit man die Verfügbarkeit (<em>A</em>) des Systems auf nur noch einen Knoten reduziert.</li>
182<li>Nur wenn alle Knoten stets miteinander kommunizieren können, kann man dauerhaft <em>C</em> und <em>A</em> aufrecht erhalten, was dann offenbar im Widerspruch zu <em>P</em> steht.</li>
183</ol>
184<hr />
185<hr />
186<ol start="7" class="example" style="list-style-type: decimal">
187<li>Vergleichen Sie relationale Datenbanksysteme mit NoSQL-Datenbanken bezüglich des CAP-Theorems.</li>
188</ol>
189<hr />
190<p>Relationale Datenbanksysteme fallen in der Regel in die CA-Kategorie, da sie großen Wert auf die Konsistenz legen und auch hohe Verfügbarkeiten garantieren. Bei Systemen, die nur auf einem Knoten laufen, kann die Ausfallsicherheit durch den Kauf sehr teurer Hardware ebenfalls nah an die 100% gebracht werden. Fällt der eine Knoten aus, ist das System aber nicht mehr verfügbar. Bei Datenbank-Clustern verringert sich die Verfügbarkeit, da die Transaktionen zur Sicherstellung der Konsistenz auf mehreren Knoten eine längere Laufzeit haben.</p>
191<p>Bei vielen NoSQL-Datenbanken kann man aufgrund der hohen Verteilung nicht auf die Partition Tolerance (<em>P</em>) verzichten. Da die Verfügbarkeit (<em>A</em>) ebenfalls einen sehr hohen Stellenwert einnimmt (da man grundsätzlich alle Anfragen an das System beantworten können möchte), bleibt nur der Ausweg, an der Konsistenz (<em>C</em>) zu sparen.</p>
192<h2 id="acid-vs.-base-..."><span class="header-section-number">1.2</span> ACID vs. BASE <a href="#TOC">...</a></h2>
193<p>Ein technischer Berater möchte seinem Kunden die Zuverlässigkeit von relationalen und NoSQL-Datenbanken erläutern.</p>
194<ol start="8" class="example" style="list-style-type: decimal">
195<li>Erklären Sie den Begriff "Transaktion".</li>
196</ol>
197<hr />
198<ul>
199<li>Eine Transaktion ist also eine Folge von Operationen, die atomar, konsistent, isoliert und dauerhaft ist.</li>
200<li>Diese Folge von Elementaroperationen wird entweder als Ganzes abgeschlossen oder in ihrer Gesamtheit abgebrochen und zurückgesetzt.</li>
201<li>Sie führt die Datenbank von einem konsistenten Zustand in einen anderem konsistenten Zustand über.</li>
202</ul>
203<hr />
204<hr />
205<ol start="9" class="example" style="list-style-type: decimal">
206<li>Nennen und beschreiben Sie die SQL-Befehle zur Transaktionskontrolle.</li>
207</ol>
208<hr />
209<p><strong>Beispiel</strong></p>
210<pre><code> BEGIN;
211 INSERT INTO dept VALUES (10, "ACCOUNTING", "NEW YORK");
212 INSERT INTO emp VALUES (7782, "CLARK", "MANAGER", 7839, "1981-06-09", "2450.00", NULL, 10);
213 INSERT INTO emp VALUES (7934, "MILLER", "CLERK", 7782, "1982-01-23", "1300.00", NULL, 10);
214 COMMIT;</code></pre>
215<p><strong><code>BEGIN</code></strong></p>
216<p>Legt den Beginn der Transaktion fest. Alle folgenden Befehle werden zu einer Transaktion gebündelt.</p>
217<p><strong><code>COMMIT</code></strong></p>
218<p>Änderungen permanent machen. Bis zur Eingabe von COMMIT können Änderungen mit ROLLBACK annulliert werden.</p>
219<p><strong><code>ROLLBACK</code></strong></p>
220<p>Macht Änderungen (INSERT, UPDATE) rückgängig und zwar bis zu dem Punkt an dem letztmalig COMMIT eingegeben wurde.</p>
221<hr />
222<hr />
223<ol start="10" class="example" style="list-style-type: decimal">
224<li>Erklären Sie das Zweiphasen-Commit-Protokoll.</li>
225</ol>
226<hr />
227<p>Das Zweiphasen-Commit-Protokoll bestimmt die Art der abschließenden Synchronisation zwischen Subtransaktionen in einem verteilten Datenbankmanagementsystem.</p>
228<hr />
229<hr />
230<ol start="11" class="example" style="list-style-type: decimal">
231<li>Nennen und beschreiben Sie die Bedingungen des ACID-Prinzips.</li>
232</ol>
233<hr />
234<ul>
235<li>Atomarität(Atomicity): Eine Transaktion wird entweder vollständig ausgeführt oder sie hinterläßt keinerlei Wirkung.</li>
236<li>Konsistenz(Consistency): Eine Transaktion führt einen konsistenten Datenbestand wieder in einen solchen über.</li>
237<li>Isolation(Isolation): Die Zwischenergebnisse einer Transaktion sind für andere Transaktionen nicht sichtbar.</li>
238<li>Dauerhaftigkeit(Durability): Die Änderungen einer beendeten und bestätigten Transaktion können weder verloren gehen noch rückgängig gemacht werden.</li>
239</ul>
240<hr />
241<hr />
242<ol start="12" class="example" style="list-style-type: decimal">
243<li>Erörtern Sie Motivation und Konsequenzen des ACID-Prinzips.</li>
244</ol>
245<hr />
246<ul>
247<li>Um eine Datenbank in einem konsistenten Zustand zu halten, ist es nötig, dass Änderungen, die ein Anwender an Datensätzen vorgenommen hat, von einem anderen <strong>nicht überschrieben</strong> werden können und somit relevante Informationen verloren gehen.</li>
248<li>Mit Hilfe von <strong>Transaktionen</strong> können also mehrere Anwender gleichzeitig mit der Datenbank arbeiten, ohne dass es zu Problemen aufgrund von Inkonsistenzen kommt.</li>
249<li>Durch die <strong>Nebenläufigkeit</strong>, also die Koexistenz mehrerer konkurrierender Transaktionen, ist das ACID-Prinzip allerdings gefährdet.</li>
250<li>Darum benötigen Transaktionssysteme
251<ul>
252<li>Maßnahmen zur <strong>Koordination von Transaktionen</strong> sowie zur</li>
253<li>Erhaltung und <strong>Wiederherstellung der Daten</strong> und ihrer Konsistenz nach Fehlern, verursacht beispielsweise durch Systemausfälle.</li>
254</ul></li>
255</ul>
256<hr />
257<hr />
258<ol start="13" class="example" style="list-style-type: decimal">
259<li>Erläutern Sie das BASE-Prinzip.</li>
260</ol>
261<hr />
262<ul>
263<li>NoSQL-Datenbanken können eine Konsistenz im Sinne des ACID-Prinzips oft nicht garantieren, gewährleisten dann aber einen anderen Grad an Konsistenz.</li>
264<li>Hier kommt der Begriff BASE ins Spiel:
265<ul>
266<li><em>B</em>asically <em>A</em>vailable</li>
267<li><em>S</em>oft State</li>
268<li><em>E</em>ventual Consistency</li>
269</ul></li>
270<li>Dieses Akronym will den Gegensatz zu ACID (im Englischen Säure) und BASE (Lauge) aus der Chemie aufgreifen.</li>
271<li>Die beiden Begriffe <em>Basically Available</em> und <em>Soft State</em> sind nicht präzise definiert, greifen aber die Verfügbarkeit (A) des CAP-Theorems auf.</li>
272<li>Unter <em>Eventual Consistency</em> wird relativ klar das C des CAP-Theorems adressiert, und zwar in dem Sinne, dass das verteilte System (nach einer möglichst kurzen Zeitspanne der Inkonsistenz) <em>letztendlich</em> wieder in einem konsistenten Zustand ist.</li>
273</ul>
274<hr />
275<hr />
276<ol start="14" class="example" style="list-style-type: decimal">
277<li>Nennen Sie ein Beispiel für die <em>Eventual Consistency</em> des BASE-Prinzips.</li>
278</ol>
279<hr />
280<p>Ein Beispiel mit zwei Knoten:</p>
281<ul>
282<li>Schreibzugriffe sind nur an einem der Knoten, den wir Master nennen, erlaubt.</li>
283<li>Der Master repliziert den Datenbestand in regelmäßigen Abständen an den anderen Knoten, den wir Slave nennen.</li>
284<li>Lesezugriffe sind an beiden Knoten erlaubt.</li>
285<li>Nach einem Schreibvorgang auf dem Master sehen Clients, die vom Slave lesen, die neuen oder geänderten Daten nicht sofort.</li>
286<li>Erst nach Abschluss der Replikation, die ggf. asynchron arbeitet, ist der Slave wieder auf dem aktuellen Stand.</li>
287</ul>
288<hr />
289<hr />
290<ol start="15" class="example" style="list-style-type: decimal">
291<li>Beschreiben Sie Transaktionen in MongoDB.</li>
292</ol>
293<hr />
294<ul>
295<li>Mit MongoDB können Sie keine Transaktionen fahren, die mehr als ein Dokument umfassen.</li>
296<li>Selbst bei Operationen auf nur einem Dokument ist kein explizites Rollback möglich.</li>
297<li>Immerhin sind Änderungen an einem Dokument aber atomar im Sinne des ACID-Prinzips. Da Sie ganze Objektnetze in einem Dokument unterbringen können, sind dokumentenübergreifende Transaktionen oft auch gar nicht notwendig.</li>
298</ul>
299<h1 id="b.-grundlagen-datenmodelle-..."><span class="header-section-number">2</span> B. Grundlagen Datenmodelle <a href="#TOC">...</a></h1>
300<h2 id="attributwerte-schlüssel-..."><span class="header-section-number">2.1</span> Attributwerte, Schlüssel <a href="#TOC">...</a></h2>
301<p>Wir betrachten eine Bank.</p>
302<blockquote>
303<ul>
304<li>Hans Meyer eröffnet am 4.7.1993 ein Geschäftskonto mit der Kontonummer 4711.<br />
305Er wird dadurch zum Kunden der Bank.<br />
306</li>
307<li>Zwei Monate später eröffnet er bei der gleichen Bank noch ein privates Konto, das die Kontonummer 1234 erhält.<br />
308</li>
309<li>Jedes Konto lautet nur auf den Namen Hans Meyer.</li>
310</ul>
311</blockquote>
312<ol start="16" class="example" style="list-style-type: decimal">
313<li>Modellieren Sie diesen Sachverhalt in einem Objektdiagramm.</li>
314</ol>
315<hr />
316<dl>
317<dt>.</dt>
318<dd><img src="/home/user/acha/www-img/db/kunde-objektdia.jpg" />
319</dd>
320</dl>
321<ul>
322<li>Bei Objektdiagrammen gehört der Klassennamen unterstrichen.</li>
323<li>Die Verbindungen zwischen den Objekten werden auch als Links bezeichnet.</li>
324<li>Es müssen nicht alle Attribute der Klasse angegeben werden.</li>
325</ul>
326<hr />
327<hr />
328<ol start="17" class="example" style="list-style-type: decimal">
329<li>Modellieren Sie diesen Sachverhalt in einem Klassendiagramm.</li>
330</ol>
331<hr />
332<dl>
333<dt>.</dt>
334<dd><img src="/home/user/acha/www-img/db/kunde-klassendia.jpg" />
335</dd>
336</dl>
337<hr />
338<hr />
339<ol start="18" class="example" style="list-style-type: decimal">
340<li>Beschreiben Sie die Darstellung von Klassen mit ihren Rubriken in UML.</li>
341</ol>
342<hr />
343<ul>
344<li>Klassen werden durch Rechtecke dargestellt, die entweder nur
345<ul>
346<li>den Namen der Klasse (fett gedruckt) tragen oder zusätzlich auch</li>
347<li>Attribute und</li>
348<li>Methoden spezifiziert haben.</li>
349</ul></li>
350<li>Dabei werden diese drei Rubriken (engl. compartment) – Klassenname, Attribute, Methoden – jeweils durch eine horizontale Linie getrennt.</li>
351<li>Wenn die Klasse keine Methoden besitzt, kann die unterste horizontale Linie entfallen.</li>
352</ul>
353<hr />
354<hr />
355<ol start="19" class="example" style="list-style-type: decimal">
356<li>Beschreiben Sie die wesentlichsten Merkmale von UML.</li>
357</ol>
358<hr />
359<ul>
360<li>UML ist die Abkürzung für Unified Modeling Language</li>
361<li>UML ist der bislang erfolgreichste Versuch, eine allgemeine Norm für technische Zeichnungen in der Informatik zu schaffen.</li>
362<li>UML hat verschiedene Diagrammtypen wie
363<ul>
364<li>Klassendiagramm</li>
365<li>Objektdiagramm</li>
366<li>Anwendungsfalldiagramm (Use-Casediagramm)</li>
367</ul></li>
368<li>Mit den UML-Diagrammen kann man Strukturen und Abläufe in objektorientierten Programmsystemen darstellen.</li>
369</ul>
370<hr />
371<hr />
372<ol start="20" class="example" style="list-style-type: decimal">
373<li><p>Vergleichen Sie die Darstellung von Attributen in Klassen- und Objekdiagrammen.</p></li>
374<li><p>Erklären Sie die Begriffe "Attribut", "optionales Attribut" und "Attributwert".</p></li>
375</ol>
376<hr />
377<hr />
378<p>Die <strong>Attribute</strong> beschreiben die Daten, die von den Objekten einer Klasse angenommen werden können. Jedes Attribut ist von einem bestimmten Typ. Alle Objekte einer Klasse besitzen dieselben Attribute, jedoch unterschiedliche <strong>Attributwerte</strong>.</p>
379<p>Während die Klasse festlegt, welche Attribute ihre Objekte besitzen, enthalten die Objekte die Attributwerte.</p>
380<p>Das Feld für den Attributwert darf leer sein. Wir sprechen von einem <strong>optionalen Attribut</strong>. Das bedeutet, daß dieses Attribut nicht bei der Erzeugung des Objekts, sondern zu irgendeinem späteren Zeitpunkt – evtl. auch nie – einen definierten Wert erhält.</p>
381<p>In Objektdiagrammen werden die Attribute mit den Attributwerten dargestellt, in Klassendiagrammen werden nur die Attribute dargestellt.</p>
382<hr />
383<p>Ein Kleinunternehmen hat sich dazu entschieden, ihre Angestellten- und Filialdaten in einer relationalen Datenbank zu verwalten. Dadurch kann das Unternehmen besonders einfach den Datenbestand auswerten.</p>
384<pre><code> |EMPNO| ENAME | JOB | MGR | HIREDATE | SAL | COMM | DEPTNO |
385 | 7782| CLARK | MANAGER | 7839 | 1981-06-09 | 2450.00 | NULL | 10 |
386 | 7839| KING | PRESIDENT | NULL | 1981-11-17 | 5000.00 | NULL | 10 |
387
388 |DEPTNO| DNAME | LOC |
389 | 10| ACCOUNTING| NEW YORK |</code></pre>
390<ol start="22" class="example" style="list-style-type: decimal">
391<li>Ermitteln Sie den Primär-, Sekundär- und Fremdschlüssel.</li>
392</ol>
393<hr />
394<p><strong>emp</strong></p>
395<ul>
396<li>Primärschlüssel: empno</li>
397<li>Fremdschlüssel: mgr, deptno</li>
398</ul>
399<p><strong>dept</strong></p>
400<ul>
401<li>Primärschlüssel: deptno</li>
402<li>Sekundärschlüssel: dname</li>
403</ul>
404<hr />
405<hr />
406<ol start="23" class="example" style="list-style-type: decimal">
407<li>Beschreiben Sie die Begriffe Schlüssel, Primär-, Sekundär- und Fremdschlüssel.</li>
408</ol>
409<hr />
410<ul>
411<li>Ein <strong>Schlüssel</strong> (=key, Schlüsselkandidat) ist eine Menge von Attributen, die ein Objekt eindeutig identifizieren.</li>
412<li>Ein Objekt kann mehrere Schlüssel haben. Genau einen dieser Schlüssel wählt besonders aus. Man nennt ihn <strong>Primärschlüssel</strong> (=primary key).</li>
413<li>Alle anderen Schlüssel sind <strong>Sekundärschlüssel</strong> (= secondary key).</li>
414<li>Ein <strong>Fremdschlüssel</strong> ist ein Attribut oder eine Attributkombination, das/die in einer anderen Relation Primärschlüssel ist.</li>
415</ul>
416<hr />
417<hr />
418<ol start="24" class="example" style="list-style-type: decimal">
419<li>Erklären Sie den Zusammenhang zwischen dem Uniqueness-Constraint und Schlüsseln.</li>
420</ol>
421<hr />
422<ul>
423<li>Der <strong>Uniqueness-Constraint</strong> (=Eindeutigkeitseinschränkung) verhindert, dass mehrere Datensätze denselben Attributwert (diesselben Attributwerte) haben.</li>
424<li>Attribute sind entweder <strong>optional</strong> oder <strong>verpflichtend(=mandatory)</strong>: Optionale Attribute können auch keinen Wert annehmen. Das heißt, sie können den Wert NULL enthalten.</li>
425<li>Attribute, die verpflichtend und unique sind, sind <strong>Schlüssel</strong>.</li>
426</ul>
427<h2 id="datentypen-..."><span class="header-section-number">2.2</span> Datentypen <a href="#TOC">...</a></h2>
428<p>Ein Kleinunternehmen hat sich dazu entschieden, ihre Angestellten- und Filialdaten in einer relationalen Datenbank zu verwalten. Dadurch kann das Unternehmen besonders einfach den Datenbestand auswerten.</p>
429<pre><code> |EMPNO| ENAME | JOB | MGR | HIREDATE | SAL | COMM | DEPTNO |
430 | 7782| CLARK | MANAGER | 7839 | 1981-06-09 | 2450.00 | NULL | 10 |
431 | 7839| KING | PRESIDENT | NULL | 1981-11-17 | 5000.00 | NULL | 10 |
432
433 |DEPTNO| DNAME | LOC |
434 | 10| ACCOUNTING| NEW YORK |</code></pre>
435<hr />
436<ol start="25" class="example" style="list-style-type: decimal">
437<li>Modellieren Sie diesen Sachverhalt in einem Objektdiagramm.</li>
438</ol>
439<hr />
440<dl>
441<dt>.</dt>
442<dd><img src="/home/user/acha/www-img/db/uml-object.jpg" />
443</dd>
444</dl>
445<hr />
446<hr />
447<ol start="26" class="example" style="list-style-type: decimal">
448<li>Beschreiben Sie die Darstellung von Datentypen in UML.</li>
449</ol>
450<hr />
451<p>In der UML ist nicht festgelegt, wie der <strong>Typ</strong> eines Attributs definiert wird. Um ein standardisiertes OOA-Modell zu erstellen, verwenden wir in der Systemanalyse folgende Typen:</p>
452<ul>
453<li>Standardtypen,</li>
454<li>Aufzählungstypen,</li>
455<li>(elementare) Klassen,</li>
456<li>list of Typ, wobei ein beliebiger Typ erlaubt ist.</li>
457</ul>
458<p>Mit anderen Worten:</p>
459<p><code>Typ = [Standardtyp | Aufzählungstyp | Klasse | list of Typ]</code></p>
460<p>In der Analyse dient die Typdefinition dem Zweck, das Attribut aus fachlicher Sicht möglichst präzise zu beschreiben. In Entwurf und Implementierung wird dann in Abhängigkeit von der gewählten Programmiersprache der Typ neu definiert.</p>
461<hr />
462<hr />
463<ol start="27" class="example" style="list-style-type: decimal">
464<li>Beschreiben Sie die Darstellung der Standardtypen in UML.</li>
465</ol>
466<hr />
467<p>Als <strong>Standardtypen</strong> stehen dem Systemanalytiker zur Verfügung:</p>
468<ul>
469<li><code>String</code> = String (Länge)</li>
470<li><code>Int</code>: ganze Zahl von 32 Bit</li>
471<li><code>UInt</code>: positive ganze Zahl 32 Bit</li>
472<li><code>Float</code>: Gleitkommazahl 32 Bit</li>
473<li><code>Double</code>: Gleitkommazahl 64 Bit</li>
474<li><code>Fixed (Vorkommastellen, Nachkommastellen)</code>: Festkommazahl</li>
475<li><code>Boolean</code></li>
476<li><code>Date</code></li>
477<li><code>Time</code></li>
478</ul>
479<hr />
480<hr />
481<ol start="28" class="example" style="list-style-type: decimal">
482<li>Beschreiben Sie die Darstellung der Aufzähltypen in UML.</li>
483</ol>
484<hr />
485<p>Für einen <strong>Aufzählungstyp</strong> sind anzugeben:</p>
486<ul>
487<li><p>Bereich</p>
488<p>Hier werden alle Werte aufgezählt, die das Attribut annehmen kann.</p></li>
489<li><p>Selektionsart</p>
490<p>Es soll möglich sein, ein oder mehrere Werte zu selektieren, wobei individuell festgelegt wird, wie viele das sein können. Daher sind Angaben zur minimalen und zur maximalen Anzahl der zu selektierenden Elemente notwendig. Als Voreinstellung wird angenommen, daß genau ein Wert selektiert wird.</p></li>
491<li><p>Die Werteliste kann erweiterbar sein.</p>
492<p>In diesem Fall kann der spätere Benutzer neue Werte eingeben, die in die Liste permanent aufgenommen werden. Wir gehen davon aus, daß diese Erweiterbarkeit standardmäßig gilt.</p></li>
493</ul>
494<p>Für die Definition von Aufzählungstypen verwenden wir folgende Notation:</p>
495<p><code>{values: W1, W2, W3,</code> ... Wertebereich.<br />
496<code>select: 1..n,</code> ... Selektionsart mit minimaler und maximaler Anzahl.<br />
497<code>noAdd}</code> ... Festlegung, daß der Wertebereich nicht erweiterbar ist.</p>
498<p>Wenn bei der Selektionsart und der Erweiterbarkeit die Voreinstellungen gelten, dann reicht die Angabe der Werte, d.h. <code>{values: W1, W2, W3}</code>.</p>
499<p><strong>Alternative</strong></p>
500<p>Alternativ kann ein Aufzählungstyp auch mit Hilfe des Klassenkonstrukts beschrieben werden. Der Typ wird als Klassenname eingetragen und mit dem Stereotypen <strong>«enumeration»</strong> gekennzeichnet. Die Werte des Aufzählungstyps werden als Attribute eingetragen.</p>
501<hr />
502<hr />
503<ol start="29" class="example" style="list-style-type: decimal">
504<li>Beschreiben Sie die Darstellung von Klassen als Typen in UML.</li>
505</ol>
506<hr />
507<dl>
508<dt>.</dt>
509<dd><img src="/home/user/acha/www-img/uml/elementare-klasse.png" />
510</dd>
511</dl>
512<p>Der Typ eines Attributs kann selbst wieder durch eine Klasse beschrieben werden. Wir bezeichnen diese Klassen als <strong>elementare Klassen</strong> (support classes) und tragen sie im Gegensatz zu den (Architektur-)Klassen nicht in das Klassendiagramm des Gesamtmodells ein. Sie werden in der Regel – in Abhängigkeit von der jeweiligen Anwendung – einmal definiert und bei jedem Projekt wiederverwendet. Um Konflikte mit Attributnamen zu vermeiden, kann man an den Namen ein "T" anhängen.</p>
513<h2 id="normalformen-..."><span class="header-section-number">2.3</span> Normalformen <a href="#TOC">...</a></h2>
514<ol start="30" class="example" style="list-style-type: decimal">
515<li>In welcher Normalform befindet sich folgendes Relationen-System?</li>
516<li>Entwerfen Sie das Relationen-System in einer höheren Normalform!</li>
517</ol>
518<pre><code>Vorgang* Datum Benutzer Straße PLZ Ort
519--------- ------- -------- ---------------- ----- -------
5201352 22.1.97 ST442 Schellingstr. 3 80799 München
5211353 22.1.97 DOZ387 Oettingenstr. 67 80538 München
522
523Signatur* Titel
524---------- ---------------------
525MAI I/1 Logic Programming
526CLO I/2 Programming in Prolog
527ZEH I/1 Informationssysteme
528
529Vorgang* Signatur*
530--------- ----------
5311352 MAI I/1
5321352 CLO I/2
5331353 ZEH I/1</code></pre>
534<p>Die Primärschlüssel sind mit "*" gekennzeichnet.</p>
535<hr />
536<p>Das Relationensystem befindet sich in der zweiten Normalform.</p>
537<p>Begründung:</p>
538<ul>
539<li>Die Straße ist von dem Nichtschlüsselattribut "Benutzer" abhängig.</li>
540<li>Kein Attribut ist von einem Teilschlüsselattribut abhängig.</li>
541</ul>
542<hr />
543<p><strong>dritte Normalform</strong></p>
544<p><em>Benutzer</em></p>
545<table>
546<thead>
547<tr class="header">
548<th>Benutzer</th>
549<th align="left">Straße</th>
550<th align="left">PLZ</th>
551</tr>
552</thead>
553<tbody>
554<tr class="odd">
555<td>ST442</td>
556<td align="left">Schellingstr. 3</td>
557<td align="left">80799</td>
558</tr>
559<tr class="even">
560<td>DOZ387</td>
561<td align="left">Oettingenstr. 67</td>
562<td align="left">80538</td>
563</tr>
564</tbody>
565</table>
566<p><em>PLZVerzeichnis</em></p>
567<table>
568<thead>
569<tr class="header">
570<th align="left">PLZ</th>
571<th align="left">Ort</th>
572</tr>
573</thead>
574<tbody>
575<tr class="odd">
576<td align="left">80799</td>
577<td align="left">München</td>
578</tr>
579<tr class="even">
580<td align="left">80538</td>
581<td align="left">München</td>
582</tr>
583</tbody>
584</table>
585<p><em>Katalog</em></p>
586<table>
587<thead>
588<tr class="header">
589<th>Signatur</th>
590<th align="left">Titel</th>
591</tr>
592</thead>
593<tbody>
594<tr class="odd">
595<td>MAI I/1</td>
596<td align="left">Logic Programming</td>
597</tr>
598<tr class="even">
599<td>CLO I/2</td>
600<td align="left">Programming in Prolog</td>
601</tr>
602<tr class="odd">
603<td>ZEH I/1</td>
604<td align="left">Informationssysteme</td>
605</tr>
606</tbody>
607</table>
608<p><em>Ausleihvorgang</em></p>
609<table>
610<thead>
611<tr class="header">
612<th>Vorgang</th>
613<th align="left">Datum</th>
614<th>Benutzer</th>
615</tr>
616</thead>
617<tbody>
618<tr class="odd">
619<td>1352</td>
620<td align="left">22.1.97</td>
621<td>ST442</td>
622</tr>
623<tr class="even">
624<td>1353</td>
625<td align="left">22.1.97</td>
626<td>DOZ387</td>
627</tr>
628</tbody>
629</table>
630<p><em>Buchverleih</em></p>
631<table>
632<thead>
633<tr class="header">
634<th>Vorgang</th>
635<th>Signatur</th>
636</tr>
637</thead>
638<tbody>
639<tr class="odd">
640<td>1352</td>
641<td>MAI I/1</td>
642</tr>
643<tr class="even">
644<td>1352</td>
645<td>CLO I/2</td>
646</tr>
647<tr class="odd">
648<td>1353</td>
649<td>ZEH I/1</td>
650</tr>
651</tbody>
652</table>
653<hr />
654<hr />
655<ol start="32" class="example" style="list-style-type: decimal">
656<li>Prüfen Sie ob es eine funktionale Abhängigkeit "Benutzer -> Vorgang" gibt.</li>
657</ol>
658<hr />
659<p>Es scheint auch eine funktionale Abhängigkeit "Benutzer -> Vorgang" zu bestehen. Diese gilt aber in der wirklichen Welt nicht, denn ein Benutzer kann unter unterschiedlichen Vorgangsnummern Bücher ausgeliehen haben, auch wenn dies in der aktuellen Datenbank nicht der Fall ist.</p>
660<!--
661
662 **Beispiel**
663
664In der realen Welt gilt die folgende funktionale Abhängigkeit in der Regel
665nicht:
666
667Straße -> Ort
668
669In einer Relation mit den folgenden Einträgen aber scheint sie zu gelten:
670
671Straße Ort
672-------------- --------
673Leopoldstraße München
674Kurfürstendamm Berlin
675Gänsemarkt Hamburg
676
677-->
678<hr />
679<hr />
680<ol start="33" class="example" style="list-style-type: decimal">
681<li>Erläutern Sie die Begriffe Schlüssel, funktionale Abhängigkeit und transitive Abhängigkeit.</li>
682</ol>
683<hr />
684<p>Innerhalb des relationalen Modells spielt die Abhängigkeit von Attributen bzw. Attributskombinationen eine bedeutende Rolle.</p>
685<p>Für eine Relation R mit Attributen X und Y heißt Y <strong>funktional abhängig</strong> von X, genau dann, wenn jeder X-Wert in R genau einen Y-Wert in R bestimmt.</p>
686<p>So könnte man sich etwa eine Kundendatenbank vorstellen, in der die Anschrift und die Telefonnummer eines Kunden eindeutig durch seine Kunden-Nr bestimmt ist.</p>
687<p>Eine besondere Stellung hat der <strong>Schlüssel</strong>: er ist ein Attribut (oder eine Attributskombination) von dem alle anderen Attribut einer Relation funktional abhängig sind.</p>
688<p>Von transitiver Abhängigkeit spricht man dann, wenn ein Attribut C von einem Attribut A derart abhängig ist, daß C funktional von einem Attribut B abhängt, das seinerseits funktional von A abhängt.</p>
689<p>Ziel der Normalisierung ist, die Attribute so zu Entitätsmengen bzw. Relationen zu ordnen, daß innerhalb einer Relation <strong>keine Redundanzen</strong> auftreten.</p>
690<p>Ob eine funktionale Abhängigkeit vorliegt, ist nicht immer einfach zu beurteilen: die Abhängigkeit kann in der modellierten Welt nicht bestehen, während sie in den Einträgen der Datenbank durchaus zu finden ist:</p>
691<hr />
692<hr />
693<ol start="34" class="example" style="list-style-type: decimal">
694<li>Erläutern Sie das Konzept der Normalformen.</li>
695</ol>
696<hr />
697<p><strong>1.e Normalform</strong></p>
698<p>Alle Wertebereiche der Attribute einer Relation sind atomar. Atomar ist ein Wertebereich dann, wenn seine Werte nicht selbst Mengen sind bzw. keine innere Struktur aufweisen.</p>
699<table>
700<thead>
701<tr class="header">
702<th><em>Vorgang</em></th>
703<th align="left">Datum</th>
704<th><em>Signatur</em></th>
705<th align="left">Titel</th>
706<th>Benutzer</th>
707<th align="left">Anschrift</th>
708</tr>
709</thead>
710<tbody>
711<tr class="odd">
712<td>1352</td>
713<td align="left">22.1.97</td>
714<td>MAI I/1</td>
715<td align="left">Logic Programming</td>
716<td>ST442</td>
717<td align="left">Schellingstr. 3, 80799 München</td>
718</tr>
719<tr class="even">
720<td>1352</td>
721<td align="left">22.1.97</td>
722<td>CLO I/2</td>
723<td align="left">Programming in Prolog</td>
724<td>ST442</td>
725<td align="left">Schellingstr. 3, 80799 München</td>
726</tr>
727<tr class="odd">
728<td>1353</td>
729<td align="left">22.1.97</td>
730<td>ZEH I/1</td>
731<td align="left">Informationssysteme</td>
732<td>DOZ387</td>
733<td align="left">Oettingenstr. 67, 80538</td>
734</tr>
735</tbody>
736</table>
737<p>Diese Relation hat die Attributkombination Vorgang und Signatur als Schlüssel. Die Schlüssel sind stets die kursiven Attribute.</p>
738<p>Obige Relation ist nicht in 1.NF, da das Attribut Anschrift offensichtlich nicht atomar ist: Die Anschrift gliedert sich in Straßenname mit Nummer, Postleitzahl, und Ort.</p>
739<table>
740<thead>
741<tr class="header">
742<th><em>Vorgang</em></th>
743<th align="left">Datum</th>
744<th><em>Signatur</em></th>
745<th align="left">Titel</th>
746<th>Benutzer</th>
747<th align="left">Straße</th>
748<th align="left">PLZ</th>
749<th align="left">Ort</th>
750</tr>
751</thead>
752<tbody>
753<tr class="odd">
754<td>1352</td>
755<td align="left">22.1.97</td>
756<td>MAI I/1</td>
757<td align="left">Logic Programming</td>
758<td>ST442</td>
759<td align="left">Schellingstr. 3</td>
760<td align="left">80799</td>
761<td align="left">München</td>
762</tr>
763<tr class="even">
764<td>1352</td>
765<td align="left">22.1.97</td>
766<td>CLO I/2</td>
767<td align="left">Programming in Prolog</td>
768<td>ST442</td>
769<td align="left">Schellingstr. 3</td>
770<td align="left">80799</td>
771<td align="left">München</td>
772</tr>
773<tr class="odd">
774<td>1353</td>
775<td align="left">22.1.97</td>
776<td>ZEH I/1</td>
777<td align="left">Informationssysteme</td>
778<td>DOZ387</td>
779<td align="left">Oettingenstr. 67</td>
780<td align="left">80538</td>
781<td align="left">München</td>
782</tr>
783</tbody>
784</table>
785<p>Man unterscheidet bei der ersten Normalform die Interpretation des darunterliegenden Wertbereiches.</p>
786<table>
787<thead>
788<tr class="header">
789<th align="left">ISBN#</th>
790<th align="left">Titel</th>
791<th align="left">Autor</th>
792</tr>
793</thead>
794<tbody>
795<tr class="odd">
796<td align="left">0070447527</td>
797<td align="left">Database System Concept</td>
798<td align="left">Korth, Silberschatz</td>
799</tr>
800</tbody>
801</table>
802<p>Obwohl die Menge aller Zeichenfolgen mit n Zeichen dem Attribut Autor zugrundeliegt, ist das Beispiel nicht in 1NF, da Autor als Menge interpretiert wird.</p>
803<p>Das Tupel</p>
804<table>
805<thead>
806<tr class="header">
807<th align="left">ISBN#</th>
808<th align="left">Titel</th>
809<th align="left">Autor</th>
810</tr>
811</thead>
812<tbody>
813<tr class="odd">
814<td align="left">0070447527</td>
815<td align="left">Database System Concept</td>
816<td align="left">Korth, Silberschatz</td>
817</tr>
818</tbody>
819</table>
820<p>ist in 1NF, da Korth-Silberschatz als atomarer Wert, d.h. eine unteilbare Zeichenfolge, angesehen wird.</p>
821<hr />
822<p><strong>2.e Normalform</strong></p>
823<p>Kein Attribut der Relation ist von einem Teilschlüssel funktional abhängig.</p>
824<table>
825<thead>
826<tr class="header">
827<th><em>Vorgang</em></th>
828<th align="left">Datum</th>
829<th>Benutzer</th>
830<th align="left">Straße</th>
831<th align="left">PLZ</th>
832<th align="left">Ort</th>
833</tr>
834</thead>
835<tbody>
836<tr class="odd">
837<td>1352</td>
838<td align="left">22.1.97</td>
839<td>ST442</td>
840<td align="left">Schellingstr. 3</td>
841<td align="left">80799</td>
842<td align="left">München</td>
843</tr>
844<tr class="even">
845<td>1353</td>
846<td align="left">22.1.97</td>
847<td>DOZ387</td>
848<td align="left">Oettingenstr. 67</td>
849<td align="left">80538</td>
850<td align="left">München</td>
851</tr>
852</tbody>
853</table>
854<table>
855<thead>
856<tr class="header">
857<th><em>Signatur</em></th>
858<th align="left">Titel</th>
859</tr>
860</thead>
861<tbody>
862<tr class="odd">
863<td>MAI I/1</td>
864<td align="left">Logic Programming</td>
865</tr>
866<tr class="even">
867<td>CLO I/2</td>
868<td align="left">Programming in Prolog</td>
869</tr>
870<tr class="odd">
871<td>ZEH I/1</td>
872<td align="left">Informationssysteme</td>
873</tr>
874</tbody>
875</table>
876<table>
877<thead>
878<tr class="header">
879<th><em>Vorgang</em></th>
880<th><em>Signatur</em></th>
881</tr>
882</thead>
883<tbody>
884<tr class="odd">
885<td>1352</td>
886<td>MAI I/1</td>
887</tr>
888<tr class="even">
889<td>1352</td>
890<td>CLO I/2</td>
891</tr>
892<tr class="odd">
893<td>1353</td>
894<td>ZEH I/1</td>
895</tr>
896</tbody>
897</table>
898<hr />
899<p><strong>3.e Normalform</strong></p>
900<p>Kein Attribut der Relation ist von einem Teilschlüssel oder Nichtschlüssel- Attributen funktional abhängig (transitiv).</p>
901<p>Von transitiver Abhängigkeit spricht man dann, wenn ein Attribut C von einem Attribut A derart abhängig ist, daß C funktional von einem Attribut B abhängt, das seinerseits funktional von A abhängt.</p>
902<p>Die obige Relation ist nicht in 3. NF, da z. B. die Straße funktional abhängig vom Nichtschlüsselattribut <strong>Benutzer</strong> ist.</p>
903<p><em>Benutzer</em></p>
904<table>
905<thead>
906<tr class="header">
907<th>Benutzer</th>
908<th align="left">Straße</th>
909<th align="left">PLZ</th>
910</tr>
911</thead>
912<tbody>
913<tr class="odd">
914<td>ST442</td>
915<td align="left">Schellingstr. 3</td>
916<td align="left">80799</td>
917</tr>
918<tr class="even">
919<td>DOZ387</td>
920<td align="left">Oettingenstr. 67</td>
921<td align="left">80538</td>
922</tr>
923</tbody>
924</table>
925<p><em>PLZVerzeichnis</em></p>
926<table>
927<thead>
928<tr class="header">
929<th align="left">PLZ</th>
930<th align="left">Ort</th>
931</tr>
932</thead>
933<tbody>
934<tr class="odd">
935<td align="left">80799</td>
936<td align="left">München</td>
937</tr>
938<tr class="even">
939<td align="left">80538</td>
940<td align="left">München</td>
941</tr>
942</tbody>
943</table>
944<p><em>Katalog</em></p>
945<table>
946<thead>
947<tr class="header">
948<th>Signatur</th>
949<th align="left">Titel</th>
950</tr>
951</thead>
952<tbody>
953<tr class="odd">
954<td>MAI I/1</td>
955<td align="left">Logic Programming</td>
956</tr>
957<tr class="even">
958<td>CLO I/2</td>
959<td align="left">Programming in Prolog</td>
960</tr>
961<tr class="odd">
962<td>ZEH I/1</td>
963<td align="left">Informationssysteme</td>
964</tr>
965</tbody>
966</table>
967<p><em>Ausleihvorgang</em></p>
968<table>
969<thead>
970<tr class="header">
971<th>Vorgang</th>
972<th align="left">Datum</th>
973<th>Benutzer</th>
974</tr>
975</thead>
976<tbody>
977<tr class="odd">
978<td>1352</td>
979<td align="left">22.1.97</td>
980<td>ST442</td>
981</tr>
982<tr class="even">
983<td>1353</td>
984<td align="left">22.1.97</td>
985<td>DOZ387</td>
986</tr>
987</tbody>
988</table>
989<p><em>Buchverleih</em></p>
990<table>
991<thead>
992<tr class="header">
993<th>Vorgang</th>
994<th>Signatur</th>
995</tr>
996</thead>
997<tbody>
998<tr class="odd">
999<td>1352</td>
1000<td>MAI I/1</td>
1001</tr>
1002<tr class="even">
1003<td>1352</td>
1004<td>CLO I/2</td>
1005</tr>
1006<tr class="odd">
1007<td>1353</td>
1008<td>ZEH I/1</td>
1009</tr>
1010</tbody>
1011</table>
1012<!--
1013
1014 **Speicherplatz**
1015
1016Eine Normalisierung erhöht die Anzahl der Relationen in einer Datenbank. Ein
1017Gewinn an Speicherplatz ist nicht immer gegeben, da für jede neue Relation
1018mindestens ein Attribut als Schlüsselattribut hinzugefügt werden muß (Signatur,
1019Benutzer, PLZ sind jetzt in jeweils zwei Relationen enthalten).
1020
1021Durch die Zerlegung in mehrere Relationen werden Abfragen komplizierter, da nun
1022vermehrt Joins formuliert werden müssen.
1023
1024 *Beispiel*
1025
1026Finde die Orte aller Benutzer vom 22.1.97
1027
1028~~~ sql
1029SELECT Ort
1030FROM Buchverleih
1031WHERE Datum = "22.1.97"
1032~~~
1033
1034In der Datenbank in 3. NF ist diese Abfrage wesentlich komplexer:
1035
1036~~~ sql
1037SELECT PLZVerzeichnis.Ort
1038FROM Ausleihvorgang, Benutzer, PLZVerzeichnis
1039WHERE Ausleihvorgang.Datum = "22.1.97"
1040 AND Ausleihvorgang.Benutzer = Benutzer.Benutzer
1041 AND Benutzer.PLZ = PLZVerzeichnis.PLZ
1042~~~
1043
1044Dem Nachteil der komplexen Abfragen steht die völlige Redundanzfreiheit von
1045Nichtschlüsselattributen gegenüber, die die Datenbank vor Inkonsistenzen
1046weitgehend schützt. Es ist z.B. nicht mehr möglich, einer Postleitzahl mehrere
1047Orte zuzuordnen, so wie dies sowohl in der Datenbank in 1. NF als auch in 2. NF
1048noch möglich war.
1049
1050Eine Normalisierung muß in jedem Fall mindestens theoretisch durchgeführt
1051werden, um alle Redundanzen zu erkennen. Ob diese normalisierte Datenbank dann
1052auch implementiert wird, muß nach Abwägung von Platzgewinn und zusätzlicher
1053Sicherheit gegenüber den komplizierteren Abfragen entschieden werden. In vielen
1054Fällen ist kontrollierte Redundanz ein guter Kompromiss: durch geeignete
1055Maßnahmen wie z.B. Datenbankprozeduren, die Änderungen an einem redundanten
1056Eintrag an allen weiteren Einträgen durchführen, werden Anomalien vermieden.
1057
1058
1059 **4.e Normalform**
1060
1061Kein Schlüssel-Attribut der Relation ist von anderen Schlüssel-Attributen
1062funktional abhängig.
1063
1064*Vorlesung* *Lehrer* *Buch*
1065----------- -------- ------------
1066Mathematik Mayer Mathematik 1
1067Mathematik Mayer Mathematik 2
1068Mathematik Mülle Mathematik 1
1069Mathematik Mülle Mathematik 2
1070
1071---
1072
1073 **Ein weiteres Beispiel**
1074
1075 *unnormalisierte Relation*
1076
1077*M#* P# MA-Name Proj-Name A# Abt-Name
1078---- --- ------- --------- -- --------
10791 1,2 Mayer WIFIS, VF 1 Personal
10802 2 Müller VF 2 EDV
10813 2 Weber VF 2 EDV
1082
1083 *erste Normalform*
1084
1085*M#* *P#* MA-Name Proj-Name A# Abt-Name
1086---- ---- ------- --------- -- ---------
10871 1 Mayer WIFIS 1 Personal
10881 2 Mayer VF 1 Personal
10892 2 Müller VF 2 EDV
10903 2 Weber VF 2 EDV
1091
1092 *zweite Normalform*
1093
1094Mitarbeiter
1095
1096*M#* MA-Name A# Abt-Name
1097---- ------- -- --------
10981 Mayer 1 Personal
10992 Müller 2 EDV
11003 Weber 2 EDV
1101
1102Projekt-Mitarbeit
1103
1104*M#* *P#*
1105---- ----
11061 1
11071 2
11082 2
11093 2
1110
1111Projekt
1112
1113*P#* Proj-Name
1114---- ---------
11151 WIFIS
11162 VF
1117
1118 *dritte Normalform*
1119
1120Abteilung
1121
1122*A#* Abt-Name
1123---- --------
11241 Personal
11252 EDV
1126
1127Mitarbeiter
1128
1129*M#* MA-Name A#
1130---- ------- --
11311 Mayer 1
11322 Müller 2
11333 Weber 2
1134
1135---
1136
1137 **Weiteres Beispiel**
1138
1139 *Unnormalisierte Form*
1140
1141RechnungsNr|Rechnungsdatum|KundenNr|Vorname|Name|Strasse|Plz|Ort|Anzahl|ArtikelNr|Artikel|Preis|Rechnungssumme
1142-|-|-|-|-|-|-|-|-|-|-|-|-|-
11431|3.2.2016|12|Hans|Mayer|Karlsplatz 3|1040|Wien|2,1|1002,1007|Linux-Magazin 6/16,Linux-CD|9,40.95|58.95
1144
1145 *erste Normalform*
1146
1147RechnungsNr|Rechnungsdatum|KundenNr|Vorname|Name|Strasse|Plz|Ort|Anzahl|ArtikelNr|Artikel|Preis|Rechnungssumme
1148-|-|-|-|-|-|-|-|-|-|-|-|-|-
11491|3.2.2016|12|Hans|Mayer|Karlsplatz 3|1040|Wien|2|1002|Linux-Magazin 6/16|9|58.95
11501|3.2.2016|12|Hans|Mayer|Karlsplatz 3|1040|Wien|1|1007|Linux-CD|40.95|58.95
1151
1152 *zweite Normalform*
1153
1154RechnungsNr|Rechnungsdatum|KundenNr|Vorname|Name|Strasse|Plz|Ort|Anzahl|ArtikelNr|Preis|Rechnungssumme
1155-|-|-|-|-|-|-|-|-|-|-|-|-|-
11561|3.2.2016|12|Hans|Mayer|Karlsplatz 3|1040|Wien|2|1002|58.95
11571|3.2.2016|12|Hans|Mayer|Karlsplatz 3|1040|Wien|1|1007|58.95
1158
1159Artikelnummer|Artikel|Einzelpreis
1160-|-|-|-|-|-|-|-|-|-|-|-|-|-
11611002|Linux-Magazin|6/97|9
11621007|Linux-CD|40.95
1163
1164 *zweite Normalform*
1165
1166RechnungsNr|Rechnungsdatum|KundenNr|Vorname|Name|Strasse|Plz|Ort|Rechnungssumme
1167-|-|-|-|-|-|-|-|-|-|-|-|-|-
11681|3.2.2016|12|Hans|Mayer|Karlsplatz 3|1040|Wien|58.95
1169
1170 Rechnungsposition
1171
1172RechnungsNr|ArtikelNr|Anzahl
1173-|-|-|-|-|-|-|-|-|-|-|-|-|-
11741|1002|2
11751|1007|1
1176
1177 *dritte Normalform*
1178
1179RechnungsNr|Rechnungsdatum|KundenNr|Rechnungssumme
1180-|-|-|-|-|-|-|-|-|-|-|-|-|-
11811|3.2.2016|12|58.95
1182
1183Kundennummer|Vorname|Name|Strasse|Plz|Ort
1184-|-|-|-|-|-|-|-|-|-|-|-|-|-
118512|Hans|Mayer|Karlsplatz 3|1040|Wien
1186
1187 *DDL*
1188
1189 CREATE TABLE Kunden (
1190 Kundennummer INT KEY,
1191 Vorname CHAR(30),
1192 Name CHAR(30) NOT NULL,
1193 Straße CHAR(40) NOT NULL,
1194 Plz INT CHECK Plz BETWEEN 1 AND 99999,
1195 Ort CHAR(35) NOT NULL
1196 )
1197
1198 CREATE TABLE Kunden (
1199 Kundennummer INT KEY,
1200 Vorname CHAR(30),
1201 Name CHAR(30) NOT NULL,
1202 Straße CHAR(40) NOT NULL,
1203 Plz INT CHECK Plz BETWEEN 1 AND 99999,
1204 Ort CHAR(35) NOT NULL
1205 )
1206
1207 CREATE TABLE Rechnung (
1208 Rechnungsnummer INT KEY,
1209 Rechnungsdatum DATE NOT NULL,
1210 Kundennummer INT REFERENCES Kunden,
1211 Rechnungspreis FIXED(10,2)
1212 )
1213
1214 CREATE TABLE Artikel (
1215 Artikelnummer INT KEY,
1216 Artikel CHAR(40) NOT NULL,
1217 Einzelpreis FIXED(10,2) NOT NULL,
1218 Mwst FIXED(2,2)
1219 )
1220
1221 CREATE TABLE Rechnungsposition (
1222 Rechnungsnummer INT,
1223 Artikelnummer INT,
1224 Anzahl INT,
1225 FOREIGN KEY (Rechnungsnummer) REFERENCES Rechnung,
1226 FOREIGN KEY (Artikelnummer) REFERENCES Artikel
1227 )
1228
1229
1230 **Kernfrage:**
1231
1232- Entwerfen Sie für die ersten drei Normalformen eine Tabelle, die diese Normalform verletzt.
1233
1234 **Zusatzfrage:**
1235
1236- Welche Probleme resultieren aus unnormalisierten Daten?
1237
1238-->
1239<hr />
1240<hr />
1241<ol start="35" class="example" style="list-style-type: decimal">
1242<li>Erläutern Sie die Anomalien, die in Relationensystemen der ersten (oder zweiten) Normalform auftreten können.</li>
1243</ol>
1244<hr />
1245<p><strong>Insert-Anomalie:</strong></p>
1246<p>Wie die Bezeichnung bereits vermuten läßt, tritt ein Problem beim Hinzufügen eines neuen Objektes auf. Und zwar genau dann, wenn keine Möglichkeit besteht, dieses Objekt einzutragen, weil sich die zu diesem Objekt gehörenden Attribute zusammen mit logisch fremden Attributen in einer Tabelle befinden.</p>
1247<p><strong>Delete-Anomalie:</strong></p>
1248<p>In einer Relation, wie eben beschrieben, existiert ein zur Insert-Anomalie inverses Problem: Wenn ein Objekt aus dem Datenbestand entfernt werden soll, werden die logisch fremden Attribute ebenfalls gelöscht, weil sie in der gleichen Zeile stehen.</p>
1249<p><strong>Update-Anomalie:</strong></p>
1250<p>Als Folgeerscheinung von Redundanz innerhalb einer Relation begegnet man der Update-Anomalie dann, wenn Änderungen in den Attributwerten eines Objekts in mehreren Zeilen gleichzeitig erfolgen müssen.</p>
1251<h1 id="c.-datenmodellierung-systemanalyse-..."><span class="header-section-number">3</span> C. Datenmodellierung / Systemanalyse <a href="#TOC">...</a></h1>
1252<h2 id="assoziationen-..."><span class="header-section-number">3.1</span> Assoziationen <a href="#TOC">...</a></h2>
1253<p>Ein Kleinunternehmen hat sich dazu entschieden, ihre Angestellten- und Filialdaten in einer relationalen Datenbank zu verwalten. Dadurch kann das Unternehmen besonders einfach den Datenbestand auswerten.</p>
1254<pre><code> |EMPNO| ENAME | JOB | MGR | HIREDATE | SAL | COMM | DEPTNO |
1255 | 7782| CLARK | MANAGER | 7839 | 1981-06-09 | 2450.00 | NULL | 10 |
1256 | 7839| KING | PRESIDENT | NULL | 1981-11-17 | 5000.00 | NULL | 10 |
1257
1258 |DEPTNO| DNAME | LOC |
1259 | 10| ACCOUNTING| NEW YORK |</code></pre>
1260<hr />
1261<ol start="36" class="example" style="list-style-type: decimal">
1262<li><p>Modellieren Sie diesen Sachverhalt in einem Klassendiagramm.</p></li>
1263<li><p>Beschreiben Sie die Attribute mit ihren Datentypen und wesentlichen Merkmalen (Primärschlüssel, Optionalität, Eindeutigkeit)</p></li>
1264</ol>
1265<hr />
1266<dl>
1267<dt>.</dt>
1268<dd><img src="/home/user/acha/www-img/db/uml-emp.jpg" />
1269</dd>
1270</dl>
1271<hr />
1272<hr />
1273<ol start="38" class="example" style="list-style-type: decimal">
1274<li>Beschreiben Sie den Begriff "Assoziation" in UML.</li>
1275</ol>
1276<hr />
1277<ul>
1278<li>Eine Assoziation beschreibt eine Beziehung zwischen zwei oder mehr Klassen.</li>
1279<li>An den Enden von Assoziationen sind häufig Kardinalitäten (Multiplizitäten) vermerkt. Diese drücken aus, wie viele dieser Objekte in Relation zu den anderen Objekten dieser Assoziation stehen.</li>
1280</ul>
1281<hr />
1282<hr />
1283<ol start="39" class="example" style="list-style-type: decimal">
1284<li>Beschreiben Sie den Begriff "Kardinalität" in UML.</li>
1285</ol>
1286<hr />
1287<ul>
1288<li>Die Kardinalität einer Beziehung bestimmt die Anzahl der Klassen, die auf beiden Seiten einer Beziehung miteinander verbunden sind.</li>
1289<li>Auf jeder Seite legt man die untere und die obere Grenze fest.</li>
1290<li>Jede Grenze ist eine ganze, nicht negative Zahl.</li>
1291<li>Die Grenze "*" steht für den Wert unbeschränkt.</li>
1292<li>"*" ist eine Abkürzung für "0..*"</li>
1293<li>Sind beide Grenzen gleich, kann nur eine obere Grenze angegeben werden.</li>
1294<li>Ein Element mit Kardinalität 0..1 wird als optional bezeichnet.</li>
1295</ul>
1296<dl>
1297<dt>.</dt>
1298<dd><img src="/home/user/acha/www-img/db/multiplizitaet.jpg" />
1299</dd>
1300</dl>
1301<hr />
1302<hr />
1303<ol start="40" class="example" style="list-style-type: decimal">
1304<li>Erläutern Sie die Assoziationstypen 1:1, 1:n und m:n mit einem Beispiel.</li>
1305</ol>
1306<hr />
1307<ul>
1308<li><p>1:1 Beziehungen</p>
1309<p>Einem Objekt aus Entität A ist genau ein Objekt aus Entität B zugeordnet und umgekehrt.</p>
1310<p>Bsp.: Die katholische Kirche geht davon aus, daß jeder Mann mit einer Frau (und nicht mehr) verheiratet ist - also eine 1:1-Relation.</p></li>
1311<li><p>1:n Beziehungen</p>
1312<p>Einem Objekt aus Entität A sind mehrere Objekte aus Entität B zugeordnet.</p>
1313<p>Bsp.: In anderen Kulturen kann ein Mann auch mit mehreren Frauen verheiratet sein. Dieser Sachverhalt läßt sich mit einer 1:n Beziehung modellieren.</p></li>
1314<li><p>m:n Beziehungen</p>
1315<p>Einem Objekt aus Entität A sind mehrere Objekte aus Entität B zugeordnet, umgekehrt sind aber auch einem Objekt aus Entität B mehrere Objekte aus Entität A zugeordnet.</p>
1316<p>Bsp.: Mir sind keine Kulturen bekannt, in denen mehrere Männer mit mehreren Frauen verheiratet sind. Es besteht also keine Notwendigkeit die Beziehung „Ehe“ mit einer m:n Beziehung darzustellen.</p></li>
1317</ul>
1318<hr />
1319<hr />
1320<ol start="41" class="example" style="list-style-type: decimal">
1321<li>Erläutern Sie den Begriff assoziative Klasse. Zeichnen Sie dazu ein aussagekräftiges Beispiel.</li>
1322</ol>
1323<hr />
1324<p>Eine assoziative Klasse ist eine Assoziation, die selbst Attribute hat.</p>
1325<p>Z. B. ist das Hochzeitsdatum Attribut der Beziehung Ehe.</p>
1326<dl>
1327<dt>.</dt>
1328<dd><img src="/home/user/acha/www-img/uml-assoziation/assoziative-klasse.png" />
1329</dd>
1330</dl>
1331<hr />
1332<hr />
1333<ol start="42" class="example" style="list-style-type: decimal">
1334<li>Erläutern Sie den Begriff rekursive Assoziation.</li>
1335</ol>
1336<hr />
1337<p>Eine rekursive Assoziation hat eine Entität mit sich selbst.</p>
1338<p>Bsp.: „ist Mutter von“ ist eine rekursive Assoziation auf der Entität „Person“</p>
1339<hr />
1340<hr />
1341<ol start="43" class="example" style="list-style-type: decimal">
1342<li>Erläutern Sie die Speicherung von Assoziationen in MongoDB.</li>
1343</ol>
1344<hr />
1345<p>MongoDB verwendet statt <strong>Fremdschlüssel</strong> das Konzept von Einbettung und Verlinkung. Ein <strong>Link</strong> ist ein Verweis auf ein anderes Dokument.</p>
1346<p>Er muss auf der Ebene der Anwendungsprogramme interpretiert und das referenzierte Dokument in einer zusätzlichen Abfrage eingelesen werden.</p>
1347<p>Bei der <strong>Einbettung</strong> werden die referenzierten Datensätze als Unterdokument in das referenzierende Dokument eingebettet.</p>
1348<p>Beispielsweise enthält ein Dokument, dass eine CD repräsentiert, ein Unterdokument für jeden Track auf der CD, das dann die Eigenschaften wie Tracknummer, Künstler, Titel, etc. enthält.</p>
1349<hr />
1350<hr />
1351<ol start="44" class="example" style="list-style-type: decimal">
1352<li><p>Entwerfen Sie die Collections für ein hochperformantes Shop-System:</p>
1353<ul>
1354<li>Eine Bestellung umfasst mehrere Bestellpositionen.</li>
1355<li>Die wesentlichen Produktdaten sollen redundant bei der Bestellung abgespeichert werden.</li>
1356</ul>
1357<p>Der Produktkatalog ist vielfältig, im Datenmodell ist das über eine Vererbungshierarchie abgebildet:</p></li>
1358</ol>
1359<dl>
1360<dt>.</dt>
1361<dd><img src="/home/user/my/acha/www-img/mongodb/produkte.png" />
1362</dd>
1363</dl>
1364<hr />
1365<dl>
1366<dt>.</dt>
1367<dd><img src="/home/user/acha/www-img/mongodb/bestellungen.png" />
1368</dd>
1369</dl>
1370<p><strong>Bestellung</strong></p>
1371<p>Objekte mit 1:n-Beziehungen können direkt in einem Datensatz (=Dokument) abspeichert werden.</p>
1372<ul>
1373<li>Jede <strong>Bestellposition</strong> einer <em>Bestellung</em> referenziert zum einen das <em>Produkt</em> mit all seinen Attributen (auch solchen, die für den Aspekt der Bestellung unwichtig sind),</li>
1374<li>zum anderen werden in der <em>ProduktInfo</em> die für die <em>Bestellung</em> relevanten Daten eines <em>Produkts</em>, z. B. der Name und die Größe, denormalisiert bei der Bestellung gespeichert.</li>
1375</ul>
1376<p><strong>Produkt</strong></p>
1377<p>All diese verschiedenen Produkte des Produktkatalogs können wir in einer Collection speichern.</p>
1378<p>In der Collection "Produkt" gibt es ein Attribut, das die Art des Produkts (CD, Buch, ...) festlegt.</p>
1379<h2 id="vererbung-attribute-..."><span class="header-section-number">3.2</span> Vererbung, Attribute <a href="#TOC">...</a></h2>
1380<p>Ein Kleinunternehmen hat sich dazu entschieden, ihre Angestellten- und Filialdaten in einer relationalen Datenbank zu verwalten. Dadurch kann das Unternehmen besonders einfach den Datenbestand auswerten.</p>
1381<ol start="45" class="example" style="list-style-type: decimal">
1382<li><p>Erweitern Sie das Klassendiagramm um folgenden Sachverhalt:</p>
1383<p>Die Analytiker Scott und Jones sind keine US-Staatsbürger. Das Unternehmen muss die Nummer der Greencard und das Ausstellungsdatum speichern.</p></li>
1384</ol>
1385<dl>
1386<dt>.</dt>
1387<dd><img src="/home/user/acha/www-img/db/uml-emp.jpg" />
1388</dd>
1389</dl>
1390<hr />
1391<dl>
1392<dt>.</dt>
1393<dd><img src="/home/user/acha/www-img/db/immigrant.jpg" />
1394</dd>
1395</dl>
1396<!--
1397greencard-id: String {mandatory}
1398greencard-issued: Date {mandatory}
1399-->
1400<hr />
1401<hr />
1402<ol start="46" class="example" style="list-style-type: decimal">
1403<li>Erläutern Sie die Vererbung mit einem Beispiel.</li>
1404</ol>
1405<hr />
1406<ul>
1407<li>Bei der Vererbung wird aus ähnlich Klassen eine <strong>Super-Klasse abstrahiert</strong>.</li>
1408<li>Alle seine <strong>Sub-Klassen erben</strong> von ihm Attribute und Beziehungen.</li>
1409<li>Nur die <strong>speziellen Eigenschaften</strong> einer Sub-Klasse <strong>verbleiben</strong> bei dieser, da sie nicht allen Typen gemein sind.</li>
1410<li>Man sagt auch, die Sub-Klasse ist eine <strong>Spezialisierung</strong> der Super-Klasse.</li>
1411</ul>
1412<p><strong>Bsp.:</strong></p>
1413<ul>
1414<li>Die Super-Klasse Produkt hat die Sub-Klassen Lebensmittel und Hygieneartikel.</li>
1415<li>Die Super-Klasse hat all die Attribute, die alle Sub-Klassen gemeinsam haben („Preis“, ...).</li>
1416<li>Die Sub-Klassen haben nur die Attribute, die sie mit den anderen Sub-Klassen nicht teilen.
1417<ul>
1418<li>So haben z. B. nur Lebensmittel ein „Ablaufdatum“.</li>
1419</ul></li>
1420<li>Die Sub-Klassen erben nun alle Attribute der Super-Klasse.</li>
1421</ul>
1422<hr />
1423<hr />
1424<ol start="47" class="example" style="list-style-type: decimal">
1425<li>Spezifizieren Sie die Attribute möglichst vollständig.<br> Spezifizieren Sie auch die zeitliche Abfolge von Geburtsdatum, Immatrikulation und Vordiplom.</li>
1426</ol>
1427<dl>
1428<dt>.</dt>
1429<dd><img src="/home/user/acha/www-img/uml/attribut.png" />
1430</dd>
1431</dl>
1432<hr />
1433<pre><code>Matrikelnr: String(7) {mandatory, key, frozen}
1434Name: NameT {mandatory}
1435Geburtsdatum: Date {mandatory, frozen}
1436Immatrikulation: Date {mandatory, Beschreibung: Datum des Studienbeginns}
1437Vordiplom: Date {Beschreibung: Datum der abschließenden Vordiplomprüfung}
1438Noten: list of NoteT
1439Restriktionen: {Geburtsdatum < Immatrikulation < Vordiplom}</code></pre>
1440<p>Bei den Typen NameT und NoteT handelt es sich um elementare Klassen.</p>
1441<p>Beim Aufzählungstyp NotenwertT soll genau ein Wert ausgewählt werden, wobei die Liste für den Benutzer nicht erweiterbar sein darf. Daher ergibt sich für NotenwertT folgende Definition:</p>
1442<pre><code> {values: 1.0, 1.3, 1.7, 2.0, 2.3, 2.7, 3.0, 3.3, 3.7, 4.0, 5.0, noAdd}</code></pre>
1443<hr />
1444<hr />
1445<ol start="48" class="example" style="list-style-type: decimal">
1446<li>Erklären Sie die Beschreibung von Attributen.<br></li>
1447</ol>
1448<hr />
1449<pre><code> Attribut: Typ = Anfangswert {Merkmal1, Merkmal2, ...}</code></pre>
1450<p>Attribute werden durch ihren Namen und ihren Typ beschrieben.</p>
1451<p>Optional können angegeben werden:</p>
1452<ul>
1453<li><p>Anfangswert (initial-value)</p>
1454<p>Er legt fest, welchen Wert ein neu erzeugtes Objekt für dieses Attribut annimmt.</p></li>
1455<li><p>Liste von Merkmalen</p>
1456<p>Hier können die Merkmale bzw. die Eigenschaften des Attributs angegeben werden.</p>
1457<pre><code>{mandatory, key, frozen, Einheit: ...., Beschreibung: ... }</code></pre>
1458<ul>
1459<li>key: Schlüssel (Sind mehrere Attribute einer Klasse mit key gekennzeichnet, dann bilden sie einen zusammengesetzten Schlüssel.)</li>
1460<li>mandatory: Muß-Attribut</li>
1461<li>frozen: Attributwert nicht änderbar</li>
1462<li>Einheit: zB Fahrzeit in [min], gefahrene Strecke in [km]</li>
1463<li>Beschreibung: Die Bedeutung des Attributs noch durch eine Beschreibung erläutert werden.</li>
1464</ul>
1465<p>Fehlen <code>mandatory, key, frozen</code>, dann gelten die <strong>Voreinstellungen</strong>, d.h. das Attribut ist ein Kann-Attribut, kein Schlüsselattribut und beliebig änderbar.</p></li>
1466</ul>
1467<hr />
1468<hr />
1469<ol start="49" class="example" style="list-style-type: decimal">
1470<li>Beschreiben Sie die grafische Notation der Attribute.<br> Erläutern Sie die Begriffe "abgeleitetes Attribut" und "Klassenattribut.</li>
1471</ol>
1472<hr />
1473<dl>
1474<dt>.</dt>
1475<dd><img src="/home/user/acha/www-img/uml/attribut-notation.png" />
1476</dd>
1477<dt>.</dt>
1478<dd><img src="/home/user/acha/www-img/uml/attribut-abgeleitet.png" />
1479</dd>
1480</dl>
1481<p>Der Wert eines <strong>abgeleiteten Attributs</strong> (derived attribute) kann jederzeit aus anderen Attributwerten berechnet werden. Abgeleitete Attribute werden mit dem <strong>Präfix »/«</strong> gekennzeichnet. Ein abgeleitetes Attribut darf nicht geändert werden.</p>
1482<p>Ein Klassenattribut liegt vor, wenn nur ein Attributwert für alle Objekte einer Klasse existiert. Klassenattribute existieren auch dann, wenn es zu einer Klasse – noch – keine Objekte gibt. Um die Klassenattribute von den (Objekt-) Attributen zu unterscheiden, werden sie in der UML <strong>unterstrichen</strong>.</p>
1483<hr />
1484<hr />
1485<ol start="50" class="example" style="list-style-type: decimal">
1486<li>Erläuten Sie die Begriffe "komplexes Objekt" und "rekursives Objekt".</li>
1487</ol>
1488<hr />
1489<p>Besitzt ein Objekt Attribute, die selbst wieder Objekte sind, so wird es als <strong>komplexes Objekt</strong> (composite object, complex object, structured object, molecular object) bezeichnet. Dieses (Unter-) Objekt kann ebenfalls komplex sein.</p>
1490<p><strong>Rekursive Objekte</strong> entstehen, wenn die Klasse eines Objekts dieselbe ist wie die eines direkten oder indirekten Unterobjekts.</p>
1491<hr />
1492<hr />
1493<ol start="51" class="example" style="list-style-type: decimal">
1494<li>Erklären Sie die Beschreibung von Restriktionen mit einem Beispiel.</li>
1495</ol>
1496<hr />
1497<p>Zwischen den Attributwerten eines Objekts können Beziehungen Restriktionen existieren, die während der Ausführung des Systems unverändert (constraints) erhalten bleiben müssen. Wir sprechen hier von Restriktionen (constraints). Eine Restriktion wird auch als Invariante bezeichnet. Es ist eine Zusicherung, die immer wahr sein muß.</p>
1498<p><em>Beispiele:</em></p>
1499<ol style="list-style-type: decimal">
1500<li><p><code>{Vordiplom > Immatrikulation > Geburtsdatum}</code></p></li>
1501<li><p><code>{Verkaufspreis >= 1.5 * Einkaufspreis}</code></p>
1502<p>Für die Klasse Artikel mit den Attributen Einkaufspreis und Verkaufspreis gilt, daß der Verkaufspreis mindestens 150 Prozent des Einkaufspreises betragen soll. Dann muß durch die Implementierung sichergestellt werden, daß beim Ändern des einen Preises auch der andere geändert wird.</p></li>
1503</ol>
1504<h1 id="d.-datenbankabfrage-sql-..."><span class="header-section-number">4</span> D. Datenbankabfrage (SQL) <a href="#TOC">...</a></h1>
1505<h2 id="joins-..."><span class="header-section-number">4.1</span> Joins <a href="#TOC">...</a></h2>
1506<p>Ein Kleinunternehmen hat sich dazu entschieden, ihre Angestellten- und Filialdaten in einer relationalen Datenbank zu verwalten. Dadurch kann das Unternehmen besonders einfach den Datenbestand auswerten.</p>
1507<pre><code>|EMPNO| ENAME | JOB | MGR | HIREDATE | SAL | COMM | DEPTNO |
1508| 7934| MILLER| CLERK | 7782 | 1982-01-23 | 1300.00 | NULL | 10 |
1509| 7782| CLARK | MANAGER | 7839 | 1981-06-09 | 2450.00 | NULL | 10 |
1510| 7839| KING | PRESIDENT | NULL | 1981-11-17 | 5000.00 | NULL | 10 |
1511| 7369| SMITH | CLERK | 7902 | 1980-12-17 | 800.00 | NULL | 20 |
1512| 7876| ADAMS | CLERK | 7788 | 1983-01-12 | 1100.00 | NULL | 20 |
1513| 7566| JONES | MANAGER | 7839 | 1981-04-02 | 2975.00 | NULL | 20 |
1514| 7788| SCOTT | ANALYST | 7566 | 1982-12-09 | 3000.00 | NULL | 20 |
1515| 7902| FORD | ANALYST | 7566 | 1981-12-03 | 3000.00 | NULL | 20 |
1516| 7900| JAMES | CLERK | 7698 | 1981-12-03 | 950.00 | NULL | 30 |
1517| 7654| MARTIN| SALESMAN | 7698 | 1981-09-28 | 1250.00 | 1400.00 | 30 |
1518| 7521| WARD | SALESMAN | 7698 | 1981-02-22 | 1250.00 | 500.00 | 30 |
1519| 7844| TURNER| SALESMAN | 7698 | 1981-09-08 | 1500.00 | 0.00 | 30 |
1520| 7499| ALLEN | SALESMAN | 7698 | 1981-02-20 | 1600.00 | 300.00 | 30 |
1521| 7698| BLAKE | MANAGER | 7839 | 1981-05-01 | 2850.00 | NULL | 30 |</code></pre>
1522<hr />
1523<ol start="52" class="example" style="list-style-type: decimal">
1524<li>Ermitteln Sie alle Mitarbeiter, die mehr verdienen als JONES. Lösen Sie dieses Problem auf zwei Arten.</li>
1525</ol>
1526<hr />
1527<div class="sourceCode"><pre class="sourceCode sql"><code class="sourceCode sql"><span class="kw">SELECT</span> e1.ename
1528<span class="kw">FROM</span> emp <span class="kw">AS</span> e1, emp <span class="kw">AS</span> e2
1529<span class="kw">WHERE</span> e2.ename = <span class="st">'JONES'</span>
1530 <span class="kw">AND</span> e1.sal > e2.sal;
1531
1532<span class="kw">SELECT</span> ename
1533<span class="kw">FROM</span> emp
1534<span class="kw">WHERE</span> sal > (<span class="kw">SELECT</span> sal <span class="kw">FROM</span> emp <span class="kw">WHERE</span> ename = <span class="st">'JONES'</span>);</code></pre></div>
1535<hr />
1536<hr />
1537<ol start="53" class="example" style="list-style-type: decimal">
1538<li>Die SQL-Befehle lassen sich drei Kategorien zuordnen. Beschreiben Sie diese.</li>
1539</ol>
1540<hr />
1541<ul>
1542<li>DML: (Data Manipulation Language) Befehle zur Datenmanipulation (Ändern, Einfügen, Löschen) und <strong>lesendem Zugriff</strong>.
1543<ul>
1544<li>Diese Befehle werden auch unter der Bezeichnung <strong>CRUD</strong> zusammengefasst.</li>
1545<li>CRUD ist ein Akronym aus den Worten "Create", "Read", "Update" und "DELETE"</li>
1546</ul></li>
1547<li>DDL: (Data Definition Language) Befehle zur Definition des Datenbankschemas</li>
1548<li>DCL: (Data Control Language) Befehle für die Rechteverwaltung und Transaktionskontrolle</li>
1549</ul>
1550<hr />
1551<hr />
1552<ol start="54" class="example" style="list-style-type: decimal">
1553<li>Das SELECT-Statement legt in seinen Klauseln relationale Operatoren fest. Erläutern Sie diese.<br> Hinweis: Die Operatoren der Grundrechnungsarten sind Addition, Subtraktion, .... -- Und Sie sollen analoge Operatoren des SELECT-Statements beschreiben.</li>
1554</ol>
1555<hr />
1556<p>Zu diesen Operatoren gehören</p>
1557<ul>
1558<li>Selektion,</li>
1559<li>Projektion und</li>
1560<li>Verbundoperation.</li>
1561</ul>
1562<p><strong>Selektion</strong> (WHERE-Klausel): Sie liefert aus einer gegebenen <strong>Relation</strong> (= Tabelle) die Menge der <strong>Tupel</strong> (=Zeilen, Datensätze), die der Selektionsbedingung genügen.</p>
1563<p><strong>Projektion</strong> (SELECT-Klausel): Bei dieser Operation erhält man eine Auswahl von Spalten einer Relation.</p>
1564<p><strong>Verbundoperationen</strong> (FROM-Klausel): Der Verbund (Join) verbindet mehrere Relationen über einen gemeinsamen Ausdruck und erzeugt eine Resultatrelation.</p>
1565<hr />
1566<hr />
1567<ol start="55" class="example" style="list-style-type: decimal">
1568<li>Beschreiben und erläutern Sie die einzelnen Schritte der SELECT-Pipeline. Also die Reihenfolge, in der das DBMS, die Query abarbeitet.</li>
1569</ol>
1570<hr />
1571<div class="sourceCode"><pre class="sourceCode sql"><code class="sourceCode sql"><span class="kw">SELECT</span> [<span class="kw">DISTINCT</span>] <span class="kw">select</span> heading
1572<span class="kw">FROM</span> <span class="kw">source</span> <span class="kw">tables</span>
1573<span class="kw">WHERE</span> <span class="kw">filter</span> expression
1574<span class="kw">GROUP</span> <span class="kw">BY</span> <span class="fu">grouping</span> expressions
1575<span class="kw">HAVING</span> <span class="kw">filter</span> expression
1576<span class="kw">ORDER</span> <span class="kw">BY</span> ordering expressions
1577<span class="kw">LIMIT</span> <span class="fu">count</span>
1578OFFSET <span class="fu">count</span></code></pre></div>
1579<ol style="list-style-type: decimal">
1580<li><code>FROM source tables</code>: Legt eine oder mehrere Ausgangstabellen fest und kombiniert sie zu einer grossen Arbeitstabelle.</li>
1581<li><code>WHERE filter expressions</code>: Filtert bestimmte Zeilen aus der Arbeittstabelle heraus.</li>
1582<li><code>GROUP BY grouping expressions</code>: Fasst Zeilen zusammen, die in bestimmten Werten übereinstimmen.</li>
1583<li><code>SELECT select heading</code>: Definiert die Kolonnen der Resultatmenge sowie die gruppierenden Funktionen (Aggregatsfunktionen), sofern diese anwendbar sind.</li>
1584<li><code>HAVING filter expression</code>: Filtert bestimmte Zeilen aus der gruppierten Tabelle. Verlangt ein GROUP BY.</li>
1585<li><code>DISTINCT</code>: Eliminiert identische Zeilen.</li>
1586<li><code>ORDER BY ordering expressions</code>: Sortiert die Zeilen der Resultatmenge.</li>
1587<li><code>OFFSET count</code>: Überspringt count Zeilen am anfang der Resultatmenge. Verlangt ein LIMIT.</li>
1588<li><code>LIMIT count</code>: Begrenzt die Anzahl der auszugebenden Zeilen der Resultatmenge auf count .</li>
1589</ol>
1590<hr />
1591<hr />
1592<ol start="56" class="example" style="list-style-type: decimal">
1593<li>Nennen und erläutern Sie die unterschiedlichen Verbundoperationen.</li>
1594</ol>
1595<hr />
1596<ul>
1597<li>Cross Join</li>
1598<li>Equijoin</li>
1599<li>Non-Equijoin</li>
1600<li>Self Join</li>
1601<li>Outer Join</li>
1602</ul>
1603<p><strong><em>Cross Join</em></strong></p>
1604<p>Entspricht dem kartesischen Produkt von zwei oder mehr selektierten Tabellen ohne Join-Bedingung.</p>
1605<p><em>Beispiel:</em></p>
1606<pre><code>sqlite> SELECT ename, loc
1607 FROM emp, dept;
1608
1609ENAME LOC
1610---------- -------------
1611SMITH NEW YORK
1612ALLEN NEW YORK
1613WARD NEW YORK
1614JONES NEW YORK
1615MARTIN NEW YORK
1616BLAKE NEW YORK
1617CLARK NEW YORK
1618SCOTT NEW YORK
1619KING NEW YORK
1620TURNER NEW YORK
1621ADAMS NEW YORK
1622JAMES NEW YORK
1623FORD NEW YORK
1624MILLER NEW YORK
1625SMITH DALLAS
1626ALLEN DALLAS
1627WARD DALLAS
1628JONES DALLAS
1629... </code></pre>
1630<p>Alternative Schreibweise:</p>
1631<pre><code>sqlite> SELECT ename, loc, grade
1632 FROM emp CROSS JOIN dept;</code></pre>
1633<p><strong><em>Equijoin</em></strong></p>
1634<p>Bei einem Equijoin werden die Tabellen über ein Gleichheitszeichen verknüpft: der Wert einer Spalte in der ersten Tabelle muss genau dem Wert einer Spalte in der zweiten Tabelle entsprechen. Zeilen ohne Entsprechung in der jeweils anderen Tabelle werden nicht ausgewählt.</p>
1635<p>Ein Equijoin wird auch als "Inner Join" bezeichnet.</p>
1636<p><em>Beispiel:</em></p>
1637<div class="sourceCode"><pre class="sourceCode sql"><code class="sourceCode sql">sqlite> <span class="kw">SELECT</span> ename, loc
1638 <span class="kw">FROM</span> emp, dept <span class="kw">ON</span> emp.deptno = dept.deptno;
1639
1640ename loc
1641<span class="co">------- ----------</span>
1642SMITH DALLAS
1643ALLEN CHICAGO
1644WARD CHICAGO
1645JONES DALLAS
1646MARTIN CHICAGO
1647BLAKE CHICAGO
1648CLARK <span class="kw">NEW</span> YORK
1649SCOTT DALLAS
1650KING <span class="kw">NEW</span> YORK
1651TURNER CHICAGO
1652ADAMS DALLAS
1653JAMES CHICAGO
1654FORD DALLAS </code></pre></div>
1655<div class="sourceCode"><pre class="sourceCode sql"><code class="sourceCode sql"><span class="kw">SELECT</span> t1.spalte1, t1.spalte2, t2.spalte1, t2.spalte2, .....
1656<span class="kw">FROM</span> tabelle1 t1 <span class="kw">JOIN</span> tabelle2 t2
1657<span class="kw">ON</span> t1.spalte1 = t2. spalte1
1658<span class="kw">WHERE</span> <weitere Bedingungen></code></pre></div>
1659<p>ODER:</p>
1660<div class="sourceCode"><pre class="sourceCode sql"><code class="sourceCode sql"><span class="kw">SELECT</span> t1.spalte1, t1.spalte2, t2.spalte1, t2.spalte2, .....
1661<span class="kw">FROM</span> tabelle1 t1, tabelle2 t2
1662<span class="kw">WHERE</span> t1.spalte1 = t2.spalte1
1663<span class="kw">AND</span> <weitere Bedingungen></code></pre></div>
1664<p>Sie können für die Tabellen einen kurzen Aliasnamen vergeben und alle Spalten mittels Punktnotation mit dem Aliasnamen ihrer Herkunftstabellen zu kennzeichnen.</p>
1665<p>Beispiel: Gesucht sind Name, Gehalt, Abteilungsname, Vorgesetzter und Arbeitsort der emp-Mitarbeiter, die mehr als 1000 € verdienen.</p>
1666<div class="sourceCode"><pre class="sourceCode sql"><code class="sourceCode sql"><span class="kw">SELECT</span> ma.ename Chef, ma.sal, d.dname, bo.ename Chef, d.loc
1667<span class="kw">FROM</span> emp ma
1668 <span class="kw">JOIN</span> dept d <span class="kw">ON</span> ma.deptno = d.deptno
1669 <span class="kw">JOIN</span> emp bo <span class="kw">ON</span> ma.mgr = bo.empno
1670<span class="kw">WHERE</span> ma.sal > <span class="dv">1000</span>;</code></pre></div>
1671<p>oder</p>
1672<div class="sourceCode"><pre class="sourceCode sql"><code class="sourceCode sql"><span class="kw">SELECT</span> ma.ename Chef, ma.sal, d.dname, bo.ename Chef, d.loc
1673<span class="kw">FROM</span> emp ma, dept d, emp bo
1674<span class="kw">WHERE</span> ma.deptno = d.deptno
1675<span class="kw">AND</span> ma.mgr = bo.empno
1676<span class="kw">AND</span> ma.sal > <span class="dv">1000</span>;
1677
1678CHEF SAL DNAME CHEF LOC
1679<span class="co">------- ------ ---------- ---------- ----------</span>
1680FORD <span class="dv">3000</span> RESEARCH JONES DALLAS
1681SCOTT <span class="dv">3000</span> RESEARCH JONES DALLAS
1682TURNER <span class="dv">1500</span> SALES BLAKE CHICAGO
1683MARTIN <span class="dv">1250</span> SALES BLAKE CHICAGO
1684WARD <span class="dv">1250</span> SALES BLAKE CHICAGO
1685ALLEN <span class="dv">1600</span> SALES BLAKE CHICAGO
1686MILLER <span class="dv">1300</span> ACCOUNTING CLARK <span class="kw">NEW</span> YORK
1687ADAMS <span class="dv">1100</span> RESEARCH SCOTT DALLAS
1688CLARK <span class="dv">2450</span> ACCOUNTING KING <span class="kw">NEW</span> YORK
1689BLAKE <span class="dv">2850</span> SALES KING CHICAGO
1690JONES <span class="dv">2975</span> RESEARCH KING DALLAS</code></pre></div>
1691<p><strong><em>Non-Equijoin</em></strong></p>
1692<p>Bei einer Verknüpfung durch einen Non-Equijoin besteht das "Problem", dass sich keine Spalten der zu verknüpfenden Tabellen direkt entsprechen und somit die Beziehung auch nicht durch ein Gleichheitszeichen dargestellt werden kann. Ein Zusammenhang ergibt sich lediglich durch überschneidende Wertebereiche der Inhalte einzelner Spalten. Zum Beispiel durch den Bereichsoperator BETWEEN ... AND.</p>
1693<p><strong><em>Self Join</em></strong></p>
1694<p>Bei einem Self Join wird eine Tabelle mit sich selbst verknüpft.</p>
1695<p>Da die Tabelle zweimal in der FROM-Klausel erscheint, muss ein Alias verwendet werden.</p>
1696<div class="sourceCode"><pre class="sourceCode sql"><code class="sourceCode sql"><span class="kw">SELECT</span> a.*, b.*
1697<span class="kw">FROM</span> tabelle1 a, tabelle1 b
1698<span class="kw">WHERE</span> a.spalte1 = b.spalte2</code></pre></div>
1699<p><em>Beispiel:</em></p>
1700<p>Geben Sie die Mitarbeiter und ihre direkten Vorgesetzten aus: </p>
1701<div class="sourceCode"><pre class="sourceCode sql"><code class="sourceCode sql">sqlite> <span class="kw">SELECT</span> arbeiter.ename <span class="ot">"Mitarbeiter"</span>, vorgesetzter.ename <span class="ot">"Chef"</span>
1702 FROM emp <span class="kw">AS</span> arbeiter, emp <span class="kw">AS</span> vorgesetzter
1703 WHERE vorgesetzter.empno=arbeiter.mgr ;
1704
1705Mitarbeiter Chef
1706<span class="co">------- --------</span>
1707SMITH FORD
1708ALLEN BLAKE
1709WARD BLAKE
1710JONES KING
1711MARTIN BLAKE
1712BLAKE KING
1713CLARK KING
1714SCOTT JONES
1715TURNER BLAKE
1716ADAMS SCOTT
1717JAMES BLAKE
1718FORD JONES
1719MILLER CLARK</code></pre></div>
1720<p><em>Hinweis:</em></p>
1721<p>Der oben genannte Self Join kann auch so geschrieben werden:</p>
1722<div class="sourceCode"><pre class="sourceCode sql"><code class="sourceCode sql"> sqlite> <span class="kw">SELECT</span> arbeiter.ename <span class="ot">"Mitarbeiter"</span>, vorgesetzter.ename <span class="ot">"Chef"</span>
1723 FROM emp arbeiter <span class="kw">JOIN</span> emp vorgesetzter ON
1724 (arbeiter.mgr=vorgesetzter.empno);</code></pre></div>
1725<p><strong><em>Outer Join</em></strong></p>
1726<ul>
1727<li>In der Join-Bedingung werden die Schlüsselwörter LEFT JOIN bzw. LEFT OUTER JOIN verwendet.</li>
1728<li>Entspricht eine Zeile nicht der Join-Bedingung, so wird die Zeile nicht in das Abfrageergebnis aufgenommen.</li>
1729<li>Durch die Bezeichnung LEFT JOIN werden auch die Zeilen, die keine Entsprechung in der anderen Tabelle aufweisen, angezeigt.</li>
1730</ul>
1731<p><em>Beispiele:</em></p>
1732<div class="sourceCode"><pre class="sourceCode sql"><code class="sourceCode sql">sqlite> <span class="kw">SELECT</span> dname, ename <span class="kw">FROM</span> dept <span class="kw">LEFT</span> <span class="kw">JOIN</span> emp <span class="kw">ON</span> dept.deptno = emp.deptno;
1733
1734dname ename
1735<span class="co">------- ----------</span>
1736ACCOUNTING CLARK
1737ACCOUNTING KING
1738ACCOUNTING MILLER
1739RESEARCH ADAMS
1740RESEARCH FORD
1741RESEARCH JONES
1742RESEARCH SCOTT
1743RESEARCH SMITH
1744SALES ALLEN
1745SALES BLAKE
1746SALES JAMES
1747SALES MARTIN
1748SALES TURNER
1749SALES WARD
1750OPERATIONS </code></pre></div>
1751<h2 id="index-..."><span class="header-section-number">4.2</span> Index <a href="#TOC">...</a></h2>
1752<p>Ein Kleinunternehmen hat sich dazu entschieden, ihre Angestellten- und Filialdaten in einer relationalen Datenbank zu verwalten. Dadurch kann das Unternehmen besonders einfach den Datenbestand auswerten.</p>
1753<pre><code>|EMPNO| ENAME | JOB | MGR | HIREDATE | SAL | COMM | DEPTNO |
1754| 7934| MILLER| CLERK | 7782 | 1982-01-23 | 1300.00 | NULL | 10 |
1755| 7782| CLARK | MANAGER | 7839 | 1981-06-09 | 2450.00 | NULL | 10 |
1756| 7839| KING | PRESIDENT | NULL | 1981-11-17 | 5000.00 | NULL | 10 |
1757| 7369| SMITH | CLERK | 7902 | 1980-12-17 | 800.00 | NULL | 20 |
1758| 7876| ADAMS | CLERK | 7788 | 1983-01-12 | 1100.00 | NULL | 20 |
1759| 7566| JONES | MANAGER | 7839 | 1981-04-02 | 2975.00 | NULL | 20 |
1760| 7788| SCOTT | ANALYST | 7566 | 1982-12-09 | 3000.00 | NULL | 20 |
1761| 7902| FORD | ANALYST | 7566 | 1981-12-03 | 3000.00 | NULL | 20 |
1762| 7900| JAMES | CLERK | 7698 | 1981-12-03 | 950.00 | NULL | 30 |
1763| 7654| MARTIN| SALESMAN | 7698 | 1981-09-28 | 1250.00 | 1400.00 | 30 |
1764| 7521| WARD | SALESMAN | 7698 | 1981-02-22 | 1250.00 | 500.00 | 30 |
1765| 7844| TURNER| SALESMAN | 7698 | 1981-09-08 | 1500.00 | 0.00 | 30 |
1766| 7499| ALLEN | SALESMAN | 7698 | 1981-02-20 | 1600.00 | 300.00 | 30 |
1767| 7698| BLAKE | MANAGER | 7839 | 1981-05-01 | 2850.00 | NULL | 30 |</code></pre>
1768<hr />
1769<ol start="57" class="example" style="list-style-type: decimal">
1770<li>Ermitteln Sie alle Abteilungen mit mindestens 3 Verkäufern.</li>
1771</ol>
1772<hr />
1773<div class="sourceCode"><pre class="sourceCode sql"><code class="sourceCode sql"><span class="kw">SELECT</span> deptno
1774<span class="kw">FROM</span> emp
1775<span class="kw">WHERE</span> job = <span class="st">'SALESMAN'</span>
1776<span class="kw">GROUP</span> <span class="kw">BY</span> deptno
1777<span class="kw">HAVING</span> <span class="fu">COUNT</span>(*) >= <span class="dv">3</span>;</code></pre></div>
1778<hr />
1779<hr />
1780<ol start="58" class="example" style="list-style-type: decimal">
1781<li>Der Suchvorgang nach dem Namen soll beschleunigt werden.</li>
1782</ol>
1783<blockquote>
1784<ul>
1785<li>Entwerfen Sie ein Verfahren, das dies ermöglicht.</li>
1786<li>Erläutern Sie die dazu notwendigen Kommandos.</li>
1787</ul>
1788</blockquote>
1789<hr />
1790<pre><code>CREATE INDEX emp_name ON emp(ename);</code></pre>
1791<hr />
1792<hr />
1793<ol start="59" class="example" style="list-style-type: decimal">
1794<li>Erläutern Sie die Befehle, mit denen ein Index erstellt oder gelöscht werden kann.</li>
1795</ol>
1796<hr />
1797<pre><code>CREATE [UNIQUE] INDEX index-name ON table-name (column [, column ...]);
1798
1799DROP INDEX index-name;</code></pre>
1800<hr />
1801<hr />
1802<ol start="60" class="example" style="list-style-type: decimal">
1803<li>Erläutern Sie den Datenbank-Index.</li>
1804</ol>
1805<hr />
1806<p>Einen Index können Sie sich wie ein <strong>Telefonbuch</strong> vorstellen.</p>
1807<p>Wenn Sie einen Namen suchen, schlagen Sie das Telefonbuch zuerst in etwa in der <strong>Mitte</strong> auf und vergleichen den Namen, den Sie dort vorfinden, mit dem von Ihnen gesuchten Namen. Ist der von Ihnen gesuchte Name größer (weiter hinten im Alphabet), so können Sie die vordere Hälfte getrost vergessen - denn der Name muss sich in der hinteren Hälfte befinden. Nun schlagen Sie die Hälfte der hinteren Hälfte auf u.s.w.</p>
1808<p>Wäre das Telefonbuch <strong>nicht alphabetisch</strong> sortiert, so müssten Sie das ganze Buch durchblättern, um die entsprechende Telefonnummer herauszubekommen.</p>
1809<hr />
1810<hr />
1811<ol start="61" class="example" style="list-style-type: decimal">
1812<li>Nennen und beschreiben Sie die wesentlichsten Eigenschaften von Indexes.</li>
1813</ol>
1814<hr />
1815<ul>
1816<li>Mit einem Index kann die <strong>Position</strong> eines Datensatzes ermittelt werden.</li>
1817<li>Ein Index ist eine Attributkombination für die eine <strong>Tabelle</strong> vom DBMS angelegt wurde.</li>
1818<li>Indizes beschleunigen Such- und Sortieraktionen, <strong>verlangsamen</strong> aber Anfügevorgänge.</li>
1819<li>Ein Index arbeitet ähnlich dem Telefonbuchprinzip. Zuerst wird die indizierte Spalte <strong>sortiert</strong> und anschließend als <strong>Baumstruktur</strong> gespeichert.</li>
1820</ul>
1821<hr />
1822<hr />
1823<ol start="62" class="example" style="list-style-type: decimal">
1824<li>Der Datenbankadministrator möchte sich die bestehende Indizes ansehen.</li>
1825</ol>
1826<blockquote>
1827<ul>
1828<li>Entwerfen Verfahren, das dies ermöglichen.</li>
1829<li>Erläutern Sie die dazu notwendigen Kommandos.</li>
1830</ul>
1831</blockquote>
1832<hr />
1833<p>Mit Hilfe bestimmter Data Dictionary Tables und Views erhalten Sie eine Übersicht über die bestehenden Indizes und die beteiligten Tabellen.</p>
1834<div class="sourceCode"><pre class="sourceCode sql"><code class="sourceCode sql">sqlite> <span class="kw">create</span> <span class="kw">table</span> t1(f, g);
1835
1836sqlite> <span class="kw">create</span> <span class="kw">index</span> i1 <span class="kw">on</span> t1(f);
1837
1838sqlite> <span class="kw">select</span> * <span class="kw">from</span> sqlite_master;
1839<span class="kw">type</span> name tbl_name rootpage sql
1840<span class="co">------- ---------- ---------- ---------- ---------------------</span>
1841<span class="kw">table</span> t1 t1 <span class="dv">2</span> <span class="kw">CREATE</span> <span class="kw">TABLE</span> t1(f, g)
1842<span class="kw">index</span> i1 t1 <span class="dv">3</span> <span class="kw">CREATE</span> <span class="kw">INDEX</span> i1 <span class="kw">on</span> t1
1843
1844sqlite> PRAGMA INDEX_LIST(<span class="st">'t1'</span>);
1845seq name <span class="kw">unique</span>
1846<span class="co">------- ---------- ----------</span>
1847<span class="dv">0</span> i1 <span class="dv">0</span>
1848
1849sqlite> PRAGMA INDEX_INFO(<span class="st">'i1'</span>);
1850seqno cid name
1851<span class="co">------- ---------- ----------</span>
1852<span class="dv">0</span> <span class="dv">0</span> f </code></pre></div>
1853<ul>
1854<li>In der Data Dictionary Sicht <strong>sqlite_master</strong> sind auch alle Indizes gespeichert.</li>
1855<li>Sie können auch das PRAGMAS "INDEX_LIST" und "INDEX_INFO" verwenden.</li>
1856</ul>
1857<hr />
1858<hr />
1859<ol start="63" class="example" style="list-style-type: decimal">
1860<li><p>Der Datenbankadministrator hat eine Hilfstabelle erstellt.<br> Prüfen Sie, ob ein Index für die Spalte "f" erstellt werden muss.</p>
1861<pre><code>CREATE TABLE t2(f INT PRIMARY KEY, g);</code></pre></li>
1862</ol>
1863<hr />
1864<ul>
1865<li>Für Primärschlüssel werden Indizes auch automatisch erstellt:</li>
1866<li>Das funktioniert aber nicht bei "INTEGER PRIMARY KEY". Da gibt es einen anderen Mechanismus, der die Funktionalität gewährleistet.</li>
1867</ul>
1868<div class="sourceCode"><pre class="sourceCode sql"><code class="sourceCode sql">sqlite> <span class="kw">CREATE</span> <span class="kw">TABLE</span> t2(f <span class="dt">INT</span> <span class="kw">PRIMARY</span> <span class="kw">KEY</span>, g);
1869
1870sqlite> PRAGMA INDEX_LIST(<span class="st">'t2'</span>);
1871seq name <span class="kw">unique</span>
1872<span class="co">------- --------------------- ----------</span>
1873<span class="dv">0</span> sqlite_autoindex_t2_1 <span class="dv">1</span>
1874
1875sqlite> PRAGMA INDEX_INFO(<span class="st">'sqlite_autoindex_t2_1'</span>);
1876seqno cid name
1877<span class="co">------- ---------- ----------</span>
1878<span class="dv">0</span> <span class="dv">0</span> f </code></pre></div>
1879<hr />
1880<hr />
1881<ol start="64" class="example" style="list-style-type: decimal">
1882<li>Entwickeln Sie Richtlinien für das Erstellen von Indexen.</li>
1883</ol>
1884<hr />
1885<ul>
1886<li>Die Spalte wird häufig als Join-Kriterium benutzt.</li>
1887<li>Die meisten Abfragen ermitteln als Ergebnismenge weniger als 5% der Gesamtmenge.</li>
1888<li>Die Tabelle enthält einen sehr selektiven Wertebereich, dass heißt, es kommen verhältnismäßig wenig doppelte Spaltenwerte vor.</li>
1889<li>Die Tabelle wird selten aktualisiert.</li>
1890<li>Die Tabelle ist groß.</li>
1891</ul>
1892<hr />
1893<hr />
1894<ol start="65" class="example" style="list-style-type: decimal">
1895<li>Erläutern Sie die Komplexität von Algorithmen.</li>
1896</ol>
1897<hr />
1898<ul>
1899<li>Komplexität bezeichnet in der Informatik die „Kompliziertheit“ von Problemen, Algorithmen oder Daten.</li>
1900<li>Unter der Komplexität (auch Aufwand oder Kosten) eines Algorithmus versteht man seinen maximalen Ressourcenbedarf.</li>
1901<li>Prozesse verbrauchen u.a. zwei Ressourcen:
1902<ul>
1903<li>Rechenzeit (=Laufzeit)</li>
1904<li>Speicherplatz</li>
1905</ul></li>
1906</ul>
1907<hr />
1908<hr />
1909<ol start="66" class="example" style="list-style-type: decimal">
1910<li>Erläutern Sie die Effektivität von Algorithmen.</li>
1911</ol>
1912<hr />
1913<p>Die Effektivität eines Algorithmus wird an der <strong>Anzahl elementarer Operationen</strong> (Schritte) gemessen, die dieses zur Lösung eines gegebenen Problems benötigt. Aufgrund dieser Zahl kann die Laufzeit ermittelt</p>
1914<ul>
1915<li>Die <strong>Laufzeit</strong> eines Computerprogramms, ist die Zeit, die ein Rechenprozess benötigt, um bei gegebenen Eingabedaten ein Resultat zu erzielen.</li>
1916<li>Die Laufzeit hängt wesentlich vom verwendeten Algorithmus ab.</li>
1917</ul>
1918<hr />
1919<hr />
1920<ol start="67" class="example" style="list-style-type: decimal">
1921<li>Erläutern Sie die O-Notation anhand von Beispielen.</li>
1922</ol>
1923<hr />
1924<ul>
1925<li>Mit der O-Notation lässt sich die Komplexität eines Algorithmus charakterisieren.</li>
1926<li>Sie stellt die Größenordnung der Komplexität dar und abstrahiert von den Details</li>
1927<li>Die O-Notation ist deshalb so wichtig, weil ab einer gewissen Problemgröße die konstanten Faktoren zusehends weniger Rolle spielen.<br />
1928</li>
1929<li>Dabei interessiert nicht der Aufwand eines konkreten Programms auf einem bestimmten Computer, sondern viel mehr, wie der Ressourcenbedarf wächst, wenn mehr Daten zu verarbeiten sind, also z. B. ob sich der Aufwand für die doppelte Datenmenge verdoppelt oder quadriert.</li>
1930</ul>
1931<hr />
1932<table>
1933<thead>
1934<tr class="header">
1935<th align="left">Ordnung</th>
1936<th align="left">Sprechweise</th>
1937<th align="left">Typische Algorithmen / Operationen</th>
1938</tr>
1939</thead>
1940<tbody>
1941<tr class="odd">
1942<td align="left">O(1)</td>
1943<td align="left">konstant</td>
1944<td align="left">Addition</td>
1945</tr>
1946<tr class="even">
1947<td align="left">O(log n)</td>
1948<td align="left">logarithmisch</td>
1949<td align="left">Suchen auf einer sortierten Menge</td>
1950</tr>
1951<tr class="odd">
1952<td align="left">O(n)</td>
1953<td align="left">linear</td>
1954<td align="left">Bearbeiten jedes Elementes einer Menge</td>
1955</tr>
1956<tr class="even">
1957<td align="left">O(n * log n)</td>
1958<td align="left"></td>
1959<td align="left">gute Sortierverfahren</td>
1960</tr>
1961<tr class="odd">
1962<td align="left">O(n<sup>2</sup>)</td>
1963<td align="left">quadratisch</td>
1964<td align="left">primitive Sortierverfahren</td>
1965</tr>
1966<tr class="even">
1967<td align="left">O(n<sup>k</sup>)</td>
1968<td align="left">polynomiell</td>
1969<td align="left"></td>
1970</tr>
1971<tr class="odd">
1972<td align="left">O(2<sup>n</sup>)</td>
1973<td align="left">exponentiell</td>
1974<td align="left">Ausprobieren von Kombinationen</td>
1975</tr>
1976</tbody>
1977</table>
1978<hr />
1979<table>
1980<thead>
1981<tr class="header">
1982<th>Ordnun</th>
1983<th>g n=</th>
1984<th>10 n=1</th>
1985<th>00 n=1000</th>
1986</tr>
1987</thead>
1988<tbody>
1989<tr class="odd">
1990<td>1</td>
1991<td>1</td>
1992<td>1</td>
1993<td>1</td>
1994</tr>
1995<tr class="even">
1996<td>log(n)</td>
1997<td>1</td>
1998<td>2</td>
1999<td>3</td>
2000</tr>
2001<tr class="odd">
2002<td>n</td>
2003<td>10</td>
2004<td>100</td>
2005<td>1000</td>
2006</tr>
2007<tr class="even">
2008<td>n*log(</td>
2009<td>n) 10</td>
2010<td>200</td>
2011<td>3000</td>
2012</tr>
2013<tr class="odd">
2014<td>n<sup>2</sup></td>
2015<td>100</td>
2016<td>1000</td>
2017<td>0 1E6</td>
2018</tr>
2019<tr class="even">
2020<td>2<sup>n</sup></td>
2021<td>102</td>
2022<td>4 1.3E</td>
2023<td>30 1.1E301</td>
2024</tr>
2025</tbody>
2026</table>
2027<p>Anmerkung: 1.3E30 = 1.3 x 10<sup>30</sup></p>
2028<hr />
2029<ul>
2030<li>Die Laufzeit eines Algorithmus der <strong>Ordnung 1 "O(1)"</strong> ist proportional zu "1". Analog dazu gibt es die Ordnungen n, n<sup>2</sup>, ....</li>
2031<li>Konstanten und Polynome niedriger Ordnung werden nicht berücksichtigt.
2032<ul>
2033<li>Bsp.: Ein Verfahren benötigt O(n<sup>2</sup>) Schritte, wenn die exakte Schrittzahl c<sub>2</sub>n<sup>2</sup> + c<sub>1</sub>n + c<sub>0</sub> ist.</li>
2034<li>Deshalb ist es auch egal, welche Basis obige Logarithmen haben.</li>
2035</ul></li>
2036<li>typische Algorithmen der Ordnung <strong>n<sup>2</sup></strong> bearbeiten alle paarweisen Kombinationen von Daten</li>
2037<li>typische Algorithmen der Ordnung <strong>2<sup>n</sup></strong> lösen Probleme "gewaltsam", in dem sie alle Möglichkeiten durchprobieren
2038<ul>
2039<li>Diese Probleme nennt man auch <strong>NP-vollständig</strong>.</li>
2040<li>NP steht für "nicht polynomial".</li>
2041<li>Polynome (Bsp.: 3x+5x3 +8x9) haben stets Konstanten im Exponenten.</li>
2042<li>Schlechtere als polynomielle Laufzeit gilt als nicht effizient.</li>
2043</ul></li>
2044</ul>
2045<hr />
2046<hr />
2047<ol start="68" class="example" style="list-style-type: decimal">
2048<li>Prüfen Sie die algorithmische Komplexität von Suchverfahren in einem geordneten Feld.</li>
2049</ol>
2050<hr />
2051<p>Sei N die Problemgröße == die Anzahl der Elemente in einem geordneten Feld</p>
2052<p>Der Algorithmus SequentialSearch,</p>
2053<ul>
2054<li>welcher das Array sequentiell durchläuft,</li>
2055<li>braucht durchschnittlich N/2 Schritte;</li>
2056<li>seine Komplexität ist O(N)</li>
2057</ul>
2058<p>Der Algorithmus BinarySearch,</p>
2059<ul>
2060<li>welcher das Element nach dem binären Suchverfahren im sortierten Array sucht,</li>
2061<li>braucht durchschnittlich ld(N) Schritte;</li>
2062<li>seine Komplexität ist O(ld(N))</li>
2063</ul>
2064<p>was wesentlich besser ist.</p>
2065<p>Anmerkung: Der Logarithmus zur Basis 2 wird auch als Logarithmus dualis bezeichnet: log2=ld.</p>
2066<h2 id="aufgaben-..."><span class="header-section-number">4.3</span> Aufgaben <a href="#TOC">...</a></h2>
2067<p>Die Datenbank finden Sie <a href="../etc/create_employee.sql.txt">hier</a>.</p>
2068<hr />
2069<hr />
2070<p>Ein Kleinunternehmen hat sich dazu entschieden, ihre Angestellten- und Filialdaten in einer relationalen Datenbank zu verwalten. Dadurch kann das Unternehmen besonders einfach den Datenbestand auswerten.</p>
2071<pre><code>|EMPNO| ENAME | JOB | MGR | HIREDATE | SAL | COMM | DEPTNO |
2072| 7934| MILLER| CLERK | 7782 | 1982-01-23 | 1300.00 | NULL | 10 |
2073| 7782| CLARK | MANAGER | 7839 | 1981-06-09 | 2450.00 | NULL | 10 |
2074| 7839| KING | PRESIDENT | NULL | 1981-11-17 | 5000.00 | NULL | 10 |
2075| 7369| SMITH | CLERK | 7902 | 1980-12-17 | 800.00 | NULL | 20 |
2076| 7876| ADAMS | CLERK | 7788 | 1983-01-12 | 1100.00 | NULL | 20 |
2077| 7566| JONES | MANAGER | 7839 | 1981-04-02 | 2975.00 | NULL | 20 |
2078| 7788| SCOTT | ANALYST | 7566 | 1982-12-09 | 3000.00 | NULL | 20 |
2079| 7902| FORD | ANALYST | 7566 | 1981-12-03 | 3000.00 | NULL | 20 |
2080| 7900| JAMES | CLERK | 7698 | 1981-12-03 | 950.00 | NULL | 30 |
2081| 7654| MARTIN| SALESMAN | 7698 | 1981-09-28 | 1250.00 | 1400.00 | 30 |
2082| 7521| WARD | SALESMAN | 7698 | 1981-02-22 | 1250.00 | 500.00 | 30 |
2083| 7844| TURNER| SALESMAN | 7698 | 1981-09-08 | 1500.00 | 0.00 | 30 |
2084| 7499| ALLEN | SALESMAN | 7698 | 1981-02-20 | 1600.00 | 300.00 | 30 |
2085| 7698| BLAKE | MANAGER | 7839 | 1981-05-01 | 2850.00 | NULL | 30 |</code></pre>
2086<pre><code>|DEPTNO| DNAME | LOC |
2087| 10| ACCOUNTING| NEW YORK |
2088| 20| RESEARCH | DALLAS |
2089| 30| SALES | CHICAGO |
2090| 40| OPERATIONS| BOSTON |</code></pre>
2091<p>Ihre Aufgabe ist es nun, die SQL-Statements für einige dieser Auswertungen zu schreiben.<br />
2092Die Tabellennamen sind "emp" und "dept".</p>
2093<ol style="list-style-type: decimal">
2094<li>Ermitteln Sie alle Informationen zu den Abteilungen. <!--
2095SELECT * FROM EMP;
2096--></li>
2097<li>Ermitteln Sie Name, Job und Einstellungsdatum der Angestellten, die in der Abteilung 10 arbeiten. <!--
2098SELECT ename, job, hiredate FROM emp WHERE deptno = 10;
2099--></li>
2100<li>Ermitteln Sie die Angestellten, die mehr Provision als Gehalt verdienen. <!--
2101SELECT ename FROM emp WHERE comm > sal;
2102--></li>
2103<li>Ermitteln Sie die Angestellten, die keine Verkäufer sind. <!--
2104SELECT ename, job FROM emp WHERE job != 'SALESMAN';
2105--></li>
2106<li>Ermitteln Sie die Angestellten, die am 3. Dezember 1981 angestellt wurden. <!--
2107SELECT ename FROM emp WHERE hiredate = '1981-12-03';
2108--></li>
2109<li>Ermitteln Sie Name und Gehalt der Angestellten, die nicht zwischen 1250 und 1600 verdienen! Trennen Sie den Namen vom Gehalt mit einen Bindestrich! Erfinden Sie eine andere Überschrift für die Ausgabe. <!--
2110SELECT ename||'-'||sal AS namgel FROM emp WHERE sal NOT BETWEEN 1250 AND 1600;
2111--></li>
2112<li>Ermitteln Sie die Angestellten, deren Provision größer als 25% ihres Gehalts ist. <!--
2113SELECT ename, sal, comm FROM emp WHERE comm > 0.25*sal;
2114--></li>
2115<li>Ermitteln Sie die Angestellten, die keine Führungskräfte (Manager und Präsident) sind. <!--
2116SELECT ename, job FROM emp WHERE job NOT IN ('MANAGER','PRESIDENT');
2117--></li>
2118<li>Ermitteln Sie die Angestellten, deren Name an dritter Stelle ein "A" hat. <!--
2119SELECT ename FROM emp WHERE ename LIKE '__A%';
2120--></li>
2121<li>Ermitteln Sie die Angestellten, die provisionsberechtigt sind (auch wenn die Provision "0" ist). <!--
2122SELECT ename FROM emp WHERE comm IS NOT NULL;
2123--></li>
2124<li>Ermitteln Sie die Angestellten, deren Name 6 Zeichen lang sind. <!--
2125SELECT ename FROM emp WHERE ename LIKE '______';
2126--></li>
2127<li>Ermitteln Sie alle Berufe. <!--
2128SELECT DISTINCT job FROM emp;
2129--></li>
2130<li>Ermitteln Sie das monatlichen Gesamtgehalt aller Angestellten. <!--
2131SELECT SUM(sal) FROM emp;
2132--></li>
2133<li>Ermitteln Sie die durchschnittliche Provision im Konzern, wenn für die Mitarbeiter, welche keine Provision eingetragen haben, eine Pauschale von 250 vorgesehen ist. <!--
2134SELECT AVG(IFNULL(comm,250)) FROM emp;
2135--></li>
2136<li>Ermitteln Sie das geringste Gehalt (inklusive Provision). <!--
2137SELECT MIN(sal+IFNULL(comm,0)) FROM emp;
2138--></li>
2139<li>Ermitteln Sie 1) die Anzahl aller Mitarbeiter, 2) die Anzahl der Mitarbeiter, die ein Gehalt bekommen und 3) die Anzahl der Mitarbeiter, die eine Provision (von mindestens 0) bekommen. <!--
2140SELECT COUNT(*), COUNT(sal), COUNT(comm) FROM emp;
2141--></li>
2142<li>Ermitteln Sie die Anzahl der Vorgesetzten! Beachten Sie, dass die Analytiker FORD und SCOTT Vorgesetzte von SMITH und ADAMS sind. <!--
2143SELECT COUNT(DISTINCT mgr) FROM emp;
2144--></li>
2145<li>Ermitteln Sie die Durchschnittsgehälter je Job, wobei Personen mit Provisionszahlungen nicht berücksichtigt werden. <!--
2146SELECT job, AVG(sal) FROM emp WHERE comm IS NULL GROUP BY job;
2147--></li>
2148<li>Ermitteln Sie das Gesamt-Jahresgehalt (incl. Provision) je Abteilung! Die Mitarbeiter, bei denen keine Provision eingetragen ist, erhalten eine Ersatzzahlung in der Höhe von 100 USD/Monat. <!--
2149SELECT deptno, SUM(12*(sal + IFNULL(comm,100))) FROM emp GROUP BY deptno;
2150--></li>
2151<li>Ermitteln Sie die Jobs, deren Durchschnittsgehalt über 1500 USD liegt und sortieren Sie die Ausgabe nach Durchschnittseinkommen. <!--
2152SELECT job, AVG(sal) FROM emp GROUP BY job HAVING AVG(sal) > 1500 ORDER BY 2;
2153--></li>
2154<li>Ermitteln Sie alle Abteilungen mit mindestens 4 Angestellten. <!--
2155SELECT MIN(sal+IFNULL(comm,0)) FROM emp;
2156--></li>
2157<li>Ermitteln Sie alle Abteilungen mit mindestens 3 Verkäufern.</li>
2158<li>Ermitteln Sie den Mitarbeiter, der am meisten verdient.</li>
2159<li>Ermitteln Sie die Mitarbeiter, die in der Abteilung "New York" arbeiten.</li>
2160<li>Ermitteln Sie die Anzahl der Mitarbeiter in der Abteilung "New York".</li>
2161<li>Ermitteln Sie die Mitarbeiter, die mehr verdienen als ihr Vorgesetzter.</li>
2162<li>Ermitteln Sie die Mitarbeiter, die weniger als 30% vom Einkommen des Präsidenten verdienen.</li>
2163<li>Ermitteln Sie die Abteilungen ohne Mitarbeiter. <!--
2164Ermitteln Sie die Mitarbeiter, die mehr verdienen als der Durchschnitt ihrer Abteilung.
2165Ermitteln Sie die Mitarbeiter, die um mehr als 10 % mehr verdienen als der Durchschnitt ihres Jobs.
2166--></li>
2167</ol>
2168<h2 id="aufgaben-nordwind-..."><span class="header-section-number">4.4</span> Aufgaben Nordwind <a href="#TOC">...</a></h2>
2169<p>Die Datenbank finden Sie <a href="../etc/northwind.sql.txt">hier</a>.</p>
2170<p><strong>Einfache SELECT-Abfragen</strong></p>
2171<ol style="list-style-type: decimal">
2172<li><p>Schreiben Sie eine Abfrage, die alle Datensätze der Tabelle products von Lieferanten mit der Nummer 1 liefert.</p></li>
2173<li><p>Schreiben Sie eine Abfrage, die alle Datensätze der Tabelle products mit der Lieferanten Nummer = 1 und Kategorie Nummer = 2 liefert.</p></li>
2174<li><p>Schreiben Sie eine Abfrage, die alle Datensätze der Tabelle products mit Preisen >= 50 und <= 100 anzeigt.</p></li>
2175<li><p>Schreiben Sie eine Abfrage, die alle Datensätze der Tabelle products mit Netto-und Bruttopreisen anzeigt.</p></li>
2176<li><p>Schreiben Sie eine Abfrage, die alle Datensätze der Tabelle employees mit Vor-und Nachname, getrennt durch ein Leerzeichen anzeigt.</p></li>
2177<li><p>Schreiben Sie eine Abfrage, die alle Datensätze der Tabelle employees mit Mitarbeitern aus London, Redmond oder Seattle liefert.</p></li>
2178<li><p>Schreiben Sie eine Abfrage, die die Nachnamen aller Mitarbeiter aus den USA anzeigt. Die Nachnamen sollen absteigend sortiert werden.</p></li>
2179<li><p>Schreiben Sie eine Abfrage, die alle Produktnamen mit deren Kategorie-ID auflistet.</p></li>
2180<li><p>Dabei soll jeweils folgender Satz ausgegeben werden: Das Produkt X gehört zur Kategorie Y.</p></li>
2181</ol>
2182<p><strong>LIKE, Platzhalter</strong></p>
2183<ol start="10" style="list-style-type: decimal">
2184<li><p>Erstellen Sie eine Abfrage, die Ihnen alle Produkte ausgibt, die mit C anfangen. Diese sollen absteigend nach dem Produktname sortiert sein.</p></li>
2185<li><p>Erstellen Sie eine Abfrage, die Ihnen alle Produkte ausgibt, die mit "A", "B" oder "C" anfangen.</p></li>
2186<li><p>Erstellen Sie eine Abfrage, die Ihnen alle Produkte ausgibt, bei denen der 5. Buchstabe ein c oder d ıst. Diese sollen aufsteigend nach dem Produktnamen sortiert sein.</p></li>
2187<li><p>Erstellen Sie eine Abfrage, die Ihnen alle Produkte ausgibt, bei denen der 5. Buchstabe kein c ıst.</p></li>
2188</ol>
2189<p><strong>Gruppierungen</strong></p>
2190<ol start="14" style="list-style-type: decimal">
2191<li><p>Schreiben Sie eine Abfrage, die Ihnen die Spalte City der Tabelle employees ausgibt. Es soll keine Stadt mehrmals auftauchen.</p>
2192<pre><code>CITY
2193---------------
2194Seattle
2195Tacoma
2196Ta</code></pre></li>
2197<li><p>Schreiben Sie eine Abfrage, die Ihnen die Summe des Warenbestandes (unitsinstock) aus der Tabelle products, gruppiert nach den Lieferantennummern (supplierid) ausgibt.</p>
2198<pre><code>SUPPLIERID SUMME
2199---------------
22001 69</code></pre></li>
2201<li><p>Schreiben Sie eine Abfrage, die Ihnen die Summe des Warenbestandes (unitsinstock) aus der Tabelle products, gruppiert nach den Lieferantennummern (supplierid) ausgibt! Es sollen nur die Lieferanten erscheinen, bei denen die Summe des warenbestandes großer als 70 ist.</p>
2202<pre><code>SUPPLIERID SUMME
2203---------------
22042 133</code></pre></li>
2205<li><p>Schreiben Sie eine Abfrage, die Ihnen die Summe des Warenbestandes (unitsinstock) aus der Tabelle products, gruppiert nach den Lieferantennummern (supplierid) und den Kategorienummern (categoryid) ausgibt!</p>
2206<pre><code>SupplierID CategoryID sum(unitsinstock)
2207---------- ---------- -----------------
22081 1 56
22091 2 13
22102 2 133
22113 2 126
22123 7 15
22134 6 29
22144 7 4
22154 8 31
22165 4 108
22176 2 39
22186 7 35
22196 8 24
22207 1 15
22217 2 24
22227 3 29
22237 6 0
22247 8 42
22258 3 74
22269 5 165
222710 1 20
222811 3 140
222912 1 125
223012 2 32
223112 5 22
223212 6 0
223312 7 26
223413 8 10
223514 4 23
223615 4 164
223716 1 183
223817 8 224
223918 1 86
224019 8 208
224120 1 17
224220 2 27
224320 5 26
224421 8 100
224522 3 51
224623 1 57
224723 3 75
224824 5 38
224924 6 0
225024 7 20
225125 6 136
225226 5 57
225327 8 62
225428 4 98
225529 2 113
225629 3 17 </code></pre></li>
2257<li><p>Listen Sie alle Lieferanten auf, die mindestens 5 Produkte liefern!</p>
2258<pre><code>SUPPLIERID
2259---------
22607
226112</code></pre></li>
2262<li><p>Listen Sie die Lieferanten mit Ihren jeweils teuersten Produkt auf. Es sollen nur die Lieferanten angezeigt werden, bei denen das teuerste Produkt billiger als 10 DM ist.</p>
2263<pre><code>SUPPLIERID MAX(UNITPRICE)
2264-------------------------
226510 4.5</code></pre></li>
2266<li><p>Zusatzfrage: Listen Sie den Nachnamen des Mitarbeiters (employees) auf, der am längsten angestellt war!</p></li>
2267<li><p>Was machen folgende Abfragen?</p>
2268<pre><code>select lastname from employees group by city;
2269-- Lösung: -- Spalte "lastname" ist sinnnlos
2270select lastname from employees where city not in(‘Berlin’,’London’);
2271-- Lösung: -- Anzeige aller Angestellten, die nicht aus Berlin oder London kommen.
2272select discontinued,sum(unitprice*unitsinstock) from products group by
2273discontinued;
2274-- Lösung: -- Zeigt den Wert der Produkte im Warenlager an
2275-- getrennt nach den Produkten die nachbestellt werden und
2276-- die, die nicht nachbestellt werden
2277select supplierid,sum(unitprice*unitsinstock) from products group by supplierid;
2278-- Lösung: -- Werte der Produkte jedes Lieferanten im Warenlager.
2279select categoryid,sum(unitprice*unitsinstock) from products group by supplierid;
2280-- Lösung: -- Spalte "categoryid" ist sinnlos
2281select sum(unitprice*unitsinstock) from products group by supplierid;
2282-- Lösung: -- Werte der Produkte jedes Lieferanten im Warenlager.
2283-- Allerdings ist nicht klar, zu welchem Lieferanten die jeweilige Summe gehört.
2284select sum(unitprice*unitsinstock) from products;
2285-- Lösung: -- Anzeige des Warenbestandes im Warenlager.</code></pre></li>
2286</ol>
2287<p><strong>JOIN</strong></p>
2288<ol start="22" style="list-style-type: decimal">
2289<li><p>Schreiben Sie eine Abfrage, die Ihnen die Kontaktnamen der Lieferanten ausgibt, die Produkte der Kategorie 1 oder 2 oder 3 liefern! <!--
2290SELECT ContactName
2291FROM Products p, suppliers s
2292 ON s.SupplierID = p.SupplierID
2293 AND CategoryID IN (1,2,3);
2294--></p>
2295<pre><code>CONTACTNAME PRODUCTNAME
2296------------------------------------------
2297Charlotte Cooper Chai
2298Charlotte Cooper Chang
2299Charlotte Cooper Aniseed Syrup
2300Shelley Burke Chef Anton s Cajun Seasoning</code></pre></li>
2301<li><p>Schreiben Sie eine Abfrage, die Ihnen die Kundennamen, die entsprechenden Bestellungnummern (orderid) und den Namen des Angestellten (employees), der die Bestellung bearbeitet hat, ausgibt. Es soll nach dem Contactname geordnet sein! <!--
2302SELECT ContactName, LastName, OrderID
2303FROM orders o, Employees e, Customers c
2304 ON c.CustomerID = o.CustomerID
2305 AND e.EmployeeID = o.EmployeeID
2306ORDER BY ContactName;
2307--></p>
2308<pre><code>CONTACTNAME ORDERID
2309LASTNAME
2310-------------------------------------------------
2311Alejandra Camino
231210281 Peacock
2313Alejandra Camino
231410282 Peacock
2315Alejandra Camino
231610306 Davolio
2317Alejandra Camino
231810917 Peacock</code></pre></li>
2319<li><p>Schreiben Sie eine Abfrage, die Ihnen alle Kundennamen ausgibt, die eine Bestellung aufgegeben haben, die Produkte beinhaltet, die von einem Lieferanten aus Berlin geliefert werden. Es soll absteigend nach den Kundennamen sortiert werden! <!--
2320SELECT ContactName
2321FROM Products p, suppliers s
2322 ON s.SupplierID = p.SupplierID
2323 AND CategoryID IN (1,2,3);
2324
2325SELECT DISTINCT ContactName
2326FROM orders o, Customers c, suppliers s
2327 ON c.CustomerID = o.CustomerID
2328 AND s.SupplierID = o.SupplierID
2329WHERE ShipCity = 'Berlin'
2330ORDER BY ContactName ASC;
2331--></p></li>
2332<li><p>Schreiben Sie eine Abfrage, die Ihnen alle Kundennamen ausgibt, die eine Bestellung aufgegeben haben, die von Speedy Express ausgeliefert wurde! <!--
2333SELECT DISTINCT Customers.CompanyName
2334FROM Orders, Shippers, Customers
2335 ON ShipperID = ShipVia
2336 AND Customers.CustomerID = Orders.CustomerID
2337WHERE Shippers.CompanyName = 'Speedy Express';
2338--></p></li>
2339<li><p>Schreiben Sie eine Abfrage, die Ihnen die Städte ausgibt, in denen Kunden wohnen und die Städte darunter ausgibt, in denen Lieferanten wohnen. Jede Stadt soll nur einmal auftauchen! <!--
2340CREATE VIEW overkill AS
2341SELECT 's' type, City FROM Suppliers
2342 EXCEPT
2343SELECT 's' type, City FROM Customers;
2344SELECT DISTINCT * FROM (
2345 SELECT 'c' type, City FROM Customers
2346 UNION
2347 SELECT * FROM overkill
2348) ORDER BY type;
2349--></p>
2350<pre><code>CITY
2351------
2352Aachen
2353Albuquerque
2354Anchorage
2355Ann Arbor</code></pre></li>
2356<li><p>Schreiben Sie eine Abfrage, die Ihnen die Stadte ausgibt, in den sowohl Kunden als auch Lieferanten wohnen. Jede Stadt soll nur einmal auftauchen! <!--
2357SELECT City FROM Customers
2358INTERSECT
2359SELECT City FROM Suppliers;
2360--></p>
2361<pre><code>CITY
2362------
2363Berlin
2364London</code></pre></li>
2365<li><p>Schreiben Sie eine Abfrage, die Ihnen die Stadte ausgibt, in den Kunden, nicht aber Lieferanten, wohnen. Jede Stadt soll nun einmal auftauchen! <!--
2366SELECT City FROM Customers
2367EXCEPT
2368SELECT City FROM Suppliers;
2369--> CITY ----- Aachen Albuquerque</p></li>
2370<li><p>Schreiben Sie eine Abfrage, die Ihnen die Lieferanten ausgibt, die keine Produkte liefern! <!--
2371SELECT SupplierID FROM Suppliers
2372WHERE SupplierID NOT IN
2373(SELECT SupplierID FROM Products);
2374
2375SELECT SupplierID FROM Suppliers
2376EXCEPT
2377SELECT SupplierID FROM Products;
2378
2379SELECT Suppliers.SupplierID FROM
2380 Suppliers LEFT JOIN Products
2381 ON Suppliers.SupplierID = Products.SupplierID WHERE Products.SupplierID IS NULL;
2382--></p></li>
2383<li><p>Schreiben Sie eine Abfrage, die Ihnen die Angestellten und Vorgesetzten ausgibt. Die reportsto-Spalte gibt die employeeid des Vorgesetzten an, der wiederum auch selbst ein Angestellter ist!</p></li>
2384<li><p>Schreiben Sie eine Abfrage, die Ihnen die Kunden und Ihren Gesamtbestellwert (ohne Discount) auflistet. <!--
2385SELECT CustomerID, SUM(UnitPrice*Quantity)
2386FROM Orders o, OrderDetails od ON od.OrderID = o.OrderID
2387GROUP BY o.CustomerID;
2388--></p>
2389<pre><code>CUSTO SUM(UNITPRICE
2390---------------
2391ALFKI 9192,4
2392ANATR 2805,9
2393ANTON 15030,7
2394AROUT 27613
2395BERGS 53936,3
2396BLAUS 4763,6</code></pre></li>
2397<li><p>Wieviel Produkte hat ALFKI bestellt? <!--
2398SELECT COUNT(DISTINCT ProductID)
2399FROM Orders o, OrderDetails d
2400ON o.OrderID = d.OrderID
2401WHERE CustomerID = 'ALFKI';
2402
2403--></p></li>
2404<li><p>Wie ist der Gesamtumsatz von ALFKI? <!--
2405SELECT SUM(UnitPrice*Quantity)
2406FROM Orders o, OrderDetails d
2407ON o.OrderID = d.OrderID
2408WHERE CustomerID = 'ALFKI';
2409--></p></li>
2410<li><p>Was machen folgende Abfragen?</p>
2411<pre><code>select * from products pr,categories ca;
2412-- Lösung: -- ??
2413select pr.productname, ca.categoryname from products rp,categories ca where
2414pr.productid=ca.categoryid;
2415-- Lösung: -- ??
2416select pr.productname, ca.categoryname from products pr,categories ca where
2417pr.categoryid(+)=ca.categoryid};
2418-- Lösung: -- ??
2419select sum(pr.unitprice*pr.unitsinstock), ca.categoryname from products
2420pr,categories ca where pr.productid=ca.categoryid group by ca.categoryname;
2421-- Lösung: -- ??
2422select sum(pr.unitprice*pr.unitsinstock), ca.categoryname from products
2423pr,categories ca group by ca.categoryname where pr.productid=ca.categoryid};
2424-- Lösung:
2425-- ??</code></pre></li>
2426</ol>
2427<!--
2428select * from products pr, categories ca;
2429-- Lösung: -- CROSS JOIN: Sinnlose Verknüpfung aller Produkte mit allen Kategorien
2430
2431select pr.productname, ca.categoryname from products rp,categories ca where
2432pr.productid=ca.categoryid;
2433-- Lösung: -- Equijoin: verknüpft die Produkte mit den dazu passenden Kategorien
2434
2435select pr.productname, ca.categoryname from products pr,categories ca where
2436pr.categoryid(+)=ca.categoryid};
2437-- Lösung: -- (LEFT) OUTER JOIN, wie oben, zeigt auch die Produkte ohne Kategorien an.
2438
2439select sum(pr.unitprice*pr.unitsinstock), ca.categoryname from products
2440pr,categories ca where pr.productid=ca.categoryid group by ca.categoryname;
2441-- Lösung: -- Zeigt den Gesamtumsatz pro Kategorie
2442
2443select sum(pr.unitprice*pr.unitsinstock), ca.categoryname from products
2444pr,categories ca group by ca.categoryname where pr.productid=ca.categoryid};
2445-- Lösung:
2446-- Fehlermeldung, weil "where" vor "group by" stehen muss
2447-->
2448<p><strong>Verschachtelte Abfragen</strong></p>
2449<ol start="35" style="list-style-type: decimal">
2450<li><p>Wie heißt der älteste Mitarbeiter? <!--
2451SELECT LastName
2452FROM Employees
2453ORDER BY HireDate
2454LIMIT 1;
2455
2456SELECT LastName
2457FROM Employees
2458WHERE HireDate =
2459(SELECT MIN(HireDate) FROM Employees);
2460--></p></li>
2461<li><p>Wie heißt das teuerste Produkt eines Lieferanten aus ”Berlin“? <!--
2462SELECT ProductName
2463FROM Products
2464WHERE SupplierID =
2465 (SELECT SupplierID FROM Suppliers WHERE City = 'Berlin')
2466ORDER BY UnitPrice DESC
2467LIMIT 1;
2468
2469SELECT CompanyName,
2470MAX(UnitPrice)
2471FROM Products p, Suppliers s
2472ON p.SupplierID = s.SupplierID
2473WHERE City = 'Berlin'
2474GROUP BY CompanyName;
2475--></p></li>
2476<li><p>Welche Produkte (productname) sind überdurchschnittlich teuer? <!--
2477SELECT ProductName
2478FROM Products
2479WHERE UnitPrice >
2480(SELECT AVG(UnitPrice) FROM Products);
2481--></p></li>
2482<li><p>Wie heißt der jüngste Mitarbeiter? <!--
2483SELECT LastName
2484FROM Employees
2485ORDER BY HireDate DESC
2486LIMIT 1;
2487--></p></li>
2488<li><p>Schreiben Sie eine Abfrage, die Ihnen die Lieferanten (Companyname) und daneben das teuerste Produkt dieses Lieferanten (Productname) und daneben den Preis ausgibt. <!--
2489SELECT ProductName, UnitPrice, CompanyName
2490FROM Products x, Suppliers s
2491ON x.SupplierID = s.SupplierID
2492WHERE UnitPrice =
2493 (SELECT MAX(UnitPrice)
2494 FROM Products
2495 WHERE SupplierID = x.SupplierID);
2496--></p></li>
2497<li><p>Welcher Kunde hat bisher am meisten bestellt? <!--
2498SELECT CustomerID FROM ORDERS
2499GROUP BY CustomerID
2500ORDER BY count(*) DESC
2501LIMIT 1;
2502--></p></li>
2503<li><p>Erstellen Sie eine Abfrage, die Ihnen die Kunden (contactname) und die bisherigen Umsätze auflistet. <!--
2504SELECT ContactName, SUM(UnitPrice*Quantity)
2505FROM Customers c, Orders o, OrderDetails od
2506ON c.CustomerID = o.CustomerID
2507 AND o.OrderID = od.OrderID
2508GROUP BY ContactName;
2509--></p></li>
2510<li><p>Welche Kunden haben bisher Chai bestellt? <!--
2511SELECT DISTINCT CustomerID
2512FROM Orders o, OrderDetails od, Products p
2513ON o.OrderID = od.OrderID
2514 AND od.ProductID = p.ProductID
2515WHERE ProductName = 'Chai';
2516--></p></li>
2517<li><p>Wie heißt der zweitälteste Mitarbeiter? <!--
2518SELECT LastName, BirthDate FROM Employees ORDER BY BirthDate LIMIT 1 OFFSET 1;
2519--></p></li>
2520<li><p>Wie heißt der drittjüngste Mitarbeiter? <!--
2521SELECT LastName, BirthDate FROM Employees ORDER BY BirthDate DESC LIMIT 1 OFFSET 2;
2522--></p></li>
2523</ol>
2524<h1 id="e.-datenbankdefinition-ddl-..."><span class="header-section-number">5</span> E. Datenbankdefinition (DDL) <a href="#TOC">...</a></h1>
2525<h2 id="constraints-..."><span class="header-section-number">5.1</span> Constraints <a href="#TOC">...</a></h2>
2526<p>Ein Kleinunternehmen hat sich dazu entschieden, ihre Angestellten- und Filialdaten in einer relationalen Datenbank zu verwalten. Dadurch kann das Unternehmen besonders einfach den Datenbestand auswerten.</p>
2527<pre><code> |DEPTNO| DNAME | LOC |
2528 | 10| ACCOUNTING| NEW YORK |
2529
2530
2531 |EMPNO| ENAME | JOB | MGR | HIREDATE | SAL | COMM | DEPTNO |
2532 | 7782| CLARK | MANAGER | 7839 | 1981-06-09 | 2450.00 | NULL | 10 |
2533 | 7839| KING | PRESIDENT | NULL | 1981-11-17 | 5000.00 | NULL | 10 |</code></pre>
2534<hr />
2535<ol start="69" class="example" style="list-style-type: decimal">
2536<li><p>Erstellen Sie eine Tabelle für die Abteilungen eines Unternehmens.</p>
2537<ul>
2538<li>Wählen Sie sinnvolle Datentypen.</li>
2539<li>Definieren Sie die Primärschlüssel.</li>
2540</ul></li>
2541</ol>
2542<hr />
2543<div class="sourceCode"><pre class="sourceCode sql"><code class="sourceCode sql"><span class="kw">DROP</span> <span class="kw">TABLE</span> <span class="kw">IF</span> <span class="kw">EXISTS</span> dept;
2544<span class="kw">CREATE</span> <span class="kw">TABLE</span> dept (
2545 deptno <span class="dt">INTEGER</span> <span class="kw">PRIMARY</span> <span class="kw">KEY</span>,
2546 dname TEXT <span class="kw">UNIQUE</span> <span class="kw">NOT</span> <span class="kw">NULL</span>,
2547 loc TEXT <span class="kw">NOT</span> <span class="kw">NULL</span>
2548);</code></pre></div>
2549<hr />
2550<hr />
2551<ol start="70" class="example" style="list-style-type: decimal">
2552<li><p>Erstellen Sie eine Tabelle für die Angestellten eines Unternehmens.</p>
2553<ul>
2554<li>"mgr" ist die empno des Vorgesetzten.</li>
2555<li>Gewährleisten Sie die referentielle Integrität.</li>
2556<li>Wählen Sie sinnvolle Datentypen.</li>
2557<li>Definieren Sie die Primärschlüssel.</li>
2558</ul></li>
2559</ol>
2560<hr />
2561<div class="sourceCode"><pre class="sourceCode sql"><code class="sourceCode sql"><span class="kw">DROP</span> <span class="kw">TABLE</span> <span class="kw">IF</span> <span class="kw">EXISTS</span> emp;
2562<span class="kw">CREATE</span> <span class="kw">TABLE</span> emp(
2563 empno <span class="dt">INTEGER</span> <span class="kw">PRIMARY</span> <span class="kw">KEY</span>,
2564 ename TEXT <span class="kw">NOT</span> <span class="kw">NULL</span>,
2565 job TEXT,
2566 mgr <span class="dt">INT</span>,
2567 hiredate TEXT,
2568 sal <span class="dt">REAL</span>,
2569 comm <span class="dt">REAL</span>,
2570 deptno <span class="dt">INT</span>,
2571 <span class="kw">FOREIGN</span> <span class="kw">KEY</span>(mgr) <span class="kw">REFERENCES</span> emp (empno),
2572 <span class="kw">FOREIGN</span> <span class="kw">KEY</span>(deptno) <span class="kw">REFERENCES</span> dept (deptno)
2573);</code></pre></div>
2574<ul>
2575<li>Eine Tabelle entfernen: DROP TABLE table</li>
2576<li>Bei <code>DROP TABLE IF EXISTS</code> gibt es keine Fehlermeldung für den Fall, dass die Tabelle gar nicht mehr existiert.</li>
2577</ul>
2578<hr />
2579<hr />
2580<ol start="71" class="example" style="list-style-type: decimal">
2581<li>Nennen Sie eine andere Möglichkeit für die Klausel <code>PRIMARY KEY</code>.</li>
2582</ol>
2583<hr />
2584<p><code>PRIMARY KEY</code> entspricht den beiden Klauseln <code>UNIQUE</code> und <code>NOT NULL</code>.</p>
2585<hr />
2586<hr />
2587<ol start="72" class="example" style="list-style-type: decimal">
2588<li>Erläutern Sie die von SQLite verwendeten Datentypen.</li>
2589</ol>
2590<hr />
2591<ul>
2592<li>SQLite speichert die Daten nicht mit einem festen Datentyp je Tabellenspalte, sondern mit einer <strong>Datentyp-Affinität</strong>. Damit ist gemeint, dass eine Spalte zwar einen Datentyp darstellt, dieser aber nur ein Hinweis darauf ist, wie die gespeicherten Daten zu interpretieren sind. Tatsächlich dürfen alle möglichen Datentypen in einer Spalte gespeichert werden.</li>
2593<li>Folgende Affinitäten kennt SQLite:
2594<ul>
2595<li>INT(EGER)</li>
2596<li>REAL</li>
2597<li>NUMERIC bedeutet "INTEGER" oder "REAL"</li>
2598<li>TEXT Zeichenkette</li>
2599<li>BLOB (Binary Large Object) exakte Kopie des Inputs, zB Medien-Dateien</li>
2600</ul></li>
2601<li>Das Datum wird als TEXT im Format 'YYYY-MM-DD' gespeichert.</li>
2602</ul>
2603<hr />
2604<hr />
2605<ol start="73" class="example" style="list-style-type: decimal">
2606<li>Erläutern Sie die Foreign-Key-Klausel.</li>
2607</ol>
2608<hr />
2609<div class="sourceCode"><pre class="sourceCode sql"><code class="sourceCode sql"><span class="kw">FOREIGN</span> <span class="kw">KEY</span> spalte, ...
2610 <span class="kw">REFERENCES</span> tabelle (spalte, ...)
2611 [<span class="kw">ON</span> <span class="kw">DELETE</span> {RESTRICT|CASCADE|SET <span class="kw">NULL</span>}]
2612 [<span class="kw">ON</span> <span class="kw">UPDATE</span> {RESTRICT|CASCADE|SET <span class="kw">NULL</span>}]</code></pre></div>
2613<ul>
2614<li>Bsp.: ON DELETE CASCADE bewirkt, dass das Löschen eines Datensatzes der Master-Tabelle alle zugehörigen Einträge in Detail-Tabelle entfernt.</li>
2615<li>ON DELETE RESTRICT verbietet das Ändern der betroffenen Spalten in der Master-Tabelle</li>
2616<li>SET NULL setzt die Fremdschlüssel auf NULL</li>
2617</ul>
2618<hr />
2619<hr />
2620<ol start="74" class="example" style="list-style-type: decimal">
2621<li>Beschreiben Sie die Begriffe Datenintegrität und referentielle Integrität.</li>
2622</ol>
2623<hr />
2624<ul>
2625<li>Datenintegrität ist die Korrektheit der gespeicherten Daten.</li>
2626<li>Die referentielle Integrität stellt sicher, daß alle Werte eines Attributes oder einer Attributkombination, das/die als Fremdschlüssel definiert ist, in einer anderen Relation (als Primärschlüssel) vorhanden ist.</li>
2627</ul>
2628<hr />
2629<hr />
2630<ol start="75" class="example" style="list-style-type: decimal">
2631<li>Erläutern Sie die Befehlsgruppe DDL.</li>
2632</ol>
2633<hr />
2634<p>Die DDL (Data Definition Language, Datenbeschreibungssprache) ist Sprache zum Erstellen und Verändern des konzeptuellen und externen Schemas. Damit erstellt man Tabellen und Views.</p>
2635<h2 id="views-collections-..."><span class="header-section-number">5.2</span> Views, Collections <a href="#TOC">...</a></h2>
2636<ol start="76" class="example" style="list-style-type: decimal">
2637<li>Erläutern Sie den Begriff "View".</li>
2638</ol>
2639<hr />
2640<ul>
2641<li>Eine Sicht ist genau genommen nichts weiter als eine <strong>gespeicherte Abfrage</strong>.</li>
2642<li>Diese gespeicherte Abfrage wird <strong>wie eine Tabelle behandelt</strong>. Sie kann genau wie eine Tabelle abgefragt werden.</li>
2643<li>Selbst <strong>DML-Statements</strong> (INSERT, UPDATE, DELETE) sind unter bestimmten Umständen möglich. Dies hängt von der gespeicherten Abfrage ab. In SQLite ist das allerdings nicht möglich</li>
2644</ul>
2645<p><strong>Views anlegen</strong>: <code>CREATE [TEMP[ORARY]] VIEW [IF NOT EXISTS] <viewname> AS <select-stmt></code></p>
2646<p><strong>Views löschen</strong>: <code>DROP VIEW [IF EXISTS] <viewname></code></p>
2647<p>Der eigentliche Nutzen einer Sicht ist das <strong>Verstecken</strong> einer recht komplizierten und umfangreichen Abfrage. So ist es einfacher, alle Datensätze der Sicht <code>research_mitarbeiter</code> abzufragen als sich die Abfrage, welche alle Research-Mitarbeiter ermittelt, zu schreiben und anschließend auszuführen.</p>
2648<hr />
2649<hr />
2650<ol start="77" class="example" style="list-style-type: decimal">
2651<li>Erstellen Sie ein View "dept_sal" für das Minimal- und das Durchschnittsgehalt jeder Abteilung. Die Gehälter der Führungskräfte (Manager, Präsident) werden dabei nicht berücksichtigt.</li>
2652</ol>
2653<hr />
2654<div class="sourceCode"><pre class="sourceCode sql"><code class="sourceCode sql"><span class="kw">CREATE</span> <span class="kw">VIEW</span> dept_sal <span class="kw">AS</span>
2655<span class="kw">SELECT</span> deptno, <span class="fu">MIN</span>(sal), <span class="fu">AVG</span>(sal) <span class="kw">FROM</span> emp
2656<span class="kw">WHERE</span> job <span class="kw">NOT</span> <span class="kw">IN</span> (<span class="st">'MANAGER'</span>, <span class="st">'PRESIDENT'</span>) <span class="kw">GROUP</span> <span class="kw">BY</span> deptno;</code></pre></div>
2657<hr />
2658<hr />
2659<ol start="78" class="example" style="list-style-type: decimal">
2660<li>Erklären Sie das Konzept von Ebenenmodellen.</li>
2661</ol>
2662<hr />
2663<p><strong>Datenunabhängigkeit</strong> bewirkt: Die Änderung der logischen und physischen Struktur der Daten erfordert keine Änderung der Anwendungsprogramme.</p>
2664<p><strong>Physische Datenunabhängigkeit</strong> betrifft die physischen Organisation der Daten (Dateien, Feldlängen, ...).</p>
2665<p><strong>Logische Datenunabhängigkeit</strong>: Die logische Sicht eines Programms auf die benutzten Daten soll von der logischen Gesamtsicht auf alle Daten unabhängig sein. Neue Felder, neue Beziehungen, ... sollen keine Änderung der Anwendungsprogramme bewirken.</p>
2666<p>Die Realisierung physischer und logischer Datenunabhängigkeit macht eine Betrachtung der gespeicherten Daten in mindestens drei verschiedenen <strong>Abstraktionsebenen</strong> erforderlich:</p>
2667<ul>
2668<li>die <strong>interne</strong> Datensicht (physische Datenorganisation; tatsächliche Speicherung der Daten),</li>
2669<li>die <strong>konzeptionelle</strong> Datensicht (logische Gesamtsicht aller Daten)</li>
2670<li>die <strong>externen</strong> Datensichten (logische Sichten von Applikationen auf Teile der Datenbank). Sie umfassen individuelle Sichten (=Views) der einzelnen Benutzergruppen. Eine <strong>View</strong> enthält nur den Ausschnitt dem konzeptionellen Schema, die der Anwender sehen möchte.</li>
2671</ul>
2672<p>Die Beschreibungen der 3 Datensichten erfolgen durch das</p>
2673<ul>
2674<li>interne Schema</li>
2675<li>konzeptionelle Schema</li>
2676<li>externe Schema</li>
2677</ul>
2678<p>Ein <strong>Schema</strong> ist eine in einer Datenbeschreibungssprache (=DDL) abgefaßte Definition der in einer Datenbank zugelassenen Datenstrukturen.</p>
2679<p><strong>Beispiel:</strong></p>
2680<p>Konzeptionelles Schema: Kursbuch der Deutschen Bundesbahn.</p>
2681<p>Verschiedene externe Schemata:</p>
2682<ul>
2683<li>Fahrplan der IC-Züge zwischen den Großstädten der BRD</li>
2684<li>Innerhalb einer Großstadt die Vorortverbindungen</li>
2685<li>Externe Datensicht des Reisenden: Abfahrt und Ankunft von einigen Anschlußzügen</li>
2686</ul>
2687<hr />
2688<hr />
2689<ol start="79" class="example" style="list-style-type: decimal">
2690<li>Vergleichen Sie MongoDB mit dem SQL-Strukturen: Datenbank, Tabelle, Datensatz.</li>
2691</ol>
2692<hr />
2693<p><em>Abbildung 3: Vergleich MongoDB – SQL-Schema</em></p>
2694<dl>
2695<dt>.</dt>
2696<dd><img src="/home/user/acha/www-img/mongodb/volke-5_1.png" /> .
2697</dd>
2698<dd><img src="/home/user/acha/www-img/mongodb/volke-5_2.png" />
2699</dd>
2700</dl>
2701<p>Dokumente werden in Collections zusammengefasst. Eine <strong>Collection</strong> ist eine benannte Menge von Dokumenten.</p>
2702<p>Jede Collection ist in einer <strong>Datenbank</strong> gespeichert und jedes MongoDB-System enthält eine Menge von Datenbanken.</p>
2703<p>Dadurch ergibt sich eine gewisse Ähnlichkeit zu der Strukturierung in relationalen Datenbankensystemen (siehe Abbildung 3).</p>
2704<p>Auch in letzteren sind die Daten in Datenbanken gespeichert, die wiederum Tabellen enthalten. Diese Tabellen entsprechen in etwa den Collections in MongoDB.</p>
2705<p>Innerhalb einer Tabelle sind die Datensätze als Zeilen gespeichert, wobei jede Zeile ein Tupel aus einem oder mehreren Werten ist.</p>
2706<p>Dies entspricht in MongoDB einem Dokument als Sammlung von Schlüssel-Werte-Paaren.</p>
2707<p>In einem RDBMS unterliegt aber die Tabelle einem Schema, sodass alle Zeilen der Tabelle den gleichen Aufbau haben, d.h. die gleiche Anzahl von Werten mit jeweils den gleichen Datentypen.</p>
2708<p>In MongoDB unterliegen die Dokumente keinem festen Schema, sondern jedes Dokument hat seine eigene Strukturierung.</p>
2709<p>Die Dokumente einer Collection können Ähnlichkeiten aufweisen, müssen es aber nicht.</p>
2710<h1 id="f.-datenbankmanipulation-dml-..."><span class="header-section-number">6</span> F. Datenbankmanipulation (DML) <a href="#TOC">...</a></h1>
2711<h2 id="grundlagen-..."><span class="header-section-number">6.1</span> Grundlagen <a href="#TOC">...</a></h2>
2712<p>Ein Kleinunternehmen hat sich dazu entschieden, ihre Angestellten- und Filialdaten in einer relationalen Datenbank zu verwalten. Dadurch kann das Unternehmen besonders einfach den Datenbestand auswerten.</p>
2713<pre><code> |DEPTNO| DNAME | LOC |
2714 | 10| ACCOUNTING| NEW YORK |
2715
2716
2717 |EMPNO| ENAME | JOB | MGR | HIREDATE | SAL | COMM | DEPTNO |
2718 | 7782| CLARK | MANAGER | 7839 | 1981-06-09 | 2450.00 | NULL | 10 |
2719 | 7839| KING | PRESIDENT | NULL | 1981-11-17 | 5000.00 | NULL | 10 |</code></pre>
2720<hr />
2721<ol start="80" class="example" style="list-style-type: decimal">
2722<li>Erstellen Sie ein Insert-Statement für die erste Abteilung und den ersten Angestellten!</li>
2723</ol>
2724<hr />
2725<div class="sourceCode"><pre class="sourceCode sql"><code class="sourceCode sql"><span class="kw">INSERT</span> <span class="kw">INTO</span> dept <span class="kw">VALUES</span>(<span class="dv">10</span>,<span class="st">'ACCOUNTING'</span>,<span class="st">'NEW YORK'</span>);
2726<span class="kw">INSERT</span> <span class="kw">INTO</span> dept <span class="kw">VALUES</span>(<span class="dv">20</span>,<span class="st">'RESEARCH'</span>,<span class="st">'DALLAS'</span>);
2727<span class="kw">INSERT</span> <span class="kw">INTO</span> dept <span class="kw">VALUES</span>(<span class="dv">30</span>,<span class="st">'SALES'</span>,<span class="st">'CHICAGO'</span>);
2728<span class="kw">INSERT</span> <span class="kw">INTO</span> dept <span class="kw">VALUES</span>(<span class="dv">40</span>,<span class="st">'OPERATIONS'</span>,<span class="st">'BOSTON'</span>);
2729
2730<span class="kw">INSERT</span> <span class="kw">INTO</span> emp <span class="kw">VALUES</span>(<span class="dv">7369</span>,<span class="st">'SMITH'</span>,<span class="st">'CLERK'</span>,<span class="dv">7902</span>,<span class="st">'1980-12-17'</span>,<span class="fl">800.0</span>,<span class="kw">NULL</span>,<span class="dv">20</span>);
2731<span class="kw">INSERT</span> <span class="kw">INTO</span> emp <span class="kw">VALUES</span>(<span class="dv">7499</span>,<span class="st">'ALLEN'</span>,<span class="st">'SALESMAN'</span>,<span class="dv">7698</span>,<span class="st">'1981-02-20'</span>,<span class="fl">1600.0</span>,<span class="fl">300.0</span>,<span class="dv">30</span>);
2732<span class="kw">INSERT</span> <span class="kw">INTO</span> emp <span class="kw">VALUES</span>(<span class="dv">7521</span>,<span class="st">'WARD'</span>,<span class="st">'SALESMAN'</span>,<span class="dv">7698</span>,<span class="st">'1981-02-22'</span>,<span class="fl">1250.0</span>,<span class="fl">500.0</span>,<span class="dv">30</span>);
2733<span class="kw">INSERT</span> <span class="kw">INTO</span> emp <span class="kw">VALUES</span>(<span class="dv">7566</span>,<span class="st">'JONES'</span>,<span class="st">'MANAGER'</span>,<span class="dv">7839</span>,<span class="st">'1981-04-02'</span>,<span class="fl">2975.0</span>,<span class="kw">NULL</span>,<span class="dv">20</span>);
2734<span class="kw">INSERT</span> <span class="kw">INTO</span> emp <span class="kw">VALUES</span>(<span class="dv">7654</span>,<span class="st">'MARTIN'</span>,<span class="st">'SALESMAN'</span>,<span class="dv">7698</span>,<span class="st">'1981-09-28'</span>,<span class="fl">1250.0</span>,<span class="fl">1400.0</span>,<span class="dv">30</span>);
2735<span class="kw">INSERT</span> <span class="kw">INTO</span> emp <span class="kw">VALUES</span>(<span class="dv">7698</span>,<span class="st">'BLAKE'</span>,<span class="st">'MANAGER'</span>,<span class="dv">7839</span>,<span class="st">'1981-05-01'</span>,<span class="fl">2850.0</span>,<span class="kw">NULL</span>,<span class="dv">30</span>);
2736<span class="kw">INSERT</span> <span class="kw">INTO</span> emp <span class="kw">VALUES</span>(<span class="dv">7782</span>,<span class="st">'CLARK'</span>,<span class="st">'MANAGER'</span>,<span class="dv">7839</span>,<span class="st">'1981-06-09'</span>,<span class="fl">2450.0</span>,<span class="kw">NULL</span>,<span class="dv">10</span>);
2737<span class="kw">INSERT</span> <span class="kw">INTO</span> emp <span class="kw">VALUES</span>(<span class="dv">7788</span>,<span class="st">'SCOTT'</span>,<span class="st">'ANALYST'</span>,<span class="dv">7566</span>,<span class="st">'1982-12-09'</span>,<span class="fl">3000.0</span>,<span class="kw">NULL</span>,<span class="dv">20</span>);
2738<span class="kw">INSERT</span> <span class="kw">INTO</span> emp <span class="kw">VALUES</span>(<span class="dv">7839</span>,<span class="st">'KING'</span>,<span class="st">'PRESIDENT'</span>,<span class="kw">NULL</span>,<span class="st">'1981-11-17'</span>,<span class="fl">5000.0</span>,<span class="kw">NULL</span>,<span class="dv">10</span>);
2739<span class="kw">INSERT</span> <span class="kw">INTO</span> emp <span class="kw">VALUES</span>(<span class="dv">7844</span>,<span class="st">'TURNER'</span>,<span class="st">'SALESMAN'</span>,<span class="dv">7698</span>,<span class="st">'1981-09-08'</span>,<span class="fl">1500.0</span>,<span class="fl">0.0</span>,<span class="dv">30</span>);
2740<span class="kw">INSERT</span> <span class="kw">INTO</span> emp <span class="kw">VALUES</span>(<span class="dv">7876</span>,<span class="st">'ADAMS'</span>,<span class="st">'CLERK'</span>,<span class="dv">7788</span>,<span class="st">'1983-01-12'</span>,<span class="fl">1100.0</span>,<span class="kw">NULL</span>,<span class="dv">20</span>);
2741<span class="kw">INSERT</span> <span class="kw">INTO</span> emp <span class="kw">VALUES</span>(<span class="dv">7900</span>,<span class="st">'JAMES'</span>,<span class="st">'CLERK'</span>,<span class="dv">7698</span>,<span class="st">'1981-12-03'</span>,<span class="fl">950.0</span>,<span class="kw">NULL</span>,<span class="dv">30</span>);
2742<span class="kw">INSERT</span> <span class="kw">INTO</span> emp <span class="kw">VALUES</span>(<span class="dv">7902</span>,<span class="st">'FORD'</span>,<span class="st">'ANALYST'</span>,<span class="dv">7566</span>,<span class="st">'1981-12-03'</span>,<span class="fl">3000.0</span>,<span class="kw">NULL</span>,<span class="dv">20</span>);
2743<span class="kw">INSERT</span> <span class="kw">INTO</span> emp <span class="kw">VALUES</span>(<span class="dv">7934</span>,<span class="st">'MILLER'</span>,<span class="st">'CLERK'</span>,<span class="dv">7782</span>,<span class="st">'1982-01-23'</span>,<span class="fl">1300.0</span>,<span class="kw">NULL</span>,<span class="dv">10</span>);</code></pre></div>
2744<hr />
2745<hr />
2746<ol start="81" class="example" style="list-style-type: decimal">
2747<li>Erhöhen Sie das Gehalt des dienstältesten Mitarbeiters um 10%.</li>
2748</ol>
2749<hr />
2750<div class="sourceCode"><pre class="sourceCode sql"><code class="sourceCode sql"><span class="kw">UPDATE</span> emp <span class="kw">SET</span> sal = sal*<span class="fl">1.1</span> <span class="kw">WHERE</span> hiredate = (<span class="kw">SELECT</span> <span class="fu">MIN</span>(hiredate) <span class="kw">from</span> emp);</code></pre></div>
2751<hr />
2752<hr />
2753<ol start="82" class="example" style="list-style-type: decimal">
2754<li>Erläutern Sie die Befehlsgruppe DML.</li>
2755</ol>
2756<hr />
2757<p>Die Befehlsgruppe <strong>DML (=Data Manipulation Language)</strong></p>
2758<ul>
2759<li>fügt Daten ein (<strong>INSERT</strong>)</li>
2760<li>ändert Daten (<strong>UPDATE</strong>)</li>
2761<li>löscht Daten (<strong>DELETE</strong>)</li>
2762</ul>
2763<p><strong>INSERT</strong></p>
2764<ul>
2765<li>Datensatz einfügen: <code>INSERT INTO tabelle VALUES (wert, ...);</code></li>
2766<li>oder: <code>INSERT INTO tabelle SELECT ...</code></li>
2767<li>Bsp: <code>INSERT INTO dept VALUES(10,'ACCOUNTING','NEW YORK');</code></li>
2768<li>Der Wert NULL bedeutet, dass kein Wert vorhanden ist.</li>
2769</ul>
2770<p><strong>UPDATE</strong></p>
2771<ul>
2772<li>Daten ändern <code>UPDATE tabelle SET spalte = wert, ... WHERE ...;</code></li>
2773<li>Bsp: <code>UPDATE emp SET sal = sal*1.1 WHERE job = 'SALESMAN';</code></li>
2774<li>Fehlt die WHERE-Bedingung, so werden alle Datensätze geändert.</li>
2775</ul>
2776<p><strong>DELETE</strong></p>
2777<ul>
2778<li>Daten löschen: <code>DELETE FROM tabelle WHERE ...</code></li>
2779<li>Bsp: <code>DELETE FROM emp where job = 'SALESMAN';</code></li>
2780<li>Fehlt die WHERE-Bedingung, so werden alle Datensätze gelöscht.</li>
2781</ul>
2782<hr />
2783<hr />
2784<ol start="83" class="example" style="list-style-type: decimal">
2785<li>Erläutern Sie den Begriff "Dokument" in MongoDB.</li>
2786</ol>
2787<hr />
2788<ul>
2789<li>Ein <em>Dokument</em> ist ein einzelner Datensatz, der im Prinzip aus einer geordneten Liste von Key-Value-Paaren besteht und als Werte auch Arrays und eingebettete Dokumente zulässt.</li>
2790<li>Ein Dokument kann man gut im JSON-Format darstellen.</li>
2791<li>Zur Speicherung verwendet MongoDB intern allerdings nicht das JSON-Format, sondern eine Abwandlung davon.</li>
2792<li>Mit diesem Datenformat adressiert MongoDB den Big-Data-Aspekt <em>Variety</em>: Ein Dokument eignet sich hervorragend zum Umgang mit semistrukturierten Daten, z. B. komplexen Vererbungshierarchien in OO-Sprachen.</li>
2793</ul>
2794<p><strong>Bsp</strong></p>
2795<pre class=".javascript"><code>{
2796 "name": "MongoDB",
2797 versionen: [
2798 { "major": 2, "minor": 6 },
2799 { "major": 2, "minor": 4 },
2800 { "major": 2, "minor": 2 }
2801 ]
2802}</code></pre>
2803<hr />
2804<hr />
2805<ol start="84" class="example" style="list-style-type: decimal">
2806<li>Erläutern Sie den Aufbau eines Dokuments in MongoDB!<br> Nennen Sie zulässige Datentypen!</li>
2807</ol>
2808<hr />
2809<p>Als Dokumenten-Datenbank bildet in MongoDB das Dokument einen zentralen Bestandteil des Datenmodells.</p>
2810<p>Ein Dokument ist im wesentlichen eine Sammlung von zusammengehörigen Daten.</p>
2811<p>In MongoDB ist ein <strong>Dokument</strong> einfach eine Menge von Feldern, wobei ein <strong>Feld</strong> ein Schlüssel-Wert-Paar ist.</p>
2812<p>Der Schlüssel ist gleichzeitig der Name des Feldes und wird als String repräsentiert.</p>
2813<p>Der Wert kann ein</p>
2814<ul>
2815<li><strong>primitiver Datentyp</strong> sein,</li>
2816<li>eine <strong>Liste</strong> von Werten oder ein</li>
2817<li><strong>Dokument</strong>.</li>
2818</ul>
2819<p>Das bedeutet insbesondere, dass jedes Dokument Subdokumente enthalten kann.</p>
2820<p>Die primitiven Datentypen sind die üblicherweise verfügbaren</p>
2821<ul>
2822<li>Boolean,</li>
2823<li>Integer,</li>
2824<li>Float</li>
2825<li>String.</li>
2826</ul>
2827<p>Die Schlüssel-Namen unterliegen fast keinen Einschränkungen.</p>
2828<p>MongoDB verbietet allerdings Bezeichner, die mit einem „$“ beginnen oder einen Punkt enthalten, da solche für die MongoDB-eigene Query-Sprache verwendet werden.</p>
2829<div class="sourceCode"><pre class="sourceCode json"><code class="sourceCode json"><span class="fu">{</span>
2830 <span class="er">boolValue</span> <span class="fu">:</span> <span class="kw">true</span><span class="fu">,</span>
2831 <span class="er">_id</span> <span class="fu">:</span> <span class="st">"eindeutige_ID_12351asd"</span><span class="fu">,</span>
2832 <span class="er">array</span> <span class="fu">:</span> <span class="ot">[</span> <span class="kw">true</span><span class="ot">,</span> <span class="st">"value2"</span><span class="ot">,</span> <span class="dv">3</span><span class="ot">,</span> <span class="ot">[</span><span class="dv">1</span><span class="ot">,</span><span class="dv">2</span><span class="ot">,</span><span class="dv">3</span><span class="ot">]</span> <span class="ot">]</span><span class="fu">,</span>
2833 <span class="er">object</span> <span class="fu">:</span> <span class="fu">{</span>
2834 <span class="er">name1</span> <span class="fu">:</span> <span class="st">"value1"</span><span class="fu">,</span>
2835 <span class="er">name2</span> <span class="fu">:</span> <span class="st">"value2"</span>
2836 <span class="fu">}</span>
2837 <span class="er">string</span> <span class="er">:</span> <span class="st">"value"</span>
2838<span class="fu">}</span></code></pre></div>
2839<p><em>Abbildung 2: Beispiel-Dokument</em></p>
2840<p>Des weiteren gibt es eine besonderes Feld, das jedes Dokument aufweist: das <strong>„_id“-Feld</strong> enthält einen innerhalb der Collection (siehe unten) eindeutigen Wert, der als Primärschlüssel verwendet wird.</p>
2841<p>In MongoDB werden Dokumente als BSON-Objekte dargestellt, also mithilfe einer speichereffizienten, binären Variante von JSON.</p>
2842<p>Eine wichtige Einschränkung ist die maximale Dokumentgröße von 16MB. Diese hat keine technischen Gründe, sondern dient mehr als eine Art Konsistenz-Check. Wenn Dokumente diese Datenmenge überschreiten, spricht das für eine schlechte Datenmodellierung.</p>
2843<hr />
2844<hr />
2845<ol start="85" class="example" style="list-style-type: decimal">
2846<li>Erstellen Sie die Collections für die Abteilungen und Angestellten eines Unternehmens.<br> Erstellen Sie ein Dokument für die erste Abteilung und den ersten Angestellten!</li>
2847</ol>
2848<hr />
2849<div class="sourceCode"><pre class="sourceCode js"><code class="sourceCode javascript"><span class="va">db</span>.<span class="va">dept</span>.<span class="at">insert</span>(<span class="op">{</span><span class="dt">_id</span><span class="op">:</span><span class="dv">10</span><span class="op">,</span> <span class="dt">dname</span><span class="op">:</span><span class="st">"ACCOUNTING"</span><span class="op">,</span> <span class="dt">loc</span><span class="op">:</span><span class="st">"NEW YORK"</span><span class="op">}</span>)<span class="op">;</span>
2850<span class="va">db</span>.<span class="va">dept</span>.<span class="at">insert</span>(<span class="op">{</span><span class="dt">_id</span><span class="op">:</span><span class="dv">20</span><span class="op">,</span> <span class="dt">dname</span><span class="op">:</span><span class="st">"RESEARCH"</span><span class="op">,</span> <span class="dt">loc</span><span class="op">:</span><span class="st">"DALLAS"</span><span class="op">}</span>)<span class="op">;</span>
2851<span class="va">db</span>.<span class="va">dept</span>.<span class="at">insert</span>(<span class="op">{</span><span class="dt">_id</span><span class="op">:</span><span class="dv">30</span><span class="op">,</span> <span class="dt">dname</span><span class="op">:</span><span class="st">"SALES"</span><span class="op">,</span> <span class="dt">loc</span><span class="op">:</span><span class="st">"CHICAGO"</span><span class="op">}</span>)<span class="op">;</span>
2852<span class="va">db</span>.<span class="va">dept</span>.<span class="at">insert</span>(<span class="op">{</span><span class="dt">_id</span><span class="op">:</span><span class="dv">40</span><span class="op">,</span> <span class="dt">dname</span><span class="op">:</span><span class="st">"OPERATIONS"</span><span class="op">,</span> <span class="dt">loc</span><span class="op">:</span><span class="st">"BOSTON"</span><span class="op">}</span>)<span class="op">;</span>
2853
2854
2855<span class="va">db</span>.<span class="va">emp</span>.<span class="at">insert</span>(<span class="op">{</span><span class="dt">_id</span><span class="op">:</span><span class="dv">7369</span><span class="op">,</span> <span class="dt">ename</span><span class="op">:</span><span class="st">"SMITH"</span><span class="op">,</span> <span class="dt">job</span><span class="op">:</span><span class="st">"CLERK"</span><span class="op">,</span> <span class="dt">mgr</span><span class="op">:</span><span class="dv">7902</span><span class="op">,</span> <span class="dt">hiredate</span><span class="op">:</span><span class="st">"1980-12-17"</span><span class="op">,</span> <span class="dt">sal</span><span class="op">:</span><span class="dv">800</span> <span class="op">,</span><span class="dt">deptno</span><span class="op">:</span><span class="dv">20</span><span class="op">}</span>)<span class="op">;</span>
2856<span class="va">db</span>.<span class="va">emp</span>.<span class="at">insert</span>(<span class="op">{</span><span class="dt">_id</span><span class="op">:</span><span class="dv">7499</span><span class="op">,</span> <span class="dt">ename</span><span class="op">:</span><span class="st">"ALLEN"</span><span class="op">,</span> <span class="dt">job</span><span class="op">:</span><span class="st">"SALESMAN"</span><span class="op">,</span> <span class="dt">mgr</span><span class="op">:</span><span class="dv">7698</span><span class="op">,</span> <span class="dt">hiredate</span><span class="op">:</span><span class="st">"1981-02-20"</span><span class="op">,</span> <span class="dt">sal</span><span class="op">:</span><span class="dv">1600</span><span class="op">,</span> <span class="dt">comm</span><span class="op">:</span><span class="dv">300</span><span class="op">,</span> <span class="dt">deptno</span><span class="op">:</span><span class="dv">30</span><span class="op">}</span>)<span class="op">;</span>
2857<span class="va">db</span>.<span class="va">emp</span>.<span class="at">insert</span>(<span class="op">{</span><span class="dt">_id</span><span class="op">:</span><span class="dv">7521</span><span class="op">,</span> <span class="dt">ename</span><span class="op">:</span><span class="st">"WARD"</span><span class="op">,</span> <span class="dt">job</span><span class="op">:</span><span class="st">"SALESMAN"</span><span class="op">,</span> <span class="dt">mgr</span><span class="op">:</span><span class="dv">7698</span><span class="op">,</span> <span class="dt">hiredate</span><span class="op">:</span><span class="st">"1981-02-22"</span><span class="op">,</span> <span class="dt">sal</span><span class="op">:</span><span class="dv">1250</span><span class="op">,</span> <span class="dt">comm</span><span class="op">:</span><span class="dv">500</span><span class="op">,</span> <span class="dt">deptno</span><span class="op">:</span><span class="dv">30</span><span class="op">}</span>)<span class="op">;</span>
2858<span class="va">db</span>.<span class="va">emp</span>.<span class="at">insert</span>(<span class="op">{</span><span class="dt">_id</span><span class="op">:</span><span class="dv">7566</span><span class="op">,</span> <span class="dt">ename</span><span class="op">:</span><span class="st">"JONES"</span><span class="op">,</span> <span class="dt">job</span><span class="op">:</span><span class="st">"MANAGER"</span><span class="op">,</span> <span class="dt">mgr</span><span class="op">:</span><span class="dv">7839</span><span class="op">,</span> <span class="dt">hiredate</span><span class="op">:</span><span class="st">"1981-04-02"</span><span class="op">,</span> <span class="dt">sal</span><span class="op">:</span><span class="dv">2975</span><span class="op">,</span> <span class="dt">deptno</span><span class="op">:</span><span class="dv">20</span><span class="op">}</span>)<span class="op">;</span>
2859<span class="va">db</span>.<span class="va">emp</span>.<span class="at">insert</span>(<span class="op">{</span><span class="dt">_id</span><span class="op">:</span><span class="dv">7654</span><span class="op">,</span> <span class="dt">ename</span><span class="op">:</span><span class="st">"MARTIN"</span><span class="op">,</span> <span class="dt">job</span><span class="op">:</span><span class="st">"SALESMAN"</span><span class="op">,</span> <span class="dt">mgr</span><span class="op">:</span><span class="dv">7698</span><span class="op">,</span> <span class="dt">hiredate</span><span class="op">:</span><span class="st">"1981-09-28"</span><span class="op">,</span> <span class="dt">sal</span><span class="op">:</span><span class="dv">1250</span><span class="op">,</span> <span class="dt">comm</span><span class="op">:</span><span class="dv">1400</span><span class="op">,</span> <span class="dt">deptno</span><span class="op">:</span><span class="dv">30</span><span class="op">}</span>)<span class="op">;</span>
2860<span class="va">db</span>.<span class="va">emp</span>.<span class="at">insert</span>(<span class="op">{</span><span class="dt">_id</span><span class="op">:</span><span class="dv">7698</span><span class="op">,</span> <span class="dt">ename</span><span class="op">:</span><span class="st">"BLAKE"</span><span class="op">,</span> <span class="dt">job</span><span class="op">:</span><span class="st">"MANAGER"</span><span class="op">,</span> <span class="dt">mgr</span><span class="op">:</span><span class="dv">7839</span><span class="op">,</span> <span class="dt">hiredate</span><span class="op">:</span><span class="st">"1981-05-01"</span><span class="op">,</span> <span class="dt">sal</span><span class="op">:</span><span class="dv">2850</span><span class="op">,</span> <span class="dt">deptno</span><span class="op">:</span><span class="dv">30</span><span class="op">}</span>)<span class="op">;</span>
2861<span class="va">db</span>.<span class="va">emp</span>.<span class="at">insert</span>(<span class="op">{</span><span class="dt">_id</span><span class="op">:</span><span class="dv">7782</span><span class="op">,</span> <span class="dt">ename</span><span class="op">:</span><span class="st">"CLARK"</span><span class="op">,</span> <span class="dt">job</span><span class="op">:</span><span class="st">"MANAGER"</span><span class="op">,</span> <span class="dt">mgr</span><span class="op">:</span><span class="dv">7839</span><span class="op">,</span> <span class="dt">hiredate</span><span class="op">:</span><span class="st">"1981-06-09"</span><span class="op">,</span> <span class="dt">sal</span><span class="op">:</span><span class="dv">2450</span><span class="op">,</span> <span class="dt">deptno</span><span class="op">:</span><span class="dv">10</span><span class="op">}</span>)<span class="op">;</span>
2862<span class="va">db</span>.<span class="va">emp</span>.<span class="at">insert</span>(<span class="op">{</span><span class="dt">_id</span><span class="op">:</span><span class="dv">7788</span><span class="op">,</span> <span class="dt">ename</span><span class="op">:</span><span class="st">"SCOTT"</span><span class="op">,</span> <span class="dt">job</span><span class="op">:</span><span class="st">"ANALYST"</span><span class="op">,</span> <span class="dt">mgr</span><span class="op">:</span><span class="dv">7566</span><span class="op">,</span> <span class="dt">hiredate</span><span class="op">:</span><span class="st">"1982-12-09"</span><span class="op">,</span> <span class="dt">sal</span><span class="op">:</span><span class="dv">3000</span><span class="op">,</span> <span class="dt">deptno</span><span class="op">:</span><span class="dv">20</span><span class="op">}</span>)<span class="op">;</span>
2863<span class="va">db</span>.<span class="va">emp</span>.<span class="at">insert</span>(<span class="op">{</span><span class="dt">_id</span><span class="op">:</span><span class="dv">7839</span><span class="op">,</span> <span class="dt">ename</span><span class="op">:</span><span class="st">"KING"</span><span class="op">,</span> <span class="dt">job</span><span class="op">:</span><span class="st">"PRESIDENT"</span><span class="op">,</span> <span class="dt">hiredate</span><span class="op">:</span><span class="st">"1981-11-17"</span><span class="op">,</span> <span class="dt">sal</span><span class="op">:</span><span class="dv">5000</span><span class="op">,</span> <span class="dt">deptno</span><span class="op">:</span><span class="dv">10</span><span class="op">}</span>)<span class="op">;</span>
2864<span class="va">db</span>.<span class="va">emp</span>.<span class="at">insert</span>(<span class="op">{</span><span class="dt">_id</span><span class="op">:</span><span class="dv">7844</span><span class="op">,</span> <span class="dt">ename</span><span class="op">:</span><span class="st">"TURNER"</span><span class="op">,</span> <span class="dt">job</span><span class="op">:</span><span class="st">"SALESMAN"</span><span class="op">,</span> <span class="dt">mgr</span><span class="op">:</span><span class="dv">7698</span><span class="op">,</span> <span class="dt">hiredate</span><span class="op">:</span><span class="st">"1981-09-08"</span><span class="op">,</span> <span class="dt">sal</span><span class="op">:</span><span class="dv">1500</span><span class="op">,</span> <span class="dt">comm</span><span class="op">:</span><span class="dv">0</span><span class="op">,</span> <span class="dt">deptno</span><span class="op">:</span><span class="dv">30</span><span class="op">}</span>)<span class="op">;</span>
2865<span class="va">db</span>.<span class="va">emp</span>.<span class="at">insert</span>(<span class="op">{</span><span class="dt">_id</span><span class="op">:</span><span class="dv">7876</span><span class="op">,</span> <span class="dt">ename</span><span class="op">:</span><span class="st">"ADAMS"</span><span class="op">,</span> <span class="dt">job</span><span class="op">:</span><span class="st">"CLERK"</span><span class="op">,</span> <span class="dt">mgr</span><span class="op">:</span><span class="dv">7788</span><span class="op">,</span> <span class="dt">hiredate</span><span class="op">:</span><span class="st">"1983-01-12"</span><span class="op">,</span> <span class="dt">sal</span><span class="op">:</span><span class="dv">1100</span><span class="op">,</span> <span class="dt">deptno</span><span class="op">:</span><span class="dv">20</span><span class="op">}</span>)<span class="op">;</span>
2866<span class="va">db</span>.<span class="va">emp</span>.<span class="at">insert</span>(<span class="op">{</span><span class="dt">_id</span><span class="op">:</span><span class="dv">7900</span><span class="op">,</span> <span class="dt">ename</span><span class="op">:</span><span class="st">"JAMES"</span><span class="op">,</span> <span class="dt">job</span><span class="op">:</span><span class="st">"CLERK"</span><span class="op">,</span> <span class="dt">mgr</span><span class="op">:</span><span class="dv">7698</span><span class="op">,</span> <span class="dt">hiredate</span><span class="op">:</span><span class="st">"1981-12-03"</span><span class="op">,</span> <span class="dt">sal</span><span class="op">:</span><span class="dv">950</span><span class="op">,</span> <span class="dt">deptno</span><span class="op">:</span><span class="dv">30</span><span class="op">}</span>)<span class="op">;</span>
2867<span class="va">db</span>.<span class="va">emp</span>.<span class="at">insert</span>(<span class="op">{</span><span class="dt">_id</span><span class="op">:</span><span class="dv">7902</span><span class="op">,</span> <span class="dt">ename</span><span class="op">:</span><span class="st">"FORD"</span><span class="op">,</span> <span class="dt">job</span><span class="op">:</span><span class="st">"ANALYST"</span><span class="op">,</span> <span class="dt">mgr</span><span class="op">:</span><span class="dv">7566</span><span class="op">,</span> <span class="dt">hiredate</span><span class="op">:</span><span class="st">"1981-12-03"</span><span class="op">,</span> <span class="dt">sal</span><span class="op">:</span><span class="dv">3000</span><span class="op">,</span> <span class="dt">deptno</span><span class="op">:</span><span class="dv">20</span><span class="op">}</span>)<span class="op">;</span>
2868<span class="va">db</span>.<span class="va">emp</span>.<span class="at">insert</span>(<span class="op">{</span><span class="dt">_id</span><span class="op">:</span><span class="dv">7934</span><span class="op">,</span> <span class="dt">ename</span><span class="op">:</span><span class="st">"MILLER"</span><span class="op">,</span> <span class="dt">job</span><span class="op">:</span><span class="st">"CLERK"</span><span class="op">,</span> <span class="dt">mgr</span><span class="op">:</span><span class="dv">7782</span><span class="op">,</span> <span class="dt">hiredate</span><span class="op">:</span><span class="st">"1982-01-23"</span><span class="op">,</span> <span class="dt">sal</span><span class="op">:</span><span class="dv">1300</span><span class="op">,</span> <span class="dt">deptno</span><span class="op">:</span><span class="dv">10</span><span class="op">}</span>)<span class="op">;</span></code></pre></div>
2869<h2 id="dml-mongodb-..."><span class="header-section-number">6.2</span> DML MongoDB <a href="#TOC">...</a></h2>
2870<ol start="86" class="example" style="list-style-type: decimal">
2871<li><p>Der Datenbankadministrator möchte mehrere Angestellte in die Datenbank einfügen. Er möchte dabei gewährleisten, dass die referentielle Integrität auch bei Netzwerk- oder Serverfehlern nicht verletzt wird.</p>
2872<pre><code>{_id:7839, ename:"KING", job:"PRESIDENT", hiredate:"1981-11-17", sal:5000, deptno:10}
2873{_id:7566, ename:"JONES", job:"MANAGER", mgr:7839, hiredate:"1981-04-02", sal:2975, deptno:20}
2874{_id:7698, ename:"BLAKE", job:"MANAGER", mgr:7839, hiredate:"1981-05-01", sal:2850, deptno:30}</code></pre></li>
2875</ol>
2876<hr />
2877<pre><code> db.emp.insert( [ {_id:7839, ename:"KING", ...}, {_id:7566, ename:"JONES", ...}, ... ] )</code></pre>
2878<ol style="list-style-type: decimal">
2879<li>Wenn Sie mehrere Dokumente in einem Rutsch einfügen wollen, bietet es sich an, einen sogenannten <strong>Bulk-Insert</strong> zu verwenden, da dieser das Netzwerk deutlich weniger belastet.</li>
2880<li>In der Mongo Shell kann man mehrere Dokumente einfügen, indem man beim Aufruf von insert() ein Array von Dokumenten übergibt.</li>
2881<li>Falls beim Einfügen mehrerer Dokumente ein Fehler auftritt, findet ein <strong>Abbruch</strong> statt und die nachfolgenden Dokumente werden nicht mehr eingefügt.</li>
2882<li>Allerdings ist es möglich, über den Treiber eine Option continueOnError anzugeben, die bei Fehlern nicht abbricht, sondern mit dem Einfügen weiterer Dokumente fortfährt.</li>
2883</ol>
2884<hr />
2885<hr />
2886<ol start="87" class="example" style="list-style-type: decimal">
2887<li>Erläutern Sie die Besonderheiten des INSERT-Kommandos!</li>
2888</ol>
2889<hr />
2890<p><strong>Bsp</strong></p>
2891<pre><code> > db.dokumente.insert({hallo: "MongoDB"})
2892 WriteResult({ "nInserted" : 1 })</code></pre>
2893<hr />
2894<ol style="list-style-type: decimal">
2895<li>Die Operation zum Einfügen neuer Dokumente heißt in MongoDB <strong>insert</strong>.</li>
2896<li>Wenn die verwendete Collection (in unserem Beispiel dokumente) noch nicht existiert, wird sie automatisch vor dem ersten Zugriff angelegt.</li>
2897<li>Grundsätzlich arbeitet MongoDB bei schreibenden Operationen nach dem Fire-and- Forget-Prinzip.</li>
2898<li>Schreibende Operationen auf einem einzelnen Dokument sind gemäß des ACID4-Prinzips atomar.</li>
2899<li>Transaktionen, bei denen die Manipulation mehrerer Datensätze zu einer atomaren Operation zusammengefasst wird, kennt MongoDB hingegen nicht.</li>
2900</ol>
2901<hr />
2902<hr />
2903<ol start="88" class="example" style="list-style-type: decimal">
2904<li>Erklären Sie das Fire-and-Forget-Prinzip!</li>
2905</ol>
2906<hr />
2907<ol style="list-style-type: decimal">
2908<li>Anwendungen müssen den Fehlerstatus der letzten Schreiboperation aktiv erfragen; der Status wird nicht automatisch vom Server zurückgeliefert.</li>
2909<li>So wird im Erfolgsfall eine bessere Performance erreicht.</li>
2910<li>Die Mongo Shell führt diese Abfrage bei Verwendung von <code>insert(...)</code> auf einer Collection automatisch aus, sodass Fehlermeldungen direkt angezeigt werden.</li>
2911</ol>
2912<hr />
2913<hr />
2914<ol start="89" class="example" style="list-style-type: decimal">
2915<li>Beschreiben Sie die Parameter des UPDATE-Kommandos!</li>
2916</ol>
2917<hr />
2918<pre><code> db.<collection>.update(query,update,upsert,multi)</code></pre>
2919<ul>
2920<li>query: Diese Abfrage legt fest, welches bzw. welche Dokument(e) geändert werden sollen.</li>
2921<li>update: Neues Dokument bei vollständiger Ersetzung bzw. Änderungsdaten bei partieller Änderung.</li>
2922<li>upsert: Falls true, wird ein Dokument erzeugt, falls die Abfrage query nichts findet. Der Default ist false. (true) oder nicht. Der Default ist false.</li>
2923<li>multi: Boolesches Flag, das steuert, ob ein oder mehrere (true) Dokumente geändert werden sollen. Der Default ist false.</li>
2924</ul>
2925<hr />
2926<hr />
2927<ol start="90" class="example" style="list-style-type: decimal">
2928<li>Erläutern Sie die Besonderheiten des UPDATE-Kommandos!</li>
2929</ol>
2930<hr />
2931<ol style="list-style-type: decimal">
2932<li>Änderungen an Dokumenten werden mit dem Kommando update() vorgenommen.</li>
2933<li>In der Mongo Shell erwartet dieses Kommando bis zu vier Parameter, die sich auch in den Treibern in der einen oder anderen Form wiederfinden.</li>
2934<li>Das Feld _id ist unveränderlich und darf daher nicht geändert werden.</li>
2935</ol>
2936<hr />
2937<hr />
2938<ol start="91" class="example" style="list-style-type: decimal">
2939<li>Vergleichen Sie die vollständige Ersetzung von JSON-Dokumenten mit partiellen Änderungen.</li>
2940</ol>
2941<hr />
2942<ol style="list-style-type: decimal">
2943<li><p><strong>Vollständige Ersetzung</strong></p>
2944<p>Legen wir zunächst ein Dokument an</p>
2945<pre><code> > db.vollständig.drop()
2946 true
2947 > db.vollständig.insert( {_id:1, a:1, b: "zwei"} )
2948 > db.vollständig.find()
2949 { "_id" : 1, "a" : 1, "b" : "zwei" }</code></pre>
2950<p>um anschließend eine Änderung vorzunehmen:</p>
2951<pre><code> > db.vollständig.update( {_id:1}, {a:2} )
2952 > db.vollständig.find()
2953 { "_id" : 1, "a" : 2 }</code></pre>
2954<p>Intuitiv hätte man vielleicht erwartet, dass das Dokument nach der Änderung</p>
2955<p>{ "_id" : 1, "a" : 2, "b" : "zwei" }</p>
2956<p>gewesen wäre. Dies ist allerdings nicht der Fall, da hier eine vollständige Ersetzung des Dokuments stattfindet (bisheriges Primärschlüsselfeld _id und alle Felder aus dem Dokument des zweiten Parameters der update-Methode).</p></li>
2957<li><p><strong>Partielle Änderungen</strong></p>
2958<pre><code>> db.partiell.drop()
2959true
2960> db.partiell.insert( {_id:1, a:2, b: "drei"} )
2961> db.partiell.update( {_id:1}, {$set: {a:2} } )
2962> db.partiell.find()
2963{ "_id" : 1, "a" : 2, "b" : "drei" }</code></pre>
2964<p>Mithilfe des Operators <code>$set</code> haben wir ein Dokument <code>{a: 2}</code> angegeben, dessen Felder die des bestehenden Dokuments überschreiben bzw. ergänzen. Alle anderen Felder des Zieldokuments bleiben unverändert.</p></li>
2965</ol>
2966<hr />
2967<hr />
2968<ol start="92" class="example" style="list-style-type: decimal">
2969<li>Nennen und beschreiben Sie die skalare Operatoren des UPDATE-Statements.</li>
2970</ol>
2971<hr />
2972<p>Diese Gruppe von Operatoren bezieht sich auf skalare Felder. Im Einzelnen sind dies die nun folgenden.</p>
2973<p><strong>$set</strong></p>
2974<p>Mit $set werden ein oder mehrere Felder auf einen konstanten, neuen Wert gesetzt. Felder, die noch nicht existieren, werden angelegt.</p>
2975<pre><code>> db.set.drop()
2976> db.set.insert( {_id:1, a:1, b: "drei"} )
2977> db.set.update( {_id:1}, {$set: {a:2, c: [4,5]} } )
2978> db.set.find()
2979{ "_id" : 1, "a" : 2, "b" : "drei", "c" : [ 4, 5 ] }</code></pre>
2980<p>$set setzt die Felder unabhängig davon, ob das Dokument geändert oder im Rahmen eines upserts (s. weiter unten) erst neu angelegt wird.</p>
2981<p><strong>$unset</strong></p>
2982<p>Zum Löschen von Feldern können Sie $unset verwenden. Die Namen der zu löschenden Felder werden als Schlüssel mit Wert 1 angegeben, analog zu einer Projektion bei einer Query:</p>
2983<pre><code>> db.unset.drop()
2984> db.unset.insert( {_id:1, a:1, b: "drei"} )
2985> db.unset.update( {_id:1}, {$unset: {b:1, c:1}})
2986> db.unset.find()
2987{ "_id" : 1, "a" : 1 }</code></pre>
2988<p>Felder, die es nicht gibt, werden beim Entfernen ohne Fehlermeldung ignoriert.</p>
2989<p><strong>$rename</strong></p>
2990<p>Eine Umbenennung eines oder mehrerer Felder wird mit $rename durchgeführt. Der Schlüssel des jeweiligen Feldes im Änderungsdokument ist der Name des umzubenennenden Feldes, der Wert der neue Name.</p>
2991<pre><code>> db.rename.drop()
2992> db.rename.insert( {_id:1, a:1, b: "drei"} )
2993> db.rename.update( {_id:1}, {$rename: {b: "c", d: "e"}})
2994> db.rename.find()
2995{ "_id" : 1, "a" : 1, "c" : "drei" }</code></pre>
2996<p>Analog zu $unset werden Felder, die es nicht gibt, auch nicht umbenannt.</p>
2997<p><strong>$inc</strong></p>
2998<p>Mithilfe des $inc-Operators lassen sich numerische Felder um einen bestimmten, festen Betrag erhöhen bzw. erniedrigen (bei negativen Werten). Werden Felder angegeben, die es zuvor nicht gab, werden diese auf den entsprechenden Wert gesetzt.</p>
2999<pre><code>> db.inc.drop()
3000> db.inc.insert( {_id:1, a:1, b: "drei"} )
3001> db.inc.update( {_id:1}, {$inc: {a:0.5, d:-5}} )
3002> db.inc.find()
3003{ "_id" : 1, "a" : 1.5, "b" : "drei", "d" : -5 }</code></pre>
3004<p>Wird $inc auf nichtnumerische Felder angewendet, führt dies zu einem Fehler:</p>
3005<pre><code>> db.inc.update({_id:1}, {$inc: {b:1}})
3006Cannot apply $inc modifier to non-number</code></pre>
3007<p><strong>$mul</strong></p>
3008<p>Dieser Operator multipliziert ein numerisches Feld mit dem angegebenen Faktor, z. B.:</p>
3009<pre><code>> db.mult.drop()
3010> db.mult.insert({_id:1, a: NumberInt(2)})
3011> db.mult.update({_id:1}, {$mul: {a: NumberLong(3) }})
3012> db.mult.find()
3013{ "_id" : 1, "a" : NumberLong(6) }</code></pre>
3014<p>Wenn das zu multiplizierende Feld nicht existiert, erhält es den Wert 0.</p>
3015<p><strong>$bit</strong></p>
3016<p>Auf ganzzahligen Feldern können mit $bit Operationen auf Bit-Ebene durchgeführt werden. Da die Mongo Shell standardmäßig nur Fließkommazahlen verwendet, müssen wir zur Erzeugen der Testdaten die Wrapper-Klasse NumberInt (für 32-Bit- Ganzzahlen) bzw. NumberLong (für 64-Bit-Ganzzahlen) verwenden.</p>
3017<pre><code>> db.bit.insert({_id:1, a: new NumberInt("4"), b: Math.PI})
3018> db.bit.update({_id:1}, {$bit: {a: {or: 2}}} )
3019> db.bit.find()
3020{ "_id": 1, "a": NumberInt(6), "b": 3.141592653589793}</code></pre>
3021<p>Bei nicht ganzzahligen Typen führt der $bit-Operator zu einem Fehler:</p>
3022<pre><code>> db.bit.update({_id:1}, {$bit: {b: {and: 1 }}})
3023$bit cannot update a value of type double</code></pre>
3024<p>Felder, die nicht existieren, werden ignoriert:</p>
3025<pre><code>> db.bit.update({_id:1}, {$bit: {c: {and: 1 }}})
3026> db.bit.find()
3027{ "_id": 1, "a": NumberLong(6), "b": 3.141592653589793}</code></pre>
3028<p>Bei der bitweisen Manipulation stehen an booleschen Operationen zurzeit nur and und or zur Verfügung.</p>
3029<p><strong>$currentDate</strong></p>
3030<p>Auf Datumsfeldern können Sie mithilfe des Operators $currentDate wie folgt das aktuelle Datum setzen:</p>
3031<pre><code>> db.log.drop()
3032> db.log.insert({
3033 _id:1,
3034 status: "aktiv",
3035 ts: ISODate("2014-03-19T12:00:00")})
3036> db.log.update({_id:1}, {$currentDate: {ts: true}})
3037> db.log.find()
3038{ "_id" : 1, "status" : "aktiv", "ts" : ISODate("2014-03-20T08:27:06.892Z") }</code></pre>
3039<p>Wenn Sie das Buch in Ihren Händen halten, dürfte das aktuelle Datum bereits deutlich weiter in der Zukunft liegen ;-) Felder, die nicht existieren, werden ggf. angelegt. Sie können mehrere Felder aktualisieren und auch noch genauer angeben, ob das aktuelle Datum in Form eines Timestamps oder eines Dates (Default) abgelegt wird:</p>
3040<pre><code>> db.log.update({_id:1},
3041 { $currentDate: {
3042 ts: {$type: "timestamp"},
3043 ts_2: {$type:"date"}
3044} })
3045> db.log.find().pretty()
3046{
3047 "_id" : 1,
3048 "status" : "aktiv",
3049 "ts" : Timestamp(1395304942, 1),
3050 "ts_2" : ISODate("2014-03-20T08:42:22.467Z")
3051}</code></pre>
3052<h2 id="dml-mongodb2-..."><span class="header-section-number">6.3</span> DML MongoDB2 <a href="#TOC">...</a></h2>
3053<hr />
3054<hr />
3055<ol start="93" class="example" style="list-style-type: decimal">
3056<li>Nennen und beschreiben Sie die Array-Operatoren des UPDATE-Statements.</li>
3057</ol>
3058<hr />
3059<p>Diese Gruppe von Operatoren dient zur Manipulation von Arrays.</p>
3060<p><strong>$push, $pushAll</strong></p>
3061<p>Der $push-Operator hängt an ein Array ein weiteres Element an. Falls das Feld noch nicht existiert, wird es angelegt.</p>
3062<pre><code>> db.array.drop()
3063> db.array.insert({_id:1, a: [1,2], b:3})
3064> db.array.update({_id:1}, {$push: {a:3}})
3065> db.array.find()
3066{ "_id" : 1, "a" : [ 1, 2, 3 ], "b" : 3 }</code></pre>
3067<p>Auf skalaren Feldern führt $push zu einem Fehler:</p>
3068<pre><code>> db.array.update({_id:1}, {$push: {b:3}})
3069Cannot apply $push/$pushAll modifier to non-array</code></pre>
3070<p>Wenn Sie mehrere Elemente anhängen wollen, können Sie den Operator $pushAll in Verbindung mit einem weiteren Array verwenden. Das Ziel-Array wird dann um alle Einträge aus dem Quell-Array ergänzt:</p>
3071<pre><code>> db.array.update({_id:1},{$pushAll: {a: [5,8]}})
3072> db.array.find()
3073{ "_id" : 1, "a" : [ 1, 2, 3, 5, 8 ], "b" : 3 }</code></pre>
3074<p>Alternativ zu $pushAll kann hier auch der Operator $each verwendet werden:</p>
3075<pre><code>> db.array.update({_id:1}, {$push: {a: {$each: [5,8]}}} )</code></pre>
3076<p>In Verbindung mit $push und $each können noch zwei weitere Operatoren zum Einsatz kommen, um beim Ändern eines Arrays für eine bestimmte Länge bzw. eine Sortierung zu sorgen:</p>
3077<p><strong>$slice</strong></p>
3078<p>Mit dem Operator $slice wird die Größe des Arrays nach dem Insert festgelegt. Dem Operator kann der Wert 0 oder eine negative –n Ganzzahl übergeben werden, deren Betrag n dann die Länge des Arrays bestimmt:</p>
3079<pre><code>> db.array.drop()
3080> db.array.insert({_id:1, a:[1,2]})
3081> db.array.insert({_id:2, a:[1,2]})
3082> db.array.update({_id:1}, {$push: {a: {$each: [3,4], $slice:-3}}})
3083> db.array.update({_id:2}, {$push: {a: {$each: [3,4], $slice:0}}})
3084> db.array.find()
3085{ "_id" : 2, "a" : [ ] }
3086{ "_id" : 1, "a" : [ 2, 3, 4 ] }</code></pre>
3087<p><strong>$sort</strong></p>
3088<p>Wenn es sich bei den Array-Einträgen um Dokumente handelt, kann in Verbindung mit $each und $slice mithilfe des $sort-Operators zusätzlich noch eine Sortierung dieser Dokumente durchgeführt werden.</p>
3089<pre><code>> db.array.drop()
3090> db.array.insert({_id:1, a:[{b:2, c:2}, {b:4,c:1}]})
3091> db.array.update({_id:1}, {$push: {a:
3092 {$each: [{b:3,c:0}], $slice:-3, $sort: {b:1}}}})
3093> db.array.find().pretty()
3094{
3095 "_id" : 1,
3096 "a" : [
3097 {
3098 "b" : 2,
3099 "c" : 2
3100 },
3101 {
3102 "b" : 3,
3103 "c" : 0
3104 },
3105 {
3106 "b" : 4,
3107 "c" : 1
3108 }
3109 ]</code></pre>
3110<p>}</p>
3111<p>Nach dem Einfügen des dritten Array-Eintrags findet noch eine aufsteigende Sortierung bzgl. des Feldes b statt, sodass das neue Dokument nun an zweiter Stelle im Array liegt.</p>
3112<p><strong>$addToSet</strong></p>
3113<p>Analog zu $push fügt $addToSet einem Array einen oder mehrere Werte hinzu, allerdings nur dann, wenn der jeweilige Wert noch nicht in dem Array enthalten ist. Das Array wird in diesem Kontext im Prinzip als Menge interpretiert, in der jeder Wert nur einmal vorkommt.</p>
3114<pre><code>> db.array.find()
3115{ "_id" : 1, "a" : [ 1, 2, 3, 5, 8 ], "b" : 3 }
3116> db.array.update({_id:1}, {$addToSet: {a: 5}})
3117> db.array.find()
3118{ "_id" : 1, "a" : [ 1, 2, 3, 5, 8 ], "b" : 3 }</code></pre>
3119<p>Zum Hinzufügen mehrerer Werte kann wie zuvor der Operator $each verwendet werden:</p>
3120<pre><code>> db.array.update({_id:1},{$addToSet:{a:{$each:[8,13]}}})
3121> db.array.find()
3122{ "_id" : 1, "a" : [ 1, 2, 3, 5, 8, 13 ], "b" : 3 }</code></pre>
3123<p><strong>$pop</strong></p>
3124<p>Der $pop-Operator ist das Gegenstück zum $push- bzw. $addToSet-Operator. Mit ihm kann das letzte bzw. erste Element eines Arrays gelöscht werden. Zum Löschen des letzten Elements ist eine 1 zu übergeben, -1 löscht hingegen das erste Element:</p>
3125<pre><code>> db.array.find()
3126{ "_id" : 1, "a" : [ 1, 2, 3, 5, 8, 13 ], "b" : 3 }
3127> db.array.update({_id:1},{$pop: {a:1}})
3128> db.array.find()
3129{ "_id" : 1, "a" : [ 1, 2, 3, 5, 8 ], "b" : 3 }
3130> db.array.update({_id:1},{$pop: {a:-1}})
3131> db.array.find()
3132{ "_id" : 1, "a" : [ 2, 3, 5, 8 ], "b" : 3 }</code></pre>
3133<p>Nach dem Entfernen des einzigen Elements eines Arrays bleibt ein leeres Array zurück. Wie alle Array-Operatoren führt auch $pop auf skalaren Feldern zu einem Fehler.</p>
3134<p><strong>$pull, $pullAll</strong></p>
3135<p>Mit $pull bzw. $pullAll lassen sich gezielt bestimmte Werte aus einem Array entfernen. $pull löscht dabei alle Vorkommen eines einzelnen Wertes, $pullAll löscht alle Vorkommen mehrerer Werte.</p>
3136<pre><code>> db.array.drop()
3137> db.array.insert({_id:1, a: [1,2,2,3,4,4]})
3138> db.array.update({_id:1}, {$pull: {a:2}})
3139> db.array.find()
3140{ "_id" : 1, "a" : [ 1, 3, 4, 4 ] }
3141> db.array.update({_id:1}, {$pullAll: {a:[3,4,5]}})
3142> db.array.find()
3143{ "_id" : 1, "a" : [ 1 ] }</code></pre>
3144<p>Zu löschende Werte, die im Array nicht enthalten sind, werden dabei stillschweigend ignoriert.</p>
3145<hr />
3146<hr />
3147<ol start="94" class="example" style="list-style-type: decimal">
3148<li>Erläutern Sie das positionsbezogenes Ändern von Array-Werten</li>
3149</ol>
3150<hr />
3151<p>Da Arrays intern wie Dokumente mit 0-basiert durchnummerierten Feldnamen behandelt werden, können mit den skalaren Operatoren $set, $unset, $inc und $bit einzelne Array-Elemente auch positionsbezogen manipuliert werden, wie folgende Beispiele demonstrieren:</p>
3152<pre><code>> db.array.drop()
3153> db.array.insert({_id:1, a: [1,2,3]})
3154> db.array.update({_id:1}, {$set: {"a.2": new NumberLong("4")}})
3155> db.array.find()
3156{ "_id" : 1, "a" : [ 1, 2, NumberLong(4) ] }
3157> db.array.update({_id:1}, {$unset: {"a.1": 1}})
3158> db.array.find()
3159{ "_id" : 1, "a" : [ 1, null, NumberLong(4)] }
3160> db.array.update({_id:1}, {$inc: {"a.0": 4}})
3161> db.array.find()
3162{ "_id" : 1, "a" : [ 5, null, NumberLong(4) ] }
3163> db.array.update({_id:1}, {$bit: {"a.2" : {or:2}}})
3164> db.array.find()
3165{ "_id" : 1, "a" : [ 5, null, NumberLong(6) ] }</code></pre>
3166<p>Analog zu den Operatoren auf skalaren Feldern werden nicht existente Felder angelegt und »Lücken« im Array mit null-Werten belegt:</p>
3167<pre><code>> db.array.update({_id:1}, {$inc: {"a.5": 4}})
3168> db.array.find()
3169{ "_id" : 1, "a" : [ 5, null, NumberLong(6), null, null, 4 ] }</code></pre>
3170<p>Die Anwendung des $rename-Operators zur Umordnung zweier Felder ist allerdings nicht möglich:</p>
3171<pre><code>> db.array.update({_id:1}, {$rename: {"a.2" :"a.1"}})</code></pre>
3172<p>$rename source field invalid</p>
3173<hr />
3174<hr />
3175<ol start="95" class="example" style="list-style-type: decimal">
3176<li>Erläutern Sie den $-Operator des UPDATE-Kommandos!</li>
3177</ol>
3178<hr />
3179<p>Wenn ein Update Elemente eines Array-Feldes manipuliert, kann die Änderung nicht an einer zuvor bekannten Position erfolgen. Um dennoch die Position der Änderung referenzieren zu können, kann der $-Operator als Platzhalter verwendet werden. In folgendem Beispiel soll der Wert 1 innerhalb des Arrays a durch 4 ersetzt werden:</p>
3180<pre><code>> db.array.drop()
3181> db.array.insert({_id:1, a: [1,2]})
3182> db.array.insert({_id:2, a: [2,3,3]})</code></pre>
3183<p>Mit dem Ausdruck a.$ kann nun die jeweilige Position im Array a beschrieben werden, auf die die ändernde Operation angewendet werden soll:</p>
3184<pre><code>> db.array.update({a:1}, {$set: {"a.$": 4}})
3185> db.array.find()
3186{ "_id" : 1, "a" : [ 4, 2 ] }
3187{ "_id" : 2, "a" : [ 2, 3, 3 ] }</code></pre>
3188<p>Dabei lässt sich allerdings immer nur die Position des ersten Vorkommens eines Elements innerhalb eines Arrays beschreiben:</p>
3189<pre><code>> db.array.update({a:3}, {$set: {"a.$": 5}})
3190> db.array.find()
3191{ "_id" : 1, "a" : [ 4, 2 ] }
3192{ "_id" : 2, "a" : [ 2, 5, 3 ] }</code></pre>
3193<p>Sinnvoll ist der $-Operator daher nur auf solchen Arrays anzuwenden, die mit $addToSet als Menge mit eindeutigen Werten verwendet werden. Wenn das Array eingebettete Dokumente enthält, kann mittels der Punktnotation über den $-Operator hinaus auf einzelne Felder in diesem Dokument weiternavigiert werden:</p>
3194<pre><code>> db.array.drop()
3195> db.array.insert({_id:1, a: [ {b:1}, {b:2} ] } )
3196> db.array.insert({_id:2, a: [ {b:2}, {b:3} ] } )
3197> db.array.find()
3198{ "_id" : 1, "a" : [ { "b" : 1 }, { "b" : 2 } ] }
3199{ "_id" : 2, "a" : [ { "b" : 2 }, { "b" : 3 } ] }</code></pre>
3200<p>Der Ausdruck a.$.b »trifft« dann das Feld b im jeweils passenden eingebetteten Dokument:</p>
3201<pre><code>> db.array.update({"a.b": 1}, {$inc: {"a.$.b": -2}})
3202> db.array.find()
3203{ "_id" : 1, "a" : [ { "b" : -1 }, { "b" : 2 } ] }
3204{ "_id" : 2, "a" : [ { "b" : 2 }, { "b" : 3 } ] }</code></pre>
3205<hr />
3206<hr />
3207<ol start="96" class="example" style="list-style-type: decimal">
3208<li>Erläutern Sie die Kombination von Operatoren des UPDATE-Kommandos!</li>
3209</ol>
3210<hr />
3211<p>Mehrere Operatoren können miteinander kombiniert werden, sofern sie sich nicht widersprechen (z. B. $set in Verbindung mit $unset). Das folgende Beispiel demonstriert dies:</p>
3212<pre><code>> db.kombi.drop()
3213> db.kombi.insert({_id:1, a:1, b: [1,2], v:0})
3214> db.kombi.update({_id:1}, {$set: {a:2, c:1}, $pushAll: {b: [3,4]}, $inc:
3215{v:1}})
3216> db.kombi.find()
3217{ "_id" : 1, "a" : 2, "b" : [ 1, 2, 3, 4 ], "c" : 1, "v" : 1 }</code></pre>
3218<p>Zwei Operatoren, die das gleiche Feld betreffen, sind hingegen nicht zulässig:</p>
3219<pre><code>> db.kombi.update({_id:1}, {$set: {a:2}, $unset: {a:1}})</code></pre>
3220<p>Field name duplication not allowed with modifiers</p>
3221<hr />
3222<hr />
3223<ol start="97" class="example" style="list-style-type: decimal">
3224<li>Beschreiben Sie das UPSERT-Kommando!</li>
3225</ol>
3226<hr />
3227<p>MongoDB bietet die Möglichkeit, Dokumente, die nicht existieren, vor Durchführung einer Änderung implizit anzulegen. So kann bequem mit einem Befehl das Suchen und (bei Nichtexistenz) das Einfügen eines Dokuments durchgeführt werden. Dies passiert mit dem Kommando upsert(...), was einer Kombination von insert(...) und update(...) entspricht. Dabei spielen die ersten drei Parameter des update- Kommandos eine Rolle:</p>
3228<pre><code>db.<collection>.update(query,update,upsert,multi)</code></pre>
3229<p>Wenn upsert = true ist (Default ist false), wird zunächst die Abfrage query ausgeführt. Liefert diese ein oder mehrere Dokumente, werden die Änderungen wie bislang beschrieben ausgeführt. Falls keine passenden Dokumente gefunden werden, wird ein neues Dokument angelegt, dessen Felder sich aus der Vereinigungsmenge von query und den Änderungen aus update zusammensetzen.</p>
3230<pre><code>> db.upsert.drop()
3231> db.upsert.insert({_id:1,a:1,b:2})
3232> db.upsert.update({_id:2,a:2}, {$inc: {a:1}, $set: {c:3, p:"o"}}, true)
3233> db.upsert.find()
3234{ "_id" : 1, "a" : 1, "b" : 2 }
3235{ "_id" : 2, "a" : 3, "c" : 3, "p" : "o" }</code></pre>
3236<p>Zunächst besteht das neue Dokument aus den Feldern der query = {_id:2, a:2 }. Anschließend wird darauf update angewandt, was zum einen zur Erhöhung des nun bereits bestehenden Feldes a, zum anderen zum Anlegen der Feldes c und p führt. Mit dieser Variante von update() lassen sich mit einem Kommando relativ elegant Dinge wie Zähler o. Ä. implementieren.</p>
3237<hr />
3238<hr />
3239<ol start="98" class="example" style="list-style-type: decimal">
3240<li>Erläutern Sie den $setOnInsert-Operator des UPSERT-Kommandos!</li>
3241</ol>
3242<hr />
3243<p>Wenn Sie bestimmte Felder nur dann setzen wollen, wenn beim Upsert ein neues Dokument eingefügt wird, können Sie den Operator $setOnInsert verwenden. Dieser hat die gleiche Syntax wie $set, wird aber nur dann berücksichtigt, wenn auch ein neues Dokument angelegt wird.</p>
3244<pre><code>> db.upsert.drop()
3245> db.upsert.insert({_id:1, alt:true})</code></pre>
3246<p>Falls nun ein neues Dokument eingefügt wird, werden mit $setOnInsert bestimmte Felder initialisiert:</p>
3247<pre><code>> db.upsert.update({_id:2}, {$setOnInsert: {neu:true}}, true)
3248> db.upsert.find()
3249{ "_id" : 1, "alt" : true }
3250{ "_id" : 2, "neu" : true }</code></pre>
3251<p>Wenn aber eine Änderung eines bestehenden Dokuments ausgeführt wird, bewirkt $setOnInsert nichts:</p>
3252<pre><code>> db.upsert.update({_id:1}, {$setOnInsert: {neu:true}}, true)
3253> db.upsert.find()
3254{ "_id" : 1, "alt" : true }
3255{ "_id" : 2, "neu" : true }</code></pre>
3256<hr />
3257<hr />
3258<ol start="99" class="example" style="list-style-type: decimal">
3259<li>Beschreiben Sie das Kommando "FindAndModify"!</li>
3260</ol>
3261<hr />
3262<p>Mit dem Kommando findAndModify() lassen sich Änderungen in Verbindung mit einer Abfrage auf einem einzelnen Dokument durchführen. Das Kommando hat folgende Syntax:</p>
3263<pre><code>db.<collection>.findAndModify(args)</code></pre>
3264<p>wobei args aus einem Dokument mit folgenden, optionalen Feldern besteht:</p>
3265<ul>
3266<li>query: Definiert die Abfrage. Sollte die Abfrage mehr als ein Dokument liefern, betrachtet findAndModify() immer nur das erste dieser Dokumente.</li>
3267<li>sort</li>
3268<li>fields: Definiert eine Projektion, d. h. eine Einschränkung auf eine Untermenge aller Felder.</li>
3269<li>update:</li>
3270<li>remove: Falls true, wird das gefundene Dokument zurückgegeben und danach gelöscht.</li>
3271<li>new: Falls true, wird das geänderte Dokument zurückgegeben, ansonsten das gefundene.</li>
3272<li>upsert:</li>
3273</ul>
3274<p>Das folgende Beispiel kann Ihnen als Grundlage weiterer, eigener Experimente dienen:</p>
3275<pre><code>> db.fam.drop()
3276> db.fam.findAndModify({
3277 query: {_id:1},
3278 update: {$inc: {a:1}},
3279 new:false,
3280 upsert:true})
3281null
3282> db.fam.find()
3283{ "_id" : 1, "a" : 1 }
3284> db.fam.findAndModify({
3285 query: {_id:1},
3286 update: {$inc: {a:1}},
3287 new:true,
3288 upsert:true})
3289{ "_id" : 1, "a" : 2 }</code></pre>
3290<hr />
3291<hr />
3292<ol start="100" class="example" style="list-style-type: decimal">
3293<li>Beschreiben Sie Änderungen an mehreren Dokumenten.</li>
3294</ol>
3295<hr />
3296<p>Alle bisherigen Änderungen haben sich immer auf ein einzelnes Dokument bezogen. Wenn Änderungen an mehreren Dokumenten durchgeführt werden sollen, kommt der vierte Parameter des insert()-Kommandos multi ins Spiel. Wird dieser auf true gesetzt (Default ist false), wirken sich die Änderungen auf mehrere Dokumente aus, sofern die entsprechende Abfrage diese auch liefert.</p>
3297<pre><code>> db.viele.drop()
3298> db.viele.insert({_id:1,a:1, b:2})
3299> db.viele.insert({_id:2,a:1, b:3})
3300> db.viele.find()
3301{ "_id" : 1, "a" : 1, "b" : 2 }
3302{ "_id" : 2, "a" : 1, "b" : 3 }</code></pre>
3303<p>Eine Änderung mit multi = false ändert nur das erste gefundene Dokument:</p>
3304<pre><code>> db.viele.update({a:1}, {$set: {c:4}})
3305> db.viele.find()
3306{ "_id" : 2, "a" : 1, "b" : 3 }
3307{ "_id" : 1, "a" : 1, "b" : 2, "c" : 4 }</code></pre>
3308<p>Sollen hingegen alle Dokumente geändert werden, die der Abfrage entsprechen, kann dies wie folgt durchgeführt werden:</p>
3309<pre><code>> db.viele.update({a:1}, {$set: {c:5}}, false, true)
3310> db.viele.find()
3311{ "_id" : 1, "a" : 1, "b" : 2, "c" : 5 }
3312{ "_id" : 2, "a" : 1, "b" : 3, "c" : 5 }</code></pre>
3313<p>Änderungen an mehreren Dokumenten werden nicht atomar durchgeführt. Bricht ein Update-Vorgang zwischendurch ab, haben Sie ggf. einen fachlich inkonsistenten Datenbestand. Es ist allerdings möglich, die Änderungen in Isolation von anderen konkurrierenden Schreiboperationen durchzuführen, indem der Operator $isolated innerhalb der Abfrage verwendet wird:</p>
3314<pre><code>> db.viele.update({a:1, $isolated:1}, {$set: {c:6}}, false ,true)</code></pre>
3315<p>Dies bewirkt, dass sich die Treffermenge, die den Suchkriterien entspricht, während der Dauer des Update-Vorgangs auch dann nicht ändert, wenn durch konkurrierende Schreibvorgänge neue Dokumente hinzukommen, die ebenfalls den Suchkriterien entsprechen. In Verbindung mit Sharding kann der Operator $isolated allerdings nicht verwendet werden.</p>
3316<hr />
3317<hr />
3318<ol start="101" class="example" style="list-style-type: decimal">
3319<li>Beschreiben Sie Optimistisches Sperren.</li>
3320</ol>
3321<hr />
3322<p>Um konkurrierende Schreibzugriffe auf dieselben Dokumente zu vermeiden, kann man (unabhängig von der konkreten Datenbank) das sogenannte Optimistische Sperren5, 6 verwenden. In MongoDB lässt sich dies auch vergleichsweise einfach realisieren. Nehmen wir an, Sie haben ein Dokument produkt aus der Collection produkte gelesen und wollen nun eine partielle Änderung auf den Feldern {f1 ... fn} durchführen. Der Einfachhalt halber nehmen wir an, dass Sie die Felder f1 ... fn mittels des Operators $set ersetzen wollen. Wenn Sie nun ein Update der Form</p>
3323<pre><code>> db.produkte.update(
3324 {_id: produkt._id},
3325 {$set: {f1:v1, ..., fn:vn}},
3326 true, false )</code></pre>
3327<p>durchführen, könnte durch die Anwendung mittlerweile bereits eine konkurrierende Änderung an produkt durchgeführt worden sein, die Sie dann überschreiben würden. Dies lässt sich leicht vermeiden, indem Sie die Abfrage um die Feldgruppe f1 ... fn erweitern:</p>
3328<pre><code>> db.produkte.update(
3329 {_id: produkt._id, f1:produkt.v1, ..., fn:produkt.vn },
3330 {$set: {f1:v1, ..., fn:vn}},
3331 true, false )</code></pre>
3332<p>Wenn in der Zwischenzeit eine Änderung an den Feldern f1 ... fn stattgefunden haben sollte, scheitert diese Änderung und Sie können in Ihrer Anwendung entsprechend reagieren, etwa indem Sie eine Rückmeldung geben, das Dokument erneut lesen usw. Alternativ zu einer Feldgruppe kann man ein rein technisches Feld, z. B. ein Integer-Feld version verwenden, in dem dann die Version des Dokuments abgelegt und bei jeder Änderung inkrementiert wird:</p>
3333<pre><code>> produkt = db.produkte.findOne(...)</code></pre>
3334<p>und später:</p>
3335<pre><code>> db.produkte.update(
3336 {_id:produkt._id, version: produkt.version},
3337 {$inc: {version: 1},
3338 {$set: {f1:v1, ..., fn:vn}},
3339 true, false)</code></pre>
3340<p>Dieses Verfahren ist nicht mit einer Historisierung zu verwechseln, es gibt immer nur genau ein Dokument, in dem die Versionsnummer hochgezählt wird. Bei einer Historisierung hingegen gibt es mehrere Dokumente, die (oft an einer zeitlichen Dimension orientiert) verschiedene Stände eines Geschäftsobjekts repräsentieren.</p>
3341<hr />
3342<hr />
3343<ol start="102" class="example" style="list-style-type: decimal">
3344<li>Beschreiben Sie das Kommando "save"!</li>
3345</ol>
3346<hr />
3347<p>Wenn Änderungen an Dokumenten nicht mit den zuvor beschriebenen Operatoren durchgeführt werden können, muss die Anwendung das Dokument laden, verändern und das Dokument wieder speichern. In der Mongo Shell sähe dies in etwa so aus:</p>
3348<pre><code>> db.dokumente.drop()
3349> db.dokumente.insert({_id:1,a:1,b:2})
3350> doc = db.foo.findOne()
3351{ "_id" : 1, "a" : 1, "b" : 2 }
3352> doc.sum = doc.a + doc.b
33533</code></pre>
3354<p>Um dieses veränderte Dokument zu speichern, kann das Kommando save() verwendet werden:</p>
3355<pre><code>> db.dokumente.save(doc)
3356> db.dokumente.find()
3357{ "_id" : 1, "a" : 1, "b" : 2, "sum" : 3 }</code></pre>
3358<p>Die interne Verarbeitung sieht so aus, dass in Abhängigkeit vom Vorhandensein des Feldes _id entweder ein insert() oder ein update() ausgeführt wird. Geben Sie dazu folgenden Befehl ein (ohne die Klammer), um die Implementierung von save() anzusehen:</p>
3359<pre><code>> db.dokumente.save</code></pre>
3360<p>Zwischen dem Suchen und einem späteren Ändern mittels save() vergeht Zeit, in der konkurrierende Schreiboperationen das Dokument ebenfalls verändern oder gar löschen könnten. Daher sollten Sie save() nur dann verwenden, wenn es unbedingt nötig ist. Wenn immer möglich, sollten Sie mit partiellen Änderungen arbeiten oder ein upsert() verwenden.</p>
3361<hr />
3362<hr />
3363<ol start="103" class="example" style="list-style-type: decimal">
3364<li>Beschreiben Sie das Kommando "remove"!</li>
3365</ol>
3366<hr />
3367<p>Zum Löschen von Dokumenten kann das Kommando</p>
3368<pre><code>> db.<collection>.remove( query )</code></pre>
3369<p>verwendet werden, wobei query eine Abfrage wie beim Kommando find() beinhalten kann. Wenn Sie nur bestimmte Dokumente löschen möchten, kann eine Abfrage wie z. B. diese hier übergeben werden:</p>
3370<pre><code>> db.dokumente.remove( {a: {$gt:10}} )</code></pre>
3371<p>Zum Löschen aller Dokumente einer Collection kann die Abfrage einfach leer bleiben:</p>
3372<pre><code>> db.dokumente.remove( {} )</code></pre>
3373<p>Wenn Sie auf diese Weise alle Dokumente löschen, wird intern über die gesamte Collection iteriert und jedes Dokument samt aller Indexeinträge einzeln gelöscht. Daher kann es deutlich schneller sein, die Collection komplett zu löschen:</p>
3374<pre><code>> db.dokumente.drop()
3375true</code></pre>
3376<dl>
3377<dt>.</dt>
3378<dd><img src="/home/user/acha/www-img/db/trigger.jpg" />
3379</dd>
3380</dl>
3381<div class="sourceCode"><pre class="sourceCode sql"><code class="sourceCode sql"><span class="co">-- create trigger, which logs inserts in dept</span>
3382<span class="kw">CREATE</span> <span class="kw">TRIGGER</span> log_insert_dept
3383<span class="kw">BEFORE</span> <span class="kw">INSERT</span> <span class="kw">ON</span> dept
3384<span class="kw">FOR</span> <span class="kw">EACH</span> <span class="kw">ROW</span>
3385<span class="kw">BEGIN</span>
3386 <span class="kw">INSERT</span> <span class="kw">INTO</span> <span class="fu">log</span> <span class="kw">VALUES</span>(NEW.deptno, datetime());
3387<span class="kw">END</span>;
3388
3389<span class="co">-- test log</span>
3390<span class="kw">INSERT</span> <span class="kw">INTO</span> dept <span class="kw">VALUES</span>(<span class="dv">50</span>, <span class="st">'CONTROLLING'</span>, <span class="st">'MIAMI'</span>);</code></pre></div>
3391<p><em>Ergebnis:</em></p>
3392<div class="sourceCode"><pre class="sourceCode sql"><code class="sourceCode sql">sqlite> <span class="kw">SELECT</span> * <span class="kw">FROM</span> <span class="fu">log</span>;
3393
3394deptno <span class="dt">timestamp</span>
3395<span class="co">---------- -------------------</span>
3396<span class="dv">50</span> <span class="dv">2018-02-26</span> <span class="dv">13</span><span class="ch">:46:52</span></code></pre></div>
3397<h1 id="g.-datenbankanwendungen-..."><span class="header-section-number">7</span> G. Datenbankanwendungen <a href="#TOC">...</a></h1>
3398<h2 id="trigger-..."><span class="header-section-number">7.1</span> Trigger <a href="#TOC">...</a></h2>
3399<hr />
3400<hr />
3401<p>Ein Kleinunternehmen hat sich dazu entschieden, ihre Angestellten- und Filialdaten in einer relationalen Datenbank zu verwalten. Dadurch kann das Unternehmen besonders einfach den Datenbestand auswerten.</p>
3402<ol start="104" class="example" style="list-style-type: decimal">
3403<li>Erstellen Sie einen Trigger, der mitprotokolliert, an welchem Datum neue Datensätze in die Tabelle dept eingefügt werden!</li>
3404</ol>
3405<hr />
3406<pre><code>Die Tabellen wurden so erzeugt:
3407
3408 CREATE TABLE log (deptno INT, timestamp TEXT NOT NULL);
3409
3410 CREATE TABLE dept (
3411 deptno INTEGER PRIMARY KEY,
3412 dname TEXT UNIQUE NOT NULL,
3413 loc TEXT NOT NULL
3414 );
3415
3416 CREATE TABLE emp(
3417 empno INTEGER PRIMARY KEY,
3418 ename TEXT NOT NULL,
3419 job TEXT,
3420 mgr INT,
3421 hiredate TEXT,
3422 sal REAL,
3423 comm REAL,
3424 deptno INT,
3425 FOREIGN KEY(mgr) REFERENCES emp (empno),
3426 FOREIGN KEY(deptno) REFERENCES dept (deptno)
3427 );</code></pre>
3428<hr />
3429<hr />
3430<ol start="105" class="example" style="list-style-type: decimal">
3431<li>Erläutern Sie, wie in Triggern auf die Daten zugreifen werden kann.</li>
3432</ol>
3433<hr />
3434<p>Um in den ausgelösten Aktionen auf die Daten zugreifen zu können, werden symbolische Namen für die Werte vor (OLD) bzw. nach (NEW) der auslösenden Anweisung verwendet.</p>
3435<ul>
3436<li>Bei einem UPDATE stehen somit die alten Werte des Datensatzes wie auch die neuen zur Verfügung.</li>
3437<li>Bei einer INSERT Anweisung kann nicht auf die alten Werte zugegriffen werden,</li>
3438<li>ebenso wie bei einem DELETE nicht auf die neuen Werte zugegriffen werden kann.</li>
3439</ul>
3440<hr />
3441<hr />
3442<ol start="106" class="example" style="list-style-type: decimal">
3443<li><p>Erstellen Sie Trigger, die die referentielle Integrität ihrer Datenbank gewährleisten:</p>
3444<ol style="list-style-type: lower-alpha">
3445<li><p>Wenn ein Datensatz gelöscht wird, dann sollen alle davon abhängigen Datensätze automatisch gelöscht werden.</p></li>
3446<li><p>Wenn es abhängige Datensätze gibt, dann soll eine Fehlermeldung ausgegeben werden.</p></li>
3447</ol></li>
3448</ol>
3449<hr />
3450<ol style="list-style-type: lower-alpha">
3451<li><p>abhängige Datensätze löschen</p>
3452<div class="sourceCode"><pre class="sourceCode sql"><code class="sourceCode sql"><span class="kw">CREATE</span> <span class="kw">TRIGGER</span> dept_delete
3453<span class="kw">BEFORE</span> <span class="kw">DELETE</span> <span class="kw">ON</span> dept
3454<span class="kw">FOR</span> <span class="kw">EACH</span> <span class="kw">ROW</span>
3455<span class="kw">BEGIN</span>
3456 <span class="kw">DELETE</span> <span class="kw">FROM</span> emp <span class="kw">WHERE</span> deptno = OLD.deptno;
3457<span class="kw">END</span>;</code></pre></div></li>
3458<li><p>Fehlermeldung ausgeben</p>
3459<div class="sourceCode"><pre class="sourceCode sql"><code class="sourceCode sql"><span class="kw">CREATE</span> <span class="kw">TRIGGER</span> dept_no_delete
3460<span class="kw">BEFORE</span> <span class="kw">DELETE</span> <span class="kw">ON</span> dept
3461<span class="kw">FOR</span> <span class="kw">EACH</span> <span class="kw">ROW</span>
3462<span class="kw">WHEN</span> <span class="kw">EXISTS</span> (<span class="kw">SELECT</span> * <span class="kw">FROM</span> emp <span class="kw">WHERE</span> deptno = OLD.deptno)
3463<span class="kw">BEGIN</span>
3464 <span class="kw">SELECT</span> RAISE(<span class="kw">ROLLBACK</span>, <span class="st">'Delete of dept forbidden'</span>);
3465<span class="kw">END</span>;</code></pre></div></li>
3466</ol>
3467<p>Anmerkung: In der WHEN-Klausel kann ein beliebiger Ausdruck stehen: ZB "NEW.name != OLD.name"</p>
3468<hr />
3469<hr />
3470<ol start="107" class="example" style="list-style-type: decimal">
3471<li>Nennen Sie die Ereignisse, die einen Trigger auslösen können.</li>
3472</ol>
3473<hr />
3474<p>Mögliche Ereignisse sind:</p>
3475<ul>
3476<li>Einfügen neuer Datensätze (INSERT)</li>
3477<li>Löschen von Datensätzen (DELETE)</li>
3478<li>Ändern von Datensätzen (UPDATE)</li>
3479</ul>
3480<hr />
3481<hr />
3482<ol start="108" class="example" style="list-style-type: decimal">
3483<li><p>Nennen Sie die Zeitpunkte, zu denen ein Trigger ausgelöst werden kann.</p></li>
3484<li><p>Erläutern Sie den Unterschied zwischen Row-level und Statement-level Triggern.</p></li>
3485</ol>
3486<hr />
3487<p>Ebenso wie das Ereignis festgelegt wird, das einen Trigger auslöst, muß auch der Zeitpunkt festgelegt werden, zu dem die Aktionen gestartet werden sollen.</p>
3488<p>Dabei gibt es sechs verschiedene Möglichkeiten:</p>
3489<ul>
3490<li><strong>Einmalig</strong> vor Ausführung der auslösenden Anweisung ( BEFORE / FOR EACH STATEMENT)</li>
3491<li><strong>Einmalig</strong> anstatt der auslösenden Anweisung (INSTEAD / FOR EACH STATEMENT)</li>
3492<li><strong>Einmalig</strong> nach Ausführung der auslösenden Anweisung (AFTER / FOR EACH STATEMENT)</li>
3493</ul>
3494<hr />
3495<ul>
3496<li>Vor jeder Manipulation eines Datensatzes der zugrundeliegenden Tabelle (BEFORE / FOR EACH ROW)</li>
3497<li>Anstatt jeder Manipulation eines Datensatzes der zugrundeliegenden Tabelle (INSTEAD / FOR EACH ROW)</li>
3498<li>Nach jeder Manipulation eines Datensatzes der zugrundeliegenden Tabelle (AFTER / FOR EACH ROW)</li>
3499</ul>
3500<h2 id="skriptsprachen-..."><span class="header-section-number">7.2</span> Skriptsprachen <a href="#TOC">...</a></h2>
3501<ol start="110" class="example" style="list-style-type: decimal">
3502<li><p>Das Unternehmen "Best of Portugal" möchte seine Datenbank von SQLite nach MySQL portieren.</p>
3503<ol style="list-style-type: lower-alpha">
3504<li><p>Entwerfen Sie ein Script für diese Aufgabe.</p></li>
3505<li><p>Erörtern Sie mögliche Probleme.</p></li>
3506<li><p>Ermitteln Sie welche Datenbankschemata davon betroffen sind.</p></li>
3507</ol></li>
3508</ol>
3509<hr />
3510<ol style="list-style-type: lower-alpha">
3511<li><p>Das Script <strong>exportiert</strong> das konzeptionelle und externe Datenbankschema und die Datensätze in Form von <strong>"INSERT"-Statements</strong> aus der SQLite-Datenbank.</p>
3512<p>Danach werden diese Statements in MySQL <strong>importiert</strong>.</p></li>
3513<li><p>Die Implementierung des SQL-Standards unterscheidet sich in den DBMS voneinander. Eventuell müssen die Statements vor den Import noch <strong>geringfügig konvertiert</strong> werden.</p></li>
3514<li><p>Das interne Schema.</p></li>
3515</ol>
3516<p><strong>Das vollständige Script</strong></p>
3517<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="bu">:</span> Datenbank anlegen
3518<span class="ex">sqlite3</span> /tmp/emp.db <span class="op"><</span> /home/user/my/acha/etc/create_employee.sql.txt
3519
3520<span class="bu">:</span> Datenbank exportieren
3521<span class="bu">echo</span> .dump <span class="kw">|</span> <span class="ex">sqlite3</span> /tmp/emp.db <span class="op">></span> /tmp/export.sql
3522
3523<span class="bu">:</span> SQL-Script an MySQL anpassen
3524<span class="bu">echo</span> <span class="st">'CREATE DATABASE emp;'</span> <span class="op">></span> /tmp/modified.sql
3525<span class="bu">echo</span> <span class="st">'USE emp;'</span> <span class="op">>></span> /tmp/modified.sql
3526<span class="fu">sed</span> <span class="st">'/^PRAGMA\|^BEGIN/ d; s/"//g'</span> <span class="op"><</span> /tmp/export.sql <span class="op">>></span> /tmp/modified.sql
3527
3528<span class="bu">:</span> Datenbank importieren
3529<span class="fu">sudo</span> mysql <span class="op"><</span> /tmp/modified.sql</code></pre></div>
3530<!--
3531~~~ bash
3532cat > /tmp/port << 'EOF'
3533
3534 #!/bin/bash
3535
3536echo "USE $2;" > /tmp/x.sql
3537sqlite3 $1 <<< .dump | egrep -v '^PRAGMA|^BEGIN' | sed 's/"//g' >> /tmp/x.sql
3538
3539mysql -u root <<< "DROP DATABASE $2;" 2> /dev/null
3540mysql -u root <<< "CREATE DATABASE $2;"
3541mysql -u root < /tmp/x.sql
3542
3543EOF
3544
3545sqlite3 /tmp/x.db < /home/user/_my/my/zzz/zzz/www/etc/create_employee.sql.txt
3546chmod +x /tmp/port
3547/tmp/port /tmp/x.db emp
3548sudo mysqldump emp | grep -c PRESIDENT
3549~~~
3550-->
3551<h1 id="h.-administration-von-datenbanksystemen-..."><span class="header-section-number">8</span> H. Administration von Datenbanksystemen <a href="#TOC">...</a></h1>
3552<h2 id="installation-konfiguration-..."><span class="header-section-number">8.1</span> Installation, Konfiguration <a href="#TOC">...</a></h2>
3553<ol start="111" class="example" style="list-style-type: decimal">
3554<li>Der Systemadministrator eines Kleinunternehmens wurde damit beauftragt MongoDB zu installieren.</li>
3555</ol>
3556<blockquote>
3557<ul>
3558<li>Entwerfen Sie ein Verfahren, das dies ermöglicht.</li>
3559<li>Erläutern Sie die dazu notwendigen Kommandos.</li>
3560</ul>
3561</blockquote>
3562<hr />
3563<ol style="list-style-type: lower-alpha">
3564<li>Das Softwarepaket für den Server suchen: <code>apt-cache search [PAKET]</code></li>
3565<li>Überprüfen, ob das Paket bereits installiert wurde: <code>dpkg -l [PAKET]</code></li>
3566<li>Die Verbreitung des Pakets recherchieren: <a href="https://popcon.debian.org/stable/by_vote" class="uri">https://popcon.debian.org/stable/by_vote</a></li>
3567<li>Die Beschreibung des Pakets anzeigen: <code>apt-cache show [PAKET]</code></li>
3568<li>Das Verzeichnis der Softwarepakete aktualisieren: <code>sudo apt-get update</code></li>
3569<li>Das Paket installieren: <code>sudo apt-get install [PAKET]</code></li>
3570<li>Die installierten Dateien eines Pakets anzeigen: <code>dpkg -L [PAKET]</code></li>
3571</ol>
3572<hr />
3573<hr />
3574<ol start="112" class="example" style="list-style-type: decimal">
3575<li>Erläutern Sie die Installation, Konfiguration und Nutzung von mongodb.</li>
3576</ol>
3577<hr />
3578<p><strong>MongoDB installieren</strong></p>
3579<pre><code>sudo apt-get install -y mongodb-server</code></pre>
3580<p><strong>MongoDB-Shell konfigurieren</strong></p>
3581<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="ex">---</span>~$ grep <span class="st">'^[^#]'</span> /etc/mongodb.conf
3582
3583<span class="va">dbpath=</span>/var/lib/mongodb
3584<span class="va">logpath=</span>/var/log/mongodb/mongodb.log
3585<span class="va">logappend=</span>true
3586<span class="ex">bind_ip</span> = 127.0.0.1
3587<span class="va">journal=</span>true</code></pre></div>
3588<p><strong>MongoDB-Shell starten</strong></p>
3589<pre><code>mongo</code></pre>
3590<p>Damit befinden wir uns in der interaktiven Konsole, ähnlich <code>sqlite3</code>, mit welcher wir zum Server und seinen Datenbanken verbunden sind.</p>
3591<p>Die Abfragesprache bei MongoDB ist dabei <code>JavaScript</code> und die Datensätze werden dementsprechend mit JSON erstellt und abgefragt.</p>
3592<hr />
3593<hr />
3594<ol start="113" class="example" style="list-style-type: decimal">
3595<li><p>Zeigen Sie die Nutzung von mongodb.</p>
3596<ul>
3597<li>Zeigen Sie alle Datenbanken.</li>
3598<li>Legen Sie eine Datenbank an.</li>
3599<li>Zeigen Sie deren Collections.</li>
3600<li>Legen Sie eine Collection an.</li>
3601<li>Fügen Sie zwei Dokumente ein.</li>
3602<li>Suchen Sie nach allen Dokumenten.</li>
3603<li>Suchen Sie ein einzelnes Dokument.</li>
3604<li>Löschen Sie ein Dokument.</li>
3605<li>Verändern Sie ein Dokument.</li>
3606</ul></li>
3607</ol>
3608<hr />
3609<div class="sourceCode"><pre class="sourceCode json"><code class="sourceCode json"><span class="er">show</span> <span class="er">dbs;</span>
3610
3611<span class="er">//</span> <span class="er">Neue</span> <span class="er">DB</span> <span class="er">anlegen</span> <span class="er">(implizit</span> <span class="er">durch</span> <span class="er">benutzen):</span>
3612<span class="er">use</span> <span class="er">test;</span>
3613
3614<span class="er">show</span> <span class="er">collections;</span>
3615<span class="er">//</span> <span class="er">Collections</span> <span class="er">entstehen</span> <span class="er">implizit,</span> <span class="er">indem</span> <span class="er">Dokumente</span> <span class="er">angelegt</span> <span class="er">werden.</span>
3616
3617<span class="er">//</span> <span class="er">Dokumente</span> <span class="er">einfügen:</span>
3618<span class="er">db.col.insert(</span><span class="fu">{</span><span class="er">a</span><span class="fu">:</span><span class="dv">1</span><span class="fu">,</span> <span class="er">b</span><span class="fu">:</span><span class="dv">2</span><span class="fu">,</span> <span class="er">c</span><span class="fu">:</span><span class="ot">[</span><span class="dv">1</span><span class="ot">,</span><span class="dv">2</span><span class="ot">,</span><span class="dv">3</span><span class="ot">]</span><span class="fu">}</span><span class="er">);</span>
3619<span class="er">db.col.insert(</span><span class="fu">{</span><span class="er">a</span><span class="fu">:</span><span class="dv">2</span><span class="fu">,</span> <span class="er">b</span><span class="fu">:</span><span class="dv">2</span><span class="fu">,</span> <span class="er">c</span><span class="fu">:</span><span class="st">"hallo"</span><span class="fu">}</span><span class="er">);</span>
3620
3621<span class="er">//</span> <span class="er">Alle</span> <span class="er">Dokumente</span> <span class="er">auflisten:</span>
3622<span class="er">db.col.find();</span>
3623
3624<span class="er">//</span> <span class="er">Dokumente</span> <span class="er">nach</span> <span class="er">Muster</span> <span class="er">finden:</span>
3625<span class="er">db.col.find(</span><span class="fu">{</span><span class="er">a</span><span class="fu">:</span><span class="dv">1</span><span class="fu">}</span><span class="er">);</span>
3626
3627<span class="er">//</span> <span class="er">Dokumente</span> <span class="er">löschen:</span>
3628<span class="er">db.col.remove(</span><span class="fu">{</span><span class="er">a</span><span class="fu">:</span><span class="dv">2</span><span class="fu">}</span><span class="er">);</span>
3629
3630<span class="er">//</span> <span class="er">Dokument</span> <span class="er">verändern:</span>
3631<span class="er">db.col.update(</span><span class="fu">{</span><span class="er">a</span><span class="fu">:</span><span class="dv">1</span><span class="fu">}</span><span class="er">,</span> <span class="fu">{</span><span class="er">b</span><span class="fu">:</span><span class="dv">3</span><span class="fu">,</span> <span class="er">c</span><span class="fu">:</span><span class="ot">[</span><span class="dv">1</span><span class="ot">]</span><span class="fu">}</span><span class="er">);</span>
3632
3633<span class="er">//</span> <span class="er">Hilfe</span> <span class="er">anzeigen:</span>
3634<span class="er">help</span></code></pre></div>
3635<hr />
3636<hr />
3637<ol start="114" class="example" style="list-style-type: decimal">
3638<li><p>Zeigen Sie die Nutzung von SQLite.</p>
3639<ul>
3640<li>Legen Sie eine Datenbank an.</li>
3641<li>Legen Sie eine Tabelle an.</li>
3642<li>Fügen Sie zwei Datensätze ein.</li>
3643<li>Suchen Sie nach allen Datensätzen.</li>
3644<li>Erstellen Sie eine View.</li>
3645<li>Löschen Sie eine View.</li>
3646<li>Verändern Sie einen Datensatz.</li>
3647<li>Löschen Sie einen Datensatz.</li>
3648<li>Erstellen Sei einen Index.</li>
3649</ul></li>
3650</ol>
3651<hr />
3652<div class="sourceCode"><pre class="sourceCode sql"><code class="sourceCode sql">user@debian:~$ sqlite3 x.db # Legt die Datenbank an
3653<span class="co">-- Loading resources from /home/user/.sqliterc</span>
3654SQLite version <span class="fl">3.16.2</span> <span class="dv">2017-01-06</span> <span class="dv">16</span><span class="ch">:32:41</span>
3655Enter <span class="ot">".help"</span> <span class="kw">for</span> <span class="kw">usage</span> hints.
3656sqlite> <span class="kw">CREATE</span> <span class="kw">TABLE</span> t(f,g);
3657sqlite> .schema
3658<span class="kw">CREATE</span> <span class="kw">TABLE</span> t(f,g);
3659sqlite> <span class="kw">INSERT</span> <span class="kw">INTO</span> t <span class="kw">VALUES</span> (<span class="dv">1</span>, <span class="st">'hallo'</span>);
3660sqlite> <span class="kw">INSERT</span> <span class="kw">INTO</span> t (g, f) <span class="kw">VALUES</span> (<span class="st">'hi'</span>, <span class="dv">2</span>);
3661sqlite> <span class="kw">SELECT</span> * <span class="kw">FROM</span> t;
3662f g
3663<span class="co">------- ----------</span>
3664<span class="dv">1</span> hallo
3665<span class="dv">2</span> hi
3666
3667sqlite> <span class="kw">CREATE</span> <span class="kw">VIEW</span> v <span class="kw">AS</span> <span class="kw">SELECT</span> g <span class="kw">FROM</span> t;
3668g
3669<span class="co">-------</span>
3670hallo
3671hi
3672
3673sqlite> <span class="kw">DROP</span> <span class="kw">VIEW</span> v;
3674
3675sqlite> <span class="kw">UPDATE</span> t <span class="kw">SET</span> g=<span class="st">'bye'</span> <span class="kw">WHERE</span> f=<span class="dv">1</span>;
3676sqlite> <span class="kw">DELETE</span> <span class="kw">FROM</span> t <span class="kw">WHERE</span> f=<span class="dv">2</span>;
3677sqlite> <span class="kw">SELECT</span> * <span class="kw">FROM</span> t;
3678f g
3679<span class="co">------- ----------</span>
3680<span class="dv">1</span> bye
3681
3682sqlite> <span class="kw">CREATE</span> <span class="kw">INDEX</span> i <span class="kw">ON</span> t(f);</code></pre></div>
3683<h2 id="export-backup-..."><span class="header-section-number">8.2</span> Export, Backup <a href="#TOC">...</a></h2>
3684<!-- Alternative: sharding, start-stop-daemon, syslogd, pkill -->
3685<hr />
3686<hr />
3687<ol start="115" class="example" style="list-style-type: decimal">
3688<li><p>Der Datenbankadministrator möchte die Geschwindigkeit des DBMS erhöhen. Deshalb weist er SQLite an:</p>
3689<ul>
3690<li>temporäre Tabellen im Arbeitsspeicher abzulegen.</li>
3691<li>das Transaktionsprotokoll zu deaktivieren.</li>
3692</ul></li>
3693</ol>
3694<blockquote>
3695<ul>
3696<li>Entwerfen Sie ein Verfahren, das dies ermöglicht.</li>
3697<li>Erläutern Sie die dazu notwendigen Kommandos.</li>
3698</ul>
3699</blockquote>
3700<hr />
3701<pre><code> PRAGMA temp_store = MEMORY;
3702 PRAGMA journal_mode = OFF;</code></pre>
3703<ul>
3704<li><code>PRAGMA temp_store;</code> zeigt den aktuellen Wert an: 0 (Default, Meistens FILE), 1 (oder FILE), 2 (oder MEMORY)</li>
3705</ul>
3706<hr />
3707<hr />
3708<ol start="116" class="example" style="list-style-type: decimal">
3709<li>Beschreiben Sie die PRAGMA-Anweisung.</li>
3710</ol>
3711<hr />
3712<p>Die PRAGMA-Anweisung ist eine SQL-Erweiterung, die für SQLite spezifisch ist und verwendet wird,</p>
3713<ul>
3714<li>um die Arbeitsweise des DBMS zu beeinflussen</li>
3715<li>oder das DMBS nach internen Daten (ohne die normalen Tabellen) abzufragen.</li>
3716</ul>
3717<hr />
3718<hr />
3719<ol start="117" class="example" style="list-style-type: decimal">
3720<li>Erklären Sie das <strong>Logging und Recovery</strong> in DBMS.</li>
3721</ol>
3722<hr />
3723<p><strong>Logging und Recovery</strong> bezeichnet eine Sammlung von Maßnahmen und Techniken, um bei Datenbanksystemen nach einem Fehlerfall (z. B. nach einem Systemabsturz oder einem Ausfall von Festplatten) den Datenverlust zu verhindern und die Fehlerfreiheit (Konsistenz) der Datenbank weiterhin zu garantieren.</p>
3724<p>Das <strong>Transaktionsprotokoll</strong> schreibt im laufenden Betrieb alle Änderungen auf der Datenbank mit, und das <strong>Recovery</strong> stellt nach dem Fehlerfall (z. B. nach dem Reboot sofern ein Systemabsturz für den Fehler verantwortlich war) den letzten aktuellen (Verhinderung von Datenverlust) und fehlerfreien (konsistenten) Zustand der Datenbank wieder her.</p>
3725<p>Das Logging und Recovery ist somit verantwortlich für die Einhaltung der <strong>Konsistenz, Dauerhaftigkeit und Atomizität</strong> in einer Datenbank, drei der ACID-Eigenschaften.</p>
3726<hr />
3727<hr />
3728<ol start="118" class="example" style="list-style-type: decimal">
3729<li>Beschreiben Sie den Datenimport und Export in SQLite.</li>
3730</ol>
3731<hr />
3732<ul>
3733<li>Datenexport: <code>echo .dump | sqlite3 DB > FILE</code>
3734<ul>
3735<li>Exportiert werden Schema und Datensätze</li>
3736<li><code>.schema</code> zeigt nur das Schema</li>
3737<li>Man kann mit <code>.dump TABLE</code> auch einzelne Tabellen exportieren.</li>
3738</ul></li>
3739<li>Datenimport: <code>sqlite3 DB < FILE</code></li>
3740</ul>
3741<hr />
3742<hr />
3743<ol start="119" class="example" style="list-style-type: decimal">
3744<li>Beschreiben Sie Archivierung und den Wiederanlauf des DBMS SQLite.</li>
3745</ol>
3746<hr />
3747<ul>
3748<li>Archivierung: Sie müssen nur eine einzige Datei (die Datenbasis) kopieren.</li>
3749<li>Wiederanlauf: Zum Betrieb von SQLite müssen Sie nichts administrieren. Die Anwendungsprogramme greifen direkt über APIs auf die Datenbasis zu.</li>
3750</ul>
3751<hr />
3752<hr />
3753<ol start="120" class="example" style="list-style-type: decimal">
3754<li>Erläutern Sie die Besonderheiten von SQLite im Gegensatz zu einem Client-Server-DBMS.</li>
3755</ol>
3756<hr />
3757<dl>
3758<dt>.</dt>
3759<dd><img src="/home/user/acha/www-img/sql/sqlite-direct.jpg" />
3760</dd>
3761</dl>
3762<ul>
3763<li>Bei der Client-Server-Architektur greifen Anwendungsprogramme nicht direkt auf die Daten zu, sondern kommunizieren mit einem separaten Prozess (dem Datenbank-Managementsystem), der seinerseits die Daten verwaltet.</li>
3764<li>Bei SQLite liest und schreiben die Anwendungsprogramme die Daten direkt über APIs in die Datenbasis.</li>
3765</ul>
3766<hr />
3767<hr />
3768<ol start="121" class="example" style="list-style-type: decimal">
3769<li>Nennen und beschreiben Sie die Merkmale des DBMS SQLite.</li>
3770</ol>
3771<hr />
3772<ul>
3773<li>benötigt keine Konfiguration</li>
3774<li>benötigt keinen administrativen Aufwand für den Betrieb</li>
3775<li>Die Datenbasis besteht aus einer einzigen Datei</li>
3776<li>unterstützt einen Großteil der im SQL-92-Standard festgelegten SQL-Sprachbefehle.</li>
3777<li>ist Public Domain</li>
3778<li>bietet keine Nutzer- und Rechteverwaltung</li>
3779<li>hat keine Stored Procedures (kann also keine Programmlogik in der Datenbank speichern)</li>
3780</ul>
3781<hr />
3782<hr />
3783<ol start="122" class="example" style="list-style-type: decimal">
3784<li>Beschreiben Sie die Begriffe Datenbanksystem, Datenbankmanagementsystem und Datenbasis.</li>
3785</ol>
3786<hr />
3787<p><strong>Datenbanksysteme</strong> sind Hilfsmittel zur rechnergestützten Verarbeitung großer Datenbestände.</p>
3788<p>Ein Datenbanksystem besteht aus</p>
3789<ul>
3790<li>der <strong>Datenbasis</strong> (in der die Daten strukturiert gespeichert werden) und</li>
3791<li>dem Datenbankmanagementsystem (=Datenbankverwaltungssystem, DBMS).</li>
3792</ul>
3793<p>Das <strong>Datenbankmanagementsystem</strong> ist ein Programmsystem</p>
3794<ul>
3795<li>zum Aufbau,</li>
3796<li>zur Kontrolle und</li>
3797<li>zur Manipulation</li>
3798</ul>
3799<p>der Datenbasis.</p>
3800<p>Der Begriff <strong>Datenbank</strong> (DB) wird sowohl für die Datenbasis, als auch für das Datenbanksystem verwendet.</p>
3801</body>
3802</html>