Microsoft SQL Server Cheatsheet¶
Microsoft SQL Server - Enterprise Database Platform
Microsoft SQL Server ist ein von Microsoft entwickeltes relationales Datenbankmanagementsystem. Es ist eine umfassende Datenbank-Plattform, die Enterprise-grade-Funktionen für Datenspeicherung, Verarbeitung und Analytik mit einer starken Integration mit Microsoft-Ökosystem bietet. < p>
Inhaltsverzeichnis¶
- [Installation](#installation
- (#basic-commands)
- [Datenbankoperationen](LINK_2__
- [Schema und User Management](#schema-and-user-management
- [Table Operations](#table-operations_
- Datentypen
- (CRUD Operationen)(LINK_6__
- [Query Operations](LINK_7__
- [Indexes](LINK_8__
- Ansichten
- (#stored-procedures_)
- Funktionen
- Trigger
- Transaktionen
- T-SQL-Programmierung
- (#backup-and-recovery)
- (#performance-tuning_)
- (Monitoring)(LINK_17_)
- [Sicherheit](#security_
- Beste Praktiken
Installation¶
SQL Server Installation (Windows)¶
# Download SQL Server from Microsoft website
# https://www.microsoft.com/en-us/sql-server/sql-server-downloads
# Silent installation example
Setup.exe /Q /IACCEPTSQLSERVERLICENSETERMS /ACTION=install /FEATURES=SQLENGINE,TOOLS /INSTANCENAME=MSSQLSERVER /SQLSVCACCOUNT="NT AUTHORITY\SYSTEM" /SQLSYSADMINACCOUNTS="BUILTIN\Administrators" /TCPENABLED=1 /SECURITYMODE=SQL /SAPWD="YourStrongPassword"
# Install SQL Server Management Studio (SSMS)
# Download from: https://docs.microsoft.com/en-us/sql/ssms/download-sql-server-management-studio-ssms
# PowerShell installation
choco install sql-server-management-studio
```_
### SQL Server auf Linux
```bash
# Add Microsoft repository (Ubuntu)
wget -qO- https://packages.microsoft.com/keys/microsoft.asc | sudo apt-key add -
sudo add-apt-repository "$(wget -qO- https://packages.microsoft.com/config/ubuntu/20.04/mssql-server-2019.list)"
# Install SQL Server
sudo apt-get update
sudo apt-get install -y mssql-server
# Configure SQL Server
sudo /opt/mssql/bin/mssql-conf setup
# Install SQL Server command-line tools
curl https://packages.microsoft.com/keys/microsoft.asc | sudo apt-key add -
curl https://packages.microsoft.com/config/ubuntu/20.04/prod.list | sudo tee /etc/apt/sources.list.d/msprod.list
sudo apt-get update
sudo apt-get install mssql-tools unixodbc-dev
# Add to PATH
echo 'export PATH="$PATH:/opt/mssql-tools/bin"' >> ~/.bashrc
source ~/.bashrc
# Start SQL Server
sudo systemctl start mssql-server
sudo systemctl enable mssql-server
```_
### Docker Installation
```bash
# Pull SQL Server image
docker pull mcr.microsoft.com/mssql/server:2019-latest
# Run SQL Server container
docker run -e "ACCEPT_EULA=Y" -e "SA_PASSWORD=YourStrongPassword123" \
-p 1433:1433 --name sql-server \
-d mcr.microsoft.com/mssql/server:2019-latest
# Connect to SQL Server
docker exec -it sql-server /opt/mssql-tools/bin/sqlcmd \
-S localhost -U SA -P "YourStrongPassword123"
# Docker Compose
cat > docker-compose.yml << EOF
version: '3.8'
services:
sqlserver:
image: mcr.microsoft.com/mssql/server:2019-latest
container_name: sqlserver
environment:
- ACCEPT_EULA=Y
- SA_PASSWORD=YourStrongPassword123
- MSSQL_PID=Express
ports:
- "1433:1433"
volumes:
- sqlserver_data:/var/opt/mssql
volumes:
sqlserver_data:
EOF
docker-compose up -d
```_
## Grundlegende Befehle
### Verbindung mit SQL Server
```bash
# Using sqlcmd
sqlcmd -S server_name -U username -P password
sqlcmd -S localhost -U sa -P password
sqlcmd -S server_name -E # Windows Authentication
# Using PowerShell
Import-Module SqlServer
Invoke-Sqlcmd -ServerInstance "localhost" -Database "master" -Query "SELECT @@VERSION"
# Connection string examples
# SQL Server Authentication
Server=localhost;Database=master;User Id=sa;Password=password;
# Windows Authentication
Server=localhost;Database=master;Integrated Security=true;
# Named instance
Server=localhost\SQLEXPRESS;Database=master;Integrated Security=true;
```_
### Grundlegende Informationsbefehle
```sql
-- SQL Server version
SELECT @@VERSION;
-- Current database
SELECT DB_NAME();
-- Current user
SELECT SYSTEM_USER, USER_NAME();
-- Server information
SELECT
SERVERPROPERTY('ServerName') AS ServerName,
SERVERPROPERTY('ProductVersion') AS Version,
SERVERPROPERTY('ProductLevel') AS ProductLevel,
SERVERPROPERTY('Edition') AS Edition;
-- Show databases
SELECT name FROM sys.databases;
-- Show tables in current database
SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE';
-- Show columns of a table
SELECT COLUMN_NAME, DATA_TYPE, IS_NULLABLE, COLUMN_DEFAULT
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'YourTableName';
-- Current date and time
SELECT GETDATE();
-- Exit sqlcmd
EXIT
QUIT
```_
## Datenbanken
### Datenbanken erstellen und verwalten
```sql
-- Create database
CREATE DATABASE MyDatabase;
-- Create database with options
CREATE DATABASE MyDatabase
ON
( NAME = 'MyDatabase_Data',
FILENAME = 'C:\Data\MyDatabase.mdf',
SIZE = 100MB,
MAXSIZE = 1GB,
FILEGROWTH = 10MB )
LOG ON
( NAME = 'MyDatabase_Log',
FILENAME = 'C:\Data\MyDatabase.ldf',
SIZE = 10MB,
MAXSIZE = 100MB,
FILEGROWTH = 10% );
-- Use database
USE MyDatabase;
-- Alter database
ALTER DATABASE MyDatabase
MODIFY FILE (NAME = 'MyDatabase_Data', SIZE = 200MB);
-- Set database options
ALTER DATABASE MyDatabase SET RECOVERY FULL;
ALTER DATABASE MyDatabase SET AUTO_SHRINK OFF;
ALTER DATABASE MyDatabase SET AUTO_UPDATE_STATISTICS ON;
-- Drop database
DROP DATABASE MyDatabase;
-- Show database information
SELECT
name,
database_id,
create_date,
collation_name,
state_desc,
recovery_model_desc
FROM sys.databases;
-- Show database files
SELECT
name,
physical_name,
size * 8 / 1024 AS size_mb,
max_size,
growth,
type_desc
FROM sys.database_files;
```_
### Backup und Wiederherstellung
```sql
-- Full backup
BACKUP DATABASE MyDatabase
TO DISK = 'C:\Backup\MyDatabase_Full.bak'
WITH FORMAT, INIT, COMPRESSION;
-- Differential backup
BACKUP DATABASE MyDatabase
TO DISK = 'C:\Backup\MyDatabase_Diff.bak'
WITH DIFFERENTIAL, COMPRESSION;
-- Transaction log backup
BACKUP LOG MyDatabase
TO DISK = 'C:\Backup\MyDatabase_Log.trn';
-- Restore database
RESTORE DATABASE MyDatabase
FROM DISK = 'C:\Backup\MyDatabase_Full.bak'
WITH REPLACE, NORECOVERY;
RESTORE DATABASE MyDatabase
FROM DISK = 'C:\Backup\MyDatabase_Diff.bak'
WITH NORECOVERY;
RESTORE LOG MyDatabase
FROM DISK = 'C:\Backup\MyDatabase_Log.trn'
WITH RECOVERY;
-- Point-in-time restore
RESTORE DATABASE MyDatabase
FROM DISK = 'C:\Backup\MyDatabase_Full.bak'
WITH REPLACE, NORECOVERY;
RESTORE LOG MyDatabase
FROM DISK = 'C:\Backup\MyDatabase_Log.trn'
WITH STOPAT = '2023-12-01 14:30:00', RECOVERY;
```_
## Schema und Benutzerverwaltung
### Logins und Benutzer erstellen
```sql
-- Create SQL Server login
CREATE LOGIN app_user WITH PASSWORD = 'StrongPassword123';
-- Create Windows login
CREATE LOGIN [DOMAIN\username] FROM WINDOWS;
-- Create user in database
USE MyDatabase;
CREATE USER app_user FOR LOGIN app_user;
-- Create user with default schema
CREATE USER app_user FOR LOGIN app_user WITH DEFAULT_SCHEMA = dbo;
-- Alter user
ALTER USER app_user WITH DEFAULT_SCHEMA = app_schema;
-- Drop user and login
DROP USER app_user;
DROP LOGIN app_user;
-- Show logins
SELECT name, type_desc, create_date, modify_date, is_disabled
FROM sys.server_principals
WHERE type IN ('S', 'U', 'G');
-- Show users in current database
SELECT name, type_desc, create_date, default_schema_name
FROM sys.database_principals
WHERE type IN ('S', 'U', 'G');
```_
### Berechtigungen und Roles
```sql
-- Grant permissions
GRANT SELECT, INSERT, UPDATE, DELETE ON dbo.Employees TO app_user;
GRANT EXECUTE ON dbo.GetEmployeeInfo TO app_user;
GRANT SELECT ON SCHEMA::dbo TO app_user;
-- Deny permissions
DENY DELETE ON dbo.Employees TO app_user;
-- Revoke permissions
REVOKE INSERT ON dbo.Employees FROM app_user;
-- Create custom role
CREATE ROLE app_role;
-- Add permissions to role
GRANT SELECT, INSERT, UPDATE ON dbo.Employees TO app_role;
-- Add user to role
ALTER ROLE app_role ADD MEMBER app_user;
-- Built-in database roles
ALTER ROLE db_datareader ADD MEMBER app_user;
ALTER ROLE db_datawriter ADD MEMBER app_user;
ALTER ROLE db_owner ADD MEMBER app_user;
-- Server roles
ALTER SERVER ROLE sysadmin ADD MEMBER app_user;
ALTER SERVER ROLE dbcreator ADD MEMBER app_user;
-- Show permissions
SELECT
p.permission_name,
p.state_desc,
pr.name AS principal_name,
o.name AS object_name
FROM sys.database_permissions p
JOIN sys.objects o ON p.major_id = o.object_id
JOIN sys.database_principals pr ON p.grantee_principal_id = pr.principal_id;
```_
### Schemata
```sql
-- Create schema
CREATE SCHEMA sales AUTHORIZATION dbo;
-- Transfer object to schema
ALTER SCHEMA sales TRANSFER dbo.Orders;
-- Drop schema
DROP SCHEMA sales;
-- Show schemas
SELECT name, schema_id, principal_id FROM sys.schemas;
```_
## Tabelle Operationen
### Tabellen erstellen
```sql
-- Basic table creation
CREATE TABLE Employees (
EmployeeID int IDENTITY(1,1) PRIMARY KEY,
FirstName nvarchar(50) NOT NULL,
LastName nvarchar(50) NOT NULL,
Email nvarchar(100) UNIQUE,
HireDate date DEFAULT GETDATE(),
Salary decimal(10,2),
DepartmentID int,
CreatedDate datetime2 DEFAULT GETDATE()
);
-- Table with constraints
CREATE TABLE Orders (
OrderID int IDENTITY(1,1) PRIMARY KEY,
CustomerID int NOT NULL,
OrderDate datetime2 DEFAULT GETDATE(),
TotalAmount decimal(10,2) CHECK (TotalAmount > 0),
Status nvarchar(20) DEFAULT 'Pending' CHECK (Status IN ('Pending', 'Processing', 'Completed', 'Cancelled')),
FOREIGN KEY (CustomerID) REFERENCES Customers(CustomerID)
);
-- Table with computed column
CREATE TABLE Products (
ProductID int IDENTITY(1,1) PRIMARY KEY,
ProductName nvarchar(100) NOT NULL,
UnitPrice decimal(10,2) NOT NULL,
Quantity int NOT NULL,
TotalValue AS (UnitPrice * Quantity) PERSISTED
);
-- Temporary table
CREATE TABLE #TempEmployees (
EmployeeID int,
FullName nvarchar(100)
);
-- Table variable
DECLARE @EmployeeTable TABLE (
EmployeeID int,
FullName nvarchar(100)
);
-- Partitioned table
CREATE PARTITION FUNCTION SalesDateRange (datetime2)
AS RANGE RIGHT FOR VALUES ('2022-01-01', '2023-01-01', '2024-01-01');
CREATE PARTITION SCHEME SalesDateScheme
AS PARTITION SalesDateRange
TO (Sales2021, Sales2022, Sales2023, Sales2024);
CREATE TABLE Sales (
SaleID int IDENTITY(1,1),
SaleDate datetime2,
Amount decimal(10,2),
CustomerID int
) ON SalesDateScheme(SaleDate);
```_
### Änderung der Tabellen
```sql
-- Add column
ALTER TABLE Employees ADD MiddleName nvarchar(50);
-- Modify column
ALTER TABLE Employees ALTER COLUMN Salary decimal(12,2);
-- Drop column
ALTER TABLE Employees DROP COLUMN MiddleName;
-- Add constraint
ALTER TABLE Employees ADD CONSTRAINT CK_Salary CHECK (Salary > 0);
-- Drop constraint
ALTER TABLE Employees DROP CONSTRAINT CK_Salary;
-- Add foreign key
ALTER TABLE Orders ADD CONSTRAINT FK_Orders_Customers
FOREIGN KEY (CustomerID) REFERENCES Customers(CustomerID);
-- Drop foreign key
ALTER TABLE Orders DROP CONSTRAINT FK_Orders_Customers;
-- Rename table
EXEC sp_rename 'OldTableName', 'NewTableName';
-- Rename column
EXEC sp_rename 'TableName.OldColumnName', 'NewColumnName', 'COLUMN';
-- Drop table
DROP TABLE Employees;
```_
### Angaben zur Tabelle
```sql
-- Describe table structure
SELECT
COLUMN_NAME,
DATA_TYPE,
CHARACTER_MAXIMUM_LENGTH,
IS_NULLABLE,
COLUMN_DEFAULT
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'Employees';
-- Show constraints
SELECT
CONSTRAINT_NAME,
CONSTRAINT_TYPE,
TABLE_NAME,
COLUMN_NAME
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc
LEFT JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE ccu
ON tc.CONSTRAINT_NAME = ccu.CONSTRAINT_NAME
WHERE tc.TABLE_NAME = 'Employees';
-- Show indexes
SELECT
i.name AS IndexName,
i.type_desc AS IndexType,
c.name AS ColumnName,
ic.key_ordinal AS KeyOrdinal
FROM sys.indexes i
JOIN sys.index_columns ic ON i.object_id = ic.object_id AND i.index_id = ic.index_id
JOIN sys.columns c ON ic.object_id = c.object_id AND ic.column_id = c.column_id
WHERE i.object_id = OBJECT_ID('Employees')
ORDER BY i.name, ic.key_ordinal;
-- Table size information
SELECT
t.name AS TableName,
p.rows AS RowCount,
SUM(a.total_pages) * 8 AS TotalSpaceKB,
SUM(a.used_pages) * 8 AS UsedSpaceKB,
(SUM(a.total_pages) - SUM(a.used_pages)) * 8 AS UnusedSpaceKB
FROM sys.tables t
JOIN sys.indexes i ON t.object_id = i.object_id
JOIN sys.partitions p ON i.object_id = p.object_id AND i.index_id = p.index_id
JOIN sys.allocation_units a ON p.partition_id = a.container_id
WHERE t.name = 'Employees'
GROUP BY t.name, p.rows;
```_
## Datentypen
### Numerische Datentypen
```sql
-- Integer types
bit -- 0, 1, or NULL
tinyint -- 0 to 255
smallint -- -32,768 to 32,767
int -- -2,147,483,648 to 2,147,483,647
bigint -- -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
-- Decimal types
decimal(p,s) -- Fixed precision and scale
numeric(p,s) -- Synonym for decimal
money -- -922,337,203,685,477.5808 to 922,337,203,685,477.5807
smallmoney -- -214,748.3648 to 214,748.3647
-- Floating point
float(n) -- Floating precision number
real -- 4-byte floating point
-- Examples
CREATE TABLE NumericExamples (
ID int IDENTITY(1,1) PRIMARY KEY,
Price decimal(10,2),
Quantity int,
IsActive bit,
LargeNumber bigint,
FloatValue float,
MoneyValue money
);
```_
### String-Datentypen
```sql
-- Character types
char(n) -- Fixed-length non-Unicode string
varchar(n) -- Variable-length non-Unicode string
varchar(max) -- Variable-length non-Unicode string (up to 2GB)
nchar(n) -- Fixed-length Unicode string
nvarchar(n) -- Variable-length Unicode string
nvarchar(max) -- Variable-length Unicode string (up to 2GB)
text -- Variable-length non-Unicode string (deprecated)
ntext -- Variable-length Unicode string (deprecated)
-- Binary types
binary(n) -- Fixed-length binary data
varbinary(n) -- Variable-length binary data
varbinary(max) -- Variable-length binary data (up to 2GB)
image -- Variable-length binary data (deprecated)
-- Examples
CREATE TABLE StringExamples (
ID int IDENTITY(1,1) PRIMARY KEY,
Code char(5),
Name nvarchar(100),
Description nvarchar(max),
BinaryData varbinary(max)
);
```_
### Datum und Uhrzeit
```sql
-- Date and time types
date -- Date only (0001-01-01 to 9999-12-31)
time -- Time only (00:00:00.0000000 to 23:59:59.9999999)
datetime -- Date and time (1753-01-01 to 9999-12-31)
datetime2 -- Date and time with higher precision
smalldatetime -- Date and time with minute precision
datetimeoffset -- Date and time with timezone offset
-- Examples
CREATE TABLE DateTimeExamples (
ID int IDENTITY(1,1) PRIMARY KEY,
BirthDate date,
StartTime time,
CreatedDateTime datetime,
PreciseDateTime datetime2(7),
SmallDateTime smalldatetime,
UTCDateTime datetimeoffset
);
-- Insert examples
INSERT INTO DateTimeExamples VALUES (
'1990-05-15',
'09:30:00',
'2023-12-01 14:30:25',
'2023-12-01 14:30:25.1234567',
'2023-12-01 14:30',
'2023-12-01 14:30:25 +05:30'
);
```_
### Sonstige Datentypen
```sql
-- Unique identifier
uniqueidentifier -- GUID
-- XML data type
xml -- XML documents
-- Spatial data types
geometry -- Planar spatial data
geography -- Ellipsoidal spatial data
-- JSON (SQL Server 2016+)
-- No native JSON type, use nvarchar(max) with JSON functions
-- Examples
CREATE TABLE OtherExamples (
ID int IDENTITY(1,1) PRIMARY KEY,
UniqueID uniqueidentifier DEFAULT NEWID(),
XMLData xml,
JSONData nvarchar(max),
Location geography
);
```_
## AUSRÜSTUNG Operationen
### Einsatzbereiche
```sql
-- Insert single row
INSERT INTO Employees (FirstName, LastName, Email, Salary, DepartmentID)
VALUES ('John', 'Doe', 'john.doe@company.com', 50000, 1);
-- Insert multiple rows
INSERT INTO Employees (FirstName, LastName, Email, Salary, DepartmentID)
VALUES
('Jane', 'Smith', 'jane.smith@company.com', 55000, 2),
('Bob', 'Johnson', 'bob.johnson@company.com', 48000, 1),
('Alice', 'Brown', 'alice.brown@company.com', 52000, 3);
-- Insert from SELECT
INSERT INTO EmployeeBackup (FirstName, LastName, Email, Salary)
SELECT FirstName, LastName, Email, Salary
FROM Employees
WHERE HireDate < '2020-01-01';
-- Insert with OUTPUT clause
INSERT INTO Employees (FirstName, LastName, Email, Salary, DepartmentID)
OUTPUT INSERTED.EmployeeID, INSERTED.FirstName, INSERTED.LastName
VALUES ('Charlie', 'Wilson', 'charlie.wilson@company.com', 60000, 2);
-- MERGE statement (UPSERT)
MERGE Employees AS target
USING (VALUES (1, 'John', 'Doe', 'john.doe@company.com', 55000))
AS source (EmployeeID, FirstName, LastName, Email, Salary)
ON target.EmployeeID = source.EmployeeID
WHEN MATCHED THEN
UPDATE SET Salary = source.Salary
WHEN NOT MATCHED THEN
INSERT (FirstName, LastName, Email, Salary)
VALUES (source.FirstName, source.LastName, source.Email, source.Salary);
```_
### Wählen Sie Operationen
```sql
-- Basic select
SELECT * FROM Employees;
-- Select specific columns
SELECT EmployeeID, FirstName, LastName, Salary FROM Employees;
-- Select with alias
SELECT EmployeeID AS ID, FirstName + ' ' + LastName AS FullName
FROM Employees;
-- Select with WHERE clause
SELECT * FROM Employees WHERE DepartmentID = 1;
SELECT * FROM Employees WHERE Salary BETWEEN 40000 AND 60000;
SELECT * FROM Employees WHERE FirstName LIKE 'J%';
SELECT * FROM Employees WHERE HireDate > '2020-01-01';
-- Select with ORDER BY
SELECT * FROM Employees ORDER BY Salary DESC;
SELECT * FROM Employees ORDER BY DepartmentID, Salary DESC;
-- Select with GROUP BY
SELECT DepartmentID, COUNT(*) AS EmployeeCount, AVG(Salary) AS AvgSalary
FROM Employees
GROUP BY DepartmentID;
-- Select with HAVING
SELECT DepartmentID, COUNT(*) AS EmployeeCount, AVG(Salary) AS AvgSalary
FROM Employees
GROUP BY DepartmentID
HAVING COUNT(*) > 5;
-- Select with TOP
SELECT TOP 10 * FROM Employees ORDER BY Salary DESC;
SELECT TOP 10 PERCENT * FROM Employees ORDER BY HireDate;
-- Select with OFFSET/FETCH (SQL Server 2012+)
SELECT * FROM Employees
ORDER BY EmployeeID
OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY;
-- Select with CTE
WITH HighEarners AS (
SELECT * FROM Employees WHERE Salary > 50000
)
SELECT * FROM HighEarners WHERE DepartmentID = 1;
```_
### Aktualisierung der Operationen
```sql
-- Update single row
UPDATE Employees
SET Salary = 55000
WHERE EmployeeID = 1;
-- Update multiple columns
UPDATE Employees
SET Salary = Salary * 1.1,
LastName = 'Smith-Johnson'
WHERE EmployeeID = 2;
-- Update with JOIN
UPDATE e
SET e.Salary = e.Salary * 1.05
FROM Employees e
JOIN Departments d ON e.DepartmentID = d.DepartmentID
WHERE d.DepartmentName = 'IT';
-- Update with OUTPUT clause
UPDATE Employees
SET Salary = Salary * 1.1
OUTPUT DELETED.EmployeeID, DELETED.Salary AS OldSalary,
INSERTED.Salary AS NewSalary
WHERE DepartmentID = 1;
-- Update with subquery
UPDATE Employees
SET Salary = (SELECT AVG(Salary) FROM Employees WHERE DepartmentID = Employees.DepartmentID)
WHERE Salary IS NULL;
```_
### Löschen von Operationen
```sql
-- Delete specific rows
DELETE FROM Employees WHERE EmployeeID = 1;
-- Delete with conditions
DELETE FROM Employees WHERE HireDate < '2010-01-01';
-- Delete with JOIN
DELETE e
FROM Employees e
JOIN Departments d ON e.DepartmentID = d.DepartmentID
WHERE d.DepartmentName = 'Temp';
-- Delete with OUTPUT clause
DELETE FROM Employees
OUTPUT DELETED.EmployeeID, DELETED.FirstName, DELETED.LastName
WHERE DepartmentID = 5;
-- Delete all rows
DELETE FROM Employees;
-- Truncate table (faster than DELETE)
TRUNCATE TABLE Employees;
```_
## Abfrage von Operationen
### Mitglieder
```sql
-- Inner join
SELECT e.FirstName, e.LastName, d.DepartmentName
FROM Employees e
INNER JOIN Departments d ON e.DepartmentID = d.DepartmentID;
-- Left outer join
SELECT e.FirstName, e.LastName, d.DepartmentName
FROM Employees e
LEFT OUTER JOIN Departments d ON e.DepartmentID = d.DepartmentID;
-- Right outer join
SELECT e.FirstName, e.LastName, d.DepartmentName
FROM Employees e
RIGHT OUTER JOIN Departments d ON e.DepartmentID = d.DepartmentID;
-- Full outer join
SELECT e.FirstName, e.LastName, d.DepartmentName
FROM Employees e
FULL OUTER JOIN Departments d ON e.DepartmentID = d.DepartmentID;
-- Cross join
SELECT e.FirstName, d.DepartmentName
FROM Employees e
CROSS JOIN Departments d;
-- Self join
SELECT e1.FirstName + ' ' + e1.LastName AS Employee,
e2.FirstName + ' ' + e2.LastName AS Manager
FROM Employees e1
LEFT JOIN Employees e2 ON e1.ManagerID = e2.EmployeeID;
```_
### Subques
```sql
-- Subquery in WHERE clause
SELECT * FROM Employees
WHERE Salary > (SELECT AVG(Salary) FROM Employees);
-- Subquery with IN
SELECT * FROM Employees
WHERE DepartmentID IN (SELECT DepartmentID FROM Departments WHERE Location = 'New York');
-- Subquery with EXISTS
SELECT * FROM Employees e
WHERE EXISTS (SELECT 1 FROM Orders o WHERE o.EmployeeID = e.EmployeeID);
-- Correlated subquery
SELECT * FROM Employees e1
WHERE Salary > (SELECT AVG(Salary) FROM Employees e2 WHERE e2.DepartmentID = e1.DepartmentID);
-- Subquery in SELECT clause
SELECT EmployeeID, FirstName, LastName,
(SELECT DepartmentName FROM Departments d WHERE d.DepartmentID = e.DepartmentID) AS DeptName
FROM Employees e;
-- Subquery in FROM clause
SELECT DeptName, AvgSalary
FROM (SELECT d.DepartmentName AS DeptName, AVG(e.Salary) AS AvgSalary
FROM Employees e
JOIN Departments d ON e.DepartmentID = d.DepartmentID
GROUP BY d.DepartmentName) AS DeptAvg;
```_
### Fensterfunktionen
```sql
-- ROW_NUMBER
SELECT EmployeeID, FirstName, LastName, Salary,
ROW_NUMBER() OVER (ORDER BY Salary DESC) AS RowNum
FROM Employees;
-- RANK and DENSE_RANK
SELECT EmployeeID, FirstName, LastName, Salary,
RANK() OVER (ORDER BY Salary DESC) AS Rank,
DENSE_RANK() OVER (ORDER BY Salary DESC) AS DenseRank
FROM Employees;
-- PARTITION BY
SELECT EmployeeID, FirstName, LastName, DepartmentID, Salary,
ROW_NUMBER() OVER (PARTITION BY DepartmentID ORDER BY Salary DESC) AS DeptRank
FROM Employees;
-- LAG and LEAD
SELECT EmployeeID, HireDate, Salary,
LAG(Salary, 1) OVER (ORDER BY HireDate) AS PrevSalary,
LEAD(Salary, 1) OVER (ORDER BY HireDate) AS NextSalary
FROM Employees;
-- FIRST_VALUE and LAST_VALUE
SELECT EmployeeID, DepartmentID, Salary,
FIRST_VALUE(Salary) OVER (PARTITION BY DepartmentID ORDER BY Salary) AS MinSalary,
LAST_VALUE(Salary) OVER (PARTITION BY DepartmentID ORDER BY Salary
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS MaxSalary
FROM Employees;
-- Running totals
SELECT EmployeeID, HireDate, Salary,
SUM(Salary) OVER (ORDER BY HireDate ROWS UNBOUNDED PRECEDING) AS RunningTotal
FROM Employees;
-- Moving averages
SELECT EmployeeID, HireDate, Salary,
AVG(Salary) OVER (ORDER BY HireDate ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS MovingAvg
FROM Employees;
```_
### Gemeinsame Tabellenausdrücke (CTE)
```sql
-- Basic CTE
WITH HighEarners AS (
SELECT * FROM Employees WHERE Salary > 50000
)
SELECT * FROM HighEarners WHERE DepartmentID = 1;
-- Recursive CTE
WITH EmployeeHierarchy AS (
-- Anchor member
SELECT EmployeeID, FirstName, LastName, ManagerID, 1 AS Level
FROM Employees
WHERE ManagerID IS NULL
UNION ALL
-- Recursive member
SELECT e.EmployeeID, e.FirstName, e.LastName, e.ManagerID, eh.Level + 1
FROM Employees e
INNER JOIN EmployeeHierarchy eh ON e.ManagerID = eh.EmployeeID
)
SELECT * FROM EmployeeHierarchy;
-- Multiple CTEs
WITH
DeptAvg AS (
SELECT DepartmentID, AVG(Salary) AS AvgSalary
FROM Employees
GROUP BY DepartmentID
),
HighPerformers AS (
SELECT e.*, da.AvgSalary
FROM Employees e
JOIN DeptAvg da ON e.DepartmentID = da.DepartmentID
WHERE e.Salary > da.AvgSalary
)
SELECT * FROM HighPerformers;
```_
## Index
### Indexe erstellen
```sql
-- Simple index
CREATE INDEX IX_Employees_LastName ON Employees(LastName);
-- Composite index
CREATE INDEX IX_Employees_Dept_Salary ON Employees(DepartmentID, Salary);
-- Unique index
CREATE UNIQUE INDEX IX_Employees_Email ON Employees(Email);
-- Clustered index (only one per table)
CREATE CLUSTERED INDEX IX_Employees_EmployeeID ON Employees(EmployeeID);
-- Non-clustered index
CREATE NONCLUSTERED INDEX IX_Employees_HireDate ON Employees(HireDate);
-- Filtered index
CREATE INDEX IX_Employees_Active ON Employees(EmployeeID)
WHERE IsActive = 1;
-- Included columns
CREATE INDEX IX_Employees_Dept_Incl ON Employees(DepartmentID)
INCLUDE (FirstName, LastName, Salary);
-- Columnstore index
CREATE COLUMNSTORE INDEX IX_Sales_Columnstore ON Sales;
-- XML index
CREATE PRIMARY XML INDEX IX_Products_XML ON Products(XMLData);
```_
### Index verwalten
```sql
-- Show indexes
SELECT
i.name AS IndexName,
i.type_desc AS IndexType,
i.is_unique,
i.is_primary_key,
c.name AS ColumnName
FROM sys.indexes i
JOIN sys.index_columns ic ON i.object_id = ic.object_id AND i.index_id = ic.index_id
JOIN sys.columns c ON ic.object_id = c.object_id AND ic.column_id = c.column_id
WHERE i.object_id = OBJECT_ID('Employees')
ORDER BY i.name, ic.key_ordinal;
-- Index usage statistics
SELECT
i.name AS IndexName,
s.user_seeks,
s.user_scans,
s.user_lookups,
s.user_updates
FROM sys.indexes i
LEFT JOIN sys.dm_db_index_usage_stats s
ON i.object_id = s.object_id AND i.index_id = s.index_id
WHERE i.object_id = OBJECT_ID('Employees');
-- Rebuild index
ALTER INDEX IX_Employees_LastName ON Employees REBUILD;
-- Reorganize index
ALTER INDEX IX_Employees_LastName ON Employees REORGANIZE;
-- Disable index
ALTER INDEX IX_Employees_LastName ON Employees DISABLE;
-- Drop index
DROP INDEX IX_Employees_LastName ON Employees;
-- Update statistics
UPDATE STATISTICS Employees;
UPDATE STATISTICS Employees IX_Employees_LastName;
```_
## Ansichten
### Ansichten erstellen
```sql
-- Simple view
CREATE VIEW vw_ActiveEmployees AS
SELECT EmployeeID, FirstName, LastName, Email, DepartmentID
FROM Employees
WHERE IsActive = 1;
-- Complex view with joins
CREATE VIEW vw_EmployeeDepartment AS
SELECT
e.EmployeeID,
e.FirstName,
e.LastName,
e.Salary,
d.DepartmentName,
d.Location
FROM Employees e
JOIN Departments d ON e.DepartmentID = d.DepartmentID;
-- View with aggregation
CREATE VIEW vw_DepartmentSummary AS
SELECT
d.DepartmentName,
COUNT(e.EmployeeID) AS EmployeeCount,
AVG(e.Salary) AS AvgSalary,
MAX(e.Salary) AS MaxSalary,
MIN(e.Salary) AS MinSalary
FROM Departments d
LEFT JOIN Employees e ON d.DepartmentID = e.DepartmentID
GROUP BY d.DepartmentName;
-- Indexed view (materialized view)
CREATE VIEW vw_SalesSummary
WITH SCHEMABINDING
AS
SELECT
ProductID,
COUNT_BIG(*) AS SalesCount,
SUM(Quantity) AS TotalQuantity,
SUM(Amount) AS TotalAmount
FROM dbo.Sales
GROUP BY ProductID;
CREATE UNIQUE CLUSTERED INDEX IX_SalesSummary ON vw_SalesSummary(ProductID);
```_
### Verwaltung von Ansichten
```sql
-- Show views
SELECT TABLE_NAME, VIEW_DEFINITION
FROM INFORMATION_SCHEMA.VIEWS;
-- Show view definition
SELECT OBJECT_DEFINITION(OBJECT_ID('vw_ActiveEmployees'));
-- Alter view
ALTER VIEW vw_ActiveEmployees AS
SELECT EmployeeID, FirstName, LastName, Email, DepartmentID, Salary
FROM Employees
WHERE IsActive = 1;
-- Drop view
DROP VIEW vw_ActiveEmployees;
-- Update through view (if updatable)
UPDATE vw_ActiveEmployees
SET Salary = 60000
WHERE EmployeeID = 1;
```_
## Gespeicherte Verfahren
### Erstellung gespeicherter Verfahren
```sql
-- Simple stored procedure
CREATE PROCEDURE GetEmployeeCount
AS
BEGIN
SELECT COUNT(*) AS EmployeeCount FROM Employees;
END;
-- Procedure with parameters
CREATE PROCEDURE GetEmployeesByDepartment
@DepartmentID int
AS
BEGIN
SELECT * FROM Employees WHERE DepartmentID = @DepartmentID;
END;
-- Procedure with input and output parameters
CREATE PROCEDURE GetEmployeeStats
@DepartmentID int,
@EmployeeCount int OUTPUT,
@AvgSalary decimal(10,2) OUTPUT
AS
BEGIN
SELECT
@EmployeeCount = COUNT(*),
@AvgSalary = AVG(Salary)
FROM Employees
WHERE DepartmentID = @DepartmentID;
END;
-- Procedure with error handling
CREATE PROCEDURE UpdateEmployeeSalary
@EmployeeID int,
@NewSalary decimal(10,2)
AS
BEGIN
SET NOCOUNT ON;
BEGIN TRY
BEGIN TRANSACTION;
IF NOT EXISTS (SELECT 1 FROM Employees WHERE EmployeeID = @EmployeeID)
BEGIN
RAISERROR('Employee not found', 16, 1);
RETURN;
END;
UPDATE Employees
SET Salary = @NewSalary
WHERE EmployeeID = @EmployeeID;
COMMIT TRANSACTION;
SELECT 'Salary updated successfully' AS Message;
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0
ROLLBACK TRANSACTION;
DECLARE @ErrorMessage nvarchar(4000) = ERROR_MESSAGE();
DECLARE @ErrorSeverity int = ERROR_SEVERITY();
DECLARE @ErrorState int = ERROR_STATE();
RAISERROR(@ErrorMessage, @ErrorSeverity, @ErrorState);
END CATCH;
END;
```_
### Calling Stored Procedures
```sql
-- Call simple procedure
EXEC GetEmployeeCount;
-- Call procedure with parameters
EXEC GetEmployeesByDepartment @DepartmentID = 1;
-- Call procedure with output parameters
DECLARE @Count int, @AvgSal decimal(10,2);
EXEC GetEmployeeStats
@DepartmentID = 1,
@EmployeeCount = @Count OUTPUT,
@AvgSalary = @AvgSal OUTPUT;
SELECT @Count AS EmployeeCount, @AvgSal AS AverageSalary;
-- Call procedure with error handling
BEGIN TRY
EXEC UpdateEmployeeSalary @EmployeeID = 1, @NewSalary = 65000;
END TRY
BEGIN CATCH
SELECT ERROR_MESSAGE() AS ErrorMessage;
END CATCH;
```_
### Verwaltung gespeicherter Verfahren
```sql
-- Show stored procedures
SELECT name, create_date, modify_date
FROM sys.procedures;
-- Show procedure definition
SELECT OBJECT_DEFINITION(OBJECT_ID('GetEmployeeCount'));
-- Alter stored procedure
ALTER PROCEDURE GetEmployeeCount
AS
BEGIN
SELECT COUNT(*) AS TotalEmployees,
COUNT(CASE WHEN IsActive = 1 THEN 1 END) AS ActiveEmployees
FROM Employees;
END;
-- Drop stored procedure
DROP PROCEDURE GetEmployeeCount;
```_
## Funktionen
### Funktionen erstellen
```sql
-- Scalar function
CREATE FUNCTION GetFullName(@FirstName nvarchar(50), @LastName nvarchar(50))
RETURNS nvarchar(101)
AS
BEGIN
RETURN @FirstName + ' ' + @LastName;
END;
-- Inline table-valued function
CREATE FUNCTION GetEmployeesByDept(@DepartmentID int)
RETURNS TABLE
AS
RETURN
(
SELECT EmployeeID, FirstName, LastName, Salary
FROM Employees
WHERE DepartmentID = @DepartmentID
);
-- Multi-statement table-valued function
CREATE FUNCTION GetEmployeeSummary(@DepartmentID int)
RETURNS @EmployeeTable TABLE
(
EmployeeID int,
FullName nvarchar(101),
Salary decimal(10,2),
SalaryGrade nvarchar(10)
)
AS
BEGIN
INSERT INTO @EmployeeTable
SELECT
EmployeeID,
FirstName + ' ' + LastName,
Salary,
CASE
WHEN Salary >= 60000 THEN 'High'
WHEN Salary >= 40000 THEN 'Medium'
ELSE 'Low'
END
FROM Employees
WHERE DepartmentID = @DepartmentID;
RETURN;
END;
-- Function with complex logic
CREATE FUNCTION CalculateBonus(@EmployeeID int, @BonusPercent decimal(5,2))
RETURNS decimal(10,2)
AS
BEGIN
DECLARE @Salary decimal(10,2);
DECLARE @YearsOfService int;
DECLARE @Bonus decimal(10,2);
SELECT @Salary = Salary, @YearsOfService = DATEDIFF(YEAR, HireDate, GETDATE())
FROM Employees
WHERE EmployeeID = @EmployeeID;
IF @YearsOfService >= 10
SET @Bonus = @Salary * (@BonusPercent * 1.5) / 100;
ELSE IF @YearsOfService >= 5
SET @Bonus = @Salary * (@BonusPercent * 1.2) / 100;
ELSE
SET @Bonus = @Salary * @BonusPercent / 100;
RETURN @Bonus;
END;
```_
### Funktionen nutzen
```sql
-- Use scalar function
SELECT EmployeeID, dbo.GetFullName(FirstName, LastName) AS FullName
FROM Employees;
-- Use inline table-valued function
SELECT * FROM dbo.GetEmployeesByDept(1);
-- Use multi-statement table-valued function
SELECT * FROM dbo.GetEmployeeSummary(2);
-- Use function in WHERE clause
SELECT * FROM Employees
WHERE dbo.CalculateBonus(EmployeeID, 10) > 5000;
```_
### Funktionen verwalten
```sql
-- Show functions
SELECT name, type_desc, create_date, modify_date
FROM sys.objects
WHERE type IN ('FN', 'IF', 'TF');
-- Show function definition
SELECT OBJECT_DEFINITION(OBJECT_ID('GetFullName'));
-- Alter function
ALTER FUNCTION GetFullName(@FirstName nvarchar(50), @LastName nvarchar(50))
RETURNS nvarchar(101)
AS
BEGIN
RETURN ISNULL(@FirstName, '') + ' ' + ISNULL(@LastName, '');
END;
-- Drop function
DROP FUNCTION GetFullName;
```_
## Auslöser
### Trigger erstellen
```sql
-- AFTER INSERT trigger
CREATE TRIGGER trg_Employee_Insert
ON Employees
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO EmployeeAudit (EmployeeID, Action, ActionDate, ActionBy)
SELECT EmployeeID, 'INSERT', GETDATE(), SYSTEM_USER
FROM inserted;
END;
-- AFTER UPDATE trigger
CREATE TRIGGER trg_Employee_Update
ON Employees
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
IF UPDATE(Salary)
BEGIN
INSERT INTO SalaryHistory (EmployeeID, OldSalary, NewSalary, ChangeDate, ChangedBy)
SELECT
i.EmployeeID,
d.Salary,
i.Salary,
GETDATE(),
SYSTEM_USER
FROM inserted i
JOIN deleted d ON i.EmployeeID = d.EmployeeID
WHERE i.Salary != d.Salary;
END;
END;
-- INSTEAD OF trigger (for views)
CREATE TRIGGER trg_EmployeeView_Insert
ON vw_EmployeeDepartment
INSTEAD OF INSERT
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO Employees (FirstName, LastName, Email, DepartmentID)
SELECT FirstName, LastName, Email,
(SELECT DepartmentID FROM Departments WHERE DepartmentName = inserted.DepartmentName)
FROM inserted;
END;
-- DDL trigger
CREATE TRIGGER trg_DatabaseChanges
ON DATABASE
FOR CREATE_TABLE, ALTER_TABLE, DROP_TABLE
AS
BEGIN
SET NOCOUNT ON;
DECLARE @EventData xml = EVENTDATA();
INSERT INTO DDLAudit (EventType, ObjectName, LoginName, EventDate, EventData)
VALUES (
@EventData.value('(/EVENT_INSTANCE/EventType)[1]', 'nvarchar(100)'),
@EventData.value('(/EVENT_INSTANCE/ObjectName)[1]', 'nvarchar(100)'),
@EventData.value('(/EVENT_INSTANCE/LoginName)[1]', 'nvarchar(100)'),
GETDATE(),
@EventData
);
END;
```_
### Verwaltung von Triggern
```sql
-- Show triggers
SELECT
t.name AS TriggerName,
o.name AS TableName,
t.type_desc,
t.is_disabled
FROM sys.triggers t
JOIN sys.objects o ON t.parent_id = o.object_id;
-- Show trigger definition
SELECT OBJECT_DEFINITION(OBJECT_ID('trg_Employee_Insert'));
-- Enable/disable trigger
DISABLE TRIGGER trg_Employee_Insert ON Employees;
ENABLE TRIGGER trg_Employee_Insert ON Employees;
-- Drop trigger
DROP TRIGGER trg_Employee_Insert;
```_
## Transaktionen
### Transaction Control
```sql
-- Basic transaction
BEGIN TRANSACTION;
INSERT INTO Employees (FirstName, LastName, Email, DepartmentID)
VALUES ('Test', 'User', 'test@company.com', 1);
UPDATE Employees SET Salary = 50000 WHERE EmployeeID = SCOPE_IDENTITY();
COMMIT TRANSACTION;
-- Transaction with rollback
BEGIN TRANSACTION;
INSERT INTO Employees (FirstName, LastName, Email, DepartmentID)
VALUES ('Test', 'User2', 'test2@company.com', 1);
-- Simulate error condition
IF @@ERROR != 0
BEGIN
ROLLBACK TRANSACTION;
RETURN;
END;
COMMIT TRANSACTION;
-- Named transaction with savepoint
BEGIN TRANSACTION MainTransaction;
INSERT INTO Employees (FirstName, LastName, Email, DepartmentID)
VALUES ('Test', 'User3', 'test3@company.com', 1);
SAVE TRANSACTION SavePoint1;
UPDATE Employees SET Salary = 60000 WHERE FirstName = 'Test';
-- Rollback to savepoint
ROLLBACK TRANSACTION SavePoint1;
COMMIT TRANSACTION MainTransaction;
```_
### Transaction Isolation Levels
```sql
-- Set isolation level
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SET TRANSACTION ISOLATION LEVEL SNAPSHOT;
-- Table hints for specific queries
SELECT * FROM Employees WITH (NOLOCK);
SELECT * FROM Employees WITH (READPAST);
SELECT * FROM Employees WITH (UPDLOCK);
SELECT * FROM Employees WITH (XLOCK);
```_
### Fehlerbehandlung bei Transaktionen
```sql
-- TRY-CATCH with transactions
BEGIN TRY
BEGIN TRANSACTION;
INSERT INTO Employees (FirstName, LastName, Email, DepartmentID)
VALUES ('John', 'Doe', 'john.doe@company.com', 1);
UPDATE Employees SET Salary = 50000 WHERE EmployeeID = SCOPE_IDENTITY();
-- Simulate error
DECLARE @Error int = 1/0;
COMMIT TRANSACTION;
SELECT 'Transaction completed successfully' AS Message;
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0
ROLLBACK TRANSACTION;
SELECT
ERROR_NUMBER() AS ErrorNumber,
ERROR_MESSAGE() AS ErrorMessage,
ERROR_SEVERITY() AS ErrorSeverity,
ERROR_STATE() AS ErrorState,
ERROR_PROCEDURE() AS ErrorProcedure,
ERROR_LINE() AS ErrorLine;
END CATCH;
```_
## T-SQL Programmierung
### Variablen und Datentypen
```sql
-- Declare variables
DECLARE @EmployeeID int;
DECLARE @FirstName nvarchar(50);
DECLARE @Salary decimal(10,2) = 50000;
DECLARE @HireDate datetime = GETDATE();
-- Set variable values
SET @EmployeeID = 1;
SET @FirstName = 'John';
-- Set from query
SELECT @FirstName = FirstName FROM Employees WHERE EmployeeID = @EmployeeID;
-- Table variables
DECLARE @EmployeeTable TABLE (
EmployeeID int,
FullName nvarchar(101),
Salary decimal(10,2)
);
INSERT INTO @EmployeeTable
SELECT EmployeeID, FirstName + ' ' + LastName, Salary
FROM Employees
WHERE DepartmentID = 1;
SELECT * FROM @EmployeeTable;
```_
### Steuerstrom
```sql
-- IF-ELSE
DECLARE @Salary decimal(10,2) = 55000;
IF @Salary > 50000
PRINT 'High salary';
ELSE IF @Salary > 30000
PRINT 'Medium salary';
ELSE
PRINT 'Low salary';
-- CASE statement
SELECT
EmployeeID,
FirstName,
LastName,
Salary,
CASE
WHEN Salary >= 60000 THEN 'High'
WHEN Salary >= 40000 THEN 'Medium'
ELSE 'Low'
END AS SalaryGrade
FROM Employees;
-- WHILE loop
DECLARE @Counter int = 1;
WHILE @Counter <= 10
BEGIN
PRINT 'Counter: ' + CAST(@Counter AS nvarchar(10));
SET @Counter = @Counter + 1;
IF @Counter = 5
BREAK;
END;
-- FOR loop (using CTE)
WITH Numbers AS (
SELECT 1 AS Number
UNION ALL
SELECT Number + 1
FROM Numbers
WHERE Number < 10
)
SELECT Number FROM Numbers;
```_
### Kuratoren
```sql
-- Declare cursor
DECLARE employee_cursor CURSOR FOR
SELECT EmployeeID, FirstName, LastName, Salary
FROM Employees
WHERE DepartmentID = 1;
-- Variables for cursor
DECLARE @EmpID int, @FName nvarchar(50), @LName nvarchar(50), @Sal decimal(10,2);
-- Open cursor
OPEN employee_cursor;
-- Fetch first row
FETCH NEXT FROM employee_cursor INTO @EmpID, @FName, @LName, @Sal;
-- Loop through cursor
WHILE @@FETCH_STATUS = 0
BEGIN
PRINT 'Employee: ' + @FName + ' ' + @LName + ', Salary: ' + CAST(@Sal AS nvarchar(20));
-- Fetch next row
FETCH NEXT FROM employee_cursor INTO @EmpID, @FName, @LName, @Sal;
END;
-- Close and deallocate cursor
CLOSE employee_cursor;
DEALLOCATE employee_cursor;
```_
### Dynamischer SQL
```sql
-- Simple dynamic SQL
DECLARE @SQL nvarchar(max);
DECLARE @TableName nvarchar(50) = 'Employees';
SET @SQL = 'SELECT COUNT(*) FROM ' + @TableName;
EXEC sp_executesql @SQL;
-- Dynamic SQL with parameters
DECLARE @SQL nvarchar(max);
DECLARE @DeptID int = 1;
SET @SQL = 'SELECT * FROM Employees WHERE DepartmentID = @DepartmentID';
EXEC sp_executesql @SQL, N'@DepartmentID int', @DepartmentID = @DeptID;
-- Building complex dynamic SQL
DECLARE @SQL nvarchar(max) = 'SELECT EmployeeID, FirstName, LastName';
DECLARE @IncludeSalary bit = 1;
DECLARE @DepartmentFilter int = NULL;
IF @IncludeSalary = 1
SET @SQL = @SQL + ', Salary';
SET @SQL = @SQL + ' FROM Employees';
IF @DepartmentFilter IS NOT NULL
SET @SQL = @SQL + ' WHERE DepartmentID = ' + CAST(@DepartmentFilter AS nvarchar(10));
PRINT @SQL;
EXEC sp_executesql @SQL;
```_
## Backup und Recovery
### Vollständige Sicherung
```sql
-- Full database backup
BACKUP DATABASE MyDatabase
TO DISK = 'C:\Backup\MyDatabase_Full.bak'
WITH FORMAT, INIT, COMPRESSION, STATS = 10;
-- Full backup with multiple files
BACKUP DATABASE MyDatabase
TO DISK = 'C:\Backup\MyDatabase_Full_1.bak',
DISK = 'C:\Backup\MyDatabase_Full_2.bak'
WITH FORMAT, INIT, COMPRESSION;
-- Full backup to URL (Azure)
BACKUP DATABASE MyDatabase
TO URL = 'https://mystorageaccount.blob.core.windows.net/backups/MyDatabase_Full.bak'
WITH CREDENTIAL = 'MyAzureCredential', COMPRESSION;
```_
### Differenzielle und Log-Backups
```sql
-- Differential backup
BACKUP DATABASE MyDatabase
TO DISK = 'C:\Backup\MyDatabase_Diff.bak'
WITH DIFFERENTIAL, COMPRESSION, STATS = 10;
-- Transaction log backup
BACKUP LOG MyDatabase
TO DISK = 'C:\Backup\MyDatabase_Log.trn'
WITH COMPRESSION, STATS = 10;
-- Backup verification
RESTORE VERIFYONLY
FROM DISK = 'C:\Backup\MyDatabase_Full.bak';
```_
### Restore Operationen
```sql
-- Full restore
RESTORE DATABASE MyDatabase
FROM DISK = 'C:\Backup\MyDatabase_Full.bak'
WITH REPLACE, NORECOVERY, STATS = 10;
-- Restore differential backup
RESTORE DATABASE MyDatabase
FROM DISK = 'C:\Backup\MyDatabase_Diff.bak'
WITH NORECOVERY, STATS = 10;
-- Restore log backup
RESTORE LOG MyDatabase
FROM DISK = 'C:\Backup\MyDatabase_Log.trn'
WITH RECOVERY, STATS = 10;
-- Point-in-time restore
RESTORE DATABASE MyDatabase
FROM DISK = 'C:\Backup\MyDatabase_Full.bak'
WITH REPLACE, NORECOVERY;
RESTORE LOG MyDatabase
FROM DISK = 'C:\Backup\MyDatabase_Log.trn'
WITH STOPAT = '2023-12-01 14:30:00', RECOVERY;
-- Restore to different database
RESTORE DATABASE MyDatabase_Test
FROM DISK = 'C:\Backup\MyDatabase_Full.bak'
WITH MOVE 'MyDatabase_Data' TO 'C:\Data\MyDatabase_Test.mdf',
MOVE 'MyDatabase_Log' TO 'C:\Data\MyDatabase_Test.ldf',
REPLACE;
```_
### Backup-Informationen
```sql
-- Show backup history
SELECT
bs.database_name,
bs.backup_start_date,
bs.backup_finish_date,
bs.type,
bs.backup_size / 1024 / 1024 AS backup_size_mb,
bmf.physical_device_name
FROM msdb.dbo.backupset bs
JOIN msdb.dbo.backupmediafamily bmf ON bs.media_set_id = bmf.media_set_id
WHERE bs.database_name = 'MyDatabase'
ORDER BY bs.backup_start_date DESC;
-- Show restore history
SELECT
rh.destination_database_name,
rh.restore_date,
rh.restore_type,
bs.backup_start_date,
bmf.physical_device_name
FROM msdb.dbo.restorehistory rh
JOIN msdb.dbo.backupset bs ON rh.backup_set_id = bs.backup_set_id
JOIN msdb.dbo.backupmediafamily bmf ON bs.media_set_id = bmf.media_set_id
WHERE rh.destination_database_name = 'MyDatabase'
ORDER BY rh.restore_date DESC;
```_
## Leistung Tuning
### Abrufleistung
```sql
-- Show execution plan
SET SHOWPLAN_ALL ON;
SELECT * FROM Employees WHERE DepartmentID = 1;
SET SHOWPLAN_ALL OFF;
-- Include actual execution plan
SET STATISTICS IO ON;
SET STATISTICS TIME ON;
SELECT * FROM Employees WHERE DepartmentID = 1;
SET STATISTICS IO OFF;
SET STATISTICS TIME OFF;
-- Query hints
SELECT * FROM Employees WITH (INDEX(IX_Employees_DepartmentID))
WHERE DepartmentID = 1;
SELECT * FROM Employees
WHERE DepartmentID = 1
OPTION (RECOMPILE);
-- Plan guides
EXEC sp_create_plan_guide
@name = N'Guide1',
@stmt = N'SELECT * FROM Employees WHERE DepartmentID = @DeptID',
@type = N'TEMPLATE',
@module_or_batch = NULL,
@params = N'@DeptID int',
@hints = N'OPTION (PARAMETERIZATION FORCED)';
```_
### Indexanalyse
```sql
-- Missing indexes
SELECT
mid.statement AS TableName,
migs.avg_total_user_cost * (migs.avg_user_impact / 100.0) * (migs.user_seeks + migs.user_scans) AS improvement_measure,
'CREATE INDEX IX_' + REPLACE(REPLACE(REPLACE(mid.statement, '[', ''), ']', ''), '.', '_') + '_' +
REPLACE(REPLACE(mid.equality_columns + ISNULL('_' + mid.inequality_columns, ''), '[', ''), ']', '') +
' ON ' + mid.statement + ' (' + ISNULL(mid.equality_columns, '') +
CASE WHEN mid.inequality_columns IS NOT NULL AND mid.equality_columns IS NOT NULL THEN ',' ELSE '' END +
ISNULL(mid.inequality_columns, '') + ')' +
ISNULL(' INCLUDE (' + mid.included_columns + ')', '') AS create_index_statement
FROM sys.dm_db_missing_index_groups mig
JOIN sys.dm_db_missing_index_group_stats migs ON migs.group_handle = mig.index_group_handle
JOIN sys.dm_db_missing_index_details mid ON mig.index_handle = mid.index_handle
WHERE migs.avg_total_user_cost * (migs.avg_user_impact / 100.0) * (migs.user_seeks + migs.user_scans) > 10
ORDER BY improvement_measure DESC;
-- Unused indexes
SELECT
i.name AS IndexName,
o.name AS TableName,
i.type_desc,
s.user_seeks,
s.user_scans,
s.user_lookups,
s.user_updates
FROM sys.indexes i
JOIN sys.objects o ON i.object_id = o.object_id
LEFT JOIN sys.dm_db_index_usage_stats s ON i.object_id = s.object_id AND i.index_id = s.index_id
WHERE o.type = 'U'
AND i.index_id > 0
AND (s.user_seeks + s.user_scans + s.user_lookups) = 0
ORDER BY o.name, i.name;
-- Index fragmentation
SELECT
OBJECT_NAME(ips.object_id) AS TableName,
i.name AS IndexName,
ips.index_type_desc,
ips.avg_fragmentation_in_percent,
ips.page_count
FROM sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, 'LIMITED') ips
JOIN sys.indexes i ON ips.object_id = i.object_id AND ips.index_id = i.index_id
WHERE ips.avg_fragmentation_in_percent > 10
AND ips.page_count > 1000
ORDER BY ips.avg_fragmentation_in_percent DESC;
```_
### Web-Shop
```sql
-- Enable Query Store
ALTER DATABASE MyDatabase SET QUERY_STORE = ON;
-- Configure Query Store
ALTER DATABASE MyDatabase SET QUERY_STORE (
OPERATION_MODE = READ_WRITE,
CLEANUP_POLICY = (STALE_QUERY_THRESHOLD_DAYS = 30),
DATA_FLUSH_INTERVAL_SECONDS = 900,
MAX_STORAGE_SIZE_MB = 1000,
INTERVAL_LENGTH_MINUTES = 60
);
-- Top resource consuming queries
SELECT
qsq.query_id,
qsqt.query_sql_text,
qsrs.avg_duration / 1000 AS avg_duration_ms,
qsrs.avg_cpu_time / 1000 AS avg_cpu_time_ms,
qsrs.avg_logical_io_reads,
qsrs.count_executions
FROM sys.query_store_query qsq
JOIN sys.query_store_query_text qsqt ON qsq.query_text_id = qsqt.query_text_id
JOIN sys.query_store_plan qsp ON qsq.query_id = qsp.query_id
JOIN sys.query_store_runtime_stats qsrs ON qsp.plan_id = qsrs.plan_id
WHERE qsrs.last_execution_time > DATEADD(day, -7, GETDATE())
ORDER BY qsrs.avg_duration DESC;
-- Clear Query Store
ALTER DATABASE MyDatabase SET QUERY_STORE CLEAR;
```_
## Überwachung
### Systeminformationen
```sql
-- Server information
SELECT
@@SERVERNAME AS ServerName,
@@VERSION AS Version,
SERVERPROPERTY('ProductVersion') AS ProductVersion,
SERVERPROPERTY('ProductLevel') AS ProductLevel,
SERVERPROPERTY('Edition') AS Edition,
SERVERPROPERTY('MachineName') AS MachineName;
-- Database information
SELECT
name AS DatabaseName,
database_id,
create_date,
state_desc AS State,
recovery_model_desc AS RecoveryModel,
collation_name AS Collation
FROM sys.databases;
-- Active connections
SELECT
s.session_id,
s.login_name,
s.host_name,
s.program_name,
s.status,
s.last_request_start_time,
r.command,
r.wait_type,
r.wait_time,
r.blocking_session_id
FROM sys.dm_exec_sessions s
LEFT JOIN sys.dm_exec_requests r ON s.session_id = r.session_id
WHERE s.is_user_process = 1;
-- Blocking sessions
SELECT
blocking.session_id AS blocking_session_id,
blocked.session_id AS blocked_session_id,
blocking_sql.text AS blocking_sql,
blocked_sql.text AS blocked_sql,
blocked.wait_type,
blocked.wait_time
FROM sys.dm_exec_requests blocked
JOIN sys.dm_exec_requests blocking ON blocked.blocking_session_id = blocking.session_id
CROSS APPLY sys.dm_exec_sql_text(blocking.sql_handle) blocking_sql
CROSS APPLY sys.dm_exec_sql_text(blocked.sql_handle) blocked_sql;
```_
### Leistungsüberwachung
```sql
-- CPU usage
SELECT
record_id,
DATEADD(ms, -1 * ((SELECT cpu_ticks / (cpu_ticks / ms_ticks) FROM sys.dm_os_sys_info) - [timestamp]), GETDATE()) AS EventTime,
100 - SystemIdle AS SQLServerCPU,
100 - SystemIdle - SQLProcessUtilization AS OtherProcessCPU
FROM (
SELECT
record.value('(./Record/@id)[1]', 'int') AS record_id,
record.value('(./Record/SchedulerMonitorEvent/SystemHealth/SystemIdle)[1]', 'int') AS SystemIdle,
record.value('(./Record/SchedulerMonitorEvent/SystemHealth/ProcessUtilization)[1]', 'int') AS SQLProcessUtilization,
timestamp
FROM (
SELECT timestamp, CONVERT(xml, record) AS record
FROM sys.dm_os_ring_buffers
WHERE ring_buffer_type = N'RING_BUFFER_SCHEDULER_MONITOR'
AND record LIKE '%<SystemHealth>%'
) AS x
) AS y
ORDER BY record_id DESC;
-- Memory usage
SELECT
(total_physical_memory_kb / 1024) AS total_physical_memory_mb,
(available_physical_memory_kb / 1024) AS available_physical_memory_mb,
(total_page_file_kb / 1024) AS total_page_file_mb,
(available_page_file_kb / 1024) AS available_page_file_mb,
(system_memory_state_desc) AS system_memory_state
FROM sys.dm_os_sys_memory;
-- Wait statistics
SELECT TOP 20
wait_type,
wait_time_ms,
signal_wait_time_ms,
waiting_tasks_count,
wait_time_ms / waiting_tasks_count AS avg_wait_time_ms
FROM sys.dm_os_wait_stats
WHERE waiting_tasks_count > 0
AND wait_type NOT IN ('CLR_SEMAPHORE', 'LAZYWRITER_SLEEP', 'RESOURCE_QUEUE', 'SLEEP_TASK',
'SLEEP_SYSTEMTASK', 'SQLTRACE_BUFFER_FLUSH', 'WAITFOR', 'LOGMGR_QUEUE',
'CHECKPOINT_QUEUE', 'REQUEST_FOR_DEADLOCK_SEARCH', 'XE_TIMER_EVENT',
'BROKER_TO_FLUSH', 'BROKER_TASK_STOP', 'CLR_MANUAL_EVENT', 'CLR_AUTO_EVENT',
'DISPATCHER_QUEUE_SEMAPHORE', 'FT_IFTS_SCHEDULER_IDLE_WAIT', 'XE_DISPATCHER_WAIT',
'XE_DISPATCHER_JOIN', 'SQLTRACE_INCREMENTAL_FLUSH_SLEEP')
ORDER BY wait_time_ms DESC;
-- I/O statistics
SELECT
DB_NAME(database_id) AS DatabaseName,
file_id,
io_stall_read_ms,
num_of_reads,
CASE WHEN num_of_reads = 0 THEN 0 ELSE io_stall_read_ms / num_of_reads END AS avg_read_stall_ms,
io_stall_write_ms,
num_of_writes,
CASE WHEN num_of_writes = 0 THEN 0 ELSE io_stall_write_ms / num_of_writes END AS avg_write_stall_ms
FROM sys.dm_io_virtual_file_stats(NULL, NULL)
ORDER BY io_stall_read_ms + io_stall_write_ms DESC;
```_
### Datenbankgröße und Wachstum
```sql
-- Database file sizes
SELECT
DB_NAME(database_id) AS DatabaseName,
name AS LogicalName,
physical_name AS PhysicalName,
type_desc AS FileType,
size * 8 / 1024 AS SizeMB,
max_size * 8 / 1024 AS MaxSizeMB,
CASE
WHEN is_percent_growth = 1 THEN CAST(growth AS varchar(10)) + '%'
ELSE CAST(growth * 8 / 1024 AS varchar(10)) + ' MB'
END AS GrowthSetting
FROM sys.master_files
ORDER BY database_id, file_id;
-- Table sizes
SELECT
t.name AS TableName,
p.rows AS RowCount,
SUM(a.total_pages) * 8 AS TotalSpaceKB,
SUM(a.used_pages) * 8 AS UsedSpaceKB,
(SUM(a.total_pages) - SUM(a.used_pages)) * 8 AS UnusedSpaceKB
FROM sys.tables t
JOIN sys.indexes i ON t.object_id = i.object_id
JOIN sys.partitions p ON i.object_id = p.object_id AND i.index_id = p.index_id
JOIN sys.allocation_units a ON p.partition_id = a.container_id
WHERE t.is_ms_shipped = 0
GROUP BY t.name, p.rows
ORDER BY SUM(a.total_pages) DESC;
```_
## Sicherheit
### Authentifizierung und Zulassung
```sql
-- Create login with password policy
CREATE LOGIN secure_user WITH PASSWORD = 'ComplexPassword123!',
CHECK_POLICY = ON,
CHECK_EXPIRATION = ON;
-- Create user with certificate
CREATE CERTIFICATE UserCert WITH SUBJECT = 'Certificate for secure_user';
CREATE LOGIN cert_user FROM CERTIFICATE UserCert;
-- Password policy
ALTER LOGIN secure_user WITH PASSWORD = 'NewComplexPassword123!',
OLD_PASSWORD = 'ComplexPassword123!';
-- Lock/unlock login
ALTER LOGIN secure_user DISABLE;
ALTER LOGIN secure_user ENABLE;
-- Show login information
SELECT
name,
type_desc,
is_disabled,
create_date,
modify_date,
default_database_name,
is_policy_checked,
is_expiration_checked
FROM sys.server_principals
WHERE type IN ('S', 'U');
```_
### Verschlüsselung
```sql
-- Transparent Data Encryption (TDE)
-- Create master key
CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'MasterKeyPassword123!';
-- Create certificate
CREATE CERTIFICATE TDECert WITH SUBJECT = 'TDE Certificate';
-- Create database encryption key
USE MyDatabase;
CREATE DATABASE ENCRYPTION KEY
WITH ALGORITHM = AES_256
ENCRYPTION BY SERVER CERTIFICATE TDECert;
-- Enable TDE
ALTER DATABASE MyDatabase SET ENCRYPTION ON;
-- Check encryption status
SELECT
db.name AS DatabaseName,
dm.encryption_state,
dm.percent_complete,
dm.key_algorithm,
dm.key_length
FROM sys.databases db
LEFT JOIN sys.dm_database_encryption_keys dm ON db.database_id = dm.database_id;
-- Column-level encryption
-- Create symmetric key
CREATE SYMMETRIC KEY ColumnKey
WITH ALGORITHM = AES_256
ENCRYPTION BY CERTIFICATE TDECert;
-- Open symmetric key
OPEN SYMMETRIC KEY ColumnKey
DECRYPTION BY CERTIFICATE TDECert;
-- Encrypt data
INSERT INTO Employees (FirstName, LastName, SSN)
VALUES ('John', 'Doe', EncryptByKey(Key_GUID('ColumnKey'), '123-45-6789'));
-- Decrypt data
SELECT FirstName, LastName,
CONVERT(varchar, DecryptByKey(SSN)) AS SSN
FROM Employees;
-- Close symmetric key
CLOSE SYMMETRIC KEY ColumnKey;
```_
### Prüfung
```sql
-- Create server audit
CREATE SERVER AUDIT ServerAudit
TO FILE (FILEPATH = 'C:\Audit\', MAXSIZE = 100 MB, MAX_ROLLOVER_FILES = 10)
WITH (ON_FAILURE = CONTINUE);
-- Enable server audit
ALTER SERVER AUDIT ServerAudit WITH (STATE = ON);
-- Create database audit specification
CREATE DATABASE AUDIT SPECIFICATION DatabaseAuditSpec
FOR SERVER AUDIT ServerAudit
ADD (SELECT, INSERT, UPDATE, DELETE ON dbo.Employees BY public),
ADD (EXECUTE ON dbo.GetEmployeeInfo BY public);
-- Enable database audit specification
ALTER DATABASE AUDIT SPECIFICATION DatabaseAuditSpec WITH (STATE = ON);
-- View audit records
SELECT
event_time,
action_id,
succeeded,
database_name,
schema_name,
object_name,
statement,
server_principal_name,
database_principal_name
FROM sys.fn_get_audit_file('C:\Audit\*.sqlaudit', DEFAULT, DEFAULT)
ORDER BY event_time DESC;
```_
### Row Level Security
```sql
-- Create security policy function
CREATE FUNCTION dbo.fn_securitypredicate(@EmployeeID int)
RETURNS TABLE
WITH SCHEMABINDING
AS
RETURN SELECT 1 AS fn_securitypredicate_result
WHERE @EmployeeID = USER_ID() OR IS_MEMBER('db_owner') = 1;
-- Create security policy
CREATE SECURITY POLICY EmployeeSecurityPolicy
ADD FILTER PREDICATE dbo.fn_securitypredicate(EmployeeID) ON dbo.Employees,
ADD BLOCK PREDICATE dbo.fn_securitypredicate(EmployeeID) ON dbo.Employees AFTER INSERT,
ADD BLOCK PREDICATE dbo.fn_securitypredicate(EmployeeID) ON dbo.Employees AFTER UPDATE
WITH (STATE = ON);
-- Dynamic data masking
ALTER TABLE Employees
ALTER COLUMN Email ADD MASKED WITH (FUNCTION = 'email()');
ALTER TABLE Employees
ALTER COLUMN Salary ADD MASKED WITH (FUNCTION = 'default()');
-- Grant unmask permission
GRANT UNMASK TO hr_manager;
```_
## Best Practices
### Schema Design Best Practices
```sql
-- Use appropriate data types
CREATE TABLE Orders (
OrderID int IDENTITY(1,1) PRIMARY KEY, -- Use IDENTITY for auto-increment
OrderDate datetime2 NOT NULL DEFAULT GETDATE(), -- Use datetime2 for better precision
Amount decimal(10,2) NOT NULL, -- Use decimal for money
Status nvarchar(20) NOT NULL DEFAULT 'Pending', -- Use nvarchar for Unicode
CustomerID int NOT NULL,
CONSTRAINT FK_Orders_Customers FOREIGN KEY (CustomerID) REFERENCES Customers(CustomerID),
CONSTRAINT CK_Orders_Amount CHECK (Amount > 0),
CONSTRAINT CK_Orders_Status CHECK (Status IN ('Pending', 'Processing', 'Completed', 'Cancelled'))
);
-- Use proper indexing strategy
CREATE INDEX IX_Orders_CustomerID ON Orders(CustomerID);
CREATE INDEX IX_Orders_OrderDate ON Orders(OrderDate);
CREATE INDEX IX_Orders_Status_OrderDate ON Orders(Status, OrderDate) INCLUDE (Amount);
-- Use schemas for organization
CREATE SCHEMA sales;
CREATE SCHEMA hr;
CREATE SCHEMA finance;
-- Move tables to appropriate schemas
ALTER SCHEMA sales TRANSFER dbo.Orders;
ALTER SCHEMA hr TRANSFER dbo.Employees;
```_
### Performance Best Practices
```sql
-- Use parameterized queries
-- Bad: Dynamic SQL without parameters
DECLARE @SQL nvarchar(max) = 'SELECT * FROM Employees WHERE DepartmentID = ' + CAST(@DeptID AS nvarchar(10));
-- Good: Parameterized query
DECLARE @SQL nvarchar(max) = 'SELECT * FROM Employees WHERE DepartmentID = @DepartmentID';
EXEC sp_executesql @SQL, N'@DepartmentID int', @DepartmentID = @DeptID;
-- Use EXISTS instead of IN for subqueries
-- Good:
SELECT * FROM Employees e
WHERE EXISTS (SELECT 1 FROM Departments d WHERE d.DepartmentID = e.DepartmentID AND d.Location = 'New York');
-- Avoid SELECT *
-- Bad: SELECT * FROM Employees;
-- Good: SELECT EmployeeID, FirstName, LastName FROM Employees;
-- Use appropriate JOIN types
-- Use INNER JOIN when possible
SELECT e.FirstName, e.LastName, d.DepartmentName
FROM Employees e
INNER JOIN Departments d ON e.DepartmentID = d.DepartmentID;
-- Use SET NOCOUNT ON in stored procedures
CREATE PROCEDURE GetEmployees
AS
BEGIN
SET NOCOUNT ON;
SELECT * FROM Employees;
END;
Sicherheit Best Practices¶
```sql -- Use least privilege principle -- Create role for specific access CREATE ROLE app_read_role; GRANT SELECT ON schema::dbo TO app_read_role; ALTER ROLE app_read_role ADD MEMBER app_user;
-- Use stored procedures for data access CREATE PROCEDURE GetEmployeeInfo @EmployeeID int AS BEGIN SET NOCOUNT ON;
SELECT EmployeeID, FirstName, LastName, Email
FROM Employees
WHERE EmployeeID = @EmployeeID;
END;
GRANT EXECUTE ON GetEmployeeInfo TO app_user;
-- Regular maintenance tasks -- Update statistics UPDATE STATISTICS Employees;
-- Rebuild indexes ALTER INDEX ALL ON Employees REBUILD;
-- Check database integrity DBCC CHECKDB('MyDatabase');
-- Backup database BACKUP DATABASE MyDatabase TO DISK = 'C:\Backup\MyDatabase_Full.bak' WITH COMPRESSION, CHECKSUM; ```_
Überwachung und Wartung¶
```sql -- Create maintenance plan queries -- Check database integrity DBCC CHECKDB('MyDatabase') WITH NO_INFOMSGS;
-- Update statistics for all tables EXEC sp_updatestats;
-- Rebuild fragmented indexes DECLARE @SQL nvarchar(max) = ''; SELECT @SQL = @SQL + 'ALTER INDEX ' + i.name + ' ON ' + OBJECT_NAME(i.object_id) + ' REBUILD;' + CHAR(13) FROM sys.indexes i JOIN sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, 'LIMITED') ps ON i.object_id = ps.object_id AND i.index_id = ps.index_id WHERE ps.avg_fragmentation_in_percent > 30 AND ps.page_count > 1000;
EXEC sp_executesql @SQL;
-- Monitor long-running queries SELECT r.session_id, r.start_time, r.status, r.command, r.percent_complete, r.estimated_completion_time, t.text AS query_text FROM sys.dm_exec_requests r CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) t WHERE r.estimated_completion_time > 0; ```_
--
Zusammenfassung¶
Microsoft SQL Server ist eine umfassende Unternehmensdatenbank-Plattform, die robuste Funktionen für Datenmanagement, Business Intelligence und Anwendungsentwicklung mit einer starken Integration mit dem Microsoft-Ökosystem bietet.
Key Strengths: - Enterprise Integration*: Nahtlose Integration mit Microsoft Technologien und Azure Cloud - **Business Intelligence: Integrierte Reporting-, Analyse- und Datenspeicherfähigkeiten - Performance: Advanced Query Optimierer und In-Memory Technologien - Sicherheit: Umfassende Sicherheitsfunktionen einschließlich TDE, RLS und Auditing - **Skalierbarkeit*: Unterstützung für große Datenbanken und hochverfügbare Lösungen
Best Use Cases: - Enterprise Anwendungen in Microsoft-Umgebungen - Unternehmensinformationen und Datenspeicherung - Anwendungen, die eine starke ACID-Compliance erfordern - Systeme, die fortschrittliche Sicherheitsfunktionen benötigen - Cloud-Hybrid-Einsätze mit Azure
Importierte Überlegungen: - Lizenzkosten können für Unternehmensmerkmale von Bedeutung sein - Beste Leistung unter Windows-Umgebungen - Erfordert regelmäßige Wartung und Überwachung - Speicher- und Speicheranforderungen können beträchtlich sein - Backup- und Recovery-Strategien müssen gut geplant sein
Durch die in diesem Cheatsheet skizzierten Praktiken und Techniken können Sie SQL Server-Datenbanken effektiv entwerfen, implementieren und pflegen, die den Anforderungen des Unternehmens an Leistung, Sicherheit und Zuverlässigkeit entsprechen und dabei die volle Leistung der Microsoft-Datenplattform nutzen.
<= <= <= <================================================================================= Funktion copyToClipboard() {\cHFFFF} const commands = document.querySelectorAll('code'); alle Befehle = ''; Befehle. Für jede(cmd) => alle Befehle += cmd.textContent + '\n'); navigator.clipboard.writeText (allCommands); Alarm ('Alle Befehle, die in die Zwischenablage kopiert werden!'); }
Funktion generierenPDF() { Fenster.print(); }