SQL kisokos

OFFSET – x. sortól y. sorig

ORDER BY Continent ASC, Subregion DESC
OFFSET 29 ROWS FETCH NEXT 50 ROWS ONLY;

WITH TIES – holtversenyben az utolsó helyen állóval

SELECT TOP 10 PERCENT WITH TIES;

COALESCE – 1. nem NULL érték

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

WHERE – karakterhelyettesítések

WHERE StockItemName LIKE '%ham[^m]%'
WHERE StockItemName LIKE 'a[l-m]%[l-p]'
WHERE CountryName LIKE 'H__[g,d]%'

WHERE IN – szerepel e egy listában

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

AGGREÁLT LEKÉRDEZÉSEK – AVG(),SUM(), MIN(), MAX(), COUNT(), COUNT_BIG()

SUM(Quantity) AS total_pack, AVG(UnitPrice) AS avg_unitprice, COUNT(OrderLineID) AS cnt_orderline

AGGREGÁLÓK – nem kezelik a NULL-ot

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

subquery – self-contained/simple

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

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

correlated subquery – last OrderID 

SELECT CustomerId, OrderId, OrderDate
FROM Sales.Orders o1
WHERE OrderID=(SELECT MAX(OrderID)
FROM Sales.Orders o2
WHERE o1.CustomerId=o2.CustomerId)
Order by orderDate DESC;

retuns with list

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 CustomerID, CustomerName
FROM Sales.Customers c
WHERE PostalCityID = 33832
AND EXISTS
(SELECT * FROM Sales.Orders o
WHERE o.CustomerID=c.CustomerID);

running-total – gordulo lekerdezes

SELECT CityID, CityName, (SELECT MIN(CityID) FROM Application.Cities c2 WHERE c2.CityID > c1.CityID) AS nextcityid
FROM Application.Cities 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 Application.Cities c1
WHERE StateProvinceID IN (SELECT StateProvinceID FROM Application.StateProvinces WHERE StateProvinceName='Colorado')
GROUP BY CityID, CityName, LatestRecordedPopulation;

DERIVED TABLE version

SELECT order_count, month_number
FROM (
SELECT MONTH(OrderDate) AS month_number, COUNT(OrderDate) AS order_count
FROM Sales.Orders
GROUP BY MONTH(OrderDate)
) AS derivedtable
WHERE order_count > 6000
ORDER BY month_number ASC;

SELECT order_count, month_number
FROM (
SELECT MONTH(OrderDate), COUNT(OrderDate)
FROM Sales.Orders
GROUP BY MONTH(OrderDate)
) AS derivedtable (month_number,order_count)
WHERE order_count > 6000
ORDER BY month_number ASC;

SELECT CustomerID, ORderID, OrderDate
FROM Sales.Orders AS a -- a=schema_name.table_name
INNER JOIN
(
SELECT MAX(OrderDate) AS maxorderdate
FROM Sales.Orders AS b
) AS derivedtable ON a.orderDate=derivedtable.maxorderdate;

CTE

WITH cte_table AS (
SELECT MONTH(OrderDate) AS month_number, COUNT(OrderDate) AS order_count
FROM Sales.Orders
GROUP BY MONTH(OrderDate)
)
SELECT order_count, month_number FROM cte_table
WHERE order_count > 6000
ORDER BY month_number ASC;

CASE – NORMAL – DERIVED TABLE – CTE 

SELECT CASE
WHEN 2013=YEAR(OrderDate) THEN '2013y'
WHEN 2014=FORMAT(OrderDate,'yyyy') THEN '2014y'
WHEN OrderDate like '2015%' THEN '2015y'
WHEN OrderDate >= '20160101' AND OrderDate < '20170101' THEN '2016y'
END AS years, COUNT(*)
FROM Sales.Orders
GROUP BY CASE
WHEN 2013=YEAR(OrderDate) THEN '2013y'
WHEN 2014=FORMAT(OrderDate,'yyyy') THEN '2014y'
WHEN OrderDate like '2015%' THEN '2015y'
WHEN OrderDate >= '20160101' AND OrderDate < '20170101' THEN '2016y'
END

SELECT years, COUNT(years)
FROM (
SELECT CASE
WHEN 2013=YEAR(OrderDate) THEN '2013y'
WHEN 2014=FORMAT(OrderDate,'yyyy') THEN '2014y'
WHEN OrderDate like '2015%' THEN '2015y'
WHEN OrderDate >= '20160101' AND OrderDate < '20170101' THEN '2016y'
END as years
FROM Sales.Orders
) AS whatever
GROUP BY years;

WITH whatever AS (
SELECT CASE
WHEN 2013=YEAR(OrderDate) THEN '2013y'
WHEN 2014=FORMAT(OrderDate,'yyyy') THEN '2014y'
WHEN OrderDate like '2015%' THEN '2015y'
WHEN OrderDate >= '20160101' AND OrderDate < '20170101' THEN '2016y'
END as years
FROM Sales.Orders)
SELECT years, COUNT(years)
FROM whatever
GROUP BY years;

JOIN AND – Ez a where-ben and kapcsolattal lenne

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

Főnök főnöke JOIN

SELECT beosztott.Nev, fonok.Nev, nagyfonok.Nev FROM dbo.emberek as Beosztott
INNER JOIN dbo.Emberek as fonok ON beosztott.FonokId = fonok.Id
LEFT JOIN dbo.Emberek as nagyfonok ON fonok.FonokId = nagyfonok.Id

data length

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

UNIQUEIDENTIFIER

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

autocreate id

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

OWN TYPE

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

Avoid autoincrement & INSERT problem

SET IDENTITY_INSERT Hr.Employees ON;

INSERT INTO HR.Employees (id,emp_name)
VALUES(666,'firstname');

SET IDENTITY_INSERT Hr.Employees OFF;

OUTPUT inserted, deleted

INSERT INTO HR.Employees (emp_name)
OUTPUT inserted.emp_name INTO HR.Emplog(emp_name)
VALUES ('testname')

DELETE Hr.Employees
OUTPUT deleted.emp_name INTO HR.Emplog
WHERE id=666;

DELETE testlines where orderdate=’20130101′ > LOG 

DELETE dbo.testlines
OUTPUT deleted.*
FROM dbo.testlines tol
INNER JOIN dbo.testorders tor ON tor.OrderID=tol.OrderID
WHERE OrderDate='20130101'

PRIMARY KEYS, FOREIGN KEYS, UNIQUE KEY, CONSTRAINTS

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 IDENTITY(1,1
,name varchar(50)
,CONSTRAINT PK_testtable4_id PRIMARY KEY(id)
);

FOREIGN KEY – 1 > N – PRIMARY KEY

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

cascade version

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

kapcsoló tábla – employees and educations – N > M

DROP TABLE IF EXISTS dbo.conn_educations_employees;
CREATE TABLE dbo.conn_educations_employees (
id INT NOT NULL IDENTITY(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
, username 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 KEY

ALTER TABLE dbo.employees
ADD CONSTRAINT UK_employees_person UNIQUE (emp_name,birth_date,mother_name);

CHECK CONSTRAINT

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

működik e a check constraint

ALTER TABLE dbo.employees WITH CHECK
CHECK CONSTRAINT CK_employees_contacts;

DEFAULT CONSTRAIT

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

temporal table sql2017+ – advanced sql server 2019 cu18

CREATE TABLE dbo.persondate (
id int IDENTITY(1,1) PRIMARY KEY NOT NULL
,last_name NVARCHAR(50) NOT NULL
,first_name NVARCHAR(50) NOT NULL
,phone_number VARCHAR(22)
,emailadress 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 MONTHS
,HISTORY_TABLE = dbo.persondate_history)
)
/* temporal table - töröltek*/
SELECT * FROM dbo.persondate_history temp
LEFT JOIN dbo.persondate actual ON temp.id=actual.id
WHERE actual.id IS NULL;

INDEX

INDEX típusok:
– in-memory index: oltp
– columnstore index
– rowstore: clustered 1 , nonclustered

rowstore index típusai:
– clustered index – telefonkönyv, teljes tábla
– non-clustered: heap – akkor heap ha nincs clustered index a táblán
címjegyzék, pl jogállamiság szó melyik oldalon szerepel 120,130. oldal

index node: index key, address
Leaf level: table
root > intermidiate > leaf node

nonclustered index. B-tree

leaf level: index key, clustered index

arra jó hogy index kulcsban jól keressünk, de nem ússzuk meg a clusterezést

CLUSTERED INDEX

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

nonclustered indexes akkor jók, ha a where-ben lévőre készítjük, olyan lekérdezés amelyet sokat használunk

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

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

index használatának kikényszerítése – ne használjuk

cost: 2.24

SELECT OrderLineID, StockItemID,UnitPrice, Quantity
FROM dbo.testlines WITH (INDEX (idx_testlines_stockitemid))
WHERE StockItemID=148;

leaf level szinten bekerül a UnitePrice, Quantity

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

Filtered index

CREATE UNIQUE INDEX idx_testorders_isinprogress ON dbo.testorders (CustomerID,isInProgress) WHERE isInProgress=1;
/*FOREIGN KEY > no index ! best practice - nonclustered index         filtered testdb isHIgh education table-ben*/
/*talán masterwork - dátumnál nem jó*/
CREATE INDEX idx_testorders_2016 ON dbo.testorders (OrderDate) INCLUDE(CustomerID) WHERE OrderDate >= '20160101' AND OrderDate<'20170101';

Változók

Batch feldolgozás és változók (GO)
– két GO között ami van az egy batch
– változók csak egy batchban élnek
DECLARE @stockItemId INT;
SET @stockItemId = 2;

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

Szűrő feltételként, akár több lekérdezésben

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;
/* Csak egy értéket tud tárolni */
/* Egyben az előzőek */
DECLARE @stockItemId INT;
SET @stockItemId = 2;
DECLARE @myStockItemName NVARCHAR(500);
SELECT @myStockItemName=StockItemName FROM Warehouse.StockItems
WHERE StockItemID = @stockItemId;

utolsó értéket veszi fel, ha egy selectben adjuk meg

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 @myStockItemName=StockItemName, @myStockItemColorId=ColorID 
FROM Warehouse.StockItems
ORDER BY StockItemName;

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

Ha nincs eredménye a lekérdezésnek, akkor a változó NULL értéket vesz fel

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 @myStockItemName=StockItemName FROM Warehouse.StockItems
WHERE StockItemID = 10000000;
SELECT @myStockItemName AS MyStockItemName;

ADATÍPUSOK

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

numeric vs float

float közelítő kerekít, nagy számoknál az integer része se biztos pontos, csak az első 7 precíz, x*2^y => 199*2*5 — fizika, statisztikai számítások nagy értékeknél, pl decimalnem elég
numeric/decimal,az amit kap, pénzügyi dolgoknál numeric pl. price is 1.99

money – ez decimal igazából, csak négy tört résszel,ami fix -eléírhatod a currency-t de nem tárolja

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;

datetimeoffset

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)='teszt'
SELECT @mychar;

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

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

DECLARE @myvarchar VARCHAR(3)='teszt'
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)='teszt'
SELECT @mychar;

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

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

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

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

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

binary

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

unicode karaktert teszik asciiba

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

túl nagy értékek

DECLARE @darabszam SMALLINT = 32768;
SELECT @darabszam;

 implicit konverzió

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

CAST vs CONVERT

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

DECLARE @ma DATETIME2 =GETUTCDATE();

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

TRY_CAST vs TRY_CONVERT

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

FORMAT

DECLARE @ma DATETIME2 =GETUTCDATE();

SELECT @ma,FORMAT(@ma,'yyyy. MM. dd.')

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 @float,FORMAT(@float,'N2')

SZÖVEG műveletek: TRIM,LTRIM,RTRIM

len a végét nem nézi a szövegnek itt:

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    '));

UPPER, LOWER

SELECT UPPER('Ékezet')
SELECT LOWER('ÉKEzet')

REPLICATE,LEFT, REVERSE, REPLACE

SELECT REPLICATE('ho',3)
SELECT LEFT('HELLO WORLD', 5)

SELECT REVERSE('hello')

SELECT REPLACE('HELLO world', 'World', 'JOE')

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

Dátum idő műveletek: DATEDIFF

SELECT ValidFrom, '2022-01-01 00:00', DATEDIFF(yyyy, ValidFrom,'2022-01-01 00:00')
FROM Warehouse.StockItems

SELECT ValidFrom, '2022-01-01 00:00', DATEDIFF(s, ValidFrom,'2022-01-01 00:00')
FROM Warehouse.StockItems

SELECT ValidFrom, '2022-01-01 00:00', DATEDIFF(s, ValidFrom,'2022-01-01 00:00')
FROM Warehouse.StockItems

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

Kerekítés

SELECT ROUND(123.45,0)
SELECT ROUND(123.55,0)
SELECT ROUND(123.55,1)

TEMP TABLE, TABLE VARIABLE

temp table

csak session-ben létezik, tempdb-ben tárolja, soknál túl nagy tempdb, táblák lekérdezésének tárolására, előnye: szűrt adatok vannak benne, gyorsabb lesz a lekérdezés, kevesebb kód, teljesítmény

CREATE TABLE #myTempTable
(
	Id uniqueidentifier primary key nonclustered,
	Name NVARCHAR(100) NOT NULL
);

Global temp talbe: session-ök között is megmarad, miután lefutott az összes query és sessionöknek vége akkor megszűnik

CREATE TABLE ##globalTempTable
(
	Id uniqueidentifier primary key nonclustered,
	Name NVARCHAR(100) NOT NULL
);
DROP TABLE ##globalTempTable;

Table variable: csak a batch-ben létezik, nem ideális sok adathoz

DECLARE @myTableVariable TABLE (
	Id uniqueidentifier primary key nonclustered,
	Name NVARCHAR(100) NOT NULL
);
-- közös tábla készítés
USE WideWorldImporters;
GO

SELECT COUNT(*) FROM Sales.Orders;
-- 0.39 cost
SELECT COUNT(*) FROM Sales.OrderLines;

SELECT TOP 1 * FROM Sales.OrderLines;

CREATE TABLE #Temp_OrderLines
(
	OrderLineID int PRIMARY KEY,
	StockItemID int NOT NULL, --/*FOREIGN KEY*/ References Warehouse.StockItems(StockItemID), --ezt ne csináljuk, mert nincs neve, meg kell találni a nevet is
	DESCRIPTION NVARCHAR(1000),
	Quantity int NOT NULL
);
-- 164 stock item id
INSERT INTO #Temp_OrderLines(OrderLineID,StockItemID,[DESCRIPTION],Quantity)
SELECT OrderLineID,StockItemID,[Description],Quantity
FROM Sales.OrderLines
WHERE StockItemID=164;

SELECT * FROM #Temp_OrderLines;
--0,013 cost
SELECT COUNT(*) FROM #Temp_OrderLines;

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

SELECT COUNT(*) FROM #Temp_OrderLines;

DECLARE @myTableVariable TABLE (
	Id uniqueidentifier primary key nonclustered,
	Name NVARCHAR(100) NOT NULL
);

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

SELECT * FROM @myTableVariable;

USE WideWorldImporters;

/*
    Declaring a table type
*/
DROP TYPE IF EXISTS mytable;
CREATE TYPE mytable AS table
(
    id int NOT NULL,
	Name NVARCHAR(100) NOT NULL
);

/*
    From now on, you don't have to declare your table variables
    with column info, just reference the type.
*/
DECLARE @t AS mytable;
INSERT INTO @t VALUES(1,'HELLO WORLD');

SELECT * FROM @t;


CREATE TABLE dbo.tesztecske AS mytable; -- nem

/*ez igen*/
SELECT * 
INTO dbo.tesztecske
FROM @t
WHERE 1 = 2; --oszlopokat megcsinálja, de sorokat nem


SELECT * FROM dbo.tesztecske;

CONTROL FLOW ELEMENTS (IF, WHILE)

code branching

IF…ELSE
IF expressions

– three-valued logic: TRUE, FALSE, UNKNOWN (NULL)
simple if example

DECLARE @year SMALLINT;
SET @year = 2022;

IF @year = YEAR(GETDATE())
BEGIN
PRINT 'Match! The current year is: ' + CAST(@year AS varchar(5));
END
ELSE
BEGIN
    PRINT 'THERE IS NO MATCH! THE Year variable:' + CAST(@year AS varchar(5));
    PRINT 'THERE IS NO MATCH! THE current year:' + 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 'Match! The current year is: ' + CAST(@year AS varchar(5));
END
ELSE
BEGIN
    PRINT 'THERE IS NO MATCH! THE Year variable:' + CAST(@year AS varchar(5));
    PRINT 'THERE IS NO MATCH! THE current year:' + CAST(YEAR(GETDATE()) AS varchar(5));
END

NULL handling nested if elements

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

IF @year = YEAR(GETDATE())
BEGIN
PRINT 'Match! The current year is: ' + CAST(@year AS varchar(5));
END
ELSE
BEGIN
    IF @year IS NOT NULL
    BEGIN 
    PRINT 'THERE IS NO MATCH! THE Year variable:' + CAST(@year AS varchar(5));
    PRINT 'THERE IS NO MATCH! THE current year:' + CAST(YEAR(GETDATE()) AS varchar(5));
    END
    ELSE
    BEGIN
    PRINT '@year value is NULL'
    END
END
GO

Active DB, ez csak a sajátnál, más sessionnél még használhatják, kill kell

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

Complex if expression

last day of last month = today-20 || today is IN (monday, tuesday, friday) || today = 2023-02-20
true or false

PRINT DAY(GETDATE())
PRINT EOMONTH(GETDATE(),-1); -- február
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 ('Monday','Tuesday', 'Friday') OR CAST(GETDATE() AS date) = '2023-02-20'
BEGIN
PRINT 'THIS IS TRUE!'
END

/*testcase-2*/

IF EOMONTH('2023-03-20',-1)= CAST(DATEADD(day, -20,GETDATE()) AS date) OR DATENAME(dw,'2023-02-19') IN ('Monday','Tuesday', 'Friday') OR CAST(GETDATE() AS date) = '2023-02-20'
BEGIN
PRINT 'THIS IS TRUE!'
PRINT 'THIS IS STILL TRUE!'
END

/*test-case 3*/

IF EOMONTH('2023-03-20',-1)= CAST(DATEADD(day, -20,GETDATE()) AS date) OR DATENAME(dw,'2023-02-19') IN ('Monday','Tuesday', 'Friday') OR CAST(GETDATE() AS date) = '2023-01-28'
BEGIN
PRINT 'THIS IS TRUE!'
PRINT 'THIS IS STILL TRUE!'
END
ELSE
BEGIN
PRINT 'NOT TRUE'
END
DECLARE @yeara SMALLINT=2015, @yearb SMALLINT;
 SELECT @yearb;

IF EXISTS

Use WideWorldImporters;
GO

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

IF EXISTS (SELECT OrderID FROM SAles.Orders WHERE YEAR(OrderDate) IN (@yeara,@yearb)
)
BEGIN
PRINT 'There are orders in ' + CAST(@yeara as VARCHAR(5))+ ' or in '+CAST(@yearb as VARCHAR(5))
END
ELSE
BEGIN
    PRINT 'There are not orders in ' + CAST(@yeara as VARCHAR(5))+ ' or in '+CAST(@yearb as VARCHAR(5))
END ;
/* Ugyanaz a feladat csak egy kis NULL-al fűszerezve*/
DECLARE @yeara SMALLINT=2015, @yearb SMALLINT;
 SELECT @yearb;

IF EXISTS (SELECT OrderID FROM SAles.Orders WHERE YEAR(OrderDate) IN (@yeara,@yearb)
)
BEGIN
PRINT 'There are orders in ' + CAST(@yeara as VARCHAR(5))+ ' or in '+CAST(@yearb as VARCHAR(5))
END
ELSE
BEGIN
    PRINT 'There are not orders in ' + CAST(@yeara as VARCHAR(5))+ ' or in '+CAST(@yearb as VARCHAR(5))
END ;

GO
/*NULL HANDLING*/

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

IF (@yeara IS NULL OR @yearb IS NULL)
BEGIN
PRINT 'UNKNOWN value(s) are detected';

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 'There are orders in ' + CAST(@yeara as VARCHAR(5))+ ' or in '+CAST(@yearb as VARCHAR(5));
END
ELSE
BEGIN
    PRINT 'There are not orders in ' + CAST(@yeara as VARCHAR(5))+ ' or in '+CAST(@yearb as VARCHAR(5));
END 
END;

LOOPS

syntax:

WHILE (expression)
BEGIN

END
(CONTINUE, BREAK, 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));

/* simple insert loop INSERT 1-1000 > dbo.t1 method 1*/

DECLARE @cnt int=1;

WHILE @cnt < 1001
BEGIN
 INSERT INTO dbo.t1 VALUES(@cnt);
 SET @cnt+= 1;
END

SELECT num FROM dbo.t1;
/*
 INSERT VALUES 1->1000 except 5 WITH Autoincrement column (method 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;  

/*
break loop at @cnt=5
*/
TRUNCATE TABLE dbo.t2;

SET IDENTITY_INSERT dbo.t2 ON;  

DECLARE @cnt int=0;
WHILE (@cnt < 1001)
BEGIN
    SET @cnt +=1;
    IF @cnt=5 
    BEGIN 
        PRINT 'loop will be terminated.';
        BREAK;
    END
    INSERT INTO dbo.t2 (num) VALUES (@cnt);
END
SELECT num FROM dbo.t2;

/*
INSERT VALUES 1-1000 -> dbo.t3 method 3
*/
INSERT INTO dbo.t3 DEFAULT VALUES;
GO 1000

SELECT * FROM dbo.t3;

loop with delaying

DECLARE @cnt int=1;

WHILE @cnt <= 10
BEGIN

    PRINT 'The counter value is '+CAST(@cnt AS varchar(5));
    WAITFOR DELAY '00:00:01'
     SET @cnt+= 1;
   

END

/*EZ A JÓ*/

DECLARE @cnt int=1;

WHILE @cnt <= 10
BEGIN

    RAISERROR('The counter value is %d',0,1,@cnt) WITH NOWAIT;
    WAITFOR DELAY '00:00:01'
     SET @cnt+= 1;
END

@@ROWCOUNT

utolsó statement-et számolja

DECLARE @rows int;
UPDATE #mytemp
SET Quantity=1000
WHERE Quantity>100;
SET @rows=@@ROWCOUNT;
If @rows > 0
BEGIN
    SELECT CAST(@rows as varchar(5)) + ' rows were updated'
END
ELSE
BEGIN
SELECT 'No rows were updated'
END

ERRPOR HANDLING

Error types:
– datatype conversion error
– valuation error (értékelési hiba)
– syntax error > can not handle in t-sql
– logical error
– name resolution error > can not handle in t-sql
– constraint violation error
– error by trigger

quantity -1000

Miért írunk hibakezelést?
– nem akarom eltörni a kódot
– logolni szeretném a hibát
– emészhetőbb formában állítjuk elő a hibakódot

Hogyan?
– ne szálljon el a kód
– vagy szálljon el a kód, hogy ne legyen nagyobb baj

Hibakezelési módok:
– structured error handling with: TRY > CATCH
– @@ERROR beépített függvény, do not use

09:17:15Started executing query at Line 42
Msg 8134, Level 16, State 1, Line 1
Divide by zero error encountered.
Total execution time: 00:00:00.013

Msg 8134 > error code (id)
Level > Severity levels
State > status
Line > row where is the error

example division by zero

PRINT 10/0;

TRY…CATCH

BEGIN TRY
    PRINT 10/0;
END TRY
BEGIN CATCH
    PRINT '0-val otszottál butus!';
END CATCH;

error handling built-in fuctions

PRINT ‘Error occurred!’;
PRINT ‘Error number: ‘ + CAST(ERROR_NUMBER() AS nvarchar(10));
PRINT ‘Error message: ‘ + ERROR_MESSAGE();
PRINT ‘Error state: ‘ + CAST(ERROR_STATE() AS nvarchar(10));
PRINT ‘Error severity: ‘ + CAST(ERROR_SEVERITY() AS nvarchar(10));
PRINT ‘Error line: ‘ + CAST(ERROR_LINE() AS nvarchar(10));
PRINT ‘Error module: ‘ + COALESCE(ERROR_PROCEDURE(),”);

BEGIN TRY
    PRINT 10/0;
END TRY
BEGIN CATCH
    PRINT 'Error occurred!';
    PRINT 'Error number: ' + CAST(ERROR_NUMBER() AS nvarchar(10));
    PRINT 'Error message: ' + ERROR_MESSAGE();
    PRINT 'Error state: ' + CAST(ERROR_STATE() AS nvarchar(10));
    PRINT 'Error severity: ' + CAST(ERROR_SEVERITY() AS nvarchar(10));
    PRINT 'Error line: ' + CAST(ERROR_LINE() AS nvarchar(10));
    PRINT 'Error module: ' + COALESCE(ERROR_PROCEDURE(),'');
END CATCH;

PRINT ‘Error module: ‘ + COALESCE(ERROR_PROCEDURE(),”);

   BEGIN TRY
   EXEC dbo.badprocedure
   END TRY
   BEGIN CATCH

   END CATCH

name resulution error

BEGIN TRY
    DECLARE @unitprice INT=0;
    SELECT * FROM dbo.notavailable;

    PRINT 10/@unitprice;
END TRY
BEGIN CATCH
    PRINT 'Error occurred!';
    PRINT 'Error number: ' + CAST(ERROR_NUMBER() AS nvarchar(10));
    PRINT 'Error message: ' + ERROR_MESSAGE();
    PRINT 'Error state: ' + CAST(ERROR_STATE() AS nvarchar(10));
    PRINT 'Error severity: ' + CAST(ERROR_SEVERITY() AS nvarchar(10));
    PRINT 'Error line: ' + CAST(ERROR_LINE() AS nvarchar(10));
    PRINT 'Error module: ' + COALESCE(ERROR_PROCEDURE(),'');
END CATCH;

name resolution error handling by module

GO
CREATE OR ALTER PROCEDURE dbo.badprocedure
AS
    SELECT * FROM dbo.notavailable;
GO
EXEC dbo.badprocedure;
BEGIN TRY
    DECLARE @unitprice int=0;
    EXEC dbo.badprocedure;
    PRINT 10/@unitprice;
END TRY
BEGIN CATCH
    PRINT 'Error occurred!';
    PRINT 'Error number: ' + CAST(ERROR_NUMBER() AS nvarchar(10));
    PRINT 'Error message: ' + ERROR_MESSAGE();
    PRINT 'Error state: ' + CAST(ERROR_STATE() AS nvarchar(10));
    PRINT 'Error severity: ' + CAST(ERROR_SEVERITY() AS nvarchar(10));
    PRINT 'Error line: ' + CAST(ERROR_LINE() AS nvarchar(10));
    PRINT 'Error module: ' + COALESCE(ERROR_PROCEDURE(),'');
END CATCH;

negative unit price error by handling THROW

BEGIN TRY
    DECLARE @unitprice INT=-20;
    IF @unitprice < 0
    BEGIN
    -- THROW valid range begrin from 50000, def. severitylevel 16
        THROW 55555, 'The @unitprice parameter value is less than zero!', 1;
    END
    PRINT 'SOR'
END TRY
BEGIN CATCH
    PRINT 'Error occurred!';
    PRINT 'Error number: ' + CAST(ERROR_NUMBER() AS nvarchar(10));
    PRINT 'Error message: ' + ERROR_MESSAGE();
    PRINT 'Error state: ' + CAST(ERROR_STATE() AS nvarchar(10));
    PRINT 'Error severity: ' + CAST(ERROR_SEVERITY() AS nvarchar(10));
    PRINT 'Error line: ' + CAST(ERROR_LINE() AS nvarchar(10));
    PRINT 'Error module: ' + COALESCE(ERROR_PROCEDURE(),'');
END CATCH;

THROW in CATCH – eltöröm a kódot, de előtte kiiratom a hiba okát

BEGIN TRY
    DECLARE @unitprice INT=-20;
    IF @unitprice < 0
    BEGIN
    -- THROW valid range begrin from 50000, def. severitylevel 16
        THROW 55555, 'The @unitprice parameter value is less than zero!', 1;
    END
    PRINT 'SOR'
END TRY
BEGIN CATCH
    PRINT 'Error occurred!';
    PRINT 'Error number: ' + CAST(ERROR_NUMBER() AS nvarchar(10));
    PRINT 'Error message: ' + ERROR_MESSAGE();
    PRINT 'Error state: ' + CAST(ERROR_STATE() AS nvarchar(10));
    PRINT 'Error severity: ' + CAST(ERROR_SEVERITY() AS nvarchar(10));
    PRINT 'Error line: ' + CAST(ERROR_LINE() AS nvarchar(10));
    PRINT 'Error module: ' + COALESCE(ERROR_PROCEDURE(),'');
    SELECT CAST(@unitprice AS NVARCHAR(100)) + ' unitprice value causes the error';
    THROW;
END CATCH;

RAISE ERROR – in catch nem töri el a kódot

BEGIN TRY
    DECLARE @myvar int;

    SET @myvar = -1;

    /* throwing an error with an argument if the value is not acceptable */
    IF @myvar < 0
        RAISERROR ('The @myvar parameter value is %d!', 16, 1, @myvar);

    PRINT 'This line does not execute!'
END TRY
BEGIN CATCH
    PRINT 'Error occurred!'
    PRINT 'Error number: ' + CAST(ERROR_NUMBER() AS nvarchar(10));
    PRINT 'Error message: ' + ERROR_MESSAGE();
    PRINT 'Error state: ' + CAST(ERROR_STATE() AS nvarchar(10));
    PRINT 'Error severity: ' + CAST(ERROR_SEVERITY() AS nvarchar(10));
    PRINT 'Error line: ' + CAST(ERROR_LINE() AS nvarchar(10));
    PRINT 'Error module: ' + COALESCE(ERROR_PROCEDURE(),'');
END CATCH;

BEGIN TRY
    DECLARE @unitprice INT=-20;
    IF @unitprice < 0
    BEGIN
    -- THROW valid range begrin from 50000, def. severitylevel 16
        THROW 55555, 'The @unitprice parameter value is less than zero!', 1;
    END
    PRINT 'SOR'
END TRY
BEGIN CATCH
    PRINT 'Error occurred!';
    PRINT 'Error number: ' + CAST(ERROR_NUMBER() AS nvarchar(10));
    PRINT 'Error message: ' + ERROR_MESSAGE();
    PRINT 'Error state: ' + CAST(ERROR_STATE() AS nvarchar(10));
    PRINT 'Error severity: ' + CAST(ERROR_SEVERITY() AS nvarchar(10));
    PRINT 'Error line: ' + CAST(ERROR_LINE() AS nvarchar(10));
    PRINT 'Error module: ' + 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 can integrate to event viewer > windows log > applications
generate unique error code

BEGIN TRY
    DECLARE @unitprice INT=-20;
    IF @unitprice < 0
    BEGIN
    -- RAISERROR
        DECLARE @myerrorcode UNIQUEIDENTIFIER=NEWID();
        DECLARE @myerrorstring varbinary(16)= CAST(@myerrorcode AS varbinary(16));
        RAISERROR ('%d unitprice value causes the error! Your error code: %x', 16, 1, @unitprice,@myerrorstring) WITH LOG;
    END
    PRINT 'SOR'
END TRY
BEGIN CATCH
    PRINT 'Error occurred!';
    PRINT 'Error number: ' + CAST(ERROR_NUMBER() AS nvarchar(10));
    PRINT 'Error message: ' + ERROR_MESSAGE();
    PRINT 'Error state: ' + CAST(ERROR_STATE() AS nvarchar(10));
    PRINT 'Error severity: ' + CAST(ERROR_SEVERITY() AS nvarchar(10));
    PRINT 'Error line: ' + CAST(ERROR_LINE() AS nvarchar(10));
    PRINT 'Error module: ' + COALESCE(ERROR_PROCEDURE(),'');
    SELECT CAST(@unitprice AS NVARCHAR(100)) + ' unitprice valuse causes the error';
    THROW;
END CATCH;

error handling with INSERT

USE testdb;
GO

DROP TABLE IF EXISTS dbo.military;
CREATE TABLE dbo.military(
    id INT IDENTITY(1,1) PRIMARY KEY
    ,soldier_name varchar(100) NOT NULL
    ,soldier_bdate date CHECK (soldier_bdate > '19780101')
)

BEGIN TRY
    INSERT INTO dbo.military (soldier_name,soldier_bdate)
    VALUES ('John Ramobo', '19770101')
    -- RAISERROR
END TRY
BEGIN CATCH
    IF ERROR_NUMBER()=547
    BEGIN
    DECLARE @myerrorcode UNIQUEIDENTIFIER=NEWID();
        DECLARE @myerrorstring varbinary(16)= CAST(@myerrorcode AS varbinary(16));
        RAISERROR ('Check constraint violation. Your error code: %x', 16, 1,@myerrorstring) WITH LOG;
    END
    PRINT 'Error occurred!';
    PRINT 'Error number: ' + CAST(ERROR_NUMBER() AS nvarchar(10));
    PRINT 'Error message: ' + ERROR_MESSAGE();
    PRINT 'Error state: ' + CAST(ERROR_STATE() AS nvarchar(10));
    PRINT 'Error severity: ' + CAST(ERROR_SEVERITY() AS nvarchar(10));
    PRINT 'Error line: ' + CAST(ERROR_LINE() AS nvarchar(10));
    PRINT 'Error module: ' + COALESCE(ERROR_PROCEDURE(),'');
END CATCH;
/*barmilyen hiba*/
BEGIN TRY
    INSERT INTO dbo.military (soldier_name,soldier_bdate)
    VALUES ('John Ramobo', '19770101')
    -- RAISERROR
END TRY
BEGIN CATCH
    DECLARE @newerrormessage NVARCHAR(1000);
    SET @newerrormessage ='Error number: ' + CAST(ERROR_NUMBER() AS nvarchar(10)) + CHAR(13) + 'Error message: ' + ERROR_MESSAGE()+ CHAR(13) +'Error state: ' + CAST(ERROR_STATE() AS nvarchar(10))+ CHAR(13) +'Error severity: ' + CAST(ERROR_SEVERITY() AS nvarchar(10))+ CHAR(13) +'Error line: ' + CAST(ERROR_LINE() AS nvarchar(10)) + CHAR(13) + 'Error module: ' + 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;

nested try-catch block

BEGIN TRY
    PRINT 10/0;
END TRY
BEGIN CATCH
    BEGIN TRY
        INSERT INTO dbo.military (id,soldier_name,soldier_bdate)
        VALUES (1,'John Ramobo', '19790101')
    END TRY
    BEGIN CATCH
        THROW 55555, 'The @unitprice parameter value is less than zero!', 2;
    END CATCH
END CATCH

VIEWS

– hivatkozás, értékeket újra számolja, ha számított, kivéve ha indexed views

— Felhasználók elől rejtek el egy view-t, egyes oszlopokat nem teszek bele a viewba és ahhoz adok hozzáférést
— gyakorlatban egy külön schema-ba tesszük és arra adunk hozzáférést

USE WideWorldImporters
GO
SELECT c.CustomerName, o.OrderID, SUM(ol.Quantity) as QuantitySum 
FROM Sales.Customers as c
JOIN Sales.Orders as o ON o.CustomerID = c.CustomerID
JOIN Sales.OrderLines as ol ON ol.OrderID = o.OrderID
JOIN Warehouse.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 Sales.Customers as c
JOIN Sales.Orders as o ON o.CustomerID = c.CustomerID
JOIN Sales.OrderLines as ol ON ol.OrderID = o.OrderID
JOIN Warehouse.StockItems as si ON si.StockItemID = ol.StockItemID
GROUP BY c.CustomerName, o.OrderID;
GO
SELECT * FROM  FirstView;

WITH SCHEMABINDING, ENCRYPTION

SCHEMABINDING: nem tudjuk úgy módosítani, hogy használhatatlan legyen pl oszlop törlés
ENCRYPTION: nem tudjuk megnézni a kódját (create to)

GO
CREATE VIEW SecondView
WITH SCHEMABINDING, ENCRYPTION
AS
SELECT c.CustomerName, o.OrderID, SUM(ol.Quantity) as QuantitySum 
FROM Sales.Customers as c
JOIN Sales.Orders as o ON o.CustomerID = c.CustomerID
JOIN Sales.OrderLines as ol ON ol.OrderID = o.OrderID
JOIN Warehouse.StockItems as si ON si.StockItemID = ol.StockItemID
GROUP BY c.CustomerName, o.OrderID;
GO

ALTER VIEW

— view módosítása drop nélkül  –  DROP VIEW IF EXISTS dbo.VarosokOrszagok2;
–hasznalja a VarosokOrszagok2Alapjan még, ott még van SCHEMABIDING

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

INDEXED VIEW

persisted?

– determinisztikusnak kell lennie a view-nak
– schemabiding kell, a felhasználói functionöknek is
– csak táblákat használhat

milyen esetekben? milyen előnyökkel jár? indexed view
– disken van ezért gyorsabb

probléma: gyorsabb lekérdezni, ha bonyolult join van
ha módosítasz, akkor a view-t is módosítani kell

ha egy táblában többet írunk vagy ugyanannyit írunk, mint amennyit olvasunk, akkor nem alkalmazzuk

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);
-- nem determinisztikus
GO
ALTER VIEW dbo.NemDet
WITH SCHEMABINDING
AS
SELECT Nev, GetDate() AS RandomDate
FROM dbo.Varosok
GO
CREATE UNIQUE CLUSTERED INDEX ix_Nemdet ON dbo.NemDet(Nev);

-- JOIN, csak az inner-re lehet

DROP VIEW IF EXISTS dbo.TobbTabla;

GO
CREATE VIEW dbo.TobbTabla
WITH SCHEMABINDING
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 - Create, Read, Update, Delete

-- ORDER BY - nem lehet alapból
-- ORDER BY - TOP-pal
GO
CREATE VIEW dbo.ViewOrderBy
WITH SCHEMABINDING
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

Tárolt Eljárások

– Bemenetek
– Kimenetek
– Többször meglehet hívni

Tárolt eljárások előnyei:

– paraméterátadás
– tárolt eljárásra létrehoz egy > végrehajtási terv – teljesítmény – parameter sniffing – másik paraméterrel lehet nagyon lassú > WITH RECPOMPILE (minden meghíváshoz új execution plan)
— meg tudod oldani, hogy külön eset legyen
-https://www.brentozar.com/archive/2013/06/the-elephant-and-the-mouse-or-parameter-sniffing-in-sql-server/

– minden paraméternél kell a típus

GO
ALTER VIEW dbo.VarosokOrszagok2
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),
	OrszagNev NVARCHAR(100),
)

INSERT INTO #Eredmeny1
EXEC dbo.TaroltEljarasVarosokOrszagok

SELECT * FROM #Eredmeny1
GO
CREATE PROCEDURE dbo.VarosKereses(@SearchName 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 @SearchName
END
GO

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

Mi az az SQL Injection?

— Mit ír be a felhasználó? Ez oké?
–“V” > OK
— “V’ ; DROP TABLE dbo.students; SELECT * FROMdbo.Teachers WHERE valami LIKE ‘” > NAGYON NEM OKE
— WHERE studentId = 123 AND v.Nev LIKE ‘”‘ ” vagy WHERE v.Nev LIKE ‘”nincs ilyen ‘ OR 1=1″ > NAGYON NEM OK
–/**/OR//**/

— Mi a megoldás?

EXEC dbo.VarosKereses '"nincs ilyen OR 1=1 "'

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

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

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

SELECT * FROM dbo.Varosok WHERE Id =100;

You’ll need to specify the stored procedure table parameter
as READONLY

DROP TYPE IF EXISTS mytable;
CREATE TYPE mytable AS table
(
    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);

EXEC dbo.GetSales @t

Hogyan kaphatunk visszaértéket?
OUTPUT – paraméter! több kimeneti értéket is ki tudunk küldeni a tárol eljárásunkból

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

-- NULL-t ad vissza
DECLARE @doubledValue int;
EXEC dbo.OutputTest 2,@doubledValue
SELECT @doubledValue;
GO

-- Ez jó:
DECLARE @doubledValue int;
EXEC dbo.OutputTest 2, @doubledValue OUTPUT
SELECT @doubledValue;

-- Paraméterek sorrendjét nem lehet felcserélni
DECLARE @doubledValue int;
EXEC dbo.OutputTest @doubledValue OUTPUT,2;
SELECT @doubledValue;
GO

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

-- kivéve haa nevükkel van megadva
GO
DECLARE @doubledValue int;
EXEC dbo.OutputTest 2,@outparam = @doubledValue OUTPUT;

SELECT @doubledValue;

Visszatérési érték – 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

Első RETURN-ig fut

– korábban megadta, ezért ez már nem írja felül

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;
--korábban már visszaadta a @varost, ezért ez már nem írja felül
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;
--korábban megadta, ezért ez már nem írja felül
EXEC @ret = dbo.ReturnTest -3, @varos OUTPUT
SELECT @ret,@varos;
GO

HIBAKEZELÉS

GO
CREATE OR ALTER PROCEDURE dbo.PlaceOrder (@PaymentDate datetime2)
AS
IF @PaymentDate > GETDATE()
THROW 50001, 'Cannot Place an order in future',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.Osztas 10,0, @ertek OUTPUT;
SELECT @ret, @ertek;

DEFAULT érték

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.Osztas 10, @hanyados = @ertek OUTPUT;
SELECT @ret, @ertek;
GO
DECLARE @ertek INT,@ret INT;
EXEC @ret=dbo.Osztas 10,5, @ertek OUTPUT;
SELECT @ret, @ertek;

SET NOCOUNT ON

GO
CREATE OR ALTER PROCEDURE dbo.TaroltEljarasVarosokOrszagok
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 like 'B%';
END
GO
EXEC dbo.TaroltEljarasVarosokOrszagok

Hány soron volt módosítás?

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

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

UDF:

– always retrun
– not state, gives data type
– input paramater
– stored procedured can not be called

Types:
– system functions
– Table-valued: view-nál nem tudom paraméterezni
– Scalar-values: can be in select
– Aggregate < külső nyelveket pl .Net and C# függvényeket be lehet hozni
https://learn.microsoft.com/en-us/sql/t-sql/statements/create-aggregate-transact-sql?view=sql-server-ver15

TRY-CATCH – NEM MŰKÖDIK!!!!!!!!!!!!!!!!
de store procedure-ból hívom és ott van akkor igen

DDL, insert,update, delete nem működik
USE WideWorldImporters;
Go
GO
CREATE OR ALTER FUNCTION Sales.function_date()
RETURNS datetime  /* specify the data type of the value you return */
AS
BEGIN
    /* return your value */
    RETURN CURRENT_TIMESTAMP;
END;
GO
-- call function
SELECT Sales.function_date();

total_sum_orderline

GO
CREATE FUNCTION Sales.total_sum_orderline(
    @ordelineID int
)
RETURNS decimal(20,3) --WITH SCHEMABINDING  -  hozzákötjük a tábla szerkezetéhez,  valamikor segít a teljesítményben
AS
BEGIN
    RETURN (SELECT Quantity*UnitPrice FROM Sales.OrderLines Where OrderLineID = @ordelineID)
END;
GO
/*
    Using the Scalar UDF to return the taxed line total value
    in the SELECT clause.
*/

SELECT Sales.total_sum_orderline(2);
SELECT Quantity*UnitPrice FROM Sales.OrderLines Where OrderLineID = 2;
/* minden sorhoz a total- lassú lesz,soronként számol és a CPU magas lesz, nem szeretjük a skaláris függvényeket */
SELECT OrderLineID,Sales.total_sum_orderline(2)
FROM Sales.OrderLines;

UDF Scalar inlining

– nem hajtódik végre az UDF, szétszedi táblaműveletekre > kevesebb CPU — ADVANCED FEATURE
2019-től, ezért pakoltuk át
Meg kell felelni:

Inlineable scalar UDF requirements rész
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

– pl. egy return lehet csak
– for example Scalar UDF inlining not working with computed column!

GO
CREATE OR ALTER FUNCTION dbo.total_sum_orderline(
    @ordelineID int
)
RETURNS decimal(20,3) WITH SCHEMABINDING  -- hozzákötjük a tábla szerkezetéhez,  valamikor segít a teljesítményben
AS
BEGIN
    RETURN (SELECT Quantity*UnitPrice FROM dbo.testlines Where OrderLineID = @ordelineID)
END;
GO
SELECT dbo.total_sum_orderline(2);
SELECT Quantity*UnitPrice FROM dbo.testlines Where OrderLineID = 2;
/* számított oszlop - itt elvesztjük az inliningot - táblán belül maradjunk, ha csinálunk ilyet
check constraintbe is elveszítjük */
ALTER TABLE dbo.testlines
ADD totalsum AS dbo.total_sum_orderline(OrderID);

SELECT OrderLineID, totalsum FROM dbo.testlines
WHERE OrderLineID<200;
/*view-n - itt használjuk inkább */
GO
CREATE OR ALTER VIEW dbo.testview
WITH SCHEMABINDING
AS
SELECT OrderLIneID AS 'lineID'
, dbo.total_sum_orderline(OrderLineID)  as 'totalsum'
FROM dbo.testlines
GO
SELECT * FROM dbo.testview
WHERE LineID < 200;
/* if the view with schemabiding contains scalar function, then scalar function must be also schemabiding!! */
/* check constraint - inlining is not working */
ALTER TABLE dbo.testlines
ADD CONSTRAINT CK_test_1 CHECK (
(OrderLineID < 200 AND dbo.total_sum_orderline(OrderLineID) IS NOT NULL) OR OrderLineID >= 200);
UPDATE dbo.testlines
SET OrderLineID=1600
WHERE OrderLineID < 200;
--------------------------------datediff---------------------------------------------------------------------
DROP TABLE IF EXISTS dbo.testorders;
SELECT *
INTO dbo.testorders
FROM WideWorldImporters.Sales.Orders;
/* scalar function datediff orderdate between, return max 500 */
/* 2 return */
GO
CREATE OR ALTER FUNCTION dbo.datediffer(@orderid int)
RETURNS SMALLINT
WITH INLINE=ON -- csak inlineolhatot hoz létre
AS
BEGIN
    DECLARE @days SMALLINT;
    --RETURN (SELECT @days= DATEDIFF(dd, OrderDate, GETDATE()) FROM dbo.testorders WHERE OrderID = @orderid )
    SELECT @days= DATEDIFF(dd, OrderDate, GETDATE()) FROM dbo.testorders WHERE OrderID = @orderid
    IF @days > 500
    RETURN 500;

    RETURN @days;
END
GO
SELECT OrderID, OrderDate, dbo.datediffer(OrderID)
FROM dbo.testorders
WHERE OrderID < 200;
/*meg mindig nem, GETDATE*/
GO
CREATE OR ALTER FUNCTION dbo.datediffer(@orderid int)
RETURNS SMALLINT
WITH INLINE=ON -- csak inlineolhatot hoz létre
AS
BEGIN
    DECLARE @days SMALLINT;
    --RETURN (SELECT @days= DATEDIFF(dd, OrderDate, GETDATE()) FROM dbo.testorders WHERE OrderID = @orderid )
    SELECT @days= DATEDIFF(dd, OrderDate, GETDATE()) FROM dbo.testorders WHERE OrderID = @orderid
    IF @days > 500
    BEGIN
        SET @days=500;
    END

    RETURN @days;
END
GO
SELECT OrderID, OrderDate, dbo.datediffer(OrderID)
FROM dbo.testorders
WHERE OrderID < 200;
/*JÓ - inputdate*/
GO
CREATE OR ALTER FUNCTION dbo.datediffer(@orderid int, @inputdate DATE)
RETURNS SMALLINT
WITH INLINE=ON -- csak inlineolhatot hoz létre
AS
BEGIN
    DECLARE @days SMALLINT;
    --RETURN (SELECT @days= DATEDIFF(dd, OrderDate, GETDATE()) FROM dbo.testorders WHERE OrderID = @orderid )
    SELECT @days = DATEDIFF(dd, OrderDate, @inputdate) FROM dbo.testorders WHERE OrderID = @orderid
    IF @days > 500
    BEGIN
        SET @days=500;
    END

    RETURN @days;
END
GO
SELECT OrderID, OrderDate, dbo.datediffer(OrderID, GETDATE())
FROM dbo.testorders
WHERE OrderID < 200;
GO
CREATE OR ALTER FUNCTION dbo.datediffer2(@orderdate date,@inputdate date)
RETURNS smallint
WITH INLINE=ON
AS
BEGIN
	DECLARE @days int;
	SET @days = DATEDIFF(dd, @orderdate,@inputdate);
	IF @days > 500
		BEGIN
			SET @days = 500;
		END
	RETURN @days
END
GO

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

DEFAULT érték scalar UDF-nél

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);

Table-valued funcions:

– return always with table
– no JOIN

Types:
– inline table-valued functions iTVF > 1 SELECT STATEMENT;
– multi statement – MSTVF(borzalmas) – ne használd, rossz optimalizáció

USE WideWorldImporters;
GO
/*
    Creating an inline TVF to get ColorId and ColorName
*/
CREATE FUNCTION Warehouse.GetColor(@colorid int)
RETURNS TABLE
AS
RETURN 
    (SELECT ColorID, ColorName 
     FROM Warehouse.Colors 
     WHERE ColorID = @colorid);
GO
/*
    Using the inline TVF in a simple SELECT query in the FROM clause.
*/
SELECT ColorId, ColorName 
FROM WareHouse.GetColor(36);

SELECT ColorId, ColorName 
FROM WareHouse.GetColor(10);

DEFAULT érték TVF UDF-nél

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

APPLY – CROSS APPLY like inner join

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

APPLY – OUTER APPLY like LEFT OR RIGHT OUTER join

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

nem függvényes rész
táblaoperátor:
cross aply instead of subquery (return )
bizonyos subquery

cross apply instead of subquery (subquery returns 1 scalar value)
for example
https://github.com/green-fox-academy/teaching-materials/blob/master/workshop/sql-server-subqueries-aggregations/correlated-quantity/correlated-quantity.md
Modify the below query per the following:
– add a new column that shows the maximum quantity for the StockItemID
– add yet another column that shows the difference between the maximum
quantity for the StockItemID and each order quantity
| OrderID | StockItemID | Quantity | Max_StockItem_Qty | Max_Diff_Qty |

/* subquery verion: 0.1452 */
SELECT	o.OrderID
				,o.StockItemID
				,o.Quantity
				,(	SELECT MAX(Quantity)
					FROM Sales.OrderLines
					WHERE StockItemID = 180
				 ) AS Max_StockItem_Qty
				,(SELECT maxq.qty - Quantity
						FROM (	SELECT MAX(Quantity) AS qty
										FROM Sales.OrderLines
										WHERE StockItemID = 180
								 ) AS maxq
				) AS Max_Diff_Qty
FROM Sales.OrderLines AS o
WHERE StockItemID = 180;
/*	CROSS APPLY - table operator version - CROSS APPLY cost 0.102256 */
SELECT OrderId,StockItemID,Quantity,Max_StockItem_Qty,Max_StockItem_Qty-Quantity AS Max_Diff_Qty
FROM Sales.OrderLines
	CROSS APPLY (SELECT MAX(Quantity) AS Max_StockItem_Qty FROM Sales.OrderLines
		WHERE StockItemID=180) temptable
WHERE StockItemID = 180;

TRIGGERS

– can I run trigger? > NO
– an event activate the trigger ! “FIRE_TRIGGER”
– can I  give parameter to the trigger? -> NO
– IF … ELSE structure  usable
– try …catch structured error handling > YES
– create simple trigger
Trigger groups:
– DML triggers: INSERT, UPDATE, DELETE > MASTERWORK
– DDL trigger: ALTER,CREATE,DROP
— logon trigger

LOGON triggers: DANGEROUS! bejelentkezést elbaszhatja

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()
);
-- login name
SELECT SUSER_NAME();
-- server name \ (instance)
SELECT @@SERVERNAME;
-- sesrver version
SELECT @@VERSION;
-- service name (instance name without server)
SELECT @@SERVICENAME;
/*trigger*/
GO
CREATE OR ALTER TRIGGER tr_logtouser
ON ALL SERVER FOR LOGON
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;
-- drop logon trigger
DROP TRIGGER tr_logtouser ON ALL SERVER;

DDL triggers

DROP TABLE IF EXISTS dbo.Invoices;
CREATE TABLE dbo.Invoices (
    id INT PRIMARY KEY,
    customer_id INT NOT NULL,
    total INT NOT NULL
);
INSERT INTO dbo.Invoices
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 'you can not change or delete any tables!'
ROLLBACK;
END
PRINT 'hello';
GO
SELECT * FROM sys.triggers;
ALTER TABLE dbo.Invoices
DROP COLUMN total;
DROP TRIGGER invoiceprotector ON DATABASE;

DML triggers:

– AFTER trigger
– INSTEAD OF trigger

AFTER DELETE

DROP TABLE IF EXISTS dbo.storno_invoices  
CREATE TABLE dbo.storno_invoices  (
    id INT, --PRIMARY KEY,
    customer_id INT NOT NULL,
    total INT NOT NULL,
    delete_time DATETIME2 NOT NULL DEFAULT CURRENT_TIMESTAMP
);
/* AFTER TRIGGER - create trigger to move deleted invoices to strono_table
SQL SERVER trigger works per statement!!!!!
- Avoid variables ! */
GO
CREATE TRIGGER dbo.TR_stroni_invoice ON dbo.Invoices AFTER DELETE
AS
SET NOCOUNT ON;
BEGIN
    INSERT INTO dbo.storno_invoices (id, customer_id,total)
    SELECT * FROM deleted;
END
GO
SELECT * FROM dbo.Invoices;
SELECT * FROM dbo.storno_invoices;

DELETE FROM dbo.Invoices
WHERE total > 1000;

SELECT * FROM dbo.Invoices;
SELECT * FROM dbo.storno_invoices;

create trigger to deny: modify invoice

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

UPDATE dbo.Invoices
SET total=1000
WHERE id=3;

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

where are the DML triggers!

!!!!! TRUNCATE can not activate with triggers !!!!!!!!!!

INSTEAD OF triggers? > DML triggers

pl. szamlaknal a nagyok máshova menjenek ritka

create a trigger
where total >= 1100 > dbo.Invoces

where total < 1100 > dbo.smalltotalinvoices

DROP TABLE IF EXISTS dbo.smalltotalinvoices
  CREATE TABLE dbo.smalltotalinvoices (
    id INT PRIMARY KEY,
    customer_id INT NOT NULL,
    total INT NOT NULL
);
SELECT * FROM dbo.Invoices;
GO 
CREATE OR ALTER TRIGGER dbo.tr_smalltotal
ON dbo.Invoices 
INSTEAD OF INSERT
AS
SET NOCOUNT ON;
BEGIN
 INSERT INTO dbo.Invoices
 SELECT * FROM inserted
 WHERE total >=1100;

 INSERT INTO dbo.smalltotalinvoices
 SELECT * FROM inserted
 WHERE total < 1100;
END
GO
 INSERT INTO dbo.Invoices
 VALUES(3,200,50000);

  INSERT INTO dbo.Invoices
 VALUES(5,200,900);

SELECT * FROM dbo.Invoices;
SELECT * FROM dbo.smalltotalinvoices;

bulk insert ignoralja a triggert alapból

bulk insert dbo.Invoices
  FROM N'C:\Users\mrhen\Documents\READER\MatReview\WEEK-4\w1d1_smalltotal.csv'
  WITH (fieldterminator=';',rowterminator='0x0A'/* nem '\n' mert Zolitól volt,  FIRSTROW=2 ha van fejlec*/)
TRUNCATE TABLE dbo.invoices;
TRUNCATE TABLE dbo.smalltotalinvoices;
/* DE FIRE_TRIGGERS */
bulk insert dbo.Invoices
  FROM N'C:\Users\mrhen\Documents\READER\MatReview\WEEK-4\w1d1_smalltotal.csv'
  WITH (fieldterminator=';',rowterminator='0x0A', FIRE_TRIGGERS/* nem '\n' mert Zolitól volt,  FIRSTROW=2 ha van fejlec*/)

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;

Window function

– Window aggregate functions (COUNT, SUM, MIN, MAX)
– Ranking functions (ROW_NUMBER, RANK, DENSE_RANK, NTILE)
– Offset functions (LAG, LEAD, FIRST_VALUE, LAST_VALUE)
– Statistical functions (PERCENTILE_CONT, PERCENTILE_DISC, PERCENT_RANK, CUME_DIST)

OVER() == Window function / SELECT /

sor halmazokat, adott sorhalmaz az ablak,

USE WideWorldImporters;
GO
/* stockitemid, sum_stock_quantities */
SELECT StockItemId, SUM(Quantity) AS sum_stock_quantities
FROM Sales.OrderLines
GROUP BY StockItemID;
GO
SELECT SUM(quantity) AS sum_all_quantitis
FROM Sales.OrderLines;
/* FELADAT
orderlineid stockitemid sum_stock sum_all
1           1               20000   9million
2           1               20000   
3             2             1000
*/
WITH myCTE AS (
    SELECT StockItemId, SUM(Quantity) AS sum_stock_quantities
    FROM Sales.OrderLines
    GROUP BY StockItemID
),
myCTE2 AS (
    SELECT SUM(quantity) AS sum_all_quantitis
    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 with window function */
SELECT SUM(Quantity) OVER ()
FROM Sales.OrderLines;
/*replacing cte1 with new function*/
SELECT SUM(Quantity) OVER (PARTITION BY StockItemID)
FROM Sales.OrderLines;
/* Window function version */
SELECT sol.StockItemID,
OrderLineID, 
SUM(Quantity) OVER (PARTITION BY StockItemID) AS sum_stock_quantitis,
SUM(Quantity) OVER () AS sum_all_quantities
, FORMAT(SUM(Quantity) OVER (PARTITION BY StockItemID)/(SUM(Quantity) OVER ()*1.0),'P2') AS pct_all_quantity
FROM Sales.OrderLines sol
ORDER BY sol.[StockItemID] ASC, OrderLineID ASC;

windows function by group by

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

ranking functions

syntax requirement: ORDER BY inside OVER clause

ROW_NUMBER, RANK, DENSE_RANK, NTILE

SELECT OrderId, Customerid,OrderDate,
    ROW_NUMBER() OVER (ORDER BY OrderDate) AS ROW_NUMBER
    , Rank() OVER(ORDER BY OrderDate) AS rnk -- holtversenynél kihagyja a és a következő rank a sor
    , DENSE_RANK() OVER(ORDER BY OrderDate) AS dense_rnk -- holtversenynél jön a következő rank
    , NTILE (20) OVER(ORDER BY OrderDate) AS n_tile -- 20 részre osztja, visszakapott halmazt
FROM Sales.Orders;

ranking by orderid per customerid

SELECT OrderId, CUstomerid,OrderDate,
    ROW_NUMBER() OVER (PARTITION BY CustomerID ORDER BY OrderDate) AS ROW_NUMBER
    , Rank() 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 -- 20 részre osztja, visszakapott halmazt
FROM Sales.Orders;

webshop rendelés milyen tételekből áll – végösszeg, orderline_number

SELECT OrderId, 
StockItemID,
Quantity,
UnitPrice, 
(UnitPrice*Quantity) AS OrderLine_SUM,
ROW_NUMBER() OVER (PARTITION BY OrderID ORDER BY (SELECT NULL)) AS orderline_number,
SUM(UnitPrice*Quantity) OVER (PARTITION BY OrderID Order BY OrderLineID) as running_total
 FROM Sales.OrderLines;

 SELECT OrderId, 
StockItemID,
Quantity,
UnitPrice, 
OrderLineID,
(UnitPrice*Quantity) AS OrderLine_SUM,
ROW_NUMBER() OVER (PARTITION BY OrderID ORDER BY (SELECT NULL)) AS orderline_number,
SUM(UnitPrice*Quantity) OVER (PARTITION BY OrderID Order BY OrderLineID DESC) as running_total
 FROM Sales.OrderLines;

running total

SELECT CityID, CityName, LatestRecordedPopulation AS population,
       (SELECT SUM(LatestRecordedPopulation) 
        FROM Application.Cities c2 
        WHERE c2.StateProvinceID = c1.StateProvinceID AND c2.CityID <= c1.CityID) AS run_total
FROM Application.Cities c1
WHERE StateProvinceID = 6
ORDER BY CityID;
/* windows function version */
 SELECT CityID, CityName, LatestRecordedPopulation,
 SUM(LatestRecordedPopulation) OVER(ORDER BY CityID) as run_total
FROM Application.Cities
WHERE StateProvinceID = 6

offset function
(LAG, LEAD, FIRST_VALUE, LAST_VALUE)

/* next cityID */
SELECT CityID, CityName, (SELECT MIN(CityID) FROM Application.Cities c2 WHERE c2.CityID > c1.CityID) AS nextcityid
FROM Application.Cities c1
ORDER by CityID ASC;
/* windows function order */
SELECT CityID, CityName, LEAD(CityID) OVER(ORDER BY CityID) AS nextcityid
FROM Application.Cities
ORDER by CityID ASC;

SELECT CityID, CityName, LAG(CityID) OVER(ORDER BY CityID) AS nextcityid
FROM Application.Cities
ORDER by CityID ASC;

DIAGNOSZTIKAI LEKÉRDEZÉSEK

Táblák lekérdezése a sys.tables-ből

SELECT * FROM sys.tables;

Táblák és sémáik – joining the sys.tables and the sys.schemas catalog views

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

melyik session-ben vagyunk

SELECT @@SPID;

get column data type info for all user tables

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;

count index per table

SELECT S.name,COUNT(SYS.INDEXES.name) FROM SYS.INDEXES
INNER JOIN SYS.OBJECTS S
ON S.OBJECT_ID=SYS.INDEXES.OBJECT_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;

list index per table

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

count constraints (check+default) in db

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

Determinisztikus?

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

Select * FROM sys.computed_columns;

Keresés  oszlop neve alapján

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

Keresés tábla neve alapján

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%'

String keresése az adatbázisban

DECLARE @SearchStr nvarchar(100)
SET @SearchStr = 'Limited Stock'

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

SET NOCOUNT ON

DECLARE @TableName nvarchar(256), @ColumnName nvarchar(128), @SearchStr2 nvarchar(110)
SET  @TableName = ''
SET @SearchStr2 = QUOTENAME('%' + @SearchStr + '%','''')

WHILE @TableName IS NOT NULL
BEGIN
    SET @ColumnName = ''
    SET @TableName = 
    (
        SELECT MIN(QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME))
        FROM     INFORMATION_SCHEMA.TABLES
        WHERE         TABLE_TYPE = 'BASE TABLE'
            AND    QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME) > @TableName
            AND    OBJECTPROPERTY(
                    OBJECT_ID(
                        QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME)
                         ), 'IsMSShipped'
                           ) = 0
    )

    WHILE (@TableName IS NOT NULL) AND (@ColumnName IS NOT NULL)
    BEGIN
        SET @ColumnName =
        (
            SELECT MIN(QUOTENAME(COLUMN_NAME))
            FROM     INFORMATION_SCHEMA.COLUMNS
            WHERE         TABLE_SCHEMA    = PARSENAME(@TableName, 2)
                AND    TABLE_NAME    = PARSENAME(@TableName, 1)
                AND    DATA_TYPE IN ('char', 'varchar', 'nchar', 'nvarchar')
                AND    QUOTENAME(COLUMN_NAME) > @ColumnName
        )

        IF @ColumnName IS NOT NULL
        BEGIN
            INSERT INTO @Results
            EXEC
            (
                'SELECT ''' + @TableName + '.' + @ColumnName + ''', LEFT(' + 
@ColumnName 
+ ', 3630) FROM ' 
+ 
@TableName 
+ ' (NOLOCK) ' +
                ' WHERE ' 
+ 
@ColumnName 
+ ' LIKE '
+ 
@SearchStr2
                
            )
        END
    END    
END

SELECT ColumnName, ColumnValue FROM @Results

Sys.messages & Modifying language in session

8134 system error messages-ben > diagn. query
SELECT * FROM sys.messages
WHERE message_id=8134;
/* modify language in session */
SET LANGUAGE hungarian;
PRINT 10/0;
SET LANGUAGE english;
PRINT 10/0;

VIEW diagnosztikai lekérés

SELECT * FROM sys.sql_modules WHERE [object_id] = OBJECT_ID('VarosokOrszagok2');
database logs per database id
SELECT b.name,a.* FROM sys.databases b
CROSS APPLY sys.dm_db_log_info(b.database_id) a
WHERE b.name = 'WideWorldImporters';

minden TRIGGER listázása

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

detect locked objects

SELECT resource_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
    and resource_database_id = DB_ID();

detect isolation level

SELECT CASE transaction_isolation_level 
    WHEN 0 THEN 'Unspecified' 
    WHEN 1 THEN 'ReadUncommitted' 
    WHEN 2 THEN 'ReadCommitted' 
    WHEN 3 THEN 'Repeatable' 
    WHEN 4 THEN 'Serializable' 
    WHEN 5 THEN 'Snapshot' END AS TRANSACTION_ISOLATION_LEVEL 
FROM sys.dm_exec_sessions 
-- use your session ID instead of 75
where session_id = 75;

SQL Kisokos

 

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

##### SQL alapok #####

SELECT IN SELECT, WHERE IN, WHERE NOT IN

SELECT TOP (1000) [SZAMLAFEJ_ID]
      ,[VEVO_ID]
      ,[KELTE]
      ,[TELJESITES]
      ,[FIZHATARIDO]
      ,[NAVATKULDVE]
      ,[STATUS]
  FROM [CEGESADATOK].[szamlazas].[szamlafej]
  WHERE VEVO_ID Not IN (select vevo_id
						from szamlazas.vevo)

UPDATE

USE [CEGESADATOK]
GO

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

INSERT INTO

USE [CEGESADATOK]
GO

INSERT INTO [szamlazas].[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 [CEGESADATOK]
GO

INSERT INTO [szamlazas].[vevo]
           ([VEVONEV]
           ,[ADOSZAM]
           ,[CIM]
           ,[TELEFON]
           ,[EMAIL]
           ,[STATUS])
     VALUES
           ('Hetedik Bt.',
           '11223344-2-05',
           'Seholgy sincs',
           '',
            null,
           0)
GO

DELETE

USE CEGESADATOK
Go

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


SELECT SZAMLAFEJ_ID
FROM szamlazas.szamlafej

DELETE FROM szamlazas.szamlatetel
WHERE SZAMLAFEJ_ID Not IN (SELECT SZAMLAFEJ_ID
							FROM szamlazas.szamlafej)
GO

DISTINCT

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

CONVERT, AVG

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

SELECT AVG(EGYSEGAR)
  FROM [CEGESADATOK].[szamlazas].[ARU]


SELECT *
  FROM [CEGESADATOK].[szamlazas].[ARU]
  where EGYSEGAR < (SELECT AVG(EGYSEGAR) as egysegar
					FROM [CEGESADATOK].[szamlazas].[ARU])

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

FROMART, CONVERT

select getdate()
select FORMAT(getdate(), 'yyyy')
select FORMAT(getdate(), 'yyyy/MM')
select FORMAT(getdate(), 'yyyy/MM/dd')
select FORMAT(getdate()+1, 'yyyy/MM/dd')
select FORMAT(getdate()-2, 'yyyy/MM/dd')
select FORMAT(getdate(), 'yyyy/MM/dd HH:mm:ss.ms')

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

HAVING

/*Feladat:
Irassuk ki azoknak a vevőknek a nevet,címét, adószámát ésa vásárlások számát, akik legalább kétszer vásároltak
ROSSZ:
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)
							from szamlazas.szamlafej
							group by szf.VEVO_ID) > 1
GROUP by v.VEVONEV
*/

select COUNT(szf.VEVO_ID), szf.VEVO_ID
							from szamlazas.szamlafej szf
							group by 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

/*Feladat:
Irassuk ki azoknak a vevőknek a nevet,címét, adószámát ésa vásárlások számát, bruttó szummáját*/
select v.VEVO_ID,v.VEVONEV,v.CIM, v.ADOSZAM, 
	CONVERT(int,SUM(t.[BRUTTO ERTEK])) as SZUMMABRUTTO
from szamlazas.vevo v inner join szamlazas.szamlafej szf on v.VEVO_ID=szf.VEVO_ID
inner join szamlazas.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 SZUMMABRUTTO
from szamlazas.vevo v inner join szamlazas.szamlafej szf on v.VEVO_ID=szf.VEVO_ID
inner join szamlazas.szamlatetel t on szf.SZAMLAFEJ_ID=t.SZAMLAFEJ_ID
inner join szamlazas.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 SZUMMABRUTTO desc

CONSISTENT FIX

use CEGESADATOK
go

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

go

SOK JOIN, SOK WHERE

USE CEGESADATOK
GO

/* Kik akik vettek A7-et?*/
select VEVONEV
From szamlazas.vevo
WHERE VEVO_ID IN (select VEVO_ID 
					FROM szamlazas.szamlafej
					WHERE SZAMLAFEJ_ID in (select SZAMLAFEJ_ID
											From szamlazas.szamlatetel 
											where ARU_ID IN (select ARU_ID 
																From szamlazas.ARU
																where ARUNEV='A7')))


select v.*
FROM szamlazas.vevo v
INNER JOIN szamlazas.szamlafej f ON v.VEVO_ID=f.VEVO_ID
	INNER JOIN szamlazas.szamlatetel t ON f.SZAMLAFEJ_ID=t.SZAMLAFEJ_ID
		INNER JOIN szamlazas.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.szamlafej sz ON v.VEVO_ID=sz.VEVO_ID
INNER JOIN szamlazas.tetelek t ON sz.SZAMLAFEJ_ID=t.SZAMLAFEJ_ID
where t.ARUNEV='A7'




select * 
FROM szamlazas.szamlafej
WHERE SZAMLAFEJ_ID in (select SZAMLAFEJ_ID
						From szamlazas.szamlatetel 
						where ARU_ID IN (select ARU_ID 
											From szamlazas.ARU
											where ARUNEV='A7'))

select * 
From szamlazas.szamlatetel 
where ARU_ID IN (select ARU_ID 
					From szamlazas.ARU
					where ARUNEV='A7')

/*
select * 
From szamlazas.tetelek t INNER JOIN szamlazas.szamlafej sz ON t.SZAMLAFEJ_ID=sz.SZAMLAFEJ_ID
where ARUNEV='A7'

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

LEKÉRDEZÉS VIEW-HOZ

USE CEGESADATOK
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) as 'BRUTTO 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 szamlazas.tetelek

CREATE VIEW

create view szamlazas.rossz_szamlafej
as
select *
from szamlazas.szamlafej
where VEVO_ID not in (select vevo_id from szamlazas.vevo)

Create schema (séma)

USE [CEGESADATOK]
GO

/****** Object:  Schema [szamlazas]    Script Date: 2022. 10. 25. 0:11:57 ******/
CREATE SCHEMA [szamlazas]
GO

Create user, login, permissions, roles

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 [CEGESADATOK]
GO
ALTER ROLE [db_backupoperator] ADD MEMBER [test1]
GO
USE [CEGESADATOK]
GO
ALTER ROLE [db_datareader] ADD MEMBER [test1]
GO
USE [CEGESADATOK]
GO
ALTER ROLE [db_datawriter] ADD MEMBER [test1]
GO
USE [CEGESADATOK]
GO
ALTER ROLE [db_ddladmin] ADD MEMBER [test1]
GO
USE [CEGESADATOK]
GO
ALTER ROLE [db_securityadmin] ADD MEMBER [test1]
GO

Tábla törlése, truncate table

/****** Script for SelectTopNRows command from SSMS  ******/
SELECT TOP (1000) [SZAMLAFEJ_ID]
      ,[VEVO_ID]
      ,[KELTE]
      ,[TELJESITES]
      ,[FIZHATARIDO]
      ,[NAVATKULDVE]
      ,[STATUS]
  FROM [CEGESADATOK].[szamlazas].[szamlafej]

  truncate table szamlazas.szamlafej

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

###### 3. vizsga SQL  #####

Táblák létrehozása (create table)

CREATE TABLE apprentices(
	id int,
	name varchar(50),
	age int,
	country varchar(50),
	cohort_id int)

CREATE TABLE cohorts(
	id int,
	name varchar(50),
	started_at date,
	type varchar(50))

Táblák importálása (bulk insert)

/****** Script for SelectTopNRows command from SSMS  ******/
  bulk insert apprentices
  FROM N'E:\apprentices.table.csv'
  WITH (fieldterminator=';',rowterminator='\n'/*,  FIRSTROW=2 ha van fejlec*/)

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

Listázd a nevét (name) és kezdési dátumát (started_at) az összes a évfolyamnak (cohorts tábla)
Filename: cohorts.sql

SELECT name, started_at
 FROM cohorts

Listázd a nevét (name) és származási országát (country) az összes a hallgatónak (apprentices tábla)
Filename: apprentices.sql

SELECT name, country
FROM apprentices

Listázd a nevét (name) és korát (age) azoknak hallgatónak (apprentices tábla), akik fiatalabbak, mint 21
Filename: apprentices-younger-21.sql

SELECT name, age
FROM apprentices
WHERE age < 21

Listázd az id-ját és nevét (name) azoknak hallgatónak (apprentices tábla), akik nem Magyarországról származnak (country)
Filename: apprentices-not-from-hu.sql

SELECT id, name
FROM apprentices
WHERE country not like 'Hungary'

Írasd ki hány darab olyan hallgató(apprentices tábla) található az adatbázisban, akik legalább 20 és legfeljebb 30 évesek
Filename: apprentices-between-20-and-30.sql

SELECT count(id)
FROM apprentices
WHERE age >= 20 and age <= 30

Írasd ki hány darab olyan évfolyam(cohorts tábla) található az adatbázisban, amelyek “part-time” típusúak (type)
Filename: cohorts-part-time.sql

SELECT count(id)
FROM cohorts
WHERE type like 'part-time'

Listázd a hallgatók nevét (as apprentice_name) és évfolyam nevét (as cohort_name) azoknak a hallgatóknak, akik 2018-as évfolyamokban kezdték (started_at) a tanulmányaikat.
Filename: apprentices-in-2018.sql

SELECT a.name as apprentice_name, c.name as cohort_name
FROM apprentices a INNER JOIN cohorts c ON a.cohort_id=c.id
WHERE FORMAT(started_at, 'yyyy')=2018

Írasd ki hány darab olyan évfolyam található az adatbázisban, amelyekhez nincs még hallgató felvéve
Filename: cohorts-without-apprentice.sql

SELECT count(id)
FROM cohorts
WHERE id NOT IN (SELECT cohort_id FROM apprentices)

Listázd a hallgatók nevét és a képzés kezdődátumát a hallgató neve alapján rendezve ABC sorrendben
Filename: apprentices-start-date-ordered.sql

SELECT a.name, c.started_at
FROM apprentices a INNER JOIN cohorts c ON a.cohort_id=c.id
ORDER BY a.name

Listázd az évfolyamok nevét és a hallgatók számát (as numberOfApprentices) az adott évfolyamban, a hallgatók számával csökkenő sorrendben. Az az évfolyam is legyen benne, ahol jelenleg 0 hallgató van.
Filename: cohort-sizes.sql

SELECT c.name, count(a.id) as numberOfApprentices
FROM cohorts c LEFT JOIN apprentices a ON a.cohort_id=c.id
GROUP BY c.name
ORDER BY count(a.id) DESC

###### SQL admin projektfeladatok #####

1) A szerverhez hozzá van adva egy disk, ami még nincs használatban
(20GB). Add hozzá a géphez S: meghajtóként, a kötet neve pedig:
SQLDATA legyen.

2) Az S: meghajtón hozzál létre egy SQLDATA könyvtárat, majd abban
további két alkönyvtárat: DB és LOG névvel.

3) Jelentkezz be az SQL szerverbe (GREENFOX instance)! (Ezt a lépést
nem kötelező elmentened! :-)

4) Töltsd vissza a C:\install\MSSQL\AdventureWorks2016.bak
adatbázist a szerver GREENFOX instance-ába úgy, hogy az adatbázis
állományok az S:\SQLDATA\DB, míg a log állományok az S:\SQLDATA\
LOG könyvtárba kerüljenek.

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

GO

5) Hozz létre egy interface_svc MS SQL autentikációjú account-ot,
minimális (public) jogokkal! A jelszava legyen: INTERface.

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

6) Hozz létre egy INTERFACE nevű adatbázist az alábbi beállításokkal:
• Adatbázis neve: INTERFACE
• Tulajdonos: interface_svc
• Recovery model: FULL
• Induló adatbázis file:
(a)méret: 32 MByte
(b)helye: S:\SQLDATA\DB
• Induló log file:
(a) méret: 16 MByte
(b)helye: S:\SQLDATA\LOG

CREATE DATABASE [INTERFACE]
 CONTAINMENT = NONE
 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 = Off;
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 = Off;
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) Adj csak lekérdezési jogot az interface_svc account számára az
AdventureWorks2016 adatbázis HumanResources sémában levő
vEmployee nézettáblájára (VIEW)!

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

8) INTERFACE adatbázisban hozz létre egy AWDB sémát! A szkript
„Create to » formátumú legyen

USE [INTERFACE]
GO

/****** Object:  Schema [AWDB]    Script Date: 12/9/2022 8:21:47 AM ******/
CREATE SCHEMA [AWDB]
GO

9) Az AWDB sémában hozz létre egy szinonimát AW_Employee néven,
ami az AdventureWorks2016 adatbázis HumanResources sémában
levő vEmployee nézettáblára mutat!

USE [INTERFACE]
GO

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

10) Készíts lekérdezést, ami az INTERFACE adatbázisnak az AWDB
sémájának az AW_Employee szinonimájának minden sorát és oszlopát
kilistázza!

USE [INTERFACE]
GO
SELECT * 
FROM AWDB.AW_Employee

11) Készíts az INTERFACE adatbázisról egy FULL mentést, az alábbiak
szerint:
a) Backup file neve: S:\SQLdata\INTERFACE.bak
b) Mentés felülírja az azonos nevű media set-et!

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) Kérdezd le az SQL szerver verzióját és az SQL szerver kiadását!

SELECT @@VERSION

2) Készíts egyszerű “Hello World!” lekérdezést!

SELECT 'Hello World!'

3) Készíts olyan SQL lekérdezést, ami kiszámítja 30 négyzetgyökét!

SELECT SQRT(30)

4) Készíts olyan SQL lekérdezést, ami visszaadja a mai dátumot!

SELECT CAST(GETDATE() as date)

5) Készíts olyan SQL lekérdezést, ami kiszámítja, hogy hány nap telt el
1989. március 15-e óta!

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

6) Készíts olyan SQL lekérdezést, ami visszaadja a korábban betöltött
AdventureWorks adatbázis Person.Address táblájának első 20 elemét
(minden mezőjét)!

/****** Script for SelectTopNRows command from SSMS  ******/
SELECT TOP (20) *
  FROM [AdventureWorks2016].[Person].[Address]

7) Készíts olyan SQL lekérdezést, ami visszaadja a korábban betöltött
AdventureWorks adatbázis Person.Person táblájának első 20 elemét
(minden mezőjét), de úgy, hogy ahol a PersonType mező értéke ‘EM’!

/****** Script for SelectTopNRows command from SSMS  ******/
SELECT TOP (20) *
  FROM [AdventureWorks2016].[Person].[Person]
  WHERE [AdventureWorks2016].[Person].[Person].PersonType='EM'

8) Készíts olyan SQL lekérdezést, ami visszaadja a korábban betöltött
AdventureWorks adatbázis Person.Person táblájának első 20 elemét, de
úgy, hogy ahol a PersonType mező értéke ‘EM’ és csak a PersonType,
FirstName, LastName mezők legyenek a lekérdezés eredményében!

/****** Script for SelectTopNRows command from SSMS  ******/
SELECT TOP (20) PersonType, FirstName, LastName
  FROM [AdventureWorks2016].[Person].[Person]
  WHERE [AdventureWorks2016].[Person].[Person].PersonType='EM'

9) Készíts olyan SQL lekérdezést, ami visszaadja a korábban betöltött
AdventureWorks adatbázis Person.Person táblájának első 20 elemét, de
úgy, hogy ahol a PersonType mező értéke ‘EM’ és csak a PersonType,
FirstName, LastName mezők legyenek a lekérdezés eredményében, de a
FirstName és LastName egy oszlopban jelenjen meg egy darab szóköz
karakterrel elválasztva!

/****** Script for SelectTopNRows command from SSMS  ******/
SELECT TOP (20) PersonType, FirstName + ' ' + LastName
  FROM [AdventureWorks2016].[Person].[Person]
  WHERE PersonType='EM'

10)Készíts olyan SQL lekérdezést, ami visszaadja a korábban betöltött
AdventureWorks adatbázis Person.Person táblájának azon rekordjait
(minden mezőjét), ahol a PersonType mező értéke ‘EM’ és a FirstName
mezőben csak a ‘John’ nevűek közül azok legyenek megjelenítve!

/****** Script for SelectTopNRows command from SSMS  ******/
SELECT *
  FROM [AdventureWorks2016].[Person].[Person]
  WHERE PersonType='EM' AND FirstName='John'

11)Készíts olyan SQL lekérdezést, ami visszaadja a korábban betöltött
AdventureWorks adatbázis Person.Person táblájának azon rekordjait
(minden mezőjét), ahol a PersonType mező értéke ‘EM’ és a FirstName
mezőben csak a ‘John’ nevűek közül azok legyenek megjelenítve, ahol a
LastName mező értéke ‘e’-karakterrel végződik!

/****** Script for SelectTopNRows command from SSMS  ******/
SELECT *
  FROM [AdventureWorks2016].[Person].[Person]
  WHERE PersonType='EM' AND FirstName='John' AND RIGHT(LastName,1)='e'

12)Készíts olyan SQL lekérdezést, ami visszaadja a korábban betöltött
AdventureWorks adatbázis Person.Person táblájának azon rekordjait
(minden mezőjét), ahol a PersonType mező értéke ‘EM’ és a FirstName
mezőben csak a ‘John’ nevűek közül azok legyenek megjelenítve, ahol a
LastName mező értéke vagy ‘Chen’ vagy ‘Kane’ neveket tartalmazzák!

/****** Script for SelectTopNRows command from SSMS  ******/
SELECT *
  FROM [AdventureWorks2016].[Person].[Person]
  WHERE PersonType='EM' AND FirstName='John' AND (LastName='Chen' OR LastName='Kane')

13) Számold meg, hogy hány különböző keresztnév (FirstName) van a
korábban betöltött AdventureWorks adatbázis Person.Person táblájában!

/****** Script for SelectTopNRows command from SSMS  ******/
SELECT COUNT(DISTINCT FirstName)
  FROM [AdventureWorks2016].[Person].[Person]

14) Számold meg, hogy hány ‘Ken’ keresztnévű (FirstName) rekord van a
korábban betöltött AdventureWorks adatbázis Person.Person táblájában!

/****** Script for SelectTopNRows command from SSMS  ******/
SELECT COUNT(FirstName)
  FROM [AdventureWorks2016].[Person].[Person]
  WHERE FirstName='Ken'

15) Számold meg, hogy hány azonos nevű (FirstName és LastName) rekord
van a korábban betöltött AdventureWorks adatbázis Person.Person
táblájában! Rendezd az eredményt úgy, hogy a legtöbbet használt
névpáros a lista elején szerepeljen és csak a legelső 20 eredmény
szerepeljen!

/****** Script for SelectTopNRows command from SSMS  ******/
SELECT TOP (20) FirstName, LastName, COUNT(1)
  FROM [AdventureWorks2016].[Person].[Person]
  GROUP BY FirstName, LastName
  ORDER BY COUNT(1) DESC

16) Számold meg, hogy hány azonos nevű (FirstName és LastName) rekord
van a korábban betöltött AdventureWorks adatbázis Person.Person
táblájában! Rendezd az eredményt úgy, hogy csak a 4 és a 4-nél többször
használt névpáros eredménye szerepeljen!

SELECT FirstName, LastName, COUNT(1)
  FROM [AdventureWorks2016].[Person].[Person]
  GROUP BY FirstName, LastName
  HAVING COUNT(1) >= 4
  ORDER BY COUNT(1) DESC

17)Készíts olyan SQL lekérdezést, ami visszaadja a korábban betöltött
AdventureWorks adatbázis Person.Person és Person.EmailAddress
tábláinak a következő mezőit: Person.Person.FirstName,
Person.Person.LastName, Person.EmailAddress.EmailAddress úgy hogy a
táblák összekapcsolásához a BusinessEntityID mezőt használjuk mindkét
táblából! Az eredmény első 50 sora jelenjen csak meg!

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)Az előző lekérdezésből készíts olyan megoldást is, ahol aze-mail címből
(EmailAddress) csak a név rész (@ előtti rész látható)!

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)Illetve egy olyan lekérdezést is, ahol csak a domain rész (@ utáni rész)
látható!

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) (IZMOS FELADAT) Készíts egy lekérdezést ami visszaadja a
Sales.SalesPerson táblából a BusinessEntityID mezőt és egy „minsales”
nevű számított oszlopot. A minsales értéke legyen soronként a SalesYTD
mező értéke, amennyiben a SalesYTD > 1000000, egyéb esetben NULL
értéket adjon.

/****** Script for SelectTopNRows command from SSMS  ******/
SELECT [BusinessEntityID], CASE WHEN SalesYTD > 1000000 THEN SalesYTD ELSE NULL END as minsales
  FROM [AdventureWorks2016].[Sales].[SalesPerson]

21) (NAGYON IZMOS FELADAT) Készíts egy lekérdezést ami visszaadja a
Sales.SalesPerson táblából a BusinessEntityID mezőt és egy „salesinfo”
nevű számított oszlopot. A salesinfo értéke legyen soronként a SalesYTD
mező értéke, amennyiben a SalesYTD >= 2000000, Amennyiben
SalesYTD<2000000 de nagyobb vagy egyenlő mint 1000000, akkor az
érték legyen 1500000, Ha 1000000-nál is kisebb akkor pedig NULL. pl.
kimenet :

/****** Script for SelectTopNRows command from SSMS  ******/
SELECT [BusinessEntityID], CASE WHEN SalesYTD >= 2000000 THEN SalesYTD ELSE CASE WHEN SalesYTD>=1000000 THEN 1500000 ELSE NULL END END as salesinfo
  FROM [AdventureWorks2016].[Sales].[SalesPerson]

Microsoft SQL szerver (továbbiakban SQL) tudásszint felmérő

  • Használj T-SQL kódot
  • Mindenképp a megadott SQL fájlneveket használd
  • A feltöltött ZIP fájlodban ne legyenek alkönyvtárak, csak a fájlokat tartalmazza
  • Ügyelj rá, hogy az adatbázis-, felhasználó-, és egyéb objektumelnevezések nagybetűérzékenyek
  • A lekérdezésekben a megjelenítendő oszlopok nevén csak akkor változtass, ha a feladat külön előírja
  • A lekérdezésekben a megjelenítendő oszlopok a feladatban megadott sorrendben jelenjenek meg
  • Figyelj oda, hogy mindig a megfelelő adatbázis legyen kiválasztva
  • Használj ASCII, vagy UTF-8 (without BOM) karakterkódolást
  • A Docker konténerben a feladatokat “futtató” MSSQL LOGIN alapértelmezett kiinduló adatbázisa az első 10 feladatban: master.
  • A Docker konténerben a feladatokat “futtató” MSSQL LOGIN alapértelmezett kiinduló adatbázisa 11)-től 20)-es feladattal bezárólag: AdventureWorks.Ezekben a feladatokban elegendő ha a feltöltött fájlod csak a lekérdezést tartalmazza.
  • Az sql kiterjesztésú fájlok kiértékelése elsődlegesen autograder révén történik, a többit manuális pontozással értékeljük.

任务。

  1. A szerverhez hozzá van adva egy diszk, ami még nincs használatban (20GB). Helyezd üzembe, hozzál létre egy 20 GByte-os partíciót NTFS file rendszerrel és a géphez S: meghajtóként mountold fel, a kötet neve pedig: SQLDATA legyen.
证据。 Computer Management => Storage => Disk Management
文件名称。 WINSQL-01.jpg
  1. S: meghajtón hozzál létre egy SQLDATA könyvtárat, majd abban további két alkönyvtárat: DB és LOG névvel.
证据。 File Explorer => S: => SQLDATA könyvtárat megnyitva, amikor látszik a kért két alkönyvtár is.
文件名称。 WINSQL-02.jpg
  1. Jelentkezz be az SQL szerverbe (GREENFOX instance) a Microsoft SQL Server Management Studio-val!
证据。 Microsoft SQL Server Management Studio-ban GREENFOX instance megnyitva.
文件名称。 WINSQL-03.jpg
  1. Töltsd vissza a C:\install\MSSQL\AdventureWorks2016.bak adatbázist a szerver GREENFOX példányába AdventureWorks néven úgy, hogy az adatbázis állományok az S:\SQLDATA\DB, míg a log állományok az S:\SQLDATA\LOG könyvtárba kerüljenek.

Gradescopeban itt találod a backupot: /AdventureWorks2016.bak, az adatbázis állományok: /SQLDATA/DB/AdventureWorks_Data.mdf, míg a log állományok az /SQLDATA/LOG/AdventureWorks_Log.ldf fájlokba kerüljenek

证据。 Microsoft SQL Server Management Studio-ban restore típusú szkript kimásolása vagy mentése.
文件名称。 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. Hozz létre egy isvc MS SQL Server autentikációjú account-ot, minimális (public) jogokkal! A jelszó legyen: interfAce21 A jelszót ne kelljen megváltoztatnia a felhasználónak első belépéskor.
证据。 Microsoft SQL Server Management Studio-ban szkript kimásolása vagy mentése.
文件名称。 WINSQL-05.sql
USE [master]
GO
CREATE LOGIN [isvc] WITH PASSWORD=N'interfAce21', DEFAULT_DATABASE=[master], CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF
GO
  1. Hozz létre egy INTERFACE nevű adatbázist az alábbi beállításokkal:
    1. Adatbázis neve: INTERFACE
    2. Tulajdonos: isvc
    3. Recovery model: FULL
    4. Induló adatbázis file:
      1. méret: 64 MByte
      2. helye: S:\SQLDATA\DB (Gradescope-on /SQLDATA/DB)
    5. Induló log file:
      1. méret: 24 MByte
      2. helye: S:\SQLDATA\LOG (Gradescope-on /SQLDATA/LOG)
CREATE DATABASE [INTERFACE]
 CONTAINMENT = NONE
 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 = Off;
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 = Off;
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. Adj csak lekérdezési jogot az isvc account számára az AdventureWorks adatbázis HumanResources sémában levő vEmployee nézettáblájára!
证据。 Microsoft SQL Server Management Studio-ban szkript kimásolása vagy mentése.
文件名称。 WINSQL-07.sql
USE [AdventureWorks]
GO
CREATE USER [isvc] FOR LOGIN [isvc]
GO
GRANT SELECT ON [HumanResources].[vEmployee] TO [isvc]
GO
  1. INTERFACE adatbázisban hozz létre egy AWdatabase sémát!
证据。 Microsoft SQL Server Management Studio-ban GREENFOX instance-ban az INTERFACE adatbázis AWdatabase séma „Create To” script.
文件名称。 WINSQL-08.sql
USE [INTERFACE]
GO

/****** Object:  Schema [dbo]    Script Date: 2023. 01. 15. 13:45:32 ******/
CREATE SCHEMA [AWdatabase]
GO
  1. Az AWdatabase sémában hozz létre egy szinonímát AW_Employee néven, ami az AdventureWorks adatbázis HumanResources sémában levő vEmployee nézettáblára mutat!
证据。 Microsoft SQL Server Management Studio-ban GREENFOX instance-ban az INTERFACE adatbázis AWdatabase séma AW_Employee szinoníma „Create To” script.
文件名称。 WINSQL-09.sql
USE [INTERFACE]
GO
CREATE SYNONYM [AWdatabase].[AW_Employee ] FOR [AdventureWorks].[HumanResources].[vEmployee]
GO
  1. Készíts az INTERFACE adatbázisról egy FULL mentést, az alábbiak szerint:
  1. Backup file neve: S:\SQLDATA\INTERFACE.bak (Gradescope-ban /var/backups/INTERFACE.bak)
  2. Mentés felülírja az azonos nevű media set-et!
证据。 Microsoft SQL Server Management Studio-ban GREENFOX instance-ban az INTERFACE adatbázis backup script.
文件名称。 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. Készíts olyan SQL lekérdezést, ami kiszámítja 25 négyzetgyökét!
证据。 Microsoft SQL Server Management Studio-ban szkript kimásolása vagy mentése.
文件名称。 WINSQL-11.sql
SELECT SQRT(25)
  1. Készíts olyan SQL lekérdezést, ami visszaadja a mai dátumot ebben a formátumban: 2022-10-25
证据。 Microsoft SQL Server Management Studio-ban szkript kimásolása vagy mentése.
文件名称。 WINSQL-12.sql
SELECT CAST(GETDATE() as date)
  1. Készíts olyan SQL lekérdezést, ami kiszámítja, hogy hány nap telt el 1994. április 25-e óta!
证据。 Microsoft SQL Server Management Studio-ban szkript kimásolása vagy mentése.
文件名称。 WINSQL-13.sql
SELECT DATEDIFF(day,'2022-04-25',GETDATE())
  1. Készíts olyan SQL lekérdezést, ami visszaadja a korábban betöltött AdventureWorks adatbázis Person.Address táblájának első 15 elemét (minden mezőjét – az oszlopok sorrendjén ne változtass)!
证据。 Microsoft SQL Server Management Studio-ban szkript kimásolása vagy mentése.
文件名称。 WINSQL-14.sql
/****** Script for SelectTopNRows command from SSMS  ******/
USE [AdventureWorks]
GO
SELECT TOP (15) *
  FROM [AdventureWorks].[Person].[Address]
  1. Készíts olyan SQL lekérdezést, ami visszaadja a korábban betöltött AdventureWorks adatbázis Person.Person táblájának első 5 elemét (minden mezőjét – az oszlopok sorrendjén ne változtass -), de úgy, hogy ahol a PersonType mező értéke ‘EM‘!
证据。 Microsoft SQL Server Management Studio-ban szkript kimásolása vagy mentése.
文件名称。 WINSQL-15.sql
USE [AdventureWorks]
GO
SELECT TOP (5) *
  FROM [AdventureWorks].[Person].[Person]
  WHERE PersonType='EM'
  1. Készíts olyan SQL lekérdezést, ami visszaadja a korábban betöltött AdventureWorks adatbázis Person.Person táblájának első 30 elemét, de úgy, hogy ahol a PersonType mező értéke ‘EM‘ és csak a PersonType, FirstName, LastName mezők legyenek a lekérdezés eredményében!
证据。 Microsoft SQL Server Management Studio-ban szkript kimásolása vagy mentése.
文件名称。 WINSQL-16.sql
USE [AdventureWorks]
GO
SELECT TOP (30) PersonType, FirstName,LastName
  FROM [AdventureWorks].[Person].[Person]
  WHERE PersonType='EM'
  1. Készíts olyan SQL lekérdezést, ami visszaadja a korábban betöltött AdventureWorks adatbázis Person.Person táblájának első 20 elemét, de úgy, hogy ahol a PersonType mező értéke ‘EM‘ és csak a PersonType, FirstName, LastName mezők legyenek a lekérdezés eredményében, de a FirstName és LastName egy oszlopban jelenjen meg egy darab szóköz karakterrel elválasztva, FullName néven!
证据。 Microsoft SQL Server Management Studio-ban szkript kimásolása vagy mentése.
文件名称。 WINSQL-17.sql
USE [AdventureWorks]
GO
SELECT TOP (20) PersonType, FirstName+ ' ' + LastName as FullName
  FROM [AdventureWorks].[Person].[Person]
  WHERE PersonType='EM'
  1. Készíts olyan SQL lekérdezést, ami visszaadja a korábban betöltött AdventureWorks adatbázis Person.Person táblájának azon rekordjait (minden oszlopát, minden mezőt – az oszlopok sorrendjén ne változtass -), ahol a PersonType mező értéke ‘EM‘ és a FirstName mezőben csak a ‘John‘ nevűek szerepeljenek!
证据。 Microsoft SQL Server Management Studio-ban szkript kimásolása vagy mentése.
文件名称。 WINSQL-18.sql
USE [AdventureWorks]
GO
SELECT *
  FROM [AdventureWorks].[Person].[Person]
  WHERE PersonType='EM' AND FirstName='John'
  1. Készíts olyan SQL lekérdezést, ami visszaadja a korábban betöltött AdventureWorks adatbázis Person.Person táblájának azon rekordjait (minden oszlopát, minden mezőt – az oszlopok sorrendjén ne változtass -), ahol a PersonType mező értéke ‘EM‘ és a FirstName mezőben csak a ‘John‘ nevűek közül is azok legyenek csak megjelenítve, ahol a LastName mező értéke ‘e‘-karakterrel végződik!
证据。 Microsoft SQL Server Management Studio-ban szkript kimásolása vagy mentése.
文件名称。 WINSQL-19.sql
USE [AdventureWorks]
GO
SELECT *
  FROM [AdventureWorks].[Person].[Person]
  WHERE PersonType='EM' AND FirstName='John' AND RIGHT(LastName,1)='e'
  1. Számold meg, hogy hány ‘Ken‘ keresztnevű (FirstName) rekord van a korábban betöltött AdventureWorks adatbázis Person.Person táblájában!
证据。 Microsoft SQL Server Management Studio-ban szkript kimásolása vagy mentése.
文件名称。 WINSQL-20.sql
USE [AdventureWorks]
GO
SELECT COUNT(*)
  FROM [AdventureWorks].[Person].[Person]
  WHERE FirstName='Ken'