8.2.3 Gespeicherte Prozeduren und CLR

Werbung
8.2 Gespeicherte Prozeduren
197
■ um den lesenden und schreibenden Zugriff auf Systemtabellen zu ermöglichen
■ um die Abfragen und Änderungen der Zugriffsrechte einer Datenbank durchzuführen
■ um die Speicherverwaltung einzelner Datenbanken zu überwachen bzw. zu
ändern
Die oben genannte Unterteilung der Systemprozeduren ist weder vollständig noch eindeutig. Viele Systemprozeduren können z.B. sowohl der ersten als auch der zweiten
Gruppe zugeordnet werden.
Weil Systemprozeduren für unterschiedliche Aufgaben angewendet werden können, werden wir sie in den entsprechenden Kapiteln beschreiben. Diese Beschreibung wird nicht alle angebotenen Prozeduren enthalten. Für eine vollständige
Auflistung der Systemprozeduren verweisen wir den Leser auf die Onlinedokumentation des Systems.
Jeder Benutzer kann auch eigene Systemprozeduren mit der CREATE PROCEDURE-Anweisung erstellen. Die Voraussetzung für solche Prozeduren ist, dass
sie mit dem Präfix sp_ beginnen und der Masterdatenbank angehören. Solche
Prozeduren können unabhängig von der augenblicklich aktuellen Datenbank
aufgerufen werden.
Benutzerdefinierte Systemprozeduren können in SQL Server 2005 durch gespeicherte
Prozeduren mit Hilfe von Common Language Runtime (CLR) implementiert werden.
Diese Prozeduren sind das Thema des folgenden Abschnitts.
8.2.3
Gespeicherte Prozeduren und CLR
In älteren SQL Server-Versionen können gespeicherte Prozeduren nur mit Hilfe
der Transact-SQL-Sprache implementiert werden. SQL Server 2005 führt zum
ersten Mal eine alternative Möglichkeit ein: Common Language Runtime (CLR).
Mit CLR können verschiedene Datenbankobjekte wie Prozeduren, Funktionen
und benutzerdefinierte Datentypen mit Hilfe verschiedener Programmiersprachen (C# und Visual Basic 2005) implementiert werden.
Um eine gespeicherte Prozedur auf der Basis von CLR zu implementieren,
übersetzen und speichern, müssen folgende Schritte (in der vorgegebenen Reihenfolge) ausgeführt werden:
■ Implementiere eine gespeicherte Prozedur mit Hilfe von C# bzw. Visual Basic
2005 und übersetze diese mit Hilfe des entsprechenden Übersetzers.
■ Verwende die CREATE ASSEMBLY-Anweisung, um die ausführbare Version
(Executable File) des Programms zu erstellen.
■ Speichere die Prozedur mit Hilfe der CREATE PROCEDURE-Anweisung.
■ Führe die Prozedur mit Hilfe der EXECUTE-Anweisung aus.
198
8 SQL-Erweiterungen und gespeicherte Prozeduren
Abb. 8–1
Ausführung einer gespeicherten Prozedur mit Hilfe von CLR
Abbildung 8–1 zeigt, wie eine gespeicherte Prozedur mit Hilfe von CLR übersetzt
und gespeichert werden kann. Man verwendet eine Programmierumgebung wie
Visual Studio 2005, um das Programm zu implementieren. Nach der Implementierung wird der entsprechende C#- bzw. Visual Studio 2005-Übersetzer gestartet,
damit der Objekt-Code erstellt wird. Der entsprechende Code, der in eine .dllDatei gespeichert ist, wird anschließend als Quelle von der CREATE ASSEMBLYAnweisung verwendet, um den Zwischencode des Programms zu erstellen.
Die anderen beiden Schritten sind schon bekannt: Mit der CREATE PROCEDURE-Anweisung wird der Code gespeichert, während die EXECUTE-Anweisung für die Ausführung der gespeicherten Prozedur verwendet wird.
Die folgenden fünf Beispiele zeigen alle oben beschriebenen Schritte. Beispiel
8.10 beginnt mit einem C#-Programm, mit dem eine gespeicherte Prozedur implementiert wird.
Beispiel 8.10
using
using
using
using
System;
System.Data;
System.Data.Sql;
System.Data.SqlServer;
8.2 Gespeicherte Prozeduren
199
using System.Data.SqlTypes;
public partial class StoredProcedures
{
[SqlProcedure]
public static int GetEmployeeCount()
{
int iRows;
SqlCommand sqlCmd = SqlContext.GetCommand();
sqlCmd.CommandText = "select count(*) as 'Employee Count' " +
"from mitarbeiter";
iRows = (int)sqlCmd.ExecuteScalar();
return iRows;
}
};
Das C#-Programm in Beispiel 8.10 verwendet eine Abfrage:
select count(*) as 'Employee Count' from mitarbeiter
Damit wird die Anzahl der Reihen der Tabelle mitarbeiter berechnet. Die
USING-Anweisungen am Anfang des Programms spezifizieren Namen von Paketen, wie z.B. System.Data. Diese Anweisungen ermöglichen die Angabe von Klassennamen innerhalb des Programms, ohne den Namen des Pakets, zu dem die
Klasse gehört, jedes Mal explizit schreiben zu müssen.
Die erste Klasse, die in Beispiel 8.10 spezifiziert wird, heißt StoredProcedures. Diese Klasse, zusammen mit dem dazugehörigen [SqlProcedure]-Attribut,
informiert das System, dass hier eine gespeicherte Prozedur mit Hilfe von
Common Language Runtime implementiert wird.
Innerhalb der StoredProcedures-Klasse wird die Methode GetEmployeeCount() implementiert. Die SqlContext-Klasse, die zum Paket System.Data.
SqlServer gehört, wird anschließend mit ihrer Methode GetCommand() verwendet,
um eine Instanz der SqlCommand-Klasse (sqlCmd) zu referenzieren, welche die Verbindung zu dem aktuellen System herstellt.
Die folgenden Programmzeilen:
sqlCmd.CommandText = "select count(*)
as 'Employee Count' " + "from mitarbeiter";
iRows = (int)sqlCmd.ExecuteScalar();
verwenden die SELECT-Anweisung für die Ermittlung der Reihenanzahl in der
Tabelle mitarbeiter und für die Ausgabe des Ergebnisses. Die Anweisung ist mit
Hilfe des CommandText-Attributes der Instanz sqlCmd spezifiziert. Danach wird die
ExecuteScalar()-Methode in Bezug auf die selbe Instanz aufgerufen, die einen
skalaren Wert zurückgibt. Dieser Wert wird umgewandelt und der iRows-Variablen zugewiesen.
200
8 SQL-Erweiterungen und gespeicherte Prozeduren
Die Verwendung von Common Language Runtime ist standardmäßig deaktiviert. Um
diese Funktionalität benutzen zu können, muss die Option clr_enabled der Systemprozedur sp_configure aktiviert werden. (Führen Sie anschließend die RECONFIGUREAnweisung aus, um die Konfigurationswerte zu aktualisieren.)
Beispiel 8.11 zeigt den ersten Schritt: die Übersetzung des in Beispiel 8.10 implementierten Programms mit Hilfe des C#-Übersetzers.
Beispiel 8.11
csc /target:library GetEmployeeCount.cs
/reference:"c:\ProgramFiles\Microsoft
SQLServer\MSSQL.1\MSSQL\Binn\sqlaccess.dll"
In Beispiel 8.11 wird das Programm namens GetEmployeeCount übersetzt. csc ist
das Betriebssystemkommando, mit dem der C#-Übersetzer aufgerufen wird. (Vor
dem Aufruf des csc-Kommandos muss sein Speicherort mit Hilfe der Umgebungsvariablen PATH spezifiziert werden.)
Die Option /target legt den Namen des C#-Quellprogramms fest, während
die Option /reference die .dll-Dateien spezifiziert, die für den Übersetzungsprozess notwendig sind.
Beispiel 8.12 zeigt den zweiten Schritt: die Verwendung der CREATE
ASSEMBLY-Anweisung, um die ausführbare Version des Programms zu erstellen.
Beispiel 8.12
CREATE ASSEMBLY GetEmployeeCount
FROM 'C:\GetEmployeeCount.dll'
WITH PERMISSION_SET = SAFE
Die CREATE ASSEMBLY-Anweisung verwendet den übersetzten Code, gespeichert in einer .dll-Datei, um das entsprechende Datenbankobjekt zu erstellen.
Diese Anweisung hat folgende allgemeine Syntax:
CREATE ASSEMBLY assembly_name
[ AUTHORIZATION owner_name ]
FROM { dll_file}
[ WITH PERMISSION_SET = { SAFE |
EXTERNAL_ACCESS | UNSAFE } ]
assembly_name ist der Name des neuen Datenbankobjektes. Die optionale
AUTHORIZATION-Klausel spezifiziert den Namen des Eigentümers des Objektes. Die FROM-Klausel definiert den Pfadnamen, wo die übersetzte Datei (in
Form einer dll-Bibliothek) sich befindet. (In Beispiel 8.12 haben wir die .dll-Datei
aus dem Framework-Verzeichnis in das C:-Dateiverzeichnis kopiert.)
8.2 Gespeicherte Prozeduren
201
Die WITH PERMISSION SET-Klausel hat sehr große Bedeutung bei der Erstellung
eines Datenbankobjektes mit Hilfe von CLR. Sie spezifiziert, auf welche Ressourcen das erstellte Datenbankobjekt zugreifen kann. Die Angabe SAFE ist die restriktivste Angabe von allen: Falls der Code eines Programms mit dieser Angabe
erstellt wird, kann das Programm auf externe Systemressourcen wie Dateien
nicht zugreifen.
Die zweite Angabe – EXTERNAL ACCESS – erlaubt dem Code, auf gewisse
externe Systemressourcen zuzugreifen, wie das Dateisystem und anderen Datenbanken mit Hilfe von ADO.NET. UNSAFE erlaubt einen uneingeschränkten
Zugriff auf Ressourcen (innerhalb und außerhalb des SQL Server-Systems).
Diese drei Angaben regeln, wie sicher der relationale Datenbankserver sein kann, dass
das erstellte Objekt das ganze Datenbanksystem gefährden kann.
Folgendes Beispiel zeigt die Erstellung der gespeicherten Prozedur auf der Basis
des C#-Programms aus Beispiel 8.10.
Beispiel 8.13
CREATE PROCEDURE GetEmployeeCount
AS EXTERNAL NAME GetEmployeeCount.StoredProcedures.GetEmployeeCount
Die CREATE PROCEDURE-Anweisung in Beispiel 8.13 zeigt eine Erweiterung,
die wir bis jetzt noch nicht gesehen haben: AS EXTERNAL NAME. Mit dieser
Option wird der Code, der mit Hilfe von CLR generiert wurde, spezifiziert. Der
Name in dieser Klausel sieht standardmäßig so aus:
assembly_name.class_name.method_name
assembly_name spezifiziert den Namen des in der CREATE ASSEMBLY-Anwei-
sung erstellten Datenbankobjektes (in diesem Fall die gespeicherte Prozedur).
class_name ist der Name der public-Klasse, die im Quellprogramm (siehe Beispiel
8.10) definiert ist, während method_name den Namen der Methode festlegt, die
innerhalb der public-Klasse angegeben ist. (In Beispiel 8.10 heißt die publicKlasse StoredProcedures und die zu ihr gehörende Methode GetEmployeeCount.)
Das letzte Beispiel in dieser Beispielfolge zeigt, wie die mit Hilfe von CLR
erstellte gespeicherte Prozedur ausgeführt werden kann.
Beispiel 8.14
DECLARE @ret INT
EXECUTE @ret=GetEmployeeCount
PRINT @ret
Beispiel 8.14 zeigt die Transact-SQL-Anweisungsfolge, mit der ein Datenbankobjekt (in diesem Fall eine gespeicherte Prozedur) ausgeführt werden kann. Der
202
8 SQL-Erweiterungen und gespeicherte Prozeduren
integer-Wert, der die Prozedur in ihrer SELECT-Anweisung ermittelt, wird einer
vorher definierten Variablen mit Hilfe der EXECUTE-Anweisung zugewiesen.
(Die anschließende PRINT-Anweisung gibt den Wert 7 aus, weil die Tabelle mitarbeiter in unserem Fall sieben Reihen enthält.)
8.3
Benutzerdefinierte Funktionen
Programmiersprachen unterstützen generell zwei Routine-Typen:
■ Prozeduren
■ benutzerdefinierte Funktionen
Prozeduren enthalten keine oder mehrere Parameter, liefern aber keine Rückgabewerte. Im Unterschied zu Prozeduren liefern Funktionen einen oder mehrere
Rückgabewerte. (Wie aus dem folgenden Unterabschnitt ersichtlich wird, können
benutzerdefinierte Funktionen beim relationalen Datenbankserver nur einen einzigen Rückgabewert liefern.)
8.3.1
Erstellung und Ausführung benutzerdefinierter Funktionen
Benutzerdefinierte Funktionen werden mit Hilfe der CREATE FUNCTIONAnweisung erstellt. Diese Anweisung hat folgende Syntax:
CREATE FUNCTION [schema_name.]funktion_name
[[(]@param_1 typ_1 [=default_1]
[{,@param_2 typ_2 [=default_2]]}...[)]]
RETURNS {skalar_wert | {[@variable} TABLE}}
[WITH {ENCRYPTION | SCHEMABINDING}
AS {block | RETURN(select_anw)}
schema_name spezifiziert den Namen des Schemas, während funktion_name den
Namen der benutzerdefinierten Funktion kennzeichnet.
@param_1, @param_2 … sind Parameternamen, während typ_1, typ_2 … ihren
Datentypen spezifizieren. (Parameter sind Werte, die von dem Aufrufprogramm
an die benutzerdefinierte Funktion geschickt und innerhalb der Funktion verwendet werden.) default_1, default_2 … kennzeichnen optionale Standardwerte der
entsprechenden Parameter.
Die RETURNS-Klausel definiert den Datentyp des Rückgabewertes. Dieser
kann entweder einen Standarddatentyp haben oder den Datentyp namens
TABLE. Eine benutzerdefinierte Funktion beim relationalen Datenbankserver
kann entweder einen skalaren Wert oder eine Tabelle als Rückgabewert liefern.
Eine Funktion liefert einen skalaren Wert, falls in der RETURNS-Klausel ein
Standarddatentyp spezifiziert wird. Jede Funktion mit der Angabe TABLE in dieser Klausel gibt eine ganze Tabelle zurück.
8.3 Benutzerdefinierte Funktionen
203
Abhängig davon, wie der Funktionskörper definiert ist, können Funktionen
mit den Tabellen als Rückgabewerten:
■ inline oder
■ mit mehreren Anweisungen
sein. Falls die RETURNS-Klausel die Option TABLE ohne irgendwelche zusätzliche Angaben verwendet, handelt es sich um eine inline-Funktion. Eine solche
Funktion liefert das Ergebnis als eine Variable vom Typ TABLE. Eine Funktion
mit mehreren Anweisungen in der RETURNS-Klausel enthält einen Namen, an
den das Schlüsselwort TABLE angefügt ist. (Der Name wird damit eine interne
Variable vom Typ TABLE.) Die Variable kann verwendet werden, um Reihen einzufügen und sie anschließend als den Rückgabewert der Funktion zurückzugeben.
Die Angabe ENCRYPTION verursacht die Verschlüsselung der Anweisungen
innerhalb der benutzerdefinierten Funktion. Diese Angabe ist empfehlenswert,
wenn die Implementierung der Funktion nicht allgemein bekannt werden darf.
Die alternative WITH SCHEMABINDING-Klausel bindet die benutzerdefinierte Funktion zum Datenbankobjekt, das sie referenziert. (Das Ergebnis dieser
Referenzierung ist, dass jeder Versuch, das Datenbankobjekt zu ändern, fehlschlägt.) Die von einer Funktion referenzierten Datenbankobjekte müssen
gewisse Kriterien erfüllen, damit die SCHEMABINDING-Klausel mit ihnen verwendet werden kann. Diese sind:
■ Alle Sichten und benutzerdefinierte Funktionen, die durch die angegebene
Funktion referenziert sind, müssen selbst gebunden werden (d.h. mit WITH
SCHEMABINDING definiert werden).
■ Alle referenzierten Datenbankobjekte (Tabellen, Sichten, benutzerdefinierte
Funktionen) müssen zu derselben Datenbank wie die angegebene Funktion
gehören.
block kennzeichnet einen BEGIN-Block, der den Implementierungsteil der Funktion enthält. Die letzte Anweisung im block muss eine RETURN-Anweisung sein.
(Der Wert des Argumenten der RETURN-Anweisung entspricht dem Rückgabewert der Funktion.) Im BEGIN-Block können nur folgende Anweisungen angegeben werden:
■
■
■
■
Zuweisungsanweisungen (z.B. die SET-Anweisung)
die WHILE- und IF-Anweisungen
die DECLARE -Anweisung
die SELECT-Anweisung, mit der den Spaltenwerten entsprechende Variablen
zugewiesen werden
■ die INSERT-, UPDATE-, und DELETE-Anweisung, die die Werte der Variablen vom Typ TABLE ändern
204
8 SQL-Erweiterungen und gespeicherte Prozeduren
Gleich nach der Erstellung einer Datenbank haben nur die Mitglieder der Datenbankrollen db_owner und db_ddladmin das Recht, die CREATE FUNCTIONAnweisung auszuführen. Anschließend können sie auch den anderen Benutzern
mit Hilfe der GRANT CREATE FUNCTION-Anweisung die Rechte zur Erstellung von Funktionen vergeben (siehe Kapitel 12).
Das folgende Beispiel zeigt die Erstellung einer einfachen benutzerdefinierten
Funktion.
Beispiel 8.15
-- Diese benutzerdefinierte Funktion berechnet zusätzliche
-- Kosten, die entstehen, falls Projektmittel erhöht werden.
USE beispiel
GO
CREATE FUNCTION compute_costs (@prozent INT =10)
RETURNS DECIMAL(16,2)
BEGIN
DECLARE @kosten DEC (14,2), @sum_mittel dec(16,2)
SELECT @sum_mittel = SUM (mittel)FROM projekt
SET @kosten = @sum_mittel * @prozent/100
RETURN @kosten
END
Die Funktion compute_costs berechnet die Kosten, die entstehen, falls alle Projektmittel erhöht werden. Im BEGIN-Block werden zuerst zwei lokale Variablen
definiert: @kosten und @sum_mittel. Der zweiten Variablen wird die Summe aller
Mittel mit Hilfe der SELECT-Anweisung zugewiesen. Danach berechnet die
Funktion alle zusätzlichen Kosten und gibt den Wert mit Hilfe der RETURNAnweisung zurück.
Jede benutzerdefinierte Funktion kann innerhalb einer DML-Anweisung
(SELECT, INSERT, UPDATE und DELETE) aufgerufen werden. Um eine benutzerdefinierte Funktion aufzurufen, muss der Funktionsname zusammen mit
einem Klammerpaar angegeben werden. Innerhalb des Klammerpaares können
ein oder mehrere Argumente spezifiziert werden. (Argumente sind Werte, die den
definierten Funktionsparametern zugewiesen werden. Jedes Argument wird dem
entsprechenden Parameter zugewiesen.)
Das folgende Beispiel zeigt, wie die Funktion compute_costs (Beispiel 8.15)
innerhalb einer SELECT-Anweisung verwendet werden kann.
Beispiel 8.16
USE beispiel
select pr_nr, pr_name
from projekt
WHERE mittel < dbo.compute_costs(25)
8.3 Benutzerdefinierte Funktionen
205
Das Ergebnis ist:
pr_nr pr_name
----------------p2
Gemini
Das Ergebnis des Beispiels 8.16 gibt alle Namen und die Nummern aller Projekte
aus, bei welchen die Mittel kleiner sind als zusätzliche Kosten der Mittelerhöhung
für den angegebenen Prozentsatz.
Jeder Name einer benutzerdefinierten Funktion, der in einer Transact-SQL-Anweisung
angegeben wird, muss in der Form:
schema_name.funktions_name
spezifiziert werden.
Das folgende Beispiel zeigt eine benutzerdefinierte Funktion, deren Rückgabewert vom Typ TABLE ist.
Beispiel 8.17
USE beispiel
GO
create function mitarbeiter_im_projekt (@pr_nummer char(4))
returns table
as return (select m_vorname, m_name
from arbeiten, mitarbeiter
where mitarbeiter.m_nr = arbeiten.m_nr
and pr_nr = @pr_nummer)
Die Funktion mitarbeiter_im_projekt wird benutzt, um die Namen aller Mitarbeiter eines Projektes zu ermitteln. Der Eingabeparameter @pr_nummer spezifiziert
eine Projektnummer. Weil die Funktion im Allgemeinen mehrere Reihen als
Ergebnis liefert, muss die RETURNS-Klausel die TABLE-Angabe enthalten.
Beispiel 8.18 gibt die Namen und Projektnummer aller Mitarbeiter aus, die
im Projekt p3 arbeiten.
Beispiel 8.18
USE beispiel
select *
from mitarbeiter_im_projekt('p3')
Das Ergebnis ist:
m_vorname
m_name
----------------------------Petra
Huber
Rainer
Meier
Brigitte
Kaufmann
206
8 SQL-Erweiterungen und gespeicherte Prozeduren
Der relationale Datenbankserver unterstützt zusätzlich die ALTER FUNCTIONAnweisung, die die Struktur einer benutzerdefinierten Funktion ändert. Diese
Anweisung wird gewöhnlich benutzt, um die WITH SCHEMABINDING-Klausel
zu entfernen. Die ALTER FUNCTION-Anweisung hat dieselben Optionen wie
die CREATE FUNCTION-Anweisung.
8.3.2
Benutzerdefinierte Funktionen und CLR
Alles, was bis jetzt über die Erstellung von gespeicherten Prozeduren mit Hilfe
von CLR gesagt wurde, gilt auch für benutzerdefinierte Funktionen. Der einzige
Unterschied ist, dass die Anweisung CREATE FUNCTION anstelle von CREATE
PROCEDURE verwendet wird, wenn man eine benutzerdefinierte Funktion als
Datenbankobjekt speichern will. (Ein zweiter Unterschied ist, dass Funktionen in
einem anderen Kontext als gespeicherte Prozeduren verwendet werden, wie wir in
Beispiel 8.22 zeigen werden.)
Folgendes Beispiel erstellt ein Programm, mit dem wir anschließend zeigen
werden, wie benutzerdefinierte Funktionen mit Hilfe der C#-Sprache übersetzt
und angewendet werden können.
Beispiel 8.19
using System;
using System.Data.Sql;
using System.Data.SqlTypes;
public class budgetPercent
{ private const float percent = 10;
public static SqlDouble computeBudget(float budget)
{ float budgetNew;
budgetNew = budget * percent;
return budgetNew;
}
};
Das C#-Programm in Beispiel 8.19 zeigt die Implementierung einer benutzerdefinierten Funktion, die einen neuen Wert der Projektmittel berechnet, in dem der
alte Wert mit der prozentuellen Erhöhung (in unserem Programm 10 %) multipliziert wird. Das C#-Programm in Beispiel 8.19 wird nicht erläutert, weil es identische Klassen und Methoden verwendet, die schon in Beispiel 8.10 vorkommen.
Genauso wird der Aufruf des csc-Kommandos nicht gezeigt. Dieser Schritt ist in
Beispiel 8.11 beschrieben.
Beispiel 8.20 zeigt die CREATE ASSEMBLY-Anweisung, mit der aus der .dllDatei das entsprechende Objekt erstellt wird.
8.4 Zusammenfassung
207
Beispiel 8.20
CREATE ASSEMBLY computeBudget
FROM 'C:\computeBudget.dll'
WITH PERMISSION_SET = SAFE
In Beispiel 8.20 wird das Objekt computeBudget erstellt, das anschließend für die
Erstellung der benutzerdefinierten Funktion verwendet wird. (Alle Optionen der
CREATE ASSEMBLY-Anweisung, die in Beispiel 8.20 vorkommen, sind im
Zusammenhang mit Beispiel 8.12 erörtert worden.)
Beispiel 8.21
CREATE FUNCTION ReturncomputeBudget (@budget Real)
RETURNS FLOAT
AS EXTERNAL NAME computeBudget.budgetPercent.computeBudget
Die CREATE FUNCTION-Anweisung in Beispiel 8.21 speichert das computeBudget-Objekt als benutzerdefinierte Funktion. Diese Funktion kann anschließend in verschiedenen DML-Anweisungen verwendet werden. Das folgende Beispiel zeigt den Aufruf dieser Funktion.
Beispiel 8.22
USE beispiel
select dbo.ReturncomputeBudget (321.50)
Mit der SELECT-Anweisung in Beispiel 8.22 wird der neue (erhöhte) Wert der
Produktmittel auf der Basis des alten Wertes (321.50) und der prozentuellen
Erhöhung (10 %) berechnet.
8.4
Zusammenfassung
Der relationale Datenbankserver ist eines der wenigen relationalen Datenbankmanagementsysteme, der prozedurale Erweiterungen sowohl im Zusammenhang
mit der SQL-Sprache selbst als auch für die Erstellung der gespeicherten Prozeduren unterstützt. (Die meisten DBMS unterstützen prozedurale Erweiterungen ausschließlich in Bezug auf gespeicherte Prozeduren.) Ein weiteres Merkmal des relationalen Datenbankservers ist die Unterstützung zahlreicher Systemprozeduren.
Diese werden u.a. für die komplette Administrierung eines SQL Server-Systems
benutzt.
Das folgende Kapitel behandelt Indizes.
208
8 SQL-Erweiterungen und gespeicherte Prozeduren
8.5
Aufgaben
A.8.1
Definieren Sie die Anweisungsfolge, die 3.000 Reihen in die Tabelle mitarbeiter lädt. Die Werte der Spalte m_nr sollen zwischen 1 und 3.000 liegen und eindeutig sein. Alle Werte der Spalten m_name, m_vorname und
abt_nr sollen auf »Kurz«, »Jochen« und »a1« in dieser Reihenfolge
gesetzt werden.
A.8.2
Modifizieren Sie die Aufgabe A.8.1 so, dass die Werte der Spalte m_nr
per Zufallsgenerator (mit Hilfe der RAND-Funktion) spezifiziert werden.
(Hinweis: Benutzen Sie auch die Systemfunktionen DATEPART und
GETDATE [siehe Kapitel 3], um Zufallswerte zu generieren.)
Herunterladen