SQL-Tutorial

OFFSET - von Zeile x nach Zeile y

ORDER BY Kontinent ASC, Teilregion DESC
OFFSET 29 ZEILEN HOLT NUR DIE NÄCHSTEN 50 ZEILEN;

WITH TIES - Unentschieden auf dem letzten Platz

WÄHLEN SIE DIE ERSTEN 10 PROZENT MIT KRAWATTEN;

COALESCE - 1. Nicht-NULL-Wert

SELECT COALESCE(NULL,NULL,2,5,NULL)
COALESCE(PickedByPersonID,BackorderOrderID);

WHERE - Zeichenersetzungen

WHERE Lagerbestandsname LIKE '%ham[^m]%'
WHERE Lagerbestandsname LIKE 'a[l-m]%[l-p]'
WHERE Ländername LIKE 'H__[g,d]%'

WHERE IN - ist es in einer Liste enthalten

WHERE PickedByPersonID IN (3,4,17) AND OrderDate >= '2013-01-01' AND OrderDate <= '2013-12-30'

AGGREGATABFRAGEN - AVG(), SUM(), MIN(), MAX(), COUNT(), COUNT_BIG()

SUM(Menge) AS total_pack, AVG(Stückpreis) AS avg_unitprice, COUNT(OrderLineID) AS cnt_orderline

AGGREGATOREN - NULL nicht behandeln

SELECT COUNT(ISNULL(KommissionierungErledigtWann,'1970-01-01'))
SELECT COUNT_BIG(*) FROM Umsatz.Auftragszeilen;
COUNT(CASE WHEN PickingCompletedWhen IS NULL THEN 1 ELSE NULL END) AS unkown_values

Unterabfrage - in sich geschlossen/einfach

SELECT OrderId, AVG(Menge) as avg_perorderid
FROM Verkäufe.OrderLines
GROUP BY OrderId
HAVING AVG(Menge) > (SELECT AVG(Menge) AS avg_q
FROM Sales.OrderLines)
ORDER BY avg_perorderid ASC;

SELECT OrderId, (SELECT AVG(Menge) AS avg_q FROM Sales.OrderLines)
FROM Sales.OrderLines;

korrelierte Unterabfrage - letzte OrderID 

SELECT CustomerId, OrderId, OrderDate
FROM Verkauf.Aufträge o1
WHERE OrderID=(SELECT MAX(OrderID)
FROM Verkäufe.Aufträge o2
WHERE o1.CustomerId=o2.CustomerId)
Reihenfolge nach orderDate DESC;

Rückläufe mit Liste

SELECT OrderID, CustomerId, OrderDate FROM Sales.Orders
WHERE CustomerID IN (SELECT CustomerID FROM Sales.Customers WHERE CreditLimit IS NULL OR CreditLimit < 2000)
ORDER BY CustomerID ASC;

EXISTS

SELECT DISTINCT KundenID, Kundenname
FROM Vertrieb.Kunden c
WHERE PostalCityID = 33832
AND EXISTS
(SELECT * FROM Verkauf.Aufträge o
WHERE o.CustomerID=c.CustomerID);

running-total - gordulo lekerdezes

SELECT StadtID, Stadtname, (SELECT MIN(StadtID) FROM Anwendung.Städte c2 WHERE c2.StadtID > c1.StadtID) AS nextcityid
FROM Anwendung.Städte c1
ORDER BY CityID ASC;
--javitani
SELECT CityID, CityName, LatestRecordedPopulation, LatestRecordedPopulation + (SELECT SUM(LatestRecordedPopulation) FROM Application.Cities c2 WHERE c1.CityID=c2.CityID) AS run_total
FROM Anwendung.Städte c1
WHERE StateProvinceID IN (SELECT StateProvinceID FROM Application.StateProvinces WHERE StateProvinceName='Colorado')
GROUP BY CityID, CityName, LatestRecordedPopulation;

DERIVED TABLE Version

SELECT auftrag_zahl, monat_nummer
FROM (
SELECT MONAT(Bestelldatum) AS month_number, COUNT(Bestelldatum) AS order_count
FROM Umsatz.Aufträge
GROUP BY MONAT(Bestelldatum)
) AS derivtable
WHERE auftrag_zahl > 6000
ORDER BY month_number ASC;

SELECT auftrag_zahl, monat_nummer
FROM (
SELECT MONAT(Datum der Bestellung), COUNT(Datum der Bestellung)
FROM Umsatz.Aufträge
GROUP BY MONAT(Bestelldatum)
) AS abgeleitete Tabelle (monat_nummer,auftrag_zahl)
WHERE auftrags_zahl > 6000
ORDER BY monat_nummer ASC;

SELECT CustomerID, ORderID, OrderDate
FROM Vertrieb.Aufträge AS a -- a=schema_name.tabellenname
INNER JOIN
(
SELECT MAX(BestellDatum) AS maxBestellDatum
FROM Verkäufe.Aufträge AS b
) AS derivedtable ON a.orderDate=derivedtable.maxorderdate;

CTE

WITH cte_table AS (
SELECT MONAT(Bestelldatum) AS MONAT_NUMMER, COUNT(Bestelldatum) AS BESTELLUNG_ZAHL
FROM Verkauf.Aufträge
GROUP BY MONAT(Bestelldatum)
)
SELECT auftrag_zahl, monat_nummer FROM cte_table
WHERE auftrag_zahl > 6000
ORDER BY monat_nummer ASC;

FALL - NORMAL - ABGELEITETE TABELLE - CTE 

SELECT CASE
WHEN 2013=YEAR(Bestelldatum) THEN '2013y'
WHEN 2014=FORMAT(Bestelldatum,'jjjj') THEN '2014j'
WHEN Bestelldatum wie '2015%' THEN '2015j'
WHEN Bestelldatum >= '20160101' AND Bestelldatum = '20160101' AND Bestelldatum = '20160101' AND Bestelldatum = '20160101' AND Bestelldatum < '20170101' THEN '2016y'
END as Jahre
FROM Umsatz.Aufträge)
SELECT jahre, COUNT(jahre)
FROM was auch immer
GROUP BY jahre;

JOIN AND - Dies wäre die Wo in und Beziehung

SELECT *
FROM dbo.Varosok v JOIN dbo.Orszagok o ON v.OrszagID = o.Id AND o.Nev='USA'

Boss Boss JOIN

SELECT untergeordnet.Nev, Zöpfe.Nev, Zöpfe.Nev FROM dbo.people as untergeordnet
INNER JOIN dbo.People as fonok ON subordinate.FonokId = fonok.Id
LEFT JOIN dbo.People as majorfonok ON fonok.Fonok.FonokId = majorfonok.Id

Datenlänge

SELECT emp_name,
LEN(mitarbeiter_name) LEN
, DATALENGTH(mitarbeiter_name) data_length
FROM dbo.mitarbeiter;

EINDEUTIGER BEZEICHNER

CREATE TABLE #testunique(
id UNIQUEIDENTIFIER DEFAULT NEWID()
, name varchar(100)
);

autocreate id

DROP TABLE IF EXISTS HR.Mitarbeiter
CREATE TABLE HR.Mitarbeiter (
id int IDENTITY(1,1)
, emp_name NVARCHAR(200)
)

EIGENER TYP

CREATE TYPE hunschema.hun_mySSN FROM varchar(9);
CREATE TABLE hunschema.testtable (
id INT NOT NULL
, socnumberHUN hunschema.hun_mySSN
);
INSERT INTO hunschema.testtable
WERTE (1, '123456789');

Problem mit Autoinkrement und INSERT vermeiden

SET IDENTITY_INSERT Hr.Employees ON;

INSERT INTO HR.Mitarbeiter (id,emp_name)
VALUES(666,'vorname');

SET IDENTITY_INSERT Hr.Employees OFF;

OUTPUT eingefügt, gelöscht

INSERT INTO HR.Mitarbeiter (mitarbeiter_name)
OUTPUT inserted.mitarbeiter_name INTO HR.Mitarbeiterprotokoll(mitarbeiter_name)
VALUES ('testname')

DELETE Hr.Mitarbeiter
OUTPUT gelöscht.emp_name INTO HR.Emplog
WHERE id=666;

DELETE testlines where orderdate='20130101′ > LOG 

DELETE dbo.testlines
OUTPUT gelöscht.*
FROM dbo.testlinien tol
INNER JOIN dbo.testorders tor ON tor.OrderID=tol.OrderID
WHERE OrderDate='20130101'

PRIMÄRSCHLÜSSEL, FREMDSCHLÜSSEL, EINDEUTIGE SCHLÜSSEL, BESCHRÄNKUNGEN

PRIMARY KEY

/* v1 */
ALTER TABLE dbo.employees
ALTER COLUMN emp_id int NOT NULL;

ALTER TABLE dbo.employees
ADD CONSTRAINT PK_employee_empid PRIMARY KEY (emp_id);
/* v2 */
ALTER TABLE dbo.employees
ADD emp_id int IDENTITY(1,1) NOT NULL
CONSTRAINT PK_employees_emp PRIMARY KEY;
/* v3 */
GO
CREATE TABLE dbo.testtable4(
id INT NOT NULL PRIMARY KEY
);
/* v4 */
DROP TABLE IF EXISTS dbo.testtable4;
CREATE TABLE dbo.testtable4(
id INT NOT NULL IDENTITÄT(1,1
,name varchar(50)
,CONSTRAINT PK_testtable4_id PRIMARY KEY(id)
);

FREMDSCHLÜSSEL - 1 > N - PRIMÄRSCHLÜSSEL

ALTER TABLE dbo.employees
ADD CONSTRAINT FK_employees_depid FOREIGN KEY(dep_id) REFERENCES dbo.departments(dep_id);

Kaskadenversion

ALTER TABLE dbo.employee
ADD CONSTRAINT FK_employees_depid FOREIGN KEY(dep_id) REFERENCES dbo.departments(dep_id) ON UPDATE CASCADE; -- ON DELETE CASCADE

Wechseltabelle - Arbeitnehmer und Ausbildungen - N > M

DROP TABLE IF EXISTS dbo.conn_educations_employees;
CREATE TABLE dbo.conn_educations_employees (
id INT NOT NULL IDENTITÄT(1,1)
CONSTRAINT PK_conn_eduemp_id PRIMARY KEY
,edu_id INT NOT NULL
CONSTRAINT FK_conn_edu_eduid FOREIGN KEY (edu_id) REFERENCES dbo.educations(edu_id)
,emp_id INT NOT NULL
CONSTRAINT FK_conn_edu_empid FOREIGN KEY (edu_id) REFERENCES dbo.employees(emp_id)
);

1 > 1

DROP TABLE IF EXISTS dbo.itusers;
CREATE TABLE dbo.itusers(
id int NOT NULL IDENTITY(1,1)
CONSTRAINT PK_itusers_id PRIMARY KEY
, benutzername VARCHAR(50) NOT NULL
CONSTRAINT UK_itsuser_username UNIQUE
, emp_id INT
CONSTRAINT FK_itusers_empid FOREIGN KEY(emp_id) REFERENCES dbo.employees(emp_id)
CONSTRAINT UK_itusers_empid UNIQUE (emp_id)
);

UNIQUE SCHLÜSSEL

ALTER TABLE dbo.employees
ADD CONSTRAINT UK_employees_person UNIQUE (mitarbeiter_name,geburtsdatum,mutter_name);

PRÜFBESCHRÄNKUNG

ALTER TABLE dbo.employees
ADD CONSTRAINT CK_employees_birthdate CHECK ( birth_date > '19600101');

Funktioniert eine Prüfbeschränkung?

ALTER TABLE dbo.employees WITH CHECK
CHECK CONSTRAINT CK_employees_contacts;

STANDARD-ZWANGSBEDINGUNG

ALTER TABLE dbo.employees
ADD CONSTRAINT DK_phonenumber DEFAULT '0690111111' FOR phone_number;

temporale tabelle sql2017+ - advanced sql server 2019 cu18

CREATE TABLE dbo.persondate (
id int IDENTITY(1,1) PRIMARY KEY NOT NULL
,nachname NVARCHAR(50) NOT NULL
,vor_name NVARCHAR(50) NOT NULL
,telefon_nummer VARCHAR(22)
,email-Adresse VARCHAR(50)
,sysfirstdate DATETIME2 GENERATED ALWAYS AS ROW START NOT NULL
,sysenddate DATETIME2 GENERATED ALWAYS AS ROW END NOT NULL
,PERIOD FOR SYSTEM_TIME(sysfirstdate,sysenddate)
) WITH (
SYSTEM_VERSIONING = ON (HISTORY_RETENTION_PERIOD = 3 MONATE
,HISTORY_TABLE = dbo.persondate_history)
)
/* temporale Tabelle - gelöscht*/
SELECT * FROM dbo.persondate_history temp
LEFT JOIN dbo.persondate actual ON temp.id=actual.id
WHERE actual.id IS NULL;

INDEX

INDEX-Typen:
- In-Memory-Index: oltp
- columnstore index
- rowstore: geclustert 1 , nicht geclustert

Rowstore-Index-Typen:
- geclusterter Index - Telefonbuch, vollständige Tabelle
- nicht geclustert: heap - heap, wenn es keinen geclusterten Index für die Tabelle gibt
Index, z.B. welche Seite das Wort "Rechtsstaatlichkeit" auf Seite 120,130 enthält

Indexknoten: Indexschlüssel, Adresse
Blattebene: Tisch
Wurzel > Zwischenknoten > Blattknoten

nicht geclusterter Index: B-Baum

Blattebene: Indexschlüssel, geclusterter Index

gut für die Suche im Indexschlüssel, aber Sie können nicht mit Clustering davonkommen

GECLUSTERTER INDEX

DROP INDEX idx_testlines_clustered ON dbo.testlines;
CREATE CLUSTERED INDEX idx_testlines_clustered ON dbo.testlines(OrderLineID DESC);

Nicht-geclusterte Indizes sind gut, wenn Sie eine Abfrage in "Where" machen, eine Abfrage, die Sie oft verwenden

CREATE CLUSTERED INDEX idx_testlines_clustered ON dbo.testlines(OrderLineID DESC);

CREATE NONCLUSTERED INDEX idx_testlines_stockitemid ON dbo.testlines(StockItemID);

die Verwendung eines Indexes erzwingen - nicht verwenden

Kosten: 2,24

SELECT OrderLineID, StockItemID,Stückpreis, Menge
FROM dbo.testlines WITH (INDEX (idx_testlines_stockitemid))
WHERE StockItemID=148;

Blattniveau ist im UnitePrice enthalten, Menge

DROP INDEX idx_testlines_stockitemid ON dbo.testlines;
CREATE NONCLUSTERED INDEX idx_testlines_stockitemid ON dbo.testlines(StockItemID) INCLUDE (UnitPrice,Quantity);

Gefilterter Index

CREATE UNIQUE INDEX idx_testorders_isinprogress ON dbo.testorders (CustomerID,isInProgress) WHERE isInProgress=1;
/*FOREIGN KEY > kein Index ! beste Praxis - nicht geclusterter Index gefiltert testdb istHIgh Bildungstabelle-ben*/
/*vielleicht Masterwork - nicht gut für Datum*/
CREATE INDEX idx_testorders_2016 ON dbo.testorders (OrderDate) INCLUDE(CustomerID) WHERE OrderDate >= '20160101' AND OrderDate<'20170101';

Variablen

Stapelverarbeitung und Variablen (GO)
- zwischen zwei GOs liegt ein Stapel
- Variablen leben nur in einer Charge
DECLARE @stockItemId INT;
SET @stockItemId = 2;

DECLARE @maxValidTo DATETIME2 = '2020-02-02';

Als Filterbedingung, auch bei Mehrfachabfragen

SELECT * FROM Warehouse.StockItems
WHERE StockItemID = @stockItemId;

DECLARE @myStockItemName NVARCHAR(500);

SET @myStockItemName = (SELECT StockItemName FROM Warehouse.StockItems
WHERE StockItemID = @stockItemId);

SELECT @myStockItemName AS MyStockItemName;
/* Kann nur einen Wert speichern */
/* Dasselbe wie oben */
DECLARE @stockItemId INT;
SET @stockItemId = 2;
DECLARE @myStockItemName NVARCHAR(500);
SELECT @myStockItemName=StockItemName FROM Warehouse.StockItems
WHERE StockItemID = @stockItemId;

nimmt den letzten Wert, wenn er in einem select

DECLARE @myStockItemName NVARCHAR(500);
SELECT @myStockItemName=StockItemName FROM Warehouse.StockItems;

DECLARE @myStockItemName NVARCHAR(500);
DECLARE @myStockItemColorId NVARCHAR(500);

SELECT @myStockItemName=StockItemName, @myStockItemColorId=ColorID FROM Warehouse.StockItems;

SELECT @meinBestandsartikelName=BestandsartikelName, @meinBestandsartikelFarbeId=FarbeID
FROM Warehouse.StockItems
ORDER BY LagerartikelName;

SELECT @myStockItemName AS MyStockItemName;
SELECT @myStockItemColorId AS MyStockColorId;

Wenn es kein Ergebnis der Abfrage gibt, nimmt die Variable den Wert NULL an

SELECT StockItemName FROM Warehouse.StockItems
WHERE StockItemID = 10000000;

DECLARE @myStockItemName NVARCHAR(500);
SET @myStockItemName = (SELECT StockItemName FROM Warehouse.StockItems
WHERE StockItemID = 10000000);
SELECT @myStockItemName AS MyStockItemName;

DECLARE @myStockItemName NVARCHAR(500);
SELECT @meinLagerPositionsName=LagerPositionsName FROM Lager.LagerPositionen
WHERE StockItemID = 10000000;
SELECT @myStockItemName AS MyStockItemName;

DATEN

https://learn.microsoft.com/en-us/sql/t-sql/data-types/data-types-transact-sql?view=sql-server-ver16

numerisch vs. float

Float-Approximator rundet, bei großen Zahlen ist der ganzzahlige Teil möglicherweise nicht genau, nur die ersten 7 sind genau, x*2^y => 199*2*5 - Physik, statistische Berechnungen für große Werte, z.B. Dezimalzahlen reichen nicht aus
numerisch/dezimal, was Sie bekommen, für finanzielle Dinge numerisch z.B. Preis ist 1,99

Geld - es ist eigentlich dezimal, nur mit vier Nachkommastellen, die fest sind - man kann die Währung schreiben, aber sie wird nicht gespeichert

DECLARE @mymoney_sm SMALLMONEY = 3148.29,
        @mymoney MONEY = 3148,29;
SELECT CAST(@mymoney_sm AS VARCHAR) AS 'SM_MONEY varchar',
        CAST(@mymoney AS DECIMAL) AS 'MONEY DECIMAL';

datetime vs datetime2

DECLARE @ido_datetime DATETIME = GETDATE();
DECLARE @ido_datetime2 DATETIME2 = GETDATE();

SELECT @ido_datetime, @ido_datetime2;

datumszeitoffset

DECLARE @ido_datetimeoffset datetimeoffset = GETDATE();
DECLARE @ido_datetimeoffset2 datetimeoffset = SYSDATETIMEOFFSET()
SELECT @ido_datetime, @ido_datetimeoffset,@ido_datetimeoffset2;

DECLARE @mostaniIdoUTC datetime2=GETUTCDATE();
SELECT @ido_datetime, @ido_datetimeoffset,@ido_datetimeoffset2,@mostaniIdoUTC;

char vs varchar

DECLARE @mychar CHAR(3)='test'
SELECT @mychar;

DECLARE @mychar CHAR(3)='te'
SELECT @mychar;

DECLARE @Meinzeichen CHAR(3)='te'
SELECT LEN(@mychar);
SELECT DATALENGTH(@mychar);

DECLARE @myvarchar VARCHAR(3)='test'
SELECT @myvarchar;

DECLARE @myvarchar VARCHAR(3)='te'
SELECT @myvarchar;

DECLARE @myvarchar VARCHAR(3)='te'
SELECT LEN(@myvarchar);
SELECT DATALENGTH(@myvarchar);

GO

nchar vs. nvarchar

DECLARE @mychar NCHAR(3)='test'
SELECT @mychar;

DECLARE @mychar NCHAR(3)='te'
SELECT @mychar;

DECLARE @mychar NCHAR(3)='te'
SELECT LEN(@mychar);
SELECT DATALENGTH(@mychar);

DECLARE @myvarchar NVARCHAR(3)='test'
SELECT @myvarchar;

DECLARE @myvarchar NVARCHAR(3)='te'
SELECT @myvarchar;

DECLARE @myvarchar NVARCHAR(3)='te'
SELECT LEN(@myvarchar);
SELECT DATALENGTH(@myvarchar);

binär

DECLARE @myBinary BINARY(10) = 0x00A1B2C3;
SELECT @myBinary;

Unicode-Zeichen in Ascii umwandeln

DECLARE @mychar CHAR(3) = 'Győr';
DECLARE @mychar2 CHAR(3) = 'Győr';
SELECT @mychar, @mychar2, LEN(@mychar), DATALENGTH(@mychar),LEN(@mychar2), DATALENGTH(@mychar2);

zu hohe Werte

DECLARE @chunk SMALLINT = 32768;
SELECT @darabszam;

 implizite Umrechnung

https://learn.microsoft.com/en-us/sql/t-sql/data-types/data-type-conversion-database-engine?view=sql-server-ver16

CAST vs. CONVERT

DECLARE @chunk SMALLINT = 32764;
SELECT @darabszam;
SELECT CAST(@darabszam AS nvarchar)+'?';

DECLARE @ma DATETIME2 =GETUTCDATE();

SELECT @ma,CONVERT(nvarchar,@ma,1)

TRY_CAST gegenüber TRY_CONVERT

DECLARE @chunk SMALLINT = 32764;
SELECT @darabszam;
SELECT TRY_CAST(CAST(@darabszam AS nvarchar)+'?' AS INT);

FORMAT

DECLARE @ma DATETIME2 =GETUTCDATE();

SELECT @ma,FORMAT(@ma,'jjjj. MM. tt.')

DECLARE @datum DATETIME2 = '2022-02-15', @datum2 DATETIME2;
SET @datum2 =CONVERT(DATETIME2, '2/15/2022',101)
SELECT @datum,@datum2

DECLARE @float FLOAT = 2.0 / 5;
SELECT @Gleitkomma,FORMAT(@Gleitkomma,'N2')

DIGITALE Operationen: TRIM,LTRIM,RTRIM

len schaut hier nicht auf das Ende des Textes:

SELECT TRIM(' a '),LEN(' a '), LEN(TRIM(' a '));
SELECT LTRIM(' a '),LEN(' a '), LEN(LTRIM(' a '));
SELECT RTRIM(' a '),LEN(' a '), LEN(RTRIM(' a '));

SELECT TRIM(' a '),LEN(' a '), LEN(TRIM(' a ')));
SELECT LTRIM(' a '),DATALENGTH(' a '), DATALENGTH(LTRIM(' a '));
SELECT RTRIM(' a '),LEN(' a '), LEN(RTRIM(' a '));

OBEN, UNTEN

SELECT UPPER('Akzent')
SELECT LOWER('SATZ')

REPLIZIEREN,LINKS, UMKEHREN, ERSETZEN

SELECT REPLICATE('ho',3)
SELECT LEFT('HALLO WELT', 5)

SELECT REVERSE('hallo')

SELECT REPLACE('HALLO Welt', 'Welt', 'JOE')

UPDATE Warehouse.StockItems
SET StockItemName = REPLACE(StockItemName,'StockItemName', 'launcher')

Datum-Zeit-Operationen: DATEDIFF

SELECT GültigAb, '2022-01-01 00:00', DATEDIFF(jjjj, GültigAb,'2022-01-01 00:00')
FROM Warehouse.StockItems

SELECT GültigAb, '2022-01-01 00:00', DATEDIFF(s, GültigAb,'2022-01-01 00:00')
FROM Lager.StockItems

SELECT GültigAb, '2022-01-01 00:00', DATEDIFF(s, GültigAb,'2022-01-01 00:00')
FROM Lager.StockItems

SELECT DATEDIFF(s,'2022-01-01 00:00','2022-01-01 05:01')

Rundung

SELECT ROUND(123.45,0)
WÄHLEN SIE ROUND(123.55,0)
WÄHLEN SIE ROUND(123,55,1)

TEMPORÄRE TABELLE, TABELLENVARIABLE

Aushilfstabelle

existiert nur in Session, speichert in tempdb, zu große tempdb für viele, um Abfragen von Tabellen zu speichern, Vorteil: gefilterte Daten, schnellere Abfragen, weniger Code, Performance

CREATE TABLE #myTempTable
(
	Id eindeutiger Bezeichner Primärschlüssel nicht geclustert,
	Name NVARCHAR(100) NOT NULL
);

Globales temporäres Talbe: bleibt zwischen den Sitzungen bestehen, wird nach Beendigung aller Abfragen und Sitzungen beendet

CREATE TABLE ##globalTempTable
(
	Id eindeutiger Bezeichner Primärschlüssel nicht geclustert,
	name NVARCHAR(100) NOT NULL
);
DROP TABLE ##globalTempTable;

Tabellenvariable: gibt es nur im Batch, nicht ideal für große Datenmengen

DECLARE @meineTabelleVariable TABLE (
	Id eindeutiger Bezeichner Primärschlüssel nicht geclustert,
	Name NVARCHAR(100) NOT NULL
);
-- Herstellung einer gemeinsamen Tafel
USE WideWorldImporters;
GO

SELECT COUNT(*) FROM Verkauf.Aufträge;
-- 0,39 Kosten
SELECT COUNT(*) FROM Sales.OrderLines;

SELECT TOP 1 * FROM Verkäufe.Auftragszeilen;

CREATE TABLE #Temp_OrderLines
(
	OrderLineID int PRIMARY KEY,
	StockItemID int NOT NULL, --/*FOREIGN KEY*/ Referenzen Warehouse.StockItems(StockItemID), --dies nicht tun, weil es keinen Namen hat, Sie müssen den Namen finden
	BESCHREIBUNG NVARCHAR(1000),
	Menge int NOT NULL
);
-- 164 Lagerartikel-ID
INSERT INTO #Temp_OrderLines(OrderLineID,StockItemID,[DESCRIPTION],Quantity)
SELECT OrderLineID,StockItemID,[Beschreibung],Menge
FROM Vertrieb.OrderLines
WHERE StockItemID=164;

SELECT * FROM #Temp_OrderLines;
--0.013 Kosten
SELECT COUNT(*) FROM #Temp_OrderLines;

INSERT INTO #TTemp_OrderLines(OrderLineID,StockItemID,[DESCRIPTION],Quantity)
VALUES (10000,1,'Test', 1);

SELECT COUNT(*) FROM #Temp_OrderLines;

DECLARE @meineTabelleVariable TABLE (
	Id eindeutiger Bezeichner Primärschlüssel nicht geclustert,
	Name NVARCHAR(100) NOT NULL
);

INSERT INTO @meineTabelleVariable (Id,Name) VALUES (NEWID(), 'Teszt');

SELECT * FROM @meineTabelleVariable;

USE WideWorldImporters;

/*
    Deklaration eines Tabellentyps
*/
DROP TYPE IF EXISTS mytable;
CREATE TYPE mytable AS table
(
    id int NOT NULL,
	name NVARCHAR(100) NOT NULL
);

/*
    Von nun an müssen Sie Ihre Tabellenvariablen nicht mehr mit Spalteninformationen deklarieren
    mit Spalteninformationen deklarieren, sondern nur noch auf den Typ verweisen.
*/
DECLARE @t AS mytable;
INSERT INTO @t VALUES(1,'HELLO WORLD');

SELECT * FROM @t;


CREATE TABLE dbo.testtable AS mytable; -- nein

/*das ist ja*/
SELECT *
INTO dbo.testtable
FROM @t
WHERE 1 = 2; -Spalten ja, aber nicht Zeilen


SELECT * FROM dbo.testtecske;

KONTROLLFLUSS-ELEMENTE (IF, WHILE)

Code-Verzweigung

WENN...ELSE
IF-Ausdrücke

- dreiwertige Logik: TRUE, FALSE, UNKNOWN (NULL)
einfaches Wenn-Beispiel

DECLARE @year SMALLINT;
SET @year = 2022;

IF @year = YEAR(GETDATE())
BEGIN
PRINT 'Treffer! Das aktuelle Jahr ist: ' + CAST(@year AS varchar(5));
END
ELSE
BEGIN
    PRINT 'ES GIBT KEINE ÜBEREINSTIMMUNG! DIE Jahresvariable:' + CAST(@year AS varchar(5));
    PRINT 'ES GIBT KEINE ÜBEREINSTIMMUNG! DAS aktuelle Jahr:' + CAST(YEAR(GETDATE()) AS varchar(5));
END

DECLARE @year SMALLINT;
SET @year = (SELECT YEAR(MAX(OrderDate)) FROM WideWorldImporters.Sales.Orders);

IF @year = YEAR(GETDATE())
BEGIN
PRINT 'Treffer! Das aktuelle Jahr ist: ' + CAST(@year AS varchar(5));
END
ELSE
BEGIN
    PRINT 'ES GIBT KEINE ÜBEREINSTIMMUNG! DIE Jahresvariable:' + CAST(@year AS varchar(5));
    PRINT 'ES GIBT KEINE ÜBEREINSTIMMUNG! DAS aktuelle Jahr:' + CAST(YEAR(GETDATE()) AS varchar(5));
END

NULL-Behandlung verschachtelter if-Elemente

DECLARE @year SMALLINT;
SET @year = (SELECT YEAR(MAX(OrderDate)) FROM WideWorldImporters.Sales.Orders WHERE OrderID=500000);

IF @year = YEAR(GETDATE())
BEGIN
PRINT 'Treffer! Das aktuelle Jahr ist: ' + CAST(@year AS varchar(5));
END
ELSE
BEGIN
    IF @year IS NOT NULL
    BEGIN
    PRINT 'ES GIBT KEINE ÜBEREINSTIMMUNG! DIE Variable Jahr:' + CAST(@year AS varchar(5));
    PRINT 'ES GIBT KEINE ÜBEREINSTIMMUNG! DAS aktuelle Jahr:' + CAST(YEAR(GETDATE()) AS varchar(5));
    END
    ELSE
    BEGIN
    PRINT '@year Wert ist NULL'
    END
END
GO

Aktive DB, nur für die eigene, andere Sitzungen können sie noch nutzen, löschen

DECLARE @year SMALLINT;
SET @year = 2023;
IF @year = YEAR(GETDATE())
BEGIN
    USE WideWorldImporters
END

Komplexer if-Ausdruck

letzter Tag des letzten Monats = heute-20 || heute ist IN (montags, dienstags, freitags) || heute = 2023-02-20
richtig oder falsch

PRINT DAY(GETDATE())
PRINT EOMONTH(GETDATE(),-1); -- Februar
PRINT DATEDIFF(dd, GETDATE(),1 )
PRINT CAST(DATEADD(day, -20,GETDATE()) AS date);
PRINT DATENAME(dw,GETDATE())
PRINT GETDATE()

IF EOMONTH(GETDATE(),-1)= CAST(DATEADD(day, -20,GETDATE()) AS date) OR DATENAME(dw,GETDATE()) IN ('Montag','Dienstag', 'Freitag') OR CAST(GETDATE() AS date) = '2023-02-20'
BEGIN
PRINT 'DAS IST WAHR!'
END

/*testcase-2*/

IF EOMONTH('2023-03-20',-1)= CAST(DATEADD(day, -20,GETDATE()) AS date) OR DATENAME(dw,'2023-02-19') IN ('Montag','Dienstag', 'Freitag') OR CAST(GETDATE() AS date) = '2023-02-20'
BEGIN
PRINT 'DIES IST WAHR!'
PRINT 'DIES IST IMMER NOCH WAHR!'
END

/*Test-Fall 3*/

IF EOMONTH('2023-03-20',-1)= CAST(DATEADD(day, -20,GETDATE()) AS date) OR DATENAME(dw,'2023-02-19') IN ('Montag','Dienstag', 'Freitag') OR CAST(GETDATE() AS date) = '2023-01-28'
BEGIN
PRINT 'DIES IST WAHR!'
PRINT 'DIES IST IMMER NOCH WAHR!'
END
ELSE
BEGIN
PRINT 'NICHT WAHR'
END
DECLARE @yeara SMALLINT=2015, @yearb SMALLINT;
 SELECT @yearb;

IF EXISTS

Verwenden Sie WideWorldImporters;
GO

DECLARE @yeara SMALLINT=2015, @yearb SMALLINT=2023;

IF EXISTS (SELECT OrderID FROM SAles.Orders WHERE YEAR(OrderDate) IN (@yeara,@yearb)
)
BEGIN
PRINT 'Es gibt Aufträge in ' + CAST(@yeara as VARCHAR(5))+ ' oder in '+CAST(@yearb as VARCHAR(5))
END
ELSE
BEGIN
    PRINT 'Es liegen keine Aufträge vor in ' + CAST(@yeara as VARCHAR(5))+ ' oder in '+CAST(@yearb as VARCHAR(5))
END ;
/* Dieselbe Aufgabe mit einem kleinen NULL-Zusatz*/
DECLARE @yeara SMALLINT=2015, @yearb SMALLINT;
 SELECT @yearb;

IF EXISTS (SELECT OrderID FROM SAles.Orders WHERE YEAR(OrderDate) IN (@yeara,@yearb)
)
BEGIN
PRINT 'Es gibt Aufträge in ' + CAST(@yeara as VARCHAR(5))+ ' oder in '+CAST(@yearb as VARCHAR(5))
END
ELSE
BEGIN
    PRINT 'Es liegen keine Aufträge vor in ' + CAST(@yeara as VARCHAR(5))+ ' oder in '+CAST(@yearb as VARCHAR(5))
END ;

GO
/*NULLBEHANDLUNG*/

DECLARE @yeara SMALLINT=2015, @yearb SMALLINT;
 SELECT @yearb;

IF (@yeara IS NULL OR @yearb IS NULL)
BEGIN
PRINT 'UNBEKANNTE(r) Wert(e) wurde(n) entdeckt';

END
ELSE
BEGIN
IF EXISTS (SELECT OrderID FROM SAles.Orders WHERE YEAR(OrderDate) IN (@yeara,@yearb) AND (@yeara IS NOT NULL OR @yearb IS NOT NULL)
)
BEGIN
PRINT 'Es gibt Bestellungen in ' + CAST(@yeara as VARCHAR(5))+ ' oder in '+CAST(@yearb as VARCHAR(5));
END
ELSE
BEGIN
    PRINT 'Es liegen keine Aufträge in ' + CAST(@yeara as VARCHAR(5))+ ' oder in '+CAST(@yearb as VARCHAR(5)) vor;
END
END;

LOOPS

Syntax:

WHILE (Ausdruck)
BEGIN

ENDE
(WEITER, PAUSE, GO 1000)

DROP TABLE IF EXISTS dbo.t1,dbo.t2,dbo.t3;
CREATE TABLE dbo.t1 (num int);
CREATE TABLE dbo.t2 (num int IDENTITY(1,1));
CREATE TABLE dbo.t3 (num int IDENTITY(1,1));

/* einfache Einfügeschleife INSERT 1-1000 > dbo.t1 Methode 1*/

DECLARE @cnt int=1;

WHILE @cnt 1000 except 5 WITH Autoincrement column (Methode 2)
 CONTINUE IF @cnt=5
*/

SET IDENTITY_INSERT dbo.t2 ON;

DECLARE @cnt int=0;
WHILE (@cnt < 1001)
BEGIN
    SET @cnt +=1;
    IF @cnt=5 CONTINUE;
    INSERT INTO dbo.t2 (num) VALUES (@cnt);
END

SELECT num FROM dbo.t2;

SET IDENTITY_INSERT dbo.t2 OFF;

/*
Schleife bei @cnt=5 unterbrechen
*/
TRUNCATE TABLE dbo.t2;

SET IDENTITY_INSERT dbo.t2 ON;

DECLARE @cnt int=0;
WHILE (@cnt  dbo.t3 Methode 3
*/
INSERT INTO dbo.t3 DEFAULT VALUES;
GO 1000

SELECT * FROM dbo.t3;

Schleife mit Verzögerung

DECLARE @cnt int=1;

WHILE @cnt <= 10
BEGIN

    PRINT 'Der Zählerstand ist '+CAST(@cnt AS varchar(5));
    WAITFOR VERZÖGERUNG '00:00:01'
     SET @cnt+= 1;
   

END

/*DAS IST GUT*/

DECLARE @cnt int=1;

WHILE @cnt <= 10
BEGIN

    RAISERROR('Der Zählerwert ist %d',0,1,@cnt) WITH NOWAIT;
    WAITFOR VERZÖGERUNG '00:00:01'
     SET @cnt+= 1;
END

@@ROWCOUNT

zählt die letzte Anweisung

DECLARE @rows int;
UPDATE #mytemp
SET Menge=1000
WHERE Menge>100;
SET @rows=@@ROWCOUNT;
Wenn @rows > 0
BEGIN
    SELECT CAST(@rows as varchar(5)) + 'Zeilen wurden aktualisiert'
END
ELSE
BEGIN
SELECT 'Es wurden keine Zeilen aktualisiert'
END

FEHLERBEHANDLUNG

Fehlerarten:
- Datentypkonvertierungsfehler
- Bewertungsfehler (Bewertungsfehler)
- Syntaxfehler > kann in t-sql nicht behandelt werden
- logischer Fehler
- Fehler bei der Namensauflösung > kann in t-sql nicht behandelt werden
- Fehler bei der Verletzung einer Nebenbedingung
- Fehler durch Auslöser

Menge -1000

Warum schreiben wir eine Fehlerbehandlung?
- Ich möchte den Code nicht verletzen
- Ich möchte den Fehler protokollieren
- den Fehlercode in einer leichter verdaulichen Form ausgeben

Wie?
- verlieren Sie den Code nicht
- oder den Code loswerden, um größere Probleme zu vermeiden

Methoden zur Fehlersuche:
- strukturierte Fehlerbehandlung mit: TRY > CATCH
- @@ERROR eingebaute Funktion, nicht verwenden

09:17:15Start der Ausführung der Abfrage in Zeile 42
Msg 8134, Ebene 16, Zustand 1, Zeile 1
Fehler beim Dividieren durch Null aufgetreten.
Ausführungszeit insgesamt: 00:00:00.013

Msg 8134 > Fehlercode (id)
Level > Schweregrade
Zustand > Status
Zeile > Zeile, in der der Fehler auftritt

Beispiel Division durch Null

PRINT 10/0;

TRY...CATCH

BEGIN TRY
    PRINT 10/0;
END TRY
BEGIN CATCH
    PRINT '0 ist dumm!';
END CATCH;

integrierte Funktionen zur Fehlerbehandlung

PRINT 'Fehler aufgetreten!';
PRINT 'Fehlernummer: ' + CAST(ERROR_NUMBER() AS nvarchar(10));
PRINT 'Fehlermeldung: ' + ERROR_MESSAGE();
PRINT 'Fehlerstatus: ' + CAST(ERROR_STATE() AS nvarchar(10));
PRINT 'Fehlerschwere: ' + CAST(ERROR_SEVERITY() AS nvarchar(10));
PRINT 'Fehlerzeile: ' + CAST(ERROR_LINE() AS nvarchar(10));
PRINT 'Fehlermodul: ' + COALESCE(ERROR_PROCEDURE(),");

BEGIN TRY
    PRINT 10/0;
END TRY
BEGIN CATCH
    PRINT 'Fehler aufgetreten!';
    PRINT 'Fehlernummer: ' + CAST(ERROR_NUMBER() AS nvarchar(10));
    PRINT 'Fehlermeldung: ' + ERROR_MESSAGE();
    PRINT 'Fehlerstatus: ' + CAST(ERROR_STATE() AS nvarchar(10));
    PRINT 'Fehlerschwere: ' + CAST(ERROR_SEVERITY() AS nvarchar(10));
    PRINT 'Fehlerzeile: ' + CAST(ERROR_LINE() AS nvarchar(10)); PRINT 'Fehlermodul: ' + CAST(ERROR_LINE() AS nvarchar(10))
    PRINT 'Fehlermodul: ' + COALESCE(ERROR_PROCEDURE(),'');
END CATCH;

PRINT 'Fehlermodul: ' + COALESCE(ERROR_PROCEDURE(),");

   BEGIN TRY
   EXEC dbo.badprocedure
   END TRY
   BEGIN CATCH

   END CATCH

Fehler bei der Namensauflösung

BEGIN TRY
    DECLARE @Stückpreis INT=0;
    SELECT * FROM dbo.notavailable;

    PRINT 10/@Stückpreis;
END TRY
BEGIN CATCH
    PRINT 'Fehler aufgetreten!';
    PRINT 'Fehlernummer: ' + CAST(ERROR_NUMBER() AS nvarchar(10));
    PRINT 'Fehlermeldung: ' + ERROR_MESSAGE();
    PRINT 'Fehlerstatus: ' + CAST(ERROR_STATE() AS nvarchar(10));
    PRINT 'Fehlerschwere: ' + CAST(ERROR_SEVERITY() AS nvarchar(10));
    PRINT 'Fehlerzeile: ' + CAST(ERROR_LINE() AS nvarchar(10)); PRINT 'Fehlermodul: ' + CAST(ERROR_LINE() AS nvarchar(10))
    PRINT 'Fehlermodul: ' + COALESCE(ERROR_PROCEDURE(),'');
END CATCH;

Fehlerbehandlung bei der Namensauflösung durch das Modul

GO
CREATE OR ALTER PROCEDURE dbo.badprocedure
AS
    SELECT * FROM dbo.notavailable;
GO
EXEC dbo.badprocedure;
BEGIN TRY
    DECLARE @Stückpreis int=0;
    EXEC dbo.badprocedure;
    PRINT 10/@Einheitspreis;
END TRY
BEGIN CATCH
    PRINT 'Fehler aufgetreten!';
    PRINT 'Fehlernummer: ' + CAST(ERROR_NUMBER() AS nvarchar(10));
    PRINT 'Fehlermeldung: ' + ERROR_MESSAGE();
    PRINT 'Fehlerstatus: ' + CAST(ERROR_STATE() AS nvarchar(10));
    PRINT 'Fehlerschwere: ' + CAST(ERROR_SEVERITY() AS nvarchar(10));
    PRINT 'Fehlerzeile: ' + CAST(ERROR_LINE() AS nvarchar(10)); PRINT 'Fehlermodul: ' + CAST(ERROR_LINE() AS nvarchar(10))
    PRINT 'Fehlermodul: ' + COALESCE(ERROR_PROCEDURE(),'');
END CATCH;

negativer Stückpreisfehler durch Behandlung von THROW

BEGIN TRY
    DECLARE @Stückpreis INT=-20;
    IF @Stückpreis < 0
    BEGIN
    -- THROW gültiger Bereich ab 50000, def. Schweregrad 16
        THROW 55555, 'Der Wert des Parameters @unitprice ist kleiner als Null!', 1;
    END
    PRINT 'SOR'
END TRY
BEGIN CATCH
    PRINT 'Fehler aufgetreten!';
    PRINT 'Fehlernummer: ' + CAST(ERROR_NUMBER() AS nvarchar(10));
    PRINT 'Fehlermeldung: ' + ERROR_MESSAGE();
    PRINT 'Fehlerstatus: ' + CAST(ERROR_STATE() AS nvarchar(10));
    PRINT 'Fehlerschwere: ' + CAST(ERROR_SEVERITY() AS nvarchar(10));
    PRINT 'Fehlerzeile: ' + CAST(ERROR_LINE() AS nvarchar(10)); PRINT 'Fehlermodul: ' + CAST(ERROR_LINE() AS nvarchar(10))
    PRINT 'Fehlermodul: ' + COALESCE(ERROR_PROCEDURE(),'');
END CATCH;

THROW in CATCH - Ich breche den Code, aber zuerst lösche ich die Fehlerursache

BEGIN TRY
    DECLARE @Stückpreis INT=-20;
    IF @Stückpreis < 0
    BEGIN
    -- THROW gültiger Bereich ab 50000, def. Schweregrad 16
        THROW 55555, 'Der Wert des Parameters @unitprice ist kleiner als Null!', 1;
    END
    PRINT 'SOR'
END TRY
BEGIN CATCH
    PRINT 'Fehler aufgetreten!';
    PRINT 'Fehlernummer: ' + CAST(ERROR_NUMBER() AS nvarchar(10));
    PRINT 'Fehlermeldung: ' + ERROR_MESSAGE();
    PRINT 'Fehlerstatus: ' + CAST(ERROR_STATE() AS nvarchar(10));
    PRINT 'Fehlerschwere: ' + CAST(ERROR_SEVERITY() AS nvarchar(10));
    PRINT 'Fehlerzeile: ' + CAST(ERROR_LINE() AS nvarchar(10)); PRINT 'Fehlermodul: ' + CAST(ERROR_LINE() AS nvarchar(10))
    PRINT 'Fehlermodul: ' + COALESCE(ERROR_PROCEDURE(),'');
    SELECT CAST(@unitprice AS NVARCHAR(100)) + ' unitprice value causes the error';
    THROW;
END CATCH;

RAISE ERROR - in catch macht den Code nicht kaputt

BEGIN TRY
    DECLARE @myvar int;

    SET @myvar = -1;

    /* Auslösen eines Fehlers mit einem Argument, wenn der Wert nicht akzeptabel ist */
    IF @myvar < 0
        RAISERROR ('Der Wert des Parameters @myvar ist %d!', 16, 1, @myvar);

    PRINT 'Diese Zeile lässt sich nicht ausführen!'
END TRY
BEGIN CATCH
    PRINT 'Fehler aufgetreten!'
    PRINT 'Fehlernummer: ' + CAST(ERROR_NUMBER() AS nvarchar(10));
    PRINT 'Fehlermeldung: ' + ERROR_MESSAGE();
    PRINT 'Fehlerstatus: ' + CAST(ERROR_STATE() AS nvarchar(10));
    PRINT 'Fehlerschwere: ' + CAST(ERROR_SEVERITY() AS nvarchar(10));
    PRINT 'Fehlerzeile: ' + CAST(ERROR_LINE() AS nvarchar(10)); PRINT 'Fehlermodul: ' + CAST(ERROR_LINE() AS nvarchar(10))
    PRINT 'Fehlermodul: ' + COALESCE(ERROR_PROCEDURE(),'');
END CATCH;

BEGIN TRY
    DECLARE @Stückpreis INT=-20;
    IF @Stückpreis < 0
    BEGIN
    -- THROW gültiger Bereich ab 50000, def. Schweregrad 16
        THROW 55555, 'Der Wert des Parameters @unitprice ist kleiner als Null!', 1;
    END
    PRINT 'SOR'
END TRY
BEGIN CATCH
    PRINT 'Fehler aufgetreten!';
    PRINT 'Fehlernummer: ' + CAST(ERROR_NUMBER() AS nvarchar(10));
    PRINT 'Fehlermeldung: ' + ERROR_MESSAGE();
    PRINT 'Fehlerstatus: ' + CAST(ERROR_STATE() AS nvarchar(10));
    PRINT 'Fehlerschwere: ' + CAST(ERROR_SEVERITY() AS nvarchar(10));
    PRINT 'Fehlerzeile: ' + CAST(ERROR_LINE() AS nvarchar(10)); PRINT 'Fehlermodul: ' + CAST(ERROR_LINE() AS nvarchar(10))
    PRINT 'Fehlermodul: ' + COALESCE(ERROR_PROCEDURE(),'');
    SELECT CAST(@unitprice AS NVARCHAR(100)) + ' unitprice valuse causes the error';
    RAISERROR ('%d unitprice value causes the error!', 15, 1, @unitprice);
END CATCH;

RAISERROR kann in die Ereignisanzeige > Windows Log > Anwendungen integriert werden
eindeutigen Fehlercode erzeugen

BEGIN TRY
    DECLARE @Stückpreis INT=-20;
    IF @Stückpreis < 0
    BEGIN
    -- RAISERROR
        DECLARE @myerrorcode UNIQUEIDENTIFIER=NEWID();
        DECLARE @myerrorstring varbinary(16)= CAST(@myerrorcode AS varbinary(16));
        RAISERROR ('%d unitprice value verursacht den Fehler! Ihr Fehlercode: %x', 16, 1, @unitprice,@myerrorstring) WITH LOG;
    END
    PRINT 'SOR'
END TRY
BEGIN CATCH
    PRINT 'Fehler aufgetreten!
    PRINT 'Fehlernummer: ' + CAST(ERROR_NUMBER() AS nvarchar(10));
    PRINT 'Fehlermeldung: ' + ERROR_MESSAGE();
    PRINT 'Fehlerstatus: ' + CAST(ERROR_STATE() AS nvarchar(10));
    PRINT 'Fehlerschwere: ' + CAST(ERROR_SEVERITY() AS nvarchar(10));
    PRINT 'Fehlerzeile: ' + CAST(ERROR_LINE() AS nvarchar(10)); PRINT 'Fehlermodul: ' + CAST(ERROR_LINE() AS nvarchar(10))
    PRINT 'Fehlermodul: ' + COALESCE(ERROR_PROCEDURE(),'');
    SELECT CAST(@unitprice AS NVARCHAR(100)) + ' unitprice valuse causes the error';
    THROW;
END CATCH;

Fehlerbehandlung bei INSERT

USE testdb;
GO

DROP TABLE IF EXISTS dbo.military;
CREATE TABLE dbo.military(
    id INT IDENTITÄT(1,1) PRIMARY KEY
    ,soldat_name varchar(100) NOT NULL
    ,soldat_bdate date CHECK (soldat_bdate > '19780101')
)

BEGIN TRY
    INSERT INTO dbo.military (soldat_name,soldat_bdate)
    VALUES ('John Ramobo', '19770101')
    -- RAISERROR
END TRY
BEGIN CATCH
    WENN FEHLER_ZAHL()=547
    BEGIN
    DECLARE @myerrorcode UNIQUEIDENTIFIER=NEWID();
        DECLARE @myerrorstring varbinary(16)= CAST(@myerrorcode AS varbinary(16));
        RAISERROR ('Check constraint violation. Ihr Fehlercode: %x', 16, 1,@myerrorstring) WITH LOG;
    END
    PRINT 'Fehler aufgetreten!
    PRINT 'Fehlernummer: ' + CAST(ERROR_NUMBER() AS nvarchar(10));
    PRINT 'Fehlermeldung: ' + ERROR_MESSAGE();
    PRINT 'Fehlerstatus: ' + CAST(ERROR_STATE() AS nvarchar(10));
    PRINT 'Fehlerschwere: ' + CAST(ERROR_SEVERITY() AS nvarchar(10));
    PRINT 'Fehlerzeile: ' + CAST(ERROR_LINE() AS nvarchar(10)); PRINT 'Fehlermodul: ' + CAST(ERROR_LINE() AS nvarchar(10))
    PRINT 'Fehlermodul: ' + COALESCE(ERROR_PROCEDURE(),'');
END CATCH;
/*beliebiger Fehler*/
BEGIN TRY
    INSERT INTO dbo.military (soldat_name,soldat_bdate)
    VALUES ('John Ramobo', '1970101')
    -- RAISERROR
END TRY
BEGIN CATCH
    DECLARE @newerrormessage NVARCHAR(1000);
    SET @newerrormessage = 'Fehlernummer: ' + CAST(ERROR_NUMBER() AS nvarchar(10)) + CHAR(13) + 'Fehlermeldung: ' + ERROR_MESSAGE()+ CHAR(13) + 'Fehlerstatus: ' + CAST(ERROR_STATE() AS nvarchar(10))+ CHAR(13) + 'Fehlerschwere: ' + CAST(ERROR_SEVERITY() AS nvarchar(10))+ CHAR(13) + 'Fehlerzeile: ' + CAST(ERROR_LINE() AS nvarchar(10)) + CHAR(13) + 'Fehlermodul: ' + COALESCE(ERROR_PROCEDURE(),'');
    DECLARE @myerrorcode UNIQUEIDENTIFIER=NEWID();
        DECLARE @myerrorstring varbinary(16)= CAST(@myerrorcode AS varbinary(16));
        RAISERROR ('%s Check constraint violation. Your error code: %x', 16, 1,@newerrormessage,@myerrorstring) WITH LOG;
END CATCH;

verschachtelter try-catch-Block

BEGIN TRY
    PRINT 10/0;
END TRY
BEGIN CATCH
    BEGIN TRY
        INSERT INTO dbo.military (id,soldat_name,soldat_bdate)
        VALUES (1,'John Ramobo', '19790101')
    END TRY
    BEGIN CATCH
        THROW 55555, 'Der Wert des Parameters @unitprice ist kleiner als Null!', 2;
    END CATCH
END CATCH

ANSICHTEN

- Referenz, werden die Werte bei der Berechnung neu berechnet, es sei denn, es handelt sich um indizierte Ansichten

- Ich verstecke eine Ansicht vor den Benutzern, ich füge einige Spalten nicht in die Ansicht ein und gebe den Zugriff auf sie frei
- In der Praxis werden die Daten in einem separaten Schema gespeichert und der Zugriff darauf ermöglicht.

USE WideWorldImporters
GO
SELECT c.CustomerName, o.OrderID, SUM(ol.Quantity) as QuantitySum
FROM Vertrieb.Kunden as c
JOIN Sales.Orders as o ON o.CustomerID = c.CustomerID
JOIN Sales.OrderLines as ol ON ol.OrderID = o.OrderID
JOIN Lager.StockItems as si ON si.StockItemID = ol.StockItemID
GROUP BY c.CustomerName, o.OrderID;
GO
DROP VIEW IF EXISTS FirsView;
GO
CREATE VIEW FirstView
AS
SELECT c.CustomerName, o.OrderID, SUM(ol.Quantity) as QuantitySum
FROM Vertrieb.Kunden as c
JOIN Sales.Orders as o ON o.CustomerID = c.CustomerID
JOIN Sales.OrderLines as ol ON ol.OrderID = o.OrderID
JOIN Lager.StockItems as si ON si.StockItemID = ol.StockItemID
GROUP BY c.CustomerName, o.OrderID;
GO
SELECT * FROM FirstView;

MIT SCHEMABINDUNG, VERSCHLÜSSELUNG

SCHEMABINDING: wir können sie nicht so verändern, dass sie unbrauchbar wird, z. B. durch das Löschen von Spalten
ENKRYPTION: wir können Ihren Code nicht sehen (erstellen Sie ihn)

GO
CREATE VIEW SecondView
MIT SCHEMABINDUNG, VERSCHLÜSSELUNG
AS
SELECT c.CustomerName, o.OrderID, SUM(ol.Quantity) as QuantitySum
FROM Vertrieb.Kunden as c
JOIN Sales.Orders as o ON o.CustomerID = c.CustomerID
JOIN Sales.OrderLines as ol ON ol.OrderID = o.OrderID
JOIN Lager.StockItems as si ON si.StockItemID = ol.StockItemID
GROUP BY c.CustomerName, o.OrderID;
GO

ALTER VIEW

- Ansicht ohne Ablegen ändern - DROP VIEW IF EXISTS dbo.VarosokOrsz odok2;
-Verwenden Sie die VarosokOrszegok2Seite noch, es gibt noch SCHEMABIDING

GO
ALTER VIEW dbo.VarosokOrsz odours2
AS
SELECT v.Nev AS VarosNev
,o.Nev AS OrszagNev
FROM dbo.Varosok v
JOIN dbo.Orszagok o ON v.OrszagId=o.Id;
GO

INDEXIERTE ANSICHT

fortbestehen?

- die Ansicht muss deterministisch sein
- Schemabildung, auch für Benutzerfunktionen
- können nur Zeichen verwenden

in welchen Fällen? was sind die Vorteile? indexierte Ansicht
- befindet sich auf der Festplatte und ist daher schneller

Problem: schnellere Abfrage, wenn es eine komplizierte Verknüpfung gibt
Wenn Sie etwas ändern, müssen Sie auch die Ansicht ändern.

Wenn Sie mehr oder genauso viel in eine Tabelle schreiben, wie Sie lesen, sollten Sie sich nicht bewerben.

GO
CREATE VIEW dbo.NemDet
AS
SELECT Nev, GetDate() AS RandomDate
FROM dbo.Varosok
GO

SELECT * FROM dbo.NemDet

CREATE UNIQUE CLUSTERED INDEX ix_Nemdet ON dbo.NemDet(Nev);
-- nicht-deterministisch
GO
ALTER VIEW dbo.NemDet
MIT SCHEMABINDUNG
AS
SELECT Nev, GetDate() AS RandomDate
FROM dbo.Varosok
GO
CREATE UNIQUE CLUSTERED INDEX ix_Nemdet ON dbo.NemDet(Nev);

-- JOIN, kann nur für innere

DROP VIEW IF EXISTS dbo.TobbTabla;

GO
CREATE VIEW dbo.TobbTabla
MIT SCHEMABINDUNG
AS
SELECT v.Nev as VarosNev, o.Nev AS OrszagNev
FROM dbo.Varosok v
JOIN dbo.Orszagok o ON v.OrszagId=o.Id

GO
SELECT * FROM dbo.TobbTabla;

CREATE UNIQUE CLUSTERED INDEX ix_Nemdet ON dbo.TobbTabla(VarosNev,OrszagNev);

-- CRUD - Erstellen, Lesen, Aktualisieren, Löschen

-- ORDER BY - standardmäßig nicht möglich
-- ORDER BY - mit TOP
GO
CREATE VIEW dbo.ViewOrderBy
MIT SCHEMABINDUNG
AS
SELECT TOP 1 v.Nev as VarosNev, o.Nev AS OrszagNev
FROM dbo.Varosok v
JOIN dbo.Orszagok o ON v.OrszagId=o.Id
ORDER BY o.Nev ASC;
GO

Gespeicherte Prozeduren

- Eingaben
- Ausgänge
- Kann mehrmals aufgerufen werden

Vorteile von gespeicherten Prozeduren:

- Parameterübergabe
- erstellt einen > Ausführungsplan für eine gespeicherte Prozedur - Leistung - Parameter-Sniffing - die Verwendung eines anderen Parameters kann sehr langsam sein > MIT RECPOMPILE (neuer Ausführungsplan für jeden Aufruf)
- können Sie daraus einen separaten Fall machen
-https://www.brentozar.com/archive/2013/06/the-elephant-and-the-mouse-or-parameter-sniffing-in-sql-server/

- für jeden Parameter muss der Typ

GO
ALTER VIEW dbo.VarosokOrsz odours2
AS
SELECT
v.Nev as VarosNev,
o.Nev as OrszagNev
FROM
dbo.Varosok as v
JOIN dbo.Orszagok as o ON v.OrszagId = o.Id
WHERE v.Nev LIKE 'B%'
GO

CREATE PROCEDURE dbo.TaroltEljarasVarosokOrszagok
AS
BEGIN
	SELECT
	v.Nev as VarosNev,
	o.Nev as OrszagNev
	FROM
	dbo.Varosok as v
	JOIN dbo.Orszagok as o ON v.OrszagId = o.Id
	WHERE v.Nev LIKE 'B%'
END

SELECT * FROM dbo.VarosokOrszagok2;

EXEC dbo.TaroltEljarasVarosokOrszagok;

CREATE TABLE #Eredmeny1
(
	VarosNev NVARCHAR(100),
	OrtNev NVARCHAR(100),
)

INSERT INTO #Eredmeny1
EXEC dbo.TaroltEljarasVarosokOrszagok

SELECT * FROM #Eredmeny1
GO
CREATE PROCEDURE dbo.VarosKereses(@Suchname NVARCHAR(100))
AS
BEGIN
	SELECT
	v.Nev as VarosNev,
	o.Nev as OrszagNev
	FROM
	dbo.Varosok as v
	JOIN dbo.Orszagok as o ON v.OrszagId = o.Id
	WHERE v.Nev LIKE @Suchname
END
GO

EXEC dbo.VarosKereses 'B%'
EXEC dbo.VarosKereses 'V%'

Was ist eine SQL-Injektion?

- Was tippt der Benutzer? Ist das in Ordnung?
- "V" > OK
- "V" ; DROP TABLE dbo.students; SELECT * FROMdbo.Teachers WHERE something LIKE '" > SEHR NICHT OK
- WHERE studentId = 123 AND v.Nev LIKE '"' " oder WHERE v.Nev LIKE '"keiner von diesen ' OR 1=1″ > SEHR NICHT OK
-/**/OR//**/

- Was ist die Lösung?

EXEC dbo.VarosKereses '"keine OR 1=1"'

DECLARE @param NVARCHAR(100) = '"keine solche OR 1=1 "';
EXEC dbo.VarosKereses @param;

GO
CREATE PROCEDURE dbo.VarosKereses2(@Suchname NVARCHAR(100))
AS
BEGIN
	SELECT * FROM dbo.Varosok WHERE Id=1 AND Nev LIKE @Suchname
END
GO

INSERT INTO dbo.Varosok(ID, NEV, OrszagId)
VALUES (100, 'keine' OR ''''=''', 1);

SELECT * FROM dbo.Varosok WHERE Id =100;

Sie müssen den Tabellenparameter der gespeicherten Prozedur angeben
als READONLY

DROP TYPE IF EXISTS mytable;
CREATE TYPE mytable AS Tabelle
(
    id int
);

GO
CREATE OR ALTER PROCEDURE dbo.GetSales(@myt mytable READONLY)
AS
SELECT id FROM @myt WHERE id > 1;
GO

DECLARE @t mytable;
INSERT INTO @t VALUES(1);
INSERT INTO @t VALUES(2);
INSERT INTO @t VALUES(3); INSERT INTO @t VALUES(3);

EXEC dbo.GetSales @t

Wie können wir eine Rückerstattung erhalten?
OUTPUT - Parameter! Wir können mehr als einen Ausgabewert von unserem Speicherverfahren senden

GO
CREATE OR ALTER PROCEDURE dbo.OutputTest (@param1 INT, @outparam int OUTPUT)
AS
BEGIN
SET @outparam=@param1*2;
END
GO

-- NULL zurückgeben
DECLARE @doubledValue int;
EXEC dbo.OutputTest 2,@doubledValue
SELECT @doubledValue;
GO

-- Das ist gut:
DECLARE @doubledValue int;
EXEC dbo.OutputTest 2, @doubledValue OUTPUT
SELECT @doubledValue;

-- Die Reihenfolge der Parameter kann nicht umgedreht werden
DECLARE @doubledValue int;
EXEC dbo.OutputTest @doubledValue OUTPUT,2;
SELECT @doubledValue;
GO

DECLARE @doubledValue int;
EXEC dbo.OutputTest 2,@doubledValue OUTPUT;
SELECT @doubledValue;

-- außer haa wird durch den Namen angegeben
GO
DECLARE @doubledValue int;
EXEC dbo.OutputTest 2,@outparam = @doubledValue OUTPUT;

SELECT @doubledValue;

Rückgabewert - RETURN

GO
CREATE OR ALTER PROCEDURE dbo.ReturnTest(@varosId INT, @varosNev NVARCHAR(100) OUTPUT )
AS
IF @varosId < 0
	RETURN 1;
ELSE
	SET @varosNev = (SELECT Nev FROM dbo.Varosok WHERE Id = @varosId);
	RETURN 0;
GO

DECLARE @ret int;
DECLARE @varos NVARCHAR(100);
EXEC @ret = dbo.ReturnTest 2, @varos OUTPUT
SELECT @ret, @varos
GO
DECLARE @ret int;
DECLARE @varos NVARCHAR(100);
EXEC @ret = dbo.ReturnTest 1, @varos OUTPUT
SELECT @ret, @varos
GO
DECLARE @ret int;
DECLARE @varos NVARCHAR(100);
EXEC @ret = dbo.ReturnTest -3, @varos OUTPUT
SELECT @ret, @varos

SELECT * FROM dbo.Varosok

Läuft bis zum ersten RETURN

- vorher, so dass dies nicht mehr über die

GO
CREATE OR ALTER PROCEDURE dbo.ReturnTest (@varosId INT, @varosNev nvarchar(100) OUTPUT)
AS
BEGIN
IF @varosID < 0
BEGIN
RETURN 1;
END

SELECT @varosNev= (SELECT Nev FROM dbo.Varosok WHERE Id = @varosID)
SET @varosNev = @varosNev + '!'
RETURN 0;
END
GO

DECLARE @ret int;
DECLARE @varos NVARCHAR(100);

EXEC @ret = dbo.ReturnTest 2, @varos OUTPUT
SELECT @ret,@varos;
- gab zuvor @varos zurück, so dass dies nicht mehr überschrieben wird
EXEC @ret = dbo.ReturnTest -3, @varos OUTPUT
SELECT @ret,@varos;
----------------MEGOLDÁS
GO
CREATE OR ALTER PROCEDURE dbo.ReturnTest (@varosId INT, @varosNev nvarchar(100) OUTPUT)
AS
SET @varosNev = NULL;
BEGIN
IF @varosID < 0
BEGIN
RETURN 1;
END

SELECT @varosNev= (SELECT Nev FROM dbo.Varosok WHERE Id = @varosID)
SET @varosNev = @varosNev + '!'
RETURN 0;
END
GO

DECLARE @ret int;
DECLARE @varos NVARCHAR(100);

EXEC @ret = dbo.ReturnTest 2, @varos OUTPUT
SELECT @ret,@varos;
--früher eingegeben, damit dies nicht mehr überschrieben wird
EXEC @ret = dbo.ReturnTest -3, @varos OUTPUT
SELECT @ret,@varos;
GO

MISTAKE

GO
CREATE OR ALTER PROCEDURE dbo.PlaceOrder (@PaymentDate datetime2)
AS
IF @Zahlungsdatum > GETDATE()
THROW 50001, 'Eine Bestellung kann nicht in der Zukunft aufgegeben werden',1;
GO
EXEC dbo.PlaceOrder '2024-01-01'
------------------------------------------------
GO
CREATE OR ALTER PROCEDURE dbo.Osztas(@v1 INT, @v2 INT, @hanyados INT OUTPUT)
AS
BEGIN TRY
SET @hanyados = @v1 / @v2
RETURN 0;
END TRY
BEGIN CATCH
SET @hanyados=NULL;
RETURN 1;
END CATCH
GO
DECLARE @ertek INT,@ret INT;
EXEC @ret=dbo.Osztas 10,2, @ertek OUTPUT;
SELECT @ret, @ertek;
GO
DECLARE @ertek INT,@ret INT;
EXEC @ret=dbo.Instal 10,0, @ertek OUTPUT;
SELECT @ret, @ertek;

DEFAULT-Wert

GO
CREATE OR ALTER PROCEDURE dbo.Osztas(@v1 INT, @v2 INT= 3, @hanyados INT OUTPUT)
AS
BEGIN TRY
SET @hanyados = @v1 / @v2
RETURN 0;
END TRY
BEGIN CATCH
SET @hanyados=NULL;
RETURN 1;
END CATCH
GO
DECLARE @ertek INT,@ret INT;
EXEC @ret=dbo.Div 10, @hanyados = @ertek OUTPUT;
SELECT @ret, @ertek;
GO
DECLARE @ertek INT,@ret INT;
EXEC @ret=dbo.Instal 10,5, @ertek OUTPUT;
SELECT @ret, @ertek;

SET NOCOUNT EIN

GO
CREATE OR ALTER PROCEDURE dbo.TaroltEljarasVarosokOrsz odors
AS
BEGIN
SET NOCOUNT ON
SELECT v.Nev AS VarosNev
,o.Nev AS OrszagNev
FROM dbo.Varosok v
JOIN dbo.Orszagok o ON v.OrszagId=o.Id
WHERE v.Nev wie 'B%';
END
GO
EXEC dbo.TaroltEljarasVarosokOrszagok

Wie viele Zeilen wurden geändert?

GO
CREATE OR ALTER PROCEDURE dbo.VarosFrissites (@searchParam nvarchar(10), @affectedRows INT OUTPUT)
AS
BEGIN
UPDATE dbo.Varosok
SET Nev =LOWER(Nev)
WHERE Nev wie @searchParam;
SET @affectedRows=@@ROWCOUNT
END
GO

DECLARE @ar INT;
EXEC dbo.VarosFrissites 'B%', @ar OUTPUT;
PRINT @ar;

UDF:

- immer wieder neu starten
- nicht Zustand, gibt Datentyp
- Eingangsparameter
- gespeicherte Prozeduren können nicht aufgerufen werden

Typen:
- Systemfunktionen
- Tabellenwert: kann in der Ansicht nicht parametrisiert werden
- Skalare Werte: können in Select sein
- Aggregate < externe Sprachen z.B. .Net und C# Funktionen können importiert werden
https://learn.microsoft.com/en-us/sql/t-sql/statements/create-aggregate-transact-sql?view=sql-server-ver15

TRY-CATCH - FUNKTIONIERT NICHT!!!!!!!!!!!!!!!!
aber ich rufe von der Speicherprozedur aus auf und es ist da, dann ja

DDL, Einfügen, Aktualisieren, Löschen funktioniert nicht
USE WideWorldImporters;
Gehe zu
GO
CREATE OR ALTER FUNCTION Sales.function_date()
RETURNS datetime /* Angabe des Datentyps des zurückgegebenen Wertes */
AS
BEGIN
    /* Geben Sie Ihren Wert zurück */
    RETURN CURRENT_TIMESTAMP;
END;
GO
-- Funktion aufrufen
SELECT Umsatz.funktion_datum();

total_sum_orderline

GO
CREATE FUNCTION Sales.total_sum_orderline(
    @ordelineID int
)
RETURNS decimal(20,3) --WITH SCHEMABINDING - wir binden es an die Tabellenstruktur an, hilft manchmal bei der Leistung
AS
BEGIN
    RETURN (SELECT Menge*Einheitspreis FROM Verkauf.Auftragszeilen Where AuftragszeilenID = @ordelineID)
END;
GO
/*
    Verwendung der Skalar-UDF zur Rückgabe des Gesamtwerts der versteuerten Zeile
    in der SELECT-Klausel.
*/

SELECT Verkäufe.gesamtsumme_auftragszeile(2);
SELECT Menge*Einheitspreis FROM Sales.OrderLines Where OrderLineID = 2;
/* für jede Zeile Summe- wird langsam, Zählung pro Zeile und CPU wird hoch sein, wir mögen keine skalaren Funktionen */
SELECT OrderLineID,Sales.total_sum_orderline(2)
FROM Sales.OrderLines;

UDF Skalar-Inlining

- führt keine UDF aus, sondern zerlegt sie in Tabellenoperationen > weniger CPU - ADVANCED FEATURE
Ab 2019 haben wir neu verpackt
Sie müssen dem nachkommen:

Inlinebarer skalarer UDF-Anforderungsteil
https://learn.microsoft.com/en-us/sql/relational-databases/user-defined-functions/scalar-udf-inlining?view=sql-server-ver15
Kiegészítés: https://support.microsoft.com/en-us/topic/kb4538581-fix-scalar-udf-inlining-issues-in-sql-server-2022-and-2019-f52d3759-a8b7-a107-1ab9-7fbee264dd5d

- z.B. kann eine Rückgabe nur sein
- z.B. Scalar UDF inlining funktioniert nicht mit berechneter Spalte!

GO
CREATE OR ALTER FUNCTION dbo.total_sum_orderline(
    @ordelineID int
)
RETURNS decimal(20,3) WITH SCHEMABINDING -- wir binden es an die Tabellenstruktur an, das hilft manchmal der Leistung
AS
BEGIN
    RETURN (SELECT Menge*Einheitspreis FROM dbo.testlines Where OrderLineID = @ordelineID)
END;
GO
SELECT dbo.total_sum_orderline(2);
SELECT Menge*Einheitspreis FROM dbo.testlines Where OrderLineID = 2;
/* berechnete Spalte - wir verlieren das Inlining hier - bleiben innerhalb der Tabelle, wenn wir dies tun
wir verlieren es auch in der Prüfbeschränkung */
ALTER TABLE dbo.testlines
ADD totalsum AS dbo.total_sum_orderline(OrderID);

SELECT OrderLineID, Gesamtsumme FROM dbo.testlines
WHERE OrderLineID<200;
/*view-n - wir bevorzugen es hier zu verwenden */
GO
CREATE OR ALTER VIEW dbo.testview
MIT SCHEMABINDUNG
AS
SELECT OrderLIneID AS 'lineID
, dbo.total_sum_orderline(OrderLineID) as 'totalsum'
FROM dbo.testlines
GO
SELECT * FROM dbo.testview
WHERE LineID < 200;
/* Wenn die Ansicht mit Schemabiding eine skalare Funktion enthält, dann muss die skalare Funktion auch schemabiding sein!!! */
/* Constraint prüfen - Inlining funktioniert nicht */
ALTER TABLE dbo.testlines
ADD CONSTRAINT CK_test_1 CHECK (
(OrderLineID = 200);
UPDATE dbo.testlines
SET OrderLineID=1600
WHERE OrderLineID  500
    RETURN 500;

    RETURN @days;
END
GO
SELECT OrderID, OrderDate, dbo.datediffer(OrderID)
FROM dbo.testorders
WHERE OrderID  500
    BEGIN
        SET @days=500;
    END

    RETURN @days;
END
GO
SELECT OrderID, OrderDate, dbo.datediffer(OrderID)
FROM dbo.testorders
WHERE OrderID  500
    BEGIN
        SET @Tage=500;
    END

    RETURN @days;
END
GO
SELECT OrderID, OrderDate, dbo.datediffer(OrderID, GETDATE())
FROM dbo.testorders
WHERE OrderID  500
		BEGIN
			SET @Tage = 500;
		END
	RETURN @Tage
END
GO

SELECT OrderID,OrderDate,dbo.datediffer2(OrderDate,GETDATE()) AS 'days'
FROM dbo.testorders;

DEFAULT-Wert für skalare UDF

GO
CREATE OR ALTER FUNCTION dbo.defaultfn(@id int=6)
RETURNS int
AS
BEGIN
    RETURN @id;
END
GO
SELECT dbo.defaultfn(2);
SELECT dbo.defaultfn(default);

Funktionen mit Tabellenwert:

- Rückgabe immer mit Tabelle
- kein JOIN

Typen:
- inline tabellenwertige Funktionen iTVF > 1 SELECT STATEMENT;
- Multianweisung - MSTVF(schrecklich) - nicht verwenden, schlechte Optimierung

USE WideWorldImporters;
GO
/*
    Erstellen einer Inline-TVF zum Abrufen von ColorId und ColorName
*/
CREATE FUNCTION Warehouse.GetColor(@colorid int)
RETURNS TABLE
AS
RETURN
    (SELECT FarbeID, Farbname
     FROM Warehouse.Colors
     WHERE ColorID = @colorid);
GO
/*
    Verwendung der Inline-TVF in einer einfachen SELECT-Abfrage in der FROM-Klausel.
*/
SELECT FarbeId, Farbname
FROM WareHouse.GetColor(36);

SELECT FarbeId, Farbname
FROM WareHouse.GetColor(10);

DEFAULT-Wert bei TVF UDF

GO
CREATE OR ALTER FUNCTION Warehouse.GetColor(@colorid int=10)
RETURNS TABLE
AS
RETURN
(SELECT FarbeID, Farbname
FROM Warehouse.Colors
WHERE ColorID = @colorid);
GO
SELECT FarbeId, Farbname
FROM WareHouse.GetColor(default);

APPLY - CROSS APPLY wie innere Verknüpfung

SELECT StockItemID,StockItemName,ColorName
FROM LagerHaus.StockItems s
CROSS APPLY WareHouse.GetColor(s.ColorID) c;

APPLY - OUTER APPLY wie LEFT OR RIGHT OUTER join

SELECT StockItemID,StockItemName,ColorName
FROM LagerHaus.StockItems s
OUTER APPLY LagerHaus.GetColor(s.ColorID) c;

nichtfunktionaler Teil
Tischbetreiber:
Kreuzanwendung anstelle einer Unterabfrage (Rückgabe)
bestimmte Unterabfrage

cross apply anstelle von subquery (subquery liefert 1 Einzelwert)
zum Beispiel
https://github.com/green-fox-academy/teaching-materials/blob/master/workshop/sql-server-subqueries-aggregations/correlated-quantity/correlated-quantity.md
Ändern Sie die Abfrage wie folgt:
- eine neue Spalte hinzufügen, die die Höchstmenge für die StockItemID anzeigt
- eine weitere Spalte hinzufügen, in der die Differenz zwischen dem maximalen
Menge für die StockItemID und jede Bestellmenge
| OrderID | StockItemID | Menge | Max_StockItem_Qty | Max_Diff_Qty | Max_Diff_Qty

/* Version der Unterabfrage: 0.1452 */
SELECT o.OrderID
				,o.StockItemID
				,o.Menge
				,( SELECT MAX(Menge)
					FROM Umsatz.Auftragszeilen
					WHERE StockItemID = 180
				 ) AS Max_StockItem_Qty
				,(SELECT maxq.menge - Menge
						FROM ( SELECT MAX(Menge) AS qty
										FROM Verkauf.Auftragszeilen
										WHERE StockItemID = 180
								 ) AS maxq
				) AS Max_Diff_Qty
FROM Sales.OrderLines AS o
WHERE StockItemID = 180;
/* CROSS APPLY - Tabellenoperator Version - CROSS APPLY Kosten 0.102256 */
SELECT OrderId,StockItemID,Menge,Max_StockItem_Qty,Max_StockItem_Qty-Quantity AS Max_Diff_Qty
FROM Sales.OrderLines
	CROSS APPLY (SELECT MAX(Menge) AS Max_StockItem_Qty FROM Sales.OrderLines
		WHERE StockItemID=180) temptable
WHERE StockItemID = 180;

TRIGGERS

- Kann ich Trigger ausführen? > NEIN
- ein Ereignis aktiviert den Trigger ! "FEUER_AUSLÖSER"
- Kann ich dem Auslöser einen Parameter geben? -> NEIN
- IF ... ELSE Struktur verwendbar
- try ...catch strukturierte Fehlerbehandlung > YES
- einfachen Trigger erstellen
Auslösende Gruppen:
- DML-Auslöser: INSERT, UPDATE, DELETE > MASTERWORK
- DDL-Auslöser: ALTER,CREATE,DROP
- Anmeldetrigger

LOGON-Trigger: DANGEROUS! Die Anmeldung kann fehlschlagen

USE testdb;
DROP TABLE IF EXISTS dbo.logonsactivity;
CREATE TABLE dbo.logonsactivity (
    id INT NOT NULL IDENTITY(1,1) PRIMARY KEY,
    login VARCHAR(50),
    servername VARCHAR(50),
    serverversion VARCHAR(350),
    servicename VARCHAR(50),
    logintime datetime2 DEFAULT GETDATE()
);
-- Anmeldename
SELECT SUSER_NAME();
-- Servername \ (Instanz)
SELECT @@SERVERNAME;
-- Version des Servers
WÄHLEN SIE @@VERSION;
-- Dienstname (Instanzname ohne Server)
WÄHLEN SIE @@SERVICENAME;
/*Auslöser*/
GO
CREATE OR ALTER TRIGGER tr_logtouser
AUF ALLEN SERVERN FÜR DIE ANMELDUNG
AS
BEGIN
    INSERT INTO testdb.dbo.logonsactivity
    SELECT SUSER_NAME(),@@SERVERNAME,@@VERSION,@@SERVICENAME,CURRENT_TIMESTAMP;
END
GO
SELECT * FROM testdb.dbo.logonsactivity;
SELECT * FROM sys.server_triggers;
-- Logon-Trigger löschen
DROP TRIGGER tr_logtouser ON ALL SERVER;

DDL-Auslöser

DROP TABLE IF EXISTS dbo.Invoices;
CREATE TABLE dbo.Invoices (
    id INT PRIMARY KEY,
    kunden_id INT NOT NULL,
    gesamt INT NOT NULL
);
INSERT INTO dbo.Rechnungen
VALUES
(3,5,200),(4,9,10000), (20,9,14000);
GO
CREATE OR ALTER TRIGGER invoiceprotector ON DATABASE FOR DROP_TABLE, ALTER_TABLE
AS
BEGIN
PRINT 'Sie können keine Tabellen ändern oder löschen!'
ROLLBACK;
END
PRINT 'hallo';
GO
SELECT * FROM sys.triggers;
ALTER TABLE dbo.Invoices
DROP COLUMN total;
DROP TRIGGER invoiceprotector ON DATABASE;

DML-Auslöser:

- AFTER-Auslöser
- ANSTELLE DES AUSLÖSERS

NACH LÖSCHEN

DROP TABLE IF EXISTS dbo.storno_invoices
CREATE TABLE dbo.storno_Rechnungen (
    id INT, --PRIMARY KEY,
    kunden_id INT NOT NULL,
    total INT NOT NULL,
    delete_time DATETIME2 NOT NULL DEFAULT CURRENT_TIMESTAMP
);
/* AFTER TRIGGER - Trigger erstellen, um gelöschte Rechnungen in die Strono_Tabelle zu verschieben
SQL SERVER Trigger funktioniert per Anweisung!!!!!
- Vermeiden Sie Variablen! */
GO
CREATE TRIGGER dbo.TR_stroni_invoice ON dbo.Invoices AFTER DELETE
AS
NOCOUNT ON SETZEN;
BEGIN
    INSERT INTO dbo.storno_rechnungen (id, kunden_id,gesamt)
    SELECT * FROM gelöscht;
END
GO
SELECT * FROM dbo.Rechnungen;
SELECT * FROM dbo.storno_Rechnungen;

DELETE FROM dbo.Rechnungen
WHERE gesamt > 1000;

SELECT * FROM dbo.Rechnungen;
SELECT * FROM dbo.storno_invoices;

Auslöser für die Ablehnung erstellen: Rechnung ändern

GO
CREATE OR ALTER TRIGGER dbo.tr_forbidden_modify_invoice
ON dbo.Invoices
AFTER UPDATE
AS
NOCOUNT ON SETZEN;
BEGIN
ROLLBACK;
END
GO
SELECT * FROM dbo.Invoices;

UPDATE dbo.Rechnungen
SET gesamt=1000
WHERE id=3;

INSERT INTO dbo.Rechnungen
VALUES (25,9,2000),(92,20,20000),(100,19,21000);
UPDATE dbo.Rechnungen
SET gesamt=1000
WHERE id=3;

Wo sind die DML-Auslöser?

!!!!! TRUNCATE kann nicht mit Triggern aktiviert werden !!!!!!!!!!

INSTAD OF triggers? > DML-Auslöser

z.B. bei samlak gehen die Großen anderswo selten

einen Auslöser erstellen
where gesamt >= 1100 > dbo.Invoces

wo gesamt dbo.smalltotalinvoices

DROP TABLE IF EXISTS dbo.smalltotalinvoices
  CREATE TABLE dbo.smalltotalinvoices (
    id INT PRIMARY KEY,
    kunden_id INT NOT NULL,
    gesamt INT NOT NULL
);
SELECT * FROM dbo.Invoices;
GO
CREATE OR ALTER TRIGGER dbo.tr_smalltotal
ON dbo.Invoices
ANSTELLE VON INSERT
AS
NOCOUNT EINSCHALTEN;
BEGIN
 INSERT INTO dbo.Rechnungen
 SELECT * FROM eingefügt
 WHERE gesamt >=1100;

 INSERT INTO dbo.smalltotalinvoices
 SELECT * FROM eingefügt
 WHERE gesamt < 1100;
END
GO
 INSERT INTO dbo.Rechnungen
 VALUES(3,200,50000);

  INSERT INTO dbo.Rechnungen
 WERTE(5,200,900);

SELECT * FROM dbo.Rechnungen;
SELECT * FROM dbo.smalltotalinvoices;

Bulk Insert ignoriert den Trigger standardmäßig

bulk insert dbo.Invoices
  FROM N'C:\Benutzer\mrhen\Dokumente\READER\MatReview\WEEK-4\w1d1_smalltotal.csv'
  WITH (fieldterminator=';',rowterminator='0x0A'/* nicht '\n', weil es von Zoli stammt, FIRSTROW=2, wenn es eine Kopfzeile gibt*/)
TRUNCATE TABLE dbo.invoices;
TRUNCATE TABLE dbo.smalltotalinvoices;
/* DE FIRE_TRIGGERS */
Bulk-Insert dbo.Invoices
  FROM 'C:\Benutzer\mrhen\Dokumente\READER\MatReview\WEEK-4\w1d1_smalltotal.csv'
  WITH (fieldterminator=';',rowterminator='0x0A', FIRE_TRIGGERS/* nicht '\n', weil es von Zoli war, FIRSTROW=2, wenn es eine Kopfzeile gibt*/)

SELECT * FROM dbo.Invoices;
SELECT * FROM dbo.smalltotalinvoices;
SELECT * FROM sys.triggers;
DROP TRIGGER dbo.TR_stroni_invoice, dbo.tr_forbidden_modify_invoice, dbo.tr_smalltotal;

Funktion des Fensters

- Fensteraggregatfunktionen (COUNT, SUM, MIN, MAX)
- Ranking-Funktionen (ROW_NUMBER, RANK, DENSE_RANK, NTILE)
- Offset-Funktionen (LAG, LEAD, FIRST_VALUE, LAST_VALUE)
- Statistische Funktionen (PERCENTILE_CONT, PERCENTILE_DISC, PERCENT_RANK, CUME_DIST)

OVER() == Fensterfunktion / SELECT /

Zeilensätze, gegeben einen Zeilensatz des Fensters,

USE WideWorldImporters;
GO
/* stockitemid, sum_stock_quantities */
SELECT StockItemId, SUM(Menge) AS sum_stock_quantities
FROM Verkäufe.OrderLines
GROUP BY StockItemID;
GO
SELECT SUM(Menge) AS sum_all_quantities
FROM Sales.OrderLines;
/* FELADAT
orderlineid stockitems sum_stock sum_all
1 1 20000 9Millionen
2 1 20000
3 2 1000
*/
WITH myCTE AS (
    SELECT StockItemId, SUM(Menge) AS sum_stock_quantities
    FROM Verkauf.Auftragszeilen
    GROUP BY StockItemID
),
myCTE2 AS (
    SELECT SUM(Menge) AS sum_all_quantities
    FROM Sales.OrderLines
)
SELECT sol.StockItemID,OrderLineID, myCTE.sum_stock_quantities,myCTE2.sum_all_quantitis, FORMAT(myCTE.sum_stock_quantities/(myCTE2.sum_all_quantitis*1.0),'P2') AS pct_all_quantity
FROM Sales.OrderLines sol
INNER JOIN myCTE ON myCTE.StockItemID=sol.StockItemID
CROSS JOIN myCTE2
ORDER BY sol.[StockItemID] ASC, OrderLineID ASC;
/*REPLACING CTE2 mit Fensterfunktion */
SELECT SUM(Menge) OVER ()
FROM Sales.OrderLines;
/*Ersetzen von CTE1 durch neue Funktion*/
SELECT SUM(Menge) OVER (PARTITION BY StockItemID)
FROM Sales.OrderLines;
/* Version der Fensterfunktion */
SELECT sol.StockItemID,
OrderLineID,
SUM(Menge) OVER (PARTITION BY StockItemID) AS sum_stock_quantitis,
SUM(Menge) OVER () AS sum_all_quantities
, FORMAT(SUM(Menge) OVER (PARTITION BY StockItemID)/(SUM(Menge) OVER ()*1.0),'P2') AS pct_all_quantity
FROM Sales.OrderLines sol
ORDER BY sol.[StockItemID] ASC, OrderLineID ASC;

fensterfunktion nach gruppe nach

SELECT sol.StockItemID,
SUM(Menge) /*OVER (PARTITION BY StockItemID)*/ AS sum_stock_quantitis,
SUM(SUM(Menge)) OVER () AS sum_all_quantities
, FORMAT(SUM(Menge) /*OVER (PARTITION BY StockItemID)*//(SUM(SUM(Menge)) OVER ()*1.0),'P2') AS pct_all_quantity
FROM Sales.OrderLines sol
GROUP BY StockItemID
ORDER BY sol.[StockItemID] ASC;

Ranking-Funktionen

Syntaxvoraussetzung: ORDER BY innerhalb der OVER-Klausel

ZEILEN_NUMMER, RANG, DENSE_RANK, NTILE

SELECT OrderId, Customerid,OrderDate,
    ROW_NUMBER() OVER (ORDER BY OrderDate) AS ROW_NUMBER
    , Rank() OVER(ORDER BY OrderDate) AS rnk -- tote Rennen werden übersprungen und der nächste Rang in der Zeile
    , DENSE_RANK() OVER(ORDER BY OrderDate) AS dense_rnk -- Sackgassen beim nächsten Rang
    NTILE (20) OVER(ORDER BY OrderDate) AS n_tile -- in 20 Teile unterteilen, Haufen zurückgeben
FROM Verkauf.Aufträge;

Rangfolge nach orderid pro customerid

SELECT OrderId, CUstomerid,OrderDate,
    ROW_NUMBER() OVER (PARTITION BY CustomerID ORDER BY OrderDate) AS ROW_NUMBER
    , Rang() OVER(PARTITION BY CustomerID ORDER BY OrderDate) AS rnk
    , DENSE_RANK() OVER(PARTITION BY CustomerID ORDER BY OrderDate) AS dense_rnk
    , NTILE (10) OVER(PARTITION BY CustomerID ORDER BY OrderDate) AS n_tile -- in 20 Teile unterteilen, Haufen zurückgeben
FROM Verkauf.Aufträge;

Webshop-Bestellung, welche Artikel in der Bestellung enthalten sind - Gesamtbetrag, Bestellzeile_Nummer

SELECT OrderId,
StockItemID,
Menge,
StückPreis,
(Stückpreis*Menge) AS OrderLine_SUM,
ROW_NUMBER() OVER (PARTITION BY OrderID ORDER BY (SELECT NULL)) AS orderline_number,
SUM(Stückpreis*Menge) OVER (PARTITION BY OrderID Order BY OrderLineID) as running_total
 FROM Vertrieb.OrderLines;

 SELECT OrderId,
StockItemID,
Menge,
Stückpreis,
OrderLineID,
(Stückpreis*Menge) AS OrderLine_SUM,
ROW_NUMBER() OVER (PARTITION BY OrderID ORDER BY (SELECT NULL)) AS orderline_number,
SUM(Stückpreis*Menge) OVER (PARTITION BY OrderID Order BY OrderLineID DESC) as running_total
 FROM Vertrieb.OrderLines;

laufende Summe

SELECT CityID, CityName, LatestRecordedPopulation AS population,
       (SELECT SUM(AktuellsteBevölkerungszahl)
        FROM Anwendung.Städte c2
        WHERE c2.StateProvinceID = c1.StateProvinceID AND c2.CityID <= c1.CityID) AS run_total
FROM Anwendung.Städte c1
WHERE StateProvinceID = 6
ORDER BY StadtID;
/* Version der Windows-Funktion */
 SELECT CityID, CityName, LatestRecordedPopulation,
 SUM(LatestRecordedPopulation) OVER(ORDER BY CityID) as run_total
FROM Anwendung.Städte
WHERE StateProvinceID = 6

Offset-Funktion
(RÜCKSTAND, VORSPRUNG, ERSTER_WERT, LETZTER_WERT)

/* nächste StadtID */
SELECT StadtID, Stadtname, (SELECT MIN(StadtID) FROM Anwendung.Städte c2 WHERE c2.StadtID > c1.StadtID) AS nextcityid
FROM Anwendung.Städte c1
ORDER by StadtID ASC;
/* windows funktion auftrag */
SELECT StadtID, Stadtname, LEAD(StadtID) OVER(ORDER BY StadtID) AS nextcityid
FROM Anwendung.Städte
ORDER by StadtID ASC;

SELECT StadtID, Stadtname, LAG(StadtID) OVER(ORDER BY StadtID) AS nextcityid
FROM Anwendung.Städte
ORDER BY CityID ASC;

DIAGNOSEABFRAGEN

Abfrage von Tabellen aus sys.tables

SELECT * FROM sys.tables;

Tabellen und ihre Schemata - Verbindung der Katalogansichten sys.tables und sys.schemas

SELECT t.name AS [tabellenname], t.type_desc, s.name AS [schema_name]
FROM sys.tables t INNER JOIN sys.schemas s ON
t.schema_id = s.schema_id;

in welcher Sitzung wir uns befinden

SELECT @@SPID;

Spaltendatentypinformationen für alle Benutzertabellen abrufen

SELECT c.object_id, OBJECT_NAME(c.object_id) AS [object_name],
s.name AS [schema], o.name AS [table_name], c.name AS [col_name],
type.name AS [col_type],
CASE c.is_nullable WHEN 1 THEN 'yes' ELSE 'no' END AS [nullable]
FROM sys.columns c INNER JOIN sys.objects o ON
c.object_id = o.object_id
INNER JOIN sys.tables t ON
t.object_id = o.object_id
INNER JOIN sys.types typ ON
c.user_type_id = typ.user_type_id
INNER JOIN sys.schemas s ON
s.schema_id = t.schema_id;

Zählindex pro Tabelle

SELECT S.name,COUNT(SYS.INDEXES.name) FROM SYS.INDEXES
INNER JOIN SYS.OBJECTS S
ON S.OBJEKT_ID=SYS.INDIZES.OBJEKT_ID
WHERE SYS.INDEXES.OBJECT_ID IN (SELECT OBJECT_ID FROM SYS.OBJECTS WHERE name IN
    (SELECT name FROM SYS.TABLES WHERE NAME  'SYSDIAGRAMS'))
GROUP BY S.name;

Listenindex pro Tabelle

SELECT S.name,SYS.INDEXES.name FROM SYS.INDEXES
INNER JOIN SYS.OBJECTS S
ON S.OBJEKT_ID=SYS.INDIZES.OBJEKT_ID
WHERE SYS.INDEXES.OBJECT_ID IN (SELECT OBJECT_ID FROM SYS.OBJECTS WHERE name IN
    (SELECT NAME FROM SYS.TABLES WHERE name  'SYSDIAGRAMS'));

Anzahl der Beschränkungen (Prüfung+Standard) in der Datenbank

SELECT (SELECT COUNT(*) FROM sys.check_constraints)+(SELECT COUNT(*) FROM sys.default_constraints);

Deterministisch?

SELECT COLUMNPROPERTY(OBJECT_ID('dbo.testlines'),'total_price','isDeterministic') AS Determ;

Select * FROM sys.computed_columns;

Suche nach Spaltennamen

SELECT *
FROM INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME LIKE '%region%'

Suche nach Tabellennamen

SELECT c.object_id, OBJECT_NAME(c.object_id) AS [object_name], s.name AS [schema], o.name AS [table_name], c.name AS [col_name], typ.name AS [col_type]
, CASE c.is_nullable WHEN 1 THEN 'yes' ELSE 'no' END AS [nullable] FROM sys.columns c
INNER JOIN sys.objects o ON c.object_id = o.object_id
INNER JOIN sys.tables t ON t.object_id = o.object_id
INNER JOIN sys.types typ ON c.user_type_id = typ.user_type_id
INNER JOIN sys.schemas s ON s.schema_id = t.schema_id
WHERE c.name LIKE '%Postal%'

Suche nach einer Zeichenkette in der Datenbank

DECLARE @SearchStr nvarchar(100)
SET @SearchStr = 'Begrenzter Bestand

DECLARE @Results TABLE(ColumnName nvarchar(370), ColumnValue nvarchar(3630))

SET NOCOUNT ON

DECLARE @Tabellenname nvarchar(256), @Spaltenname nvarchar(128), @SuchStr2 nvarchar(110)
SET @Tabellenname = ''
SET @SuchStr2 = QUOTENAME('%' + @SuchStr + '%','''')

WHILE @Tabellenname IST NICHT NULL
BEGIN
    SET @SpaltenName = ''
    SET @Tabellenname =
    (
        SELECT MIN(QUOTENAME(TABELLEN_SCHEMA) + '.' + QUOTENAME(TABELLENNAME))
        FROM INFORMATION_SCHEMA.TABLES
        WHERE TABLE_TYPE = 'BASISTABELLE'
            AND QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME) > @TableName
            UND OBJECTPROPERTY(
                    OBJECT_ID(
                        QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME)
                         ), 'IsMSShipped'
                           ) = 0
    )

    WHILE (@Tabellenname IST NICHT NULL) AND (@Spaltenname IST NICHT NULL)
    BEGIN
        SET @SpaltenName =
        (
            SELECT MIN(QUOTENNAME(SPALTEN_NAME))
            FROM INFORMATION_SCHEMA.SPALTEN
            WHERE TABLE_SCHEMA = PARSENAME(@Tabellenname, 2)
                AND TABLE_NAME = PARSENAME(@Tabellenname, 1)
                AND DATA_TYPE IN ('char', 'varchar', 'nchar', 'nvarchar')
                AND QUOTENAME(COLUMN_NAME) > @ColumnName
        )

        IF @Spaltenname IST NICHT NULL
        BEGIN
            INSERT INTO @Ergebnisse
            EXEC
            (
                'SELECT ''' + @Tabellenname + '.' + @Spaltenname + '''', LEFT(' +
@SpaltenName
+ ', 3630) FROM '
+
@Tabellenname
+ ' (NOLOCK) ' +
                ' WHERE '
+
@SpaltenName
+ ' LIKE '
+
@SuchStr2
                
            )
        END
    END
END

SELECT SpaltenName, SpaltenWert FROM @Ergebnisse

Sys.messages & Ändern der Sprache in der Sitzung

8134 Systemfehlermeldungen > diagn. Abfrage
SELECT * FROM sys.messages
WHERE message_id=8134;
/* Sprache in der Sitzung ändern */
SET LANGUAGE ungarisch;
PRINT 10/0;
SET LANGUAGE englisch;
PRINT 10/0;

VIEW-Diagnoseabfrage

SELECT * FROM sys.sql_modules WHERE [object_id] = OBJECT_ID('VarosokOrszagok2');
Datenbankprotokolle pro Datenbank-ID
SELECT b.name,a.* FROM sys.databases b
CROSS APPLY sys.dm_db_log_info(b.datenbank_id) a
WHERE b.name = 'WideWorldImporters';

alle TRIGGER auflisten

SELECT * FROM sys.sql_modules WHERE [object_id] = OBJECT_ID('VarosokOrszagok2');

gesperrte Objekte erkennen

SELECT ressource_type,request_status, request_mode, o.object_id, o.name, o.type_desc
FROM sys.dm_tran_locks l, sys.objects o
WHERE l.resource_associated_entity_id = o.object_id
    und resource_database_id = DB_ID();

Isolationsniveau erkennen

SELECT CASE transaction_isolation_level
    WHEN 0 THEN 'Nicht spezifiziert'
    WHEN 1 THEN 'ReadUncommitted'
    WHEN 2 THEN 'ReadCommitted'
    WHEN 3 THEN 'Wiederholbar
    WHEN 4 THEN 'Serialisierbar
    WHEN 5 THEN 'Snapshot' END AS TRANSACTION_ISOLATION_LEVEL
FROM sys.dm_exec_sessions
-- Verwenden Sie Ihre Sitzungs-ID anstelle von 75
where session_id = 75;

SQL-Quiz

 

https://github.com/green-fox-academy/safely-syllabus/tree/master/materialreview/mssql

##### SQL-Fonds ######

SELECT IN SELECT, WHERE IN, WHERE NOT IN

SELECT TOP (1000) [SAMLAHEAD_ID]
      ,[VEVO_ID]
      ,[CELTE]
      ,[TELJESITES]
      ,[FIZHATARIDO]
      ,[NAVATKULDVE]
      ,[STATUS]
  FROM [CEGESADATOK].[samlazas].[samlahead].
  WHERE VEVO_ID Not IN (select vevo_id
						from samlazas.vevo)

UPDATE

VERWENDUNG [CEGESADATA]
GO

UPDATE [samlazas].[vevo]
   SET [STATUS] = 1
      ,[LASTUPDATE] = (GETDATE())
 WHERE STATUS=0
GO

INSERT INTO

VERWENDUNG [CEGESADATA]
GO

INSERT INTO [samlazas].[vevo]
           ([VEVONEV], [ADOSZAM], [CIM])
     VALUES
           ('öTÖDIK Nyrt','3499789012-4-04','4000 Kisvarda, Negyedik utca. 5'),
		   ('Hatodik Nyrt','3456789099-4-04','4000 Kisvarda, Negyedik utca. 6')
GO
/* MASIK */
USE [CEGESDATA]
GO

INSERT INTO [samlazas].[vevo]
           ([VEVONEV]
           ,[ADOSZAM]
           ,[CIM]
           ,[PHONE]
           ,[EMAIL]
           ,[STATUS])
     VALUES
           ('Hetedik Bt,
           '11223344-2-05',
           'Keine',
           '',
            null,
           0)
GO

DELETE

CEGESDATA BENUTZEN
Weiter zu

SELECT *
FROM szamlazas.szamlatetel
WHERE SZAMLAFEJ_ID Not IN (SELECT SZAMLAFEJ_ID
							FROM samlazas.samlahead)


SELECT HEAD_ID
FROM samlazas.samlahead

DELETE FROM samlazas.samlatetel
WHERE SZAMLAFEJ_ID Nicht IN (SELECT SZAMLAFEJ_ID
							FROM samlazas.samlahead)
GO

DISTINCT

SELECT DISTINCT v.*
FROM szamlazas.vevo v INNER JOIN szamlazas.szamlahead szf ON v.VEVO_ID=szf.VEVO_ID
WHERE v.STATUS=1 und szf.STATUS='normal'

KONVERTIEREN, AVG

SELECT *
  FROM [CEGESADATOK].[szamlazas].[ARU]

SELECT AVG(ASEGAR)
  FROM [CEGESADATOK].[samlazas].[ARU]


SELECT *
  FROM [CEGESADATOK].[samlazas].[ARU]
  wo EGYSEGAR < (SELECT AVG(EGYSEGAR) as EGYSEGAR
					FROM [CEGESADATOK].[samlazas].[ARU])

SELECT ARU_ID, ARUNEV, MENNYEGYS,CONVERT(int,EGYSEGAR) as EGYSEGAR, CONVERT(int,AFAKULCS) as AFAKULCS, STATUS
  FROM [CEGESADATOK].[szamlazas].[ARU]
  wo EGYSEGAR < (SELECT AVG(EGYSEGAR) as EGYSEGAR
					FROM [CEGESADATOK].[samlazas].[ARU])

FROMART, KONVERTIEREN

select getdate()
select FORMAT(getdate(), 'jjjj')
wähle FORMAT(getdate(), 'jjjj/MM')
wähle FORMAT(getdate(), 'jjjj/MM/dd')
select FORMAT(getdate()+1, 'jjjj/MM/tt')
wähle FORMAT(getdate()-2, 'jjjj/MM/tt')
select FORMAT(getdate(), 'jjjj/MM/tt HH:mm:ss.ms')

select '2022/3/15'
select CONVERT(datetime, '2022/3/25')

HABEN

/*Aufgabe:
Finde die Namen, Adressen, Steuernummern und die Anzahl der Käufe von Kunden, die mindestens zwei Käufe getätigt haben
FALSCH:
select v.VEVONEV
from szamlazas.vevo v inner join szamlazas.szamlafej szf on v.VEVO_ID=szf.VEVO_ID
where (select COUNT(szf.VEVO_ID)
							aus szamlazas.szamlafej
							group by szf.VEVO_ID) > 1
GROUP by v.VEVONEV
*/

select COUNT(szf.VEVO_ID), szf.VEVO_ID
							aus szamlazas.szamlafej szf
							gruppieren nach szf.VEVO_ID

select v.VEVONEV,v.CIM, v.ADOSZAM,
	COUNT(szf.VEVO_ID) as VASARLASSZAM
from szamlazas.vevo v inner join szamlazas.szamlafej szf on v.VEVO_ID=szf.VEVO_ID
GROUP by v.VEVONEV,v.CIM, v.ADOSZAM
HAVING COUNT(szf.VEVO_ID) >=2
ORDER BY VASARLASSZAM

/*Aufgabe:
Ermitteln des Namens, der Adresse, der Steuernummer und der Anzahl der Einkäufe, Bruttosumme*/
select v.VEVO_ID,v.VEVONEV,v.CIM, v.ADOSZAM,
	CONVERT(int,SUM(t.[BRUTTO ERTEK])) as SUM
from szamlazas.vevo v inner join szamlazas.szamlafej szf on v.VEVO_ID=szf.VEVO_ID
inner join samlazas.tetelek t on szf.SZAMLAFEJ_ID=t.SZAMLAFEJ_ID
GROUP by v.VEVO_ID,v.VEVONEV,v.CIM, v.ADOSZAM
ORDER BY SZUMMABRUTTO desc


select v.VEVO_ID,v.VEVONEV,v.CIM, v.ADOSZAM,
	CONVERT(int,SUM(t.MENNYISEG*a.EGYSEGAR*(a.AFAKULCS/100+1))) as SUMABRUTTO
from szamlazas.vevo v inner join szamlazas.szamlafej szf on v.VEVO_ID=szf.VEVO_ID
inner join samlazas.szamlatetel t on szf.SZAMLAFEJ_ID=t.SZAMLAFEJ_ID
inner join samlazas.ARU a on t.ARU_ID=a.ARU_ID
WHERE v.CIM like '%Budapest%'
GROUP by v.VEVO_ID,v.VEVONEV,v.CIM, v.ADOSZAM
HAVING CONVERT(int,SUM(t.MENNYISEG*a.EGYSEGAR*(a.AFAKULCS/100+1))) > 121000
ORDER BY SUMABRUTTO desc

KONSISTENT FIX

CEGESADATOK verwenden
gehen Sie zu

szamlazas.szamlafej aktualisieren
	set STATUS='Fehler'
where SZAMLAFEJ_ID not in (select SZAMLAFEJ_ID from szamlazas.szamlatetel)

weiter zu

SOK JOIN, SOK WHERE

USE CEGESDATA
GO

/* Wer hat A7 gekauft?*/
VEVONEV auswählen
Von samlazas.vevo
WHERE VEVO_ID IN (select VEVO_ID
					FROM samlazas.samlahead
					WHERE SZAMLAFEJ_ID in (select SZAMLAFEJ_ID
											From samlazas.szamlatetel
											where ARU_ID IN (select ARU_ID
																von samlazas.ARU
																where ARUNEV='A7')))


select v.*
FROM szamlazas.vevo v
INNER JOIN samlazas.samlahead f ON v.VEVO_ID=f.VEVO_ID
	INNER JOIN samlazas.szamlatetel t ON f.SZAMLAFEJ_ID=t.SZAMLAFEJ_ID
		INNER JOIN samlazas.ARU a ON t.ARU_ID=a.ARU_ID
			WHERE a.ARUNEV='A7'
ORDER BY VEVO_ID

select *
From szamlazas.vevo v INNER JOIN szamlazas.szamlazfej sz ON v.VEVO_ID=sz.VEVO_ID
INNER JOIN samlazas.tetelek t ON sz.SZAMLAFEJ_ID=t.SZAMLAFEJ_ID
wo t.ARUNEV='A7'




select *
FROM samlazas.samlahead
WHERE SZAMLAFEJ_ID in (select SZAMLAFEJ_ID
						From samlazas.szamlatetel
						where ARU_ID IN (select ARU_ID
											von samlazas.ARU
											where ARUNEV='A7'))

select *
Von szamlazas.szamlatetel
wo ARU_ID IN (select ARU_ID
					von szamlazas.ARU
					wo ARUNEV='A7')

/*
wähle *
From samlazas.tetelek t INNER JOIN samlazas.samlafej sz ON t.SZAMLAFEJ_ID=sz.SZAMLAFEJ_ID
wo ARUNEV='A7'

select *
From samlazas.vevo v INNER JOIN (samlazas.tetelek t INNER JOIN samlazas.samlahead sz ON t.SZAMLAFEJ_ID=sz.SZAMLAFEJ_ID) ON
where ARUNEV='A7'
*/

QUERY VIEW TO

USE CEGESDATA
GO

SELECT t.*, a.ARUNEV, a.MENNYEGYS, a.EGYSEGAR, a.EGYSEGAR*t.MENNYISEG as 'Netto ertek', a.EGYSEGAR*t.MENNYISEG*(a.AFAKULCS/100) as 'AFA ERTEK'
, (a.EGYSEGAR*t.MENNYISEG*(a.AFAKULCS/100))+(a.EGYSEGAR*t.MENNYISEG) als 'GROSS ERTEK'
FROM szamlazas.szamlatetel t INNER JOIN szamlazas.ARU a ON t.ARU_ID=a.ARU_ID
/*WHERE (t.ARU_ID=a.ARU_ID)*/

SELECT *
FROM samlazas.tetelek

VIEW ERSTELLEN

create view samlazas.bad_samla_head
als
wähle *
from samlazas.samlahead
where VEVO_ID not in (select vevo_id from szamlazas.vevo)

Schema erstellen

VERWENDUNG [CEGESADATA]
GO

/****** Objekt: schema [samlazas] Skript Datum: 2022. 10/25 0:11:57 ******/
CREATE SCHEMA [samlazas]
GO

Benutzer anlegen, Login, Berechtigungen, Rollen

USE [master]
GO
CREATE LOGIN [test1] WITH PASSWORD=N'Password123', DEFAULT_DATABASE=[CEGESADATOK], CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF
GO
USE [CEGESADATOK]
GO
CREATE USER [test1] FOR LOGIN [test1]
GO
USE [CEGESDATA]
GO
ALTER ROLE [db_backupoperator] ADD MEMBER [test1]
GO
USE [CEGESDATA]
GO
ALTER ROLE [db_datareader] ADD MEMBER [test1]
GO
USE [CEGESADATA]
GO
ALTER ROLE [db_datawriter] ADD MEMBER [test1]
GO
USE [CEGESDATA]
GO
ALTER ROLE [db_ddladmin] ADD MEMBER [test1]
GO
USE [CEGESDATA]
GO
ALTER ROLE [db_securityadmin] ADD MEMBER [test1]
GO

Tabelle löschen, Tabelle abschneiden

/****** Skript für den Befehl SelectTopNRows aus SSMS ******/
SELECT TOP (1000) [SAMLAHEAD_ID]
      ,[VEVO_ID]
      ,[KELTE]
      ,[TELJESITES]
      ,[FIZHATARIDO]
      ,[NAVATKULDVE]
      ,[STATUS]
  VON [CEGESADATOK].[samlazas].[samlahead].

  Tabelle szamlazas.szamlafej abschneiden

  bulk insert samlazas.samlahead
  FROM N'E:\szamlafej.table.csv'
  with (feldterminator=';',rowterminator='\n')

######3 Prüfung SQL #######

Tabellen erstellen (Tabelle erstellen)

CREATE TABLE Lehrlinge(
	id int,
	name varchar(50),
	Alter int,
	land varchar(50),
	kohorte_id int)

CREATE TABLE kohorten(
	id int,
	name varchar(50),
	start_at datum,
	typ varchar(50))

Tabellen importieren (Bulk Insert)

/****** Script für den Befehl SelectTopNRows aus SSMS ******/
  Bulk-Insert Lehrlinge
  FROM N'E:\apprentices.table.csv'
  WITH (fieldterminator=';',rowterminator='\n'/*, FIRSTROW=2 ha van fejlec*/)

  bulk insert kohorten
  FROM N'E:\cohorts.table.csv'
  WITH (fieldterminator=';',rowterminator='\n')

Auflistung des Namens (name) und des Anfangsdatums (started_at) aller Kohorten (Tabelle cohorts)
Dateiname: kohorten.sql

SELECT name, start_at
 FROM kohorten

Geben Sie den Namen und das Herkunftsland aller Schüler an (Tabelle für Auszubildende)
Dateiname: lehrlinge.sql

SELECT Name, Land
FROM Auszubildende

Geben Sie den Namen und das Alter der Schüler (Tabelle der Auszubildenden) an, die jünger als 21 Jahre sind.
Dateiname: lehrlinge-juenger-21.sql

SELECT Name, Alter
FROM Auszubildende
WHERE Alter < 21

Geben Sie die Kennung und den Namen der Auszubildenden (Tabelle) an, die nicht aus Ungarn (Land) stammen.
Dateiname: lehrlinge-nicht-aus-hu.sql

SELECT id, name
FROM Auszubildende
WHERE Land nicht wie 'Ungarn'

Geben Sie an, wie viele Schüler (Lehrlingstabellen) in der Datenbank 20 oder mehr und 30 oder weniger Jahre alt sind.
Dateiname: lehrlinge-zwischen-20-und-30.sql

SELECT count(id)
FROM Auszubildende
WHERE Alter >= 20 und Alter <= 30

Geben Sie an, wie viele Kohortentabellen in der Datenbank vom Typ "Teilzeit" sind (Typ)
Dateiname: kohorten-teilzeit.sql

SELECT count(id)
FROM kohorten
WHERE Typ wie 'Teilzeit'

Geben Sie den Namen des Auszubildenden (als "apprentice_name") und den Namen der Kohorte (als "cohort_name") für Studierende an, die ihr Studium in den Kohorten 2018 begonnen haben.
Dateiname: lehrlinge-in-2018.sql

SELECT a.name as auszubildende_name, c.name as kohorte_name
FROM auszubildende a INNER JOIN kohorten c ON a.kohorten_id=c.id
WHERE FORMAT(beginn_am, 'jjjj')=2018

Geben Sie die Anzahl der Klassen in der Datenbank an, für die es keine Schüler in der Datenbank gibt.
Dateiname: kohorten-ohne-auszubildende.sql

SELECT count(id)
FROM kohorten
WHERE id NOT IN (SELECT kohorten_id FROM auszubildende)

Führen Sie die Namen der Teilnehmer und das Datum des Beginns der Ausbildung in alphabetischer Reihenfolge auf
Dateiname: auszubildende-start-datum-geordnet.sql

SELECT a.name, c.started_at
FROM lehrlinge a INNER JOIN kohorten c ON a.kohorten_id=c.id
ORDER BY a.name

Auflistung der Namen der Klassen und der Anzahl der Auszubildenden (als numberOfApprentices) in der jeweiligen Klasse, in absteigender Reihenfolge der Anzahl der Auszubildenden. Einschließlich der Kohorte, die derzeit 0 Auszubildende hat.
Dateiname: kohorte-grössen.sql

SELECT c.name, count(a.id) as numberOfApprentices
FROM kohorten c LEFT JOIN auszubildende a ON a.kohorten_id=c.id
GROUP BY c.name
ORDER BY count(a.id) DESC

###### SQL-Administrator-Projektaufgaben ######

1) Dem Server wird eine Festplatte hinzugefügt, die noch nicht in Gebrauch ist
(20 GB) Fügen Sie S: als Laufwerk und Volume-Namen hinzu:
SQLDATA sollte sein.

2) Erstellen Sie auf dem Laufwerk S: ein Verzeichnis SQLDATA, und darin
zwei weitere Unterverzeichnisse namens DB und LOG.

3) Melden Sie sich am SQL-Server (GREENFOX-Instanz) an (Dieser Schritt
Sie müssen es nicht speichern! :-)

4) Stellen Sie die Datei C:\install\MSSQL\AdventureWorks2016.bak wieder her.
Datenbank auf die GREENFOX-Instanz des Servers, damit die Datenbank
Dateien befinden sich in S:\SQLDATA\DB, während die Protokolldateien in S:\SQLDATA\
LOG-Bibliothek.

 
USE [master]
RESTORE DATABASE [AdventureWorks2016] FROM DISK = N'C:\install\MSSQL\AdventureWorks2016.bak' WITH FILE = 1, MOVE N'AdventureWorks2016_Data' TO N'S:\SQLDATADB\AdventureWorks2016_Data.mdf', MOVE N'AdventureWorks2016_Log' TO N'S:\SQLDATA\LOG\AdventureWorks2016_Log.ldf', NOUNLOAD, STATS = 5

GO

5) Erstellen Sie ein authentifiziertes interface_svc MS SQL-Konto,
mit minimalen (öffentlichen) Rechten! Ihr Passwort sollte INTERface lauten.

USE [master]
GO
CREATE LOGIN [interface_svc] WITH PASSWORD=N'INTERFACE', DEFAULT_DATABASE=[master], CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF
GO

6) Erstellen Sie eine Datenbank namens INTERFACE mit den folgenden Einstellungen:
- Name der Datenbank: INTERFACE
- Eigentümer: interface_svc
- Einziehungsmodell: FULL
- Ursprüngliche Datenbankdatei:
(a)Größe: 32 MByte
(b)Standort: S:\SQLDATA\DB
- Startup-Protokolldatei:
(a) Größe: 16 MByte
(b)Standort: S:\SQLDATA\LOG

DATENBANK ERSTELLEN [SCHNITTSTELLE]
 CONTAINMENT = KEINE
 ON PRIMARY
( NAME = N'INTERFACE', FILENAME = N'S:\SQLDATA\DB\INTERFACE.mdf' , SIZE = 32768KB , FILEGROWTH = 65536KB )
 LOG ON
( NAME = N'INTERFACE_log' , FILENAME = N'S:\SQLDATA\LOG\INTERFACE_log.ldf' , SIZE = 16384KB , FILEGROWTH = 65536KB )
GO

USE [INTERFACE]
GO
ALTER AUTHORIZATION ON DATABASE::[INTERFACE] TO [interface_svc]
/*
exec sp_changedbowner 'interface_svc'
GO
*/

ALTER DATABASE [INTERFACE] SET COMPATIBILITY_LEVEL = 150
GO
ALTER DATABASE [INTERFACE] SET ANSI_NULL_DEFAULT OFF
GO
ALTER DATABASE [INTERFACE] SET ANSI_NULLS OFF
GO
ALTER DATABASE [INTERFACE] SET ANSI_PADDING OFF
GO
ALTER DATABASE [INTERFACE] SET ANSI_WARNINGS OFF
GO
ALTER DATABASE [INTERFACE] SET ARITHABORT OFF
GO
ALTER DATABASE [INTERFACE] SET AUTO_CLOSE OFF
GO
ALTER DATABASE [INTERFACE] SET AUTO_SHRINK OFF
GO
ALTER DATABASE [INTERFACE] SET AUTO_CREATE_STATISTICS ON(INCREMENTAL = OFF)
GO
ALTER DATABASE [INTERFACE] SET AUTO_UPDATE_STATISTICS ON
GO
ALTER DATABASE [INTERFACE] SET CURSOR_CLOSE_ON_COMMIT OFF
GO
ALTER DATABASE [INTERFACE] SET CURSOR_DEFAULT GLOBAL
GO
ALTER DATABASE [INTERFACE] SET CONCAT_NULL_YIELDS_NULL OFF
GO
ALTER DATABASE [INTERFACE] SET NUMERIC_ROUNDABORT OFF
GO
ALTER DATABASE [INTERFACE] SET QUOTED_IDENTIFIER OFF
GO
ALTER DATABASE [INTERFACE] SET RECURSIVE_TRIGGERS OFF
GO
ALTER DATABASE [INTERFACE] SET DISABLE_BROKER
GO
ALTER DATABASE [INTERFACE] SET AUTO_UPDATE_STATISTICS_ASYNC OFF
GO
ALTER DATABASE [INTERFACE] SET DATE_CORRELATION_OPTIMIZATION OFF
GO
ALTER DATABASE [INTERFACE] SET PARAMETERIZATION SIMPLE
GO
ALTER DATABASE [INTERFACE] SET READ_COMMITTED_SNAPSHOT OFF
GO
ALTER DATABASE [INTERFACE] SET READ_WRITE
GO
ALTER DATABASE [INTERFACE] SET RECOVERY FULL
GO
ALTER DATABASE [INTERFACE] SET MULTI_USER
GO
ALTER DATABASE [INTERFACE] SET PAGE_VERIFY CHECKSUM
GO
ALTER DATABASE [INTERFACE] SET TARGET_RECOVERY_TIME = 60 SECONDS
GO
ALTER DATABASE [INTERFACE] SET DELAYED_DURABILITY = DISABLED
GO
USE [INTERFACE]
GO
ALTER DATABASE SCOPED CONFIGURATION SET LEGACY_CARDINALITY_ESTIMATION = Aus;
GO
ALTER DATABASE SCOPED CONFIGURATION FOR SECONDARY SET LEGACY_CARDINALITY_ESTIMATION = Primary;
GO
ALTER DATABASE SCOPED CONFIGURATION SET MAXDOP = 0;
GO
ALTER DATABASE SCOPED CONFIGURATION FOR SECONDARY SET MAXDOP = PRIMARY;
GO
ALTER DATABASE SCOPED CONFIGURATION SET PARAMETER_SNIFFING = On;
GO
ALTER DATABASE SCOPED CONFIGURATION FOR SECONDARY SET PARAMETER_SNIFFING = Primary;
GO
ALTER DATABASE SCOPED CONFIGURATION SET QUERY_OPTIMIZER_HOTFIXES = Aus;
GO
ALTER DATABASE SCOPED CONFIGURATION FOR SECONDARY SET QUERY_OPTIMIZER_HOTFIXES = Primary;
GO
USE [INTERFACE]
GO
IF NOT EXISTS (SELECT name FROM sys.filegroups WHERE is_default=1 AND name = N'PRIMARY') ALTER DATABASE [INTERFACE] MODIFY FILEGROUP [PRIMARY] DEFAULT
GO

7) Erteilen Sie dem interface_svc-Konto nur Abfrageberechtigung mit
AdventureWorks2016-Datenbank im Schema HumanResources
vAnsichtsfenster des Mitarbeiters (VIEW)!

verwenden [AdventureWorks2016]
GO
CREATE USER [interface_svc] FOR LOGIN [interface_svc]
GO
GRANT SELECT ON [HumanResources].[vEmployee] TO [interface_svc]
GO

8) Erstellen Sie ein AWDB-Schema in der Datenbank INTERFACE. Das Skript
"Erstellen bis" Format

VERWENDEN [SCHNITTSTELLE]
GO

/****** Objekt: schema [AWDB] Script Datum: 12/9/2022 8:21:47 AM ******/
SCHEMA ERSTELLEN [AWDB]
GO

9) Erstellen Sie im AWDB-Schema ein Synonym namens AW_Employee,
die sich im HumanResources-Schema der AdventureWorks2016-Datenbank befindet
zeigt auf das Ansichtsfenster vEmployee!

VERWENDEN [SCHNITTSTELLE]
GO

/****** Objekt: Synonym [AWDB].[AW_Employee] Script Date: 12/6/2022 1:59:44 PM ******/
CREATE SYNONYM [AWDB].[AW_Employee] FOR [AdventureWorks2016].[HumanResources].[vEmployee]
GO

10) Erstellen Sie eine Abfrage, die mit Hilfe der AWDB an die INTERFACE-Datenbank gesendet werden soll
alle Zeilen und Spalten des Synonyms AW_Employee im Schema
.................

VERWENDEN [SCHNITTSTELLE]
GO
SELECT *
FROM AWDB.AW_Employee

11) Erstellen Sie ein FULL-Backup der INTERFACE-Datenbank mit folgendem Inhalt
nach:
a) Name der Sicherungsdatei: S:\SQLdata\INTERFACE.bak
b) Speichern überschreibt den gleichnamigen Mediensatz!

BACKUP DATABASE [INTERFACE] TO DISK = N'S:\SQLdata\INTERFACE.bak' WITH NOFORMAT, INIT, NAME = N'S:\SQLdata\INTERFACE.bak', SKIP, NOREWIND, NOUNLOAD, STATS = 10
GO

1) Ermitteln Sie die SQL-Server-Version und das SQL-Server-Release!

WÄHLEN SIE @@VERSION

2) Erstellen Sie eine einfache "Hello World!" Abfrage!

SELECT 'Hallo Welt!'

3) Erstellen Sie eine SQL-Abfrage, die die Quadratwurzel von 30 berechnet!

SELECT SQRT(30)

4) Erstellen Sie eine SQL-Abfrage, die das heutige Datum zurückgibt!

SELECT CAST(GETDATE() as date)

5) Erstellen Sie eine SQL-Abfrage, die berechnet, wie viele Tage vergangen sind.
Seit dem 15. März 1989!

SELECT DATEDIFF(day,'1989-03-15', GETDATE());

6) Erstellen Sie eine SQL-Abfrage, die die zuvor geladenen
Die ersten 20 Elemente der Tabelle Person.Address in der AdventureWorks-Datenbank
(alle Felder)!

/****** Skript für den Befehl SelectTopNRows aus SSMS ******/
SELECT TOP (20) *
  FROM [AdventureWorks2016].[Person].[Adresse]

7) Erstellen Sie eine SQL-Abfrage, die die zuvor geladenen
Die ersten 20 Elemente der Tabelle Person.Person in der AdventureWorks-Datenbank
(alle Felder), aber das Feld PersonType ist 'EM'!

/****** Skript für den Befehl SelectTopNRows aus SSMS ******/
SELECT TOP (20) *
  FROM [AdventureWorks2016].[Person].[Person]
  WHERE [AdventureWorks2016].[Person].[Person].PersonType='EM'

8) Erstellen Sie eine SQL-Abfrage, die die zuvor geladenen
die ersten 20 Elemente der Tabelle Person.Person in der AdventureWorks-Datenbank, aber
so dass, wenn das Feld PersonType 'EM' ist und nur PersonType,
Die Felder FirstName, LastName sollten im Abfrageergebnis enthalten sein!

/****** Skript für den Befehl SelectTopNRows aus SSMS ******/
SELECT TOP (20) PersonType, Vorname, Nachname
  FROM [AdventureWorks2016].[Person].[Person]
  WHERE [AdventureWorks2016].[Person].[Person].PersonType='EM'

9) Erstellen Sie eine SQL-Abfrage, die die zuvor geladenen
die ersten 20 Elemente der Tabelle Person.Person in der AdventureWorks-Datenbank, aber
so dass, wenn das Feld PersonType 'EM' ist und nur PersonType,
Die Felder Vorname, Nachname sollten im Abfrageergebnis enthalten sein, aber die
Vorname und Nachname sollten in einer Spalte mit einem einzigen Leerzeichen erscheinen
durch ein Zeichen getrennt!

/****** Skript für den Befehl SelectTopNRows aus SSMS ******/
SELECT TOP (20) PersonType, Vorname + ' ' + Nachname
  FROM [AdventureWorks2016].[Person].[Person]
  WHERE PersonType='EM'

10)Erstellen Sie eine SQL-Abfrage, die die zuvor geladenen
Datensätze in der Tabelle Person.Person der AdventureWorks-Datenbank
(alle Felder), wobei das Feld PersonType 'EM' und das Feld FirstName
sollten nur diejenigen angezeigt werden, die den Namen "John" tragen!

/****** Skript für den Befehl SelectTopNRows aus SSMS ******/
SELECT *
  FROM [AdventureWorks2016].[Person].[Person]
  WHERE PersonType='EM' AND FirstName='John'

11)Erstellen Sie eine SQL-Abfrage, die die zuvor geladenen
Datensätze in der Tabelle Person.Person der AdventureWorks-Datenbank
(alle Felder), wobei das Feld PersonType 'EM' und das Feld FirstName
sollten nur diejenigen mit dem Namen "John" angezeigt werden, bei denen die
Der Wert des Feldes LastName endet mit dem Zeichen 'e'!

/****** Skript für den Befehl SelectTopNRows aus SSMS ******/
SELECT *
  FROM [AdventureWorks2016].[Person].[Person]
  WHERE PersonType='EM' AND FirstName='John' AND RIGHT(LastName,1)='e'

12)Erstellen Sie eine SQL-Abfrage, die die zuvor geladenen
Datensätze in der Tabelle Person.Person der AdventureWorks-Datenbank
(alle Felder), wobei das Feld PersonType 'EM' und das Feld FirstName
sollten nur diejenigen mit dem Namen "John" angezeigt werden, bei denen die
Die Werte im Feld Nachname enthalten entweder 'Chen' oder 'Kane'!

/****** Skript für den Befehl SelectTopNRows aus SSMS ******/
SELECT *
  FROM [AdventureWorks2016].[Person].[Person]
  WHERE PersonType='EM' AND FirstName='John' AND (LastName='Chen' OR LastName='Kane')

13) Zähle, wie viele verschiedene Vornamen (FirstName) es in der
in der Tabelle Person.Person einer zuvor geladenen AdventureWorks-Datenbank!

/****** Skript für den Befehl SelectTopNRows aus SSMS ******/
SELECT COUNT(DISTINCT Vorname)
  FROM [AdventureWorks2016].[Person].[Person]

14) Zählen Sie die Anzahl der Datensätze mit dem Vornamen "Ken" (FirstName) in der Datei
in der Tabelle Person.Person einer zuvor geladenen AdventureWorks-Datenbank!

/****** Skript für den Befehl SelectTopNRows aus SSMS ******/
SELECT COUNT(Vorname)
  FROM [AdventureWorks2016].[Person].[Person]
  WHERE Vorname='Ken'

15) Zählen Sie, wie viele Datensätze mit demselben Namen (Vorname und Nachname)
ist die zuvor geladene AdventureWorks-Datenbank Person.Person
auf Ihrer Tafel! Ordnen Sie die Ergebnisse so an, dass die meistgenutzten
Namenspaare am Anfang der Liste und nur die ersten 20 Ergebnisse
einbezogen werden!

/****** Skript für den Befehl SelectTopNRows aus SSMS ******/
SELECT TOP (20) Vorname, Nachname, COUNT(1)
  FROM [AdventureWorks2016].[Person].[Person]
  GROUP BY Vorname, Nachname
  ORDER BY COUNT(1) DESC

16) Zählen Sie, wie viele Datensätze mit demselben Namen (Vorname und Nachname)
ist die zuvor geladene AdventureWorks-Datenbank Person.Person
auf deinem Brett! Ordne das Ergebnis so an, dass nur 4 und mehr als 4
die im Namenspaar verwendet werden, sollten aufgeführt werden!

SELECT Vorname, Nachname, COUNT(1)
  FROM [AdventureWorks2016].[Person].[Person]
  GROUP BY Vorname, Nachname
  MIT COUNT(1) >= 4
  REIHENFOLGE NACH COUNT(1) DESC

17)Erstellen Sie eine SQL-Abfrage, die die zuvor geladenen
AdventureWorks-Datenbank Person.Person und Person.EmailAddress
Tabellen mit den folgenden Feldern: Person.Person.FirstName,
Person.Person.LastName, Person.EmailAddress.EmailAddress, so dass die
um Tabellen zu verknüpfen, wird das Feld BusinessEntityID sowohl für
von der Tafel! Zeige nur die ersten 50 Zeilen des Ergebnisses an!

SELECT TOP (50) p.FirstName, p.LastName, e.EmailAddress
  FROM [AdventureWorks2016].[Person].[Person] p INNER JOIN [AdventureWorks2016].[Person].[EmailAddress] e on p.BusinessEntityID=e.BusinessEntityID

18) Erstellen Sie anhand der vorherigen Abfrage eine Lösung, bei der die E-Mail-Adresse
(EmailAddress) nur der Namensteil (vor dem @-Teil ist sichtbar)!

SELECT TOP (50) p.FirstName, p.LastName, LEFT(e.EmailAddress,CHARINDEX('@',e.EmailAddress)-1)
  FROM [AdventureWorks2016].[Person].[Person] p INNER JOIN [AdventureWorks2016].[Person].[EmailAddress] e on p.BusinessEntityID=e.BusinessEntityID

19)Oder eine Abfrage, bei der nur der Domänenteil (nach @)
sichtbar!

SELECT TOP (50) p.FirstName, p.LastName, RIGHT(e.EmailAddress,LEN(e.EmailAddress)- CHARINDEX('@',e.EmailAddress))
  FROM [AdventureWorks2016].[Person].[Person] p INNER JOIN [AdventureWorks2016].[Person].[EmailAddress] e on p.BusinessEntityID=e.BusinessEntityID

20) (ZEIT AUFGABE) Erstellen Sie eine Abfrage, die die
Sales.SalesPerson aus dem Feld BusinessEntityID und ein "minsales"
ist eine berechnete Spalte genannt. Der Wert von minsales sollte, Zeile für Zeile, SalesYTD sein
Feld, wenn SalesYTD > 1000000, sonst NULL
Mehrwert schaffen.

/****** Skript für den Befehl SelectTopNRows aus SSMS ******/
SELECT [BusinessEntityID], CASE WHEN SalesYTD > 1000000 THEN SalesYTD ELSE NULL END as minsales
  FROM [AdventureWorks2016].[Sales].[SalesPerson]

21) (SEHR WICHTIGE AUFGABE) Erstellen Sie eine Abfrage, die die
Sales.SalesPerson aus dem Feld BusinessEntityID und einer "salesinfo".
ist eine berechnete Spalte genannt. Der Wert von salesinfo sollte pro Zeile in SalesYTD gesetzt werden
Feld wenn SalesYTD >= 2000000, Wenn
SalesYTD<2000000 aber größer oder gleich 1000000, dann ist die
Wert sollte 1500000 sein, wenn weniger als 1000000 dann NULL. z.B.
Ausgänge :

/****** Skript für den Befehl SelectTopNRows aus SSMS ******/
SELECT [BusinessEntityID], CASE WHEN SalesYTD >= 2000000 THEN SalesYTD ELSE CASE WHEN SalesYTD>=1000000 THEN 1500000 ELSE NULL END END als salesinfo
  FROM [AdventureWorks2016].[Sales].[SalesPerson]

Bewertung des Microsoft SQL Server (im Folgenden SQL) Wissensstandes

  • T-SQL-Code verwenden
  • Achten Sie darauf, die angegebenen SQL-Dateinamen zu verwenden
  • Ihre hochgeladene ZIP-Datei sollte keine Unterverzeichnisse enthalten, sondern nur die Dateien
  • Stellen Sie sicher, dass bei Datenbank-, Benutzer- und anderen Objektnamen zwischen Groß- und Kleinschreibung unterschieden wird.
  • Ändern Sie in Abfragen die Namen der Spalten, die nur angezeigt werden sollen, wenn die Aufgabe dies ausdrücklich erfordert
  • Die Abfragen, die im Fenster Spalten in der in der Übung angegebenen Reihenfolge erscheinen
  • Stellen Sie sicher, dass Sie immer die richtige Datenbank auswählen
  • ASCII- oder UTF-8-Zeichenkodierung (ohne BOM) verwenden
  • Die Standard-Startdatenbank für das MSSQL LOGIN, das die Aufträge im Docker-Container "ausführt", sind die ersten 10 Aufträge: Meister.
  • Im Docker-Container ist die Standard-Startdatenbank für das MSSQL LOGIN, das die Aufträge im Docker-Container "ausführt", von 11) bis 20) Aufträge: AbenteuerWerkeFür diese Aufgaben ist es ausreichend, wenn Ihre hochgeladene Datei nur die Abfrage enthält.
  • Die Auswertung von Sql-Erweiterungsdateien ist in erster Linie Autograder die anderen werden manuell bewertet.

Aufgaben:

  1. Dem Server wird ein Laufwerk hinzugefügt, das noch nicht in Gebrauch ist (20GBInstallieren Sie es, erstellen Sie eine 20 GB große Partition mit NTFS-Dateisystem und fügen Sie S: ist als Laufwerk gemountet, und der Volume-Name lautet: SQLDATA sein sollte.
Evidencia: Computerverwaltung => Speicher => Datenträgerverwaltung
Dateiname: WINSQL-01.jpg
  1. S: Antrieb zur Schaffung eines SQLDATA und zwei weitere Unterverzeichnisse innerhalb dieses Verzeichnisses: DB und LOG mit dem Namen.
Evidencia: Öffnen Sie den Datei-Explorer => S: => SQLDATA-Verzeichnis, wenn Sie die beiden angeforderten Unterverzeichnisse sehen.
Dateiname: WINSQL-02.jpg
  1. Melden Sie sich am SQL-Server an (GREENFOX Instanz) mit Microsoft SQL Server Management Studio!
Evidencia: GREENFOX-Instanz geöffnet in Microsoft SQL Server Management Studio.
Dateiname: WINSQL-03.jpg
  1. Rufen Sie die C:\install\MSSQL\AdventureWorks2016.bak Datenbank auf die GREENFOX-Instanz des Servers AbenteuerWerke so dass sich die Datenbankdateien im Verzeichnis S:\SQLDATA\DB, während die Protokolldateien im Verzeichnis S:\SQLDATA\LOG zur Bibliothek.

Gradescopeban finden Sie das Backup hier: /AbenteuerWerke2016.bakdie Datenbankdateien: /SQLDATA/DB/AdventureWorks_Data.mdf, während die Protokolldateien im Verzeichnis /SQLDATA/LOG/AdventureWorks_Log.ldf zu Dateien

Evidencia: Kopieren oder speichern Sie ein Wiederherstellungsskript in Microsoft SQL Server Management Studio.
Dateiname: WINSQL-04.sql
USE [master]
RESTORE DATABASE [AdventureWorks] FROM DISK = N'/home/AdventureWorks2016.bak' WITH FILE = 1, MOVE N'AdventureWorks2016_Data' TO N'/SQLDATA/DB/AdventureWorks_Data.mdf', MOVE N'AdventureWorks2016_Log' TO N'/SQLDATA/LOG/AdventureWorks_Log.ldf', NOUNLOAD, STATS = 5

GO
  1. Erstellen einer isvc MS SQL Server authentifiziertes Konto mit minimalen (öffentlichen) Rechten! Das Passwort sollte lauten: interfAce21 Das Passwort sollte vom Benutzer bei der ersten Anmeldung nicht geändert werden müssen.
Evidencia: Kopieren oder speichern Sie ein Skript in Microsoft SQL Server Management Studio.
Dateiname: WINSQL-05.sql
USE [master]
GO
CREATE LOGIN [isvc] WITH PASSWORD=N'interfAce21', DEFAULT_DATABASE=[master], CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF
GO
  1. Erstellen einer INTERFACE mit den folgenden Einstellungen:
    1. Name der Datenbank: INTERFACE
    2. Eigentümer: isvc
    3. Einziehungsmodell: FULL
    4. Ursprüngliche Datenbankdatei:
      1. Größe: 64 MByte
      2. Speicherort: S:\SQLDATA\DB (Gradescope auf /SQLDATA/DB)
    5. Startup-Protokolldatei:
      1. Größe: 24 MByte
      2. Speicherort: S:\SQLDATA\LOG (Gradescope auf /SQLDATA/LOG)
DATENBANK ERSTELLEN [SCHNITTSTELLE]
 CONTAINMENT = KEINE
 ON PRIMARY
( NAME = N'INTERFACE', FILENAME = N'/SQLDATA/DB/INTERFACE.mdf' , SIZE = 65536KB , FILEGROWTH = 65536KB )
 LOG ON
( NAME = N'INTERFACE_log', FILENAME = N'/SQLDATA/LOG/INTERFACE_log.ldf' , SIZE = 24576KB , FILEGROWTH = 65536KB )
GO

USE [INTERFACE]
GO
ALTER AUTHORIZATION ON DATABASE::[INTERFACE] TO [isvc]

ALTER DATABASE [INTERFACE] SET COMPATIBILITY_LEVEL = 150
GO
ALTER DATABASE [INTERFACE] SET ANSI_NULL_DEFAULT OFF
GO
ALTER DATABASE [INTERFACE] SET ANSI_NULLS OFF
GO
ALTER DATABASE [INTERFACE] SET ANSI_PADDING OFF
GO
ALTER DATABASE [INTERFACE] SET ANSI_WARNINGS OFF
GO
ALTER DATABASE [INTERFACE] SET ARITHABORT OFF
GO
ALTER DATABASE [INTERFACE] SET AUTO_CLOSE OFF
GO
ALTER DATABASE [INTERFACE] SET AUTO_SHRINK OFF
GO
ALTER DATABASE [INTERFACE] SET AUTO_CREATE_STATISTICS ON(INCREMENTAL = OFF)
GO
ALTER DATABASE [INTERFACE] SET AUTO_UPDATE_STATISTICS ON
GO
ALTER DATABASE [INTERFACE] SET CURSOR_CLOSE_ON_COMMIT OFF
GO
ALTER DATABASE [INTERFACE] SET CURSOR_DEFAULT GLOBAL
GO
ALTER DATABASE [INTERFACE] SET CONCAT_NULL_YIELDS_NULL OFF
GO
ALTER DATABASE [INTERFACE] SET NUMERIC_ROUNDABORT OFF
GO
ALTER DATABASE [INTERFACE] SET QUOTED_IDENTIFIER OFF
GO
ALTER DATABASE [INTERFACE] SET RECURSIVE_TRIGGERS OFF
GO
ALTER DATABASE [INTERFACE] SET DISABLE_BROKER
GO
ALTER DATABASE [INTERFACE] SET AUTO_UPDATE_STATISTICS_ASYNC OFF
GO
ALTER DATABASE [INTERFACE] SET DATE_CORRELATION_OPTIMIZATION OFF
GO
ALTER DATABASE [INTERFACE] SET PARAMETERIZATION SIMPLE
GO
ALTER DATABASE [INTERFACE] SET READ_COMMITTED_SNAPSHOT OFF
GO
ALTER DATABASE [INTERFACE] SET READ_WRITE
GO
ALTER DATABASE [INTERFACE] SET RECOVERY FULL
GO
ALTER DATABASE [INTERFACE] SET MULTI_USER
GO
ALTER DATABASE [INTERFACE] SET PAGE_VERIFY CHECKSUM
GO
ALTER DATABASE [INTERFACE] SET TARGET_RECOVERY_TIME = 60 SECONDS
GO
ALTER DATABASE [INTERFACE] SET DELAYED_DURABILITY = DISABLED
GO
USE [INTERFACE]
GO
ALTER DATABASE SCOPED CONFIGURATION SET LEGACY_CARDINALITY_ESTIMATION = Aus;
GO
ALTER DATABASE SCOPED CONFIGURATION FOR SECONDARY SET LEGACY_CARDINALITY_ESTIMATION = Primary;
GO
ALTER DATABASE SCOPED CONFIGURATION SET MAXDOP = 0;
GO
ALTER DATABASE SCOPED CONFIGURATION FOR SECONDARY SET MAXDOP = PRIMARY;
GO
ALTER DATABASE SCOPED CONFIGURATION SET PARAMETER_SNIFFING = On;
GO
ALTER DATABASE SCOPED CONFIGURATION FOR SECONDARY SET PARAMETER_SNIFFING = Primary;
GO
ALTER DATABASE SCOPED CONFIGURATION SET QUERY_OPTIMIZER_HOTFIXES = Aus;
GO
ALTER DATABASE SCOPED CONFIGURATION FOR SECONDARY SET QUERY_OPTIMIZER_HOTFIXES = Primary;
GO
USE [INTERFACE]
GO
IF NOT EXISTS (SELECT name FROM sys.filegroups WHERE is_default=1 AND name = N'PRIMARY') ALTER DATABASE [INTERFACE] MODIFY FILEGROUP [PRIMARY] DEFAULT
GO
  1. Geben Sie nur Abfragerechte an isvc Konto für die AbenteuerWerke Datenbank HumanResources in der Regelung vMitarbeiter auf Ihrer Beobachtungsliste!
Evidencia: Kopieren oder speichern Sie ein Skript in Microsoft SQL Server Management Studio.
Dateiname: WINSQL-07.sql
USE [AdventureWorks]
GO
CREATE USER [isvc] FOR LOGIN [isvc]
GO
GRANT SELECT ON [HumanResources].[vEmployee] TO [isvc]
GO
  1. INTERFACE Datenbank zur Erstellung einer AWDatenbank Schema!
Evidencia: Microsoft SQL Server Management Studio in der GREENFOX-Instanz in der Datenbank INTERFACE AWdatabase schema "Create To" script.
Dateiname: WINSQL-08.sql
VERWENDEN [SCHNITTSTELLE]
GO

/****** Objekt: schema [dbo] Script Datum: 2023 Jan 15 13:45:32 ******/
CREATE SCHEMA [AWdatabase]
GO
  1. Von AWDatenbank Schema zur Erstellung eines Synonym AW_Employee die die AbenteuerWerke Datenbank HumanResources in der Regelung vMitarbeiter zeigt auf das Ansichtsfenster!
Evidencia: Microsoft SQL Server Management Studio in GREENFOX Instanz der Datenbank INTERFACE AWdatabase schema AW_Employee gleichbedeutend mit dem Skript "Create To".
Dateiname: WINSQL-09.sql
VERWENDEN [SCHNITTSTELLE]
GO
CREATE SYNONYM [AWdatabase].[AW_Employee ] FOR [AdventureWorks].[HumanResources].[vEmployee]
GO
  1. Machen Sie die INTERFACE eine FULL-Sicherung der Datenbank, wie folgt:
  1. Name der Sicherungsdatei: S:\SQLDATA\INTERFACE.bak (In Gradescope /var/backups/INTERFACE.bak)
  2. Speichern überschreibt den gleichnamigen Mediensatz!
Evidencia: In Microsoft SQL Server Management Studio in der GREENFOX-Instanz, das INTERFACE-Datenbank-Backup-Skript.
Dateiname: WINSQL-10.sql
BACKUP DATABASE [INTERFACE] TO DISK = N'/var/backups/INTERFACE.bak' WITH NOFORMAT, INIT, NAME = N'INTERFACE-Full Database Backup', SKIP, NOREWIND, NOUNLOAD, STATS = 10
GO
  1. Erstellen Sie eine SQL-Abfrage, die die Quadratwurzel von 25 berechnet!
Evidencia: Kopieren oder speichern Sie ein Skript in Microsoft SQL Server Management Studio.
Dateiname: WINSQL-11.sql
SELECT SQRT(25)
  1. Erstellen Sie eine SQL-Abfrage, die das heutige Datum in diesem Format zurückgibt: 2022-10-25
Evidencia: Kopieren oder speichern Sie ein Skript in Microsoft SQL Server Management Studio.
Dateiname: WINSQL-12.sql
SELECT CAST(GETDATE() as date)
  1. Erstellen Sie eine SQL-Abfrage, die berechnet, wie viele Tage seit dem 25. April 1994 vergangen sind!
Evidencia: Kopieren oder speichern Sie ein Skript in Microsoft SQL Server Management Studio.
Dateiname: WINSQL-13.sql
SELECT DATEDIFF(Tag,'2022-04-25',GETDATE())
  1. Erstellen Sie eine SQL-Abfrage, die die zuvor geladenen AbenteuerWerke Datenbank Person.Adresse Tabelle (alle Felder - ändern Sie nicht die Reihenfolge der Spalten)!
Evidencia: Kopieren oder speichern Sie ein Skript in Microsoft SQL Server Management Studio.
Dateiname: WINSQL-14.sql
/****** Skript für den Befehl SelectTopNRows aus SSMS ******/
USE [AdventureWorks]
GO
SELECT TOP (15) *
  FROM [AdventureWorks].[Person].[Adresse]
  1. Erstellen Sie eine SQL-Abfrage, die die zuvor geladenen AbenteuerWerke Datenbank Person.Person von der Website von die ersten 5 Elemente(alle Felder - ändern Sie nicht die Reihenfolge der Spalten), sondern so, dass dort, wo die PersonType Feldwert 'EM‘!
Evidencia: Kopieren oder speichern Sie ein Skript in Microsoft SQL Server Management Studio.
Dateiname: WINSQL-15.sql
USE [AdventureWorks]
GO
SELECT TOP (5) *
  FROM [AdventureWorks].[Person].[Person]
  WHERE PersonType='EM'
  1. Erstellen Sie eine SQL-Abfrage, die die zuvor geladenen AbenteuerWerke Datenbank Person.Person von der Website von die ersten 30 Artikelsondern so, dass dort, wo die PersonType Feldwert 'EM' und nur die PersonType, Vorname, Nachname Felder im Abfrageergebnis!
Evidencia: Kopieren oder speichern Sie ein Skript in Microsoft SQL Server Management Studio.
Dateiname: WINSQL-16.sql
USE [AdventureWorks]
GO
SELECT TOP (30) PersonType, Vorname,Nachname
  FROM [AdventureWorks].[Person].[Person]
  WHERE PersonType='EM'
  1. Erstellen Sie eine SQL-Abfrage, die die zuvor geladenen AbenteuerWerke Datenbank Person.Person von der Website von die ersten 20 Punktesondern so, dass dort, wo die PersonType Feldwert 'EM' und nur die PersonType, Vorname, Nachname Felder im Abfrageergebnis, aber die Vorname und Nachname sollten in einer Spalte stehen, getrennt durch ein einzelnes Leerzeichen, Vollständiger Name unter dem Namen!
Evidencia: Kopieren oder speichern Sie ein Skript in Microsoft SQL Server Management Studio.
Dateiname: WINSQL-17.sql
USE [AdventureWorks]
GO
SELECT TOP (20) PersonType, Vorname+ ' ' + Nachname as FullName
  FROM [AdventureWorks].[Person].[Person]
  WHERE PersonType='EM'
  1. Erstellen Sie eine SQL-Abfrage, die die zuvor geladenen AbenteuerWerke Datenbank Person.Person der Tabelle (alle Spalten, alle Felder - ändern Sie nicht die Reihenfolge der Spalten), wobei PersonType Feldwert 'EM' und Vorname enthält nur das Feld 'John' sollte enthalten sein!
Evidencia: Kopieren oder speichern Sie ein Skript in Microsoft SQL Server Management Studio.
Dateiname: WINSQL-18.sql
USE [AdventureWorks]
GO
SELECT *
  FROM [AdventureWorks].[Person].[Person]
  WHERE PersonType='EM' AND FirstName='John'
  1. Erstellen Sie eine SQL-Abfrage, die die zuvor geladenen AbenteuerWerke Datenbank Person.Person der Tabelle (alle Spalten, alle Felder - ändern Sie nicht die Reihenfolge der Spalten), wobei PersonType Feldwert 'EM' und Vorname enthält nur das Feld 'John', sollten nur die angezeigt werden, bei denen die Nachname Feldwert 'e'-Zeichen Ende!
Evidencia: Kopieren oder speichern Sie ein Skript in Microsoft SQL Server Management Studio.
Dateiname: WINSQL-19.sql
USE [AdventureWorks]
GO
SELECT *
  FROM [AdventureWorks].[Person].[Person]
  WHERE PersonType='EM' AND FirstName='John' AND RIGHT(LastName,1)='e'
  1. Zählen Sie, wie viele 'Ken' Vornamen (Vorname) ist der zuvor geladene Datensatz AbenteuerWerke Datenbank Person.Person auf Ihrem Brett!
Evidencia: Kopieren oder speichern Sie ein Skript in Microsoft SQL Server Management Studio.
Dateiname: WINSQL-20.sql
USE [AdventureWorks]
GO
SELECT COUNT(*)
  FROM [AdventureWorks].[Person].[Person]
  WHERE Vorname='Ken'