Difference between revisions of "6238 Databaser Agenda/Mere sql"

From Teknologisk videncenter
Jump to: navigation, search
(ON DELETE CASCADE)
(LEFT JOIN)
 
(20 intermediate revisions by the same user not shown)
Line 1: Line 1:
==Views==
+
==ON DELETE CASCADE==
Med Views kan vi gemme nogle af de lange select sætninger.
+
On delete fortæller hvad databasen skal gøre hvis man forsøger at slette data der anvendes som foreign key af andre tabeller.
I vores eksempel fra tidligere er det f.eks. forbundet med en del besvær at finde telefon nr og bilmærker for en sælger da det kræver to JOINs.
 
 
 
Ved at lave et View kan man gemme SELECT sætningen en gang for alle sådan her
 
  
<source lang=sql>
 
Create View SaelgerView AS
 
SELECT MedarbNr,Navn,StartDato,Email,Nr AS TelefoonNr, RegNr AS Bil,Maerke,RegAar AS BilRegAar FROM Saelger
 
JOIN Bil ON Saelger.MedarbNr = bil.Saelger
 
JOIN TelefonNr ON TelefonNr.Saelger = Saelger.MedarbNr;
 
</source>
 
 
Efterfølgende gør man blot sådan for at anvende viewet
 
 
<source lang=sql>
 
Select * from SaelgerView;
 
</source>
 
 
Resultatet
 
 
[[File:6238 Databaser Agenda SQL Views4.gif]]
 
 
==Insert via View==
 
Bemærk at et View kun giver et udtræk af databasens tabeller og ikke er en tabel i sig selv
 
 
Derfor er det normalt ikke muligt at anvende insert og delete på views, dog er der visse undtagelse hvor det er muligt, men det vil jeg ikke komme nærmere ind på i dette kursus.
 
 
==Opgave==
 
Lav views som viser Kunder incl. oplysninger om hvilken sælger de betjenes af og sælgerens navn og telefon nummer
 
 
Lav view som viser varer og hvilken kunde de købes af
 
 
==ON DELETE CASCADE==
 
 
<source lang=sql>
 
<source lang=sql>
 
CREATE TABLE Saelger(
 
CREATE TABLE Saelger(
Line 55: Line 24:
 
</source>
 
</source>
  
I eksemplet her laves først tabellen sælger og derefter TelefonNr der har Saelger som FK.
+
I eksemplet her laves først tabellen sælger og derefter TelefonNr der har Saelger som FK. Bemærk ON DELETE CASCADE efter FOREIGN KEY på TelefonNr.
  
 
Efterfølgende indsættes en sælger og en telefon med reference til sælgeren hvorefter vi forsøger at slette sælgeren.
 
Efterfølgende indsættes en sælger og en telefon med reference til sælgeren hvorefter vi forsøger at slette sælgeren.
Line 61: Line 30:
 
Normalt vil dette ikke være muligt, men fordi vi har indsat ON DELETE Cascade vil den blot slette de numre som referere til Sælgeren når Sælgeren slettes.
 
Normalt vil dette ikke være muligt, men fordi vi har indsat ON DELETE Cascade vil den blot slette de numre som referere til Sælgeren når Sælgeren slettes.
  
==Opgave==
+
===Opgave===
 
Forsøg på sælger databasen at slette en Vare
 
Forsøg på sælger databasen at slette en Vare
 +
 
Ret i databasen ved at tilføje de nødvendige ON DELETE sådan at en Vare kan slettes uden problemer
 
Ret i databasen ved at tilføje de nødvendige ON DELETE sådan at en Vare kan slettes uden problemer
 +
 
Ret derefter også sådan at en Sælger kan slettes uden problemer. Dette er nok ikke praktisk i virkeligheden men prøv alligevel
 
Ret derefter også sådan at en Sælger kan slettes uden problemer. Dette er nok ikke praktisk i virkeligheden men prøv alligevel
© Mercantec 2014
+
 
 
==SELECT DISTINCT==
 
==SELECT DISTINCT==
Afprøv selv forskellen på  
+
Med DISTINCT kommer hvert resultat kun en gang i output. Afprøv selv forskellen på  
 +
 
 +
<source lang=sql>
 
SELECT Navn FROM KoebesAf  
 
SELECT Navn FROM KoebesAf  
 
JOIN Kunde ON Kunde.KundeNr = KoebesAf.Kunde
 
JOIN Kunde ON Kunde.KundeNr = KoebesAf.Kunde
OG
+
</source>
 +
 
 +
og
 +
 
 +
<source lang=sql>
 
SELECT DISTINCT Navn FROM KoebesAf  
 
SELECT DISTINCT Navn FROM KoebesAf  
 
JOIN Kunde ON Kunde.KundeNr = KoebesAf.Kunde
 
JOIN Kunde ON Kunde.KundeNr = KoebesAf.Kunde
 +
</source>
 +
 +
==IDENTITY/AUTO_INCREMENT==
 +
Ofte vi vi ønske at have et index der automatisk tæller op.
 +
 +
Det er muligt i både Ms-Sql og MySql men på to forskellige måder.
  
© Mercantec 2014
+
<source lang=sql>
==IDENTITY, AUTO_INCREMENT==
 
 
/* Opret tabellen Saelger */
 
/* Opret tabellen Saelger */
 +
/*MS-Sql*/
 
CREATE TABLE Saelger
 
CREATE TABLE Saelger
 
(
 
(
Line 82: Line 65:
 
StartDato DATETIME NOT NULL,
 
StartDato DATETIME NOT NULL,
 
Email NVARCHAR(20) NOT NULL,
 
Email NVARCHAR(20) NOT NULL,
MedarbNr INT IDENTITY ,//Hedder AUTO_INCREMENT i MySQL
+
MedarbNr INT IDENTITY ,
 
PRIMARY KEY(MedarbNr)
 
PRIMARY KEY(MedarbNr)
 
);
 
);
  
 +
/*MySql*/
 +
CREATE TABLE Saelger
 +
(
 +
Navn NVARCHAR(20) NOT NULL,
 +
StartDato DATETIME NOT NULL,
 +
Email NVARCHAR(20) NOT NULL,
 +
MedarbNr INT AUTO_INCREMENT,
 +
PRIMARY KEY(MedarbNr)
 +
);
 +
</source>
 +
 +
Hvis du benytter en autoincrementeret værdi må denne ikke længere være med under INSERT
 +
<source lang=sql>
 
INSERT INTO Saelger (Navn,StartDato,Email) VALUES ('Ole','1-1-1','ole@mail.dk');
 
INSERT INTO Saelger (Navn,StartDato,Email) VALUES ('Ole','1-1-1','ole@mail.dk');
 +
</source>
  
© Mercantec 2014
 
Med IDENTITY kan man bestemme at databasen selv skal tælle værdien MedarbNr op hver gang der indsættes en ny.
 
Bemærk at MedarbNr nu ikke længere er med.
 
 
==Unique==
 
==Unique==
 +
Med UNIQI kan vi bestemme at en attribut skal være unik selv om den ikke er nøgle attribut.
 +
 +
Derved kan vi anvende den som reference til foreign key.
 +
 +
I eksemplet her anvendes MedarbNr som nøgle, men vi vælger at angive Navn som UNIQ og kan derfor anvende det som Foreign key på TelefonNr.
 +
<source lang=sql>
 
/* Opret tabellen Saelger */
 
/* Opret tabellen Saelger */
 
CREATE TABLE Saelger
 
CREATE TABLE Saelger
 
(
 
(
 
Navn NVARCHAR(20) NOT NULL,
 
Navn NVARCHAR(20) NOT NULL,
StartDato DATETIMENOT NULL,
+
StartDato DATETIME NOT NULL,
 
Email NVARCHAR(20) NOT NULL,
 
Email NVARCHAR(20) NOT NULL,
 
MedarbNr INT NOT NULL,
 
MedarbNr INT NOT NULL,
Line 111: Line 111:
 
FOREIGN KEY(SaelgerNavn) REFERENCES Saelger(Navn)  
 
FOREIGN KEY(SaelgerNavn) REFERENCES Saelger(Navn)  
 
);
 
);
 +
</source>
 +
 +
==LEFT JOIN==
 +
I Sales databasen havde vi blandt andet tabellerne Saelger, TelefonNR og KundeNr.
 +
 +
De kunne samles med dette JOIN
 +
<source lang=sql>
 +
Select * from Saelger
 +
JOIN Kunde on Kunde.Saelger = Saelger.MedarbNr
 +
JOIN TelefonNr ON TelefonNr.Saelger = Saelger.MedarbNr
 +
</source>
  
© Mercantec 2014
+
Problemet opstår på TelefonNr da en af sælgerne ikke har nogen telefon og derfor ikke kommer med i listen.
Med UNIQI kan vi bestemme at en attribut skal være unik selv om den ikke er nøgle attribut. Derved kan vi anvende den som reference til foreign key
 
==Stored procedure==
 
CREATE PROCEDURE InsertSaelger @navn NVARCHAR(20), @email NVARCHAR(20), @startDato DATETIME,  @saelgerNr INT, @telefonNr NVARCHAR(8)
 
AS
 
IF NOT EXISTS (SELECT Navn FROM Saelger WHERE Saelger.MedarbNr = @saelgerNr)
 
BEGIN
 
INSERT INTO Saelger(Navn,Email,StartDato,MedarbNr)VALUES(@navn,@email,@startDato,@saelgerNr);
 
END
 
INSERT INTO TelefonNr(Nr,Saelger) VALUES (@telefonNr,@saelgerNr);
 
GO
 
  
EXECUTE InsertSaelger 'Jens', 'jens@mail.dk', '2001-1-1',4,'67891234';
+
Det kan løses med en LEFT JOIN. Med LEFT JOIN medtages alle entry fra venstre side selv om de ikke har nogen match i højre side.
EXECUTE InsertSaelger 'Jens', 'jens@mail.dk', '2001-1-1',4,'67891235';
+
<source lang=sql>
 +
Select * from Saelger
 +
JOIN Kunde on Kunde.Saelger = Saelger.MedarbNr
 +
LEFT JOIN TelefonNr ON TelefonNr.Saelger = Saelger.MedarbNr
 +
</source>
  
© Mercantec 2014
+
Du kan læse mere om JOINs i Læs SQL Tutorial Kapitel 26
Med stored procedure kan man automatiserer nogle processer.
 
Her er f.eks. vist hvordan vi indsætter Saelger og telefon nr i en og samme arbejdsgang.
 

Latest revision as of 11:18, 3 November 2015

ON DELETE CASCADE

On delete fortæller hvad databasen skal gøre hvis man forsøger at slette data der anvendes som foreign key af andre tabeller.

CREATE TABLE Saelger(
Navn NVARCHAR(20)NOT NULL,
StartDatoDATETIMENOT NULL,
EmailNVARCHAR(20)NOT NULL,
MedarbNrINTNOT NULL,
PRIMARY KEY(MedarbNr)
);

CREATE TABLE TelefonNr(
Nr NVARCHAR(8) NOT NULL,
SaelgerINT NOT NULL,
PRIMARY KEY(Nr),
FOREIGN KEY(Saelger) REFERENCES Saelger(MedarbNr) ON DELETE Cascade
);

INSERT INTO Saelger (Navn, StartDato,Email,MedarbNr) VALUES ('Hans','2001-1-1','Hans@mail.dk',1);
INSERT INTO TelefonNr (Nr, Saelger) VALUES ('12345678',1);

DELETE FROM Saelger WHERE MedarbNr = 1;

I eksemplet her laves først tabellen sælger og derefter TelefonNr der har Saelger som FK. Bemærk ON DELETE CASCADE efter FOREIGN KEY på TelefonNr.

Efterfølgende indsættes en sælger og en telefon med reference til sælgeren hvorefter vi forsøger at slette sælgeren.

Normalt vil dette ikke være muligt, men fordi vi har indsat ON DELETE Cascade vil den blot slette de numre som referere til Sælgeren når Sælgeren slettes.

Opgave

Forsøg på sælger databasen at slette en Vare

Ret i databasen ved at tilføje de nødvendige ON DELETE sådan at en Vare kan slettes uden problemer

Ret derefter også sådan at en Sælger kan slettes uden problemer. Dette er nok ikke praktisk i virkeligheden men prøv alligevel

SELECT DISTINCT

Med DISTINCT kommer hvert resultat kun en gang i output. Afprøv selv forskellen på

SELECT Navn FROM KoebesAf 
JOIN Kunde ON Kunde.KundeNr = KoebesAf.Kunde

og

SELECT DISTINCT Navn FROM KoebesAf 
JOIN Kunde ON Kunde.KundeNr = KoebesAf.Kunde

IDENTITY/AUTO_INCREMENT

Ofte vi vi ønske at have et index der automatisk tæller op.

Det er muligt i både Ms-Sql og MySql men på to forskellige måder.

/* Opret tabellen Saelger */
/*MS-Sql*/
CREATE TABLE Saelger
(
	Navn 	NVARCHAR(20)	NOT NULL,
	StartDato	DATETIME	NOT NULL,
	Email	NVARCHAR(20)	NOT NULL,
	MedarbNr	INT	IDENTITY ,
	PRIMARY KEY(MedarbNr)
);

/*MySql*/
CREATE TABLE Saelger
(
	Navn 	NVARCHAR(20)	NOT NULL,
	StartDato	DATETIME	NOT NULL,
	Email	NVARCHAR(20)	NOT NULL,
	MedarbNr	INT	AUTO_INCREMENT,
	PRIMARY KEY(MedarbNr)
);

Hvis du benytter en autoincrementeret værdi må denne ikke længere være med under INSERT

INSERT INTO Saelger (Navn,StartDato,Email) VALUES ('Ole','1-1-1','ole@mail.dk');

Unique

Med UNIQI kan vi bestemme at en attribut skal være unik selv om den ikke er nøgle attribut.

Derved kan vi anvende den som reference til foreign key.

I eksemplet her anvendes MedarbNr som nøgle, men vi vælger at angive Navn som UNIQ og kan derfor anvende det som Foreign key på TelefonNr.

/* Opret tabellen Saelger */
CREATE TABLE Saelger
(
	Navn 	NVARCHAR(20)	NOT NULL,
	StartDato	DATETIME NOT 	NULL,
	Email	NVARCHAR(20)	NOT NULL,
	MedarbNr	INT	NOT NULL,
	UNIQUE (Navn),
	PRIMARY KEY(MedarbNr)
);

/* Opret tabellen TelefonNr */
CREATE TABLE TelefonNr
(
	Nr 	NVARCHAR(8) 	NOT NULL,
	SaelgerNavn 	NVARCHAR(20) 		NOT NULL,
	PRIMARY KEY(Nr),
	FOREIGN KEY(SaelgerNavn) REFERENCES Saelger(Navn) 
);

LEFT JOIN

I Sales databasen havde vi blandt andet tabellerne Saelger, TelefonNR og KundeNr.

De kunne samles med dette JOIN

Select * from Saelger
JOIN Kunde on Kunde.Saelger = Saelger.MedarbNr
JOIN TelefonNr ON TelefonNr.Saelger = Saelger.MedarbNr

Problemet opstår på TelefonNr da en af sælgerne ikke har nogen telefon og derfor ikke kommer med i listen.

Det kan løses med en LEFT JOIN. Med LEFT JOIN medtages alle entry fra venstre side selv om de ikke har nogen match i højre side.

Select * from Saelger
JOIN Kunde on Kunde.Saelger = Saelger.MedarbNr
LEFT JOIN TelefonNr ON TelefonNr.Saelger = Saelger.MedarbNr

Du kan læse mere om JOINs i Læs SQL Tutorial Kapitel 26