В този урок по SQL за начинаещи ще създадете своя собствена база данни, ще вмъкнете данни в тази база данни и след това ще стартирате заявки към тази база данни.
Този урок за SQL ще ви накара да стартирате SQL заявки за нула време!
Пример за SQL
Ето примерен SQL израз:
SELECT *
FROM Pets;
Това е перфектен пример за това колко лесно може да бъде писането на SQL. Този прост SQL израз всъщност прави много. Връща цялата таблица. Връща всички колони и всички редове от таблицата, наречена Pets
.
Звездичката (*
) е заместващ знак, което означава „всички колони“. Това е бърз и лесен начин да получите всички колони, без да се налага да ги пишете.
Това е едно от красивите неща за SQL. Най-простите SQL заявки обикновено са най-мощните. Ако искаме да върнем по-малко данни, всъщност ще трябва да напишем повече .
Например, ако искаме само домашни любимци на име Извличане , бихме добавили WHERE
клауза, която предвижда това изискване.
Като това:
SELECT *
FROM Pets
WHERE PetName = 'Fetch';
WHERE
клаузата филтрира нашата заявка само до редовете, където PetName
колоната има стойност Fetch
.
Тази заявка предполага, че има колона, наречена PetName
и таблица, наречена Pets
в базата данни.
В този урок за SQL ще ви покажа как да създадете такава база данни с помощта на SQL.
Също така ще ви покажа как да вмъквате данни в тази база данни, да актуализирате данни, да изтривате данни и да изпълнявате заявки към нея.
Какво е SQL?
SQL е акроним за Structured Query Language.
SQL е стандартният език за заявки, използван за работа с релационни бази данни.
SQL се използва от всички основни системи за управление на релационни бази данни (RDBMS), включително:
- Microsoft Access
- SQL сървър
- Oracle
- PostgreSQL
- MySQL
- SQLite
Какво мога да направя с SQL?
Можете да използвате SQL за изпълнение на заявки към база данни, вмъкване на записи, актуализиране на записи и изтриване на записи. Можете също да създавате нови обекти на база данни като бази данни и таблици. Можете също да изпълнявате задачи за администриране на база данни, като създаване на данни за влизане, автоматизирани задания, архивиране на база данни и много други.
Дори когато правите неща с помощта на графичен потребителски интерфейс (GUI), вашата система за управление на бази данни (DBMS) почти сигурно ще използва SQL зад кулисите, за да изпълни тази задача.
Например, когато създавате база данни, като щракнете върху Създаване на база данни и въвеждане на подробностите за новата база данни в диалогов прозорец, след като щракнете върху OK или Създаване или каквото и да чете бутонът, вашата система от база данни ще използва SQL CREATE DATABASE
изявление, за да продължите и да създадете базата данни, както е посочено.
Същото важи и за други задачи, като изпълнение на заявки, вмъкване на данни и т.н.
SQL също така ви позволява да извършвате по-разширени действия, като например създаване на съхранени процедури (самостоятелни скриптове), изгледи (предварително направени заявки) и задаване на разрешения за обекти на база данни (като таблици, съхранени процедури и изгледи).
Въпреки това не е нужно да научавате всички разширени неща, за да започнете с SQL. Хубавото на SQL е, че някои от най-често срещаните задачи са най-лесни за писане.
SQL стандарт
SQL е стандартизиран в ANSI X3.135 през 1986 г. и в рамките на няколко месеца е приет от ISO като ISO 9075-1987. Международният стандарт (сега ISO/IEC 9075) се преразглежда периодично оттогава и понастоящем съществува в 9 части.
Повечето големи доставчици на бази данни са склонни да се придържат към стандарта SQL. Хубавото на това е, че не е нужно да изучавате нов език за заявки всеки път, когато изучавате нова СУБД.
На практика обаче има вариации между начина, по който всеки доставчик на база данни прилага стандарта SQL. Следователно кодът, който пишете в една СУБД, може да не работи винаги в друга без нужда от модификации.
Добрата новина е, че всички основни СУБД поддържат най-често срещаните задачи по един и същи начин.
Произношение на SQL
SQL обикновено се произнася по един от двата начина:
- „ess-que-el ” (т.е. изписване на всяка буква)
- „продължение ” (както в оригиналния правопис/произношение).
Вижте дали се произнася S-Q-L или продължение, ако се чудите защо.
Какво ми трябва за този урок за SQL?
За да се възползвате наистина от този урок за SQL, трябва да следвате примерите. Това означава, че ще трябва някъде да въведете SQL заявките. Ще трябва да имате нещо подобно:
Ако ще изпълнявате SQL заявки, ще ви трябва:
- Инсталирана RDBMS (като SQL Server, MySQL, PostgreSQL, SQLite и др.).
- Инструмент за база данни, който ви позволява да изпълнявате SQL заявки към тази RDBMS (като MySQL WorkBench, Azure Data Studio (на снимката), DBeaver и SSMS).
Ако вече имате инсталиран по един от всеки, страхотно! Можете да продължите с урока.
Ако не ги инсталирате, вижте Какво ми трябва, за да стартирам SQL? за инструкции относно инсталирането на RDBMS и съответния инструмент за управление на база данни, преди да се върнете към този урок за SQL.
Създайте база данни
След като инсталирате своята RDBMS и подходящия инструмент за база данни, сте готови да създадете база данни:
CREATE DATABASE PetHotel;
Свършен!
Това изявление всъщност създаде база данни. Празна база данни, но въпреки това база данни.
Тази база данни ще съдържа таблиците и данните, използвани в този урок за SQL. Когато създадем таблица или вмъкнем данни, ще го направим в тази база данни.
Трябва да спомена, че SQLite използва различен синтаксис за създаване на бази данни. Ако използвате SQLite, ето как да създадете база данни в SQLite.
Свържете се с базата данни
Преди да започнете да създавате таблици, да вмъквате данни и т.н., трябва да сте сигурни, че сте в правилната база данни. Създаването на база данни (както току-що направихме) не ви свързва непременно с тази база данни.
В много СУБД (като SQL сървър , MySQL и MariaDB ), можем да използваме следното, за да преминем към посочената база данни:
USE PetHotel;
Това прави PetHotel
текущата база данни.
В SQLite , вероятно вече сте в базата данни, след като сте я създали. Ако не, можете да прикачите базата данни (която също ще я създаде, ако все още не съществува):
ATTACH DATABASE 'PetHotel.db' AS Pets;
В PostgreSQL , ако използвате инструмента psql, можете да използвате следното:
\connect PetHotel
Или съкратената версия:
\c PetHotel
Трябва да спомена, че процесът на създаване и свързване към бази данни може да се различава значително между СУБД.
За щастие повечето GUI инструменти ви позволяват да се свържете с база данни, като щракнете двукратно върху базата данни или щракнете с десния бутон върху името на базата данни и изберете нов раздел за заявка от контекстното меню. Ако се окажете блокирани на тази стъпка, просто използвайте графичния интерфейс, за да създадете и/или да се свържете с вашата DB.
Създайте таблица
След като сте се свързали с правилната база данни, можете да продължите и да създадете някои таблици.
За да създадете таблица в SQL, използвайте CREATE TABLE
изявление.
Когато създавате таблица, трябва да посочите какви колони ще бъдат в таблицата, както и техните типове данни. Можете също да посочите други подробности, но нека не се изпреварваме.
Нека създадем таблица:
CREATE TABLE PetTypes
(
PetTypeId int NOT NULL PRIMARY KEY,
PetType varchar(60) NOT NULL
);
В този случай създаваме таблица, наречена PetTypes
. Знаем това, защото името на таблицата идва непосредствено след CREATE TABLE
малко.
След това идва списък с колони, затворени в скоби.
Таблицата по-горе съдържа следните колони:
PetIdId
PetType
Всяка колона е последвана от нейния тип данни:
int
означава, че тази колона приема цели числа. Доколкото знам, повечето основни СУБД поддържат деклариране на колони катоint
. Ако имате някакви проблеми, опитайте да използватеinteger
.varchar(60)
означава, че тази колона приема низове с дължина до 60 знака.varchar
колоните са низове с променлива дължина. Друг тип низ данни еchar
(което е низ с фиксирана дължина). Ако имате проблеми, опитвайки се да дефинирате колона катоvarchar(60)
, опитайте да използватеchar(60)
.
NOT NULL
Ограничения
В този пример и двете колони са дефинирани с NOT NULL
ограничения. NOT NULL
ограничение означава, че тази колона не може да бъде празна. Когато се вмъкне нов ред, всеки NOT NULL
колони трябва съдържат стойност. Други колони могат да останат празни, ако няма данни за тези колони.
Ако NULL
стойностите са разрешени в колоната, можете да пропуснете NOT NULL
част или го декларирайте като NULL
(което означава, NULL
стойности са разрешени в тази колона).
Някои СУБД (като DB2) не поддържат NULL
ключова дума така или иначе, така че ще трябва да я пропуснете, когато работите с такива СУБД.
Първични ключове
Направихме и PetTypeId
колона първичния ключ. Първичният ключ е една или повече колони, които уникално идентифицират всеки ред в таблицата. Вие посочвате избраната от вас колона/и като първичен ключ, като използвате ограничение за първичен ключ. Можете да направите това в CREATE TABLE
изявление (както направихме тук), или можете да добавите такъв по-късно с ALTER TABLE
изявление.
Първичните ключове трябва да съдържат уникални стойности. Тоест, за всеки ред в тази таблица, стойността в колоните/ите на първичния ключ трябва да е различна във всеки ред. Това може да бъде толкова просто, колкото да имате нарастващи числа (като 1, 2, 3... и т.н.) или да е продуктов код (като pr4650, pr2784, pr5981... и т.н.).
Освен това първичните ключове трябва да съдържат стойност. Не може да бъде NULL
.
Въпреки че първичните ключове не се изискват, обикновено се счита за добра практика да се дефинира първичен ключ във всяка таблица.
Създаване на още таблици
Нека създадем още две таблици:
CREATE TABLE Owners
(
OwnerId int NOT NULL PRIMARY KEY,
FirstName varchar(60) NOT NULL,
LastName varchar(60) NOT NULL,
Phone varchar(20) NOT NULL,
Email varchar(254)
);
CREATE TABLE Pets
(
PetId int NOT NULL PRIMARY KEY,
PetTypeId int NOT NULL REFERENCES PetTypes (PetTypeId),
OwnerId int NOT NULL REFERENCES Owners (OwnerId),
PetName varchar(60) NOT NULL,
DOB date NULL
);
И двете от тези таблици са подобни на първата, с изключение на това, че имат повече редове и няколко допълнителни части, които ще обясня по-долу.
Ако се интересувате, вижте SQL CREATE TABLE за начинаещи за още няколко прости примера за създаване на таблици в SQL.
Взаимоотношения
Когато създадохме нашите Pets
таблица, ние всъщност създадохме връзка между трите таблици.
Тази връзка е изобразена на следващата диаграма.
Връзките с базата данни са важна част от SQL. Връзките ни позволяват да правим заявки за множество таблици за свързани данни и да получаваме точни и последователни резултати.
В нашия случай искаме да можем да търсим домашни любимци по собственик или домашни любимци по тип домашни любимци и т.н. И искаме резултатите ни да са точни и последователни.
За да постигнем това, трябва да настояваме всички домашни любимци да бъдат въведени заедно с техния собственик и тип домашен любимец. Ето защо трябва да гарантираме, че всеки път, когато се добавя нов домашен любимец към Pets
таблица, вече има съответен собственик в Owners
таблица и съответен тип домашен любимец в PetTypes
маса.
По принцип нашите изисквания са следните:
- Всяка стойност в
Pets.PetTypeId
колоната трябва да съвпада със стойност вPetTypes.PetTypeId
колона. - Всяка стойност в
Pets.OwnerId
колоната трябва да съвпада със стойност вOwners.OwnerId
колона.
Можем да гарантираме горните изисквания, като създадем ограничение за външен ключ спрямо приложимите колони. Външен ключ ограничението се използва, за да се посочи, че определена колона препраща към първичния ключ на друга таблица.
Горният код наистина създаде две ограничения на външния ключ за Pets
таблица.
Забележете, че PetTypeId
и OwnerId
колоните имат допълнителен код, който започва с REFERENCES...
. Това са частите, които създадоха двата външни ключа.
Когато създадохме Pets
таблица, неговият PetTypeId
колоната има малко, което отива REFERENCES PetTypes (PetTypeId)
. Това означава, че Pets.PetTypeId
колоната препраща към PetTypeId
колона в PetTypes
таблица.
Това е същата сделка за OwnerId
колона. Той препраща към OwnerId
колона на Owners
таблица.
В повечето СУБД външни ключове могат да бъдат създадени и в съществуваща таблица, като се използва ALTER TABLE
изявление, но тук няма да разглеждаме това. Вижте Как да създадете връзка в SQL за повече информация.
Както и да е, нашите външни ключове са създадени. Сега, когато някой вмъкне нов домашен любимец в Pets
таблица, PetTypeId
и OwnerId
стойностите ще трябва да имат съответна стойност в PetTypes
и Owners
таблици съответно. Ако някой от тях не го направи, базата данни ще върне грешка.
Това е предимството на външните ключове. Помага да се предотврати въвеждането на лоши данни. Той помага да се поддържа целостта на данните и по-конкретно референтната цялост.
Проверете ограниченията
Ограничение за проверка е друг тип ограничение, за което трябва да сте наясно. Ограничението за проверка проверява данните, преди да влязат в базата данни. Когато дадена таблица има активирано ограничение за проверка, данните могат да влизат в таблицата само ако не нарушават това ограничение. Данните, които нарушават ограничението, не могат да влязат в таблицата.
Например, можете да създадете ограничение за проверка на Price
колона, за да се гарантира, че приема само стойности, които са по-големи от нула. Или можем да приложим ограничение за проверка към нашите Pets
таблица, за да се гарантира, че DOB
колоната не е в бъдещето.
За пример вижте Какво е ограничение CHECK?
Пространство
Може би сте забелязали, че моите примери включват празно пространство. Например, разпределих кода на няколко реда и използвах раздели за отстъп на типовете данни и т.н.
Това е напълно валидно в SQL. Можете безопасно да направите това и това няма да повлияе на резултата. SQL ви позволява да разпределите кода си на няколко реда, ако желаете, и ви позволява да използвате множество интервали или табулатори, за да подобрите четливостта.
Коментари
Можете също да включите коментари във вашия код. Коментарите могат да бъдат полезни, след като започнете да пишете по-дълги SQL скриптове. След като скриптът стане доста дълъг, коментарите могат да улеснят бързото идентифициране какво прави всяка част.
Вградени коментари
Можете да създавате вградени коментари, като поставите префикс към коментара си с две тирета (--
):
SELECT * FROM Pets; --This is a comment
-- This is a comment
SELECT * FROM Owners;
В този пример и двете заявки ще се изпълняват без проблеми. Коментарите ще бъдат игнорирани от СУБД.
Многоредови коментари
Можете да разпределите коментари на няколко реда, като обградите коментара с /*
и */
:
/*
This is a longer comment so
it's spread across multiple lines
*/
SELECT * FROM Pets;
В този пример и двете заявки ще се изпълняват без проблеми. Коментарите ще бъдат игнорирани от СУБД.
MySQL
Ако използвате MySQL, можете също да използвате знак за число/хеш знак (#
) за едноредови коментари.
# This is a comment
SELECT * FROM Pets;
Коментиране на код
Друго страхотно предимство на коментарите е, че можете да коментирате код. Например, ако имате дълъг SQL скрипт, който прави много неща, но искате да изпълните само една или две части от него, можете да коментирате останалата част от скрипта.
Ето един пример:
-- SELECT * FROM Pets;
SELECT * FROM Owners;
В този случай първият SELECT
изразът е коментиран и така само вторият SELECT
изявление ще се изпълни.
Можете също да използвате многоредови коментари за тази техника.
Вмъкване на данни
Сега, след като създадохме три таблици и създадохме съответните външни ключове, можем да продължим и да добавим данни.
Най-често срещаният начин за вмъкване на данни в SQL е с INSERT
изявление. Става нещо подобно:
INSERT INTO MyTable( Column1, Column2, Column3, ... )
VALUES( Value1, Value2, Value3, ... );
Просто заменяте MyTable
с името на таблицата, в която вмъквате данни. По същия начин заменяте Column1
и т.н. с имената на колоните и Value1
и т.н. със стойностите, които влизат в тези колони.
Например, можем да направим това:
INSERT INTO Pets( PetId, PetTypeId, OwnerId, PetName, DOB )
VALUES( 1, 2, 3, 'Fluffy', '2020-12-20' );
Всяка стойност е в същия ред, в който е посочена колоната.
Имайте предвид, че имената на колоните съвпадат с имената, които сме използвали, когато създадохме таблицата.
Можете да пропуснете имената на колоните, ако вмъквате данни във всички колони. Така че можем да променим горния пример, за да изглежда така:
INSERT INTO Pets
VALUES( 1, 2, 3, 'Fluffy', '2020-12-20' );
За този урок ще добавим още доста реда, така че ще добавим още INSERT INTO
изрази – по един за всеки ред, който искаме да вмъкнем.
Така че нека да продължим и да попълним нашите таблици.
INSERT INTO Owners( OwnerId, FirstName, LastName, Phone, Email )
VALUES( 1, 'Homer', 'Connery', '(308) 555-0100', '[email protected]' );
INSERT INTO Owners(OwnerId, FirstName, LastName, Phone, Email)
VALUES( 2, 'Bart', 'Pitt', '(231) 465-3497', '[email protected]' );
INSERT INTO Owners(OwnerId, FirstName, LastName, Phone)
VALUES( 3, 'Nancy', 'Simpson', '(489) 591-0408' );
INSERT INTO Owners(OwnerId, FirstName, LastName, Phone)
VALUES( 4, 'Boris', 'Trump', '(349) 611-8908' );
INSERT INTO PetTypes( PetTypeId, PetType )
VALUES( 1, 'Bird' );
INSERT INTO PetTypes( PetTypeId, PetType )
VALUES( 2, 'Cat' );
INSERT INTO PetTypes( PetTypeId, PetType )
VALUES( 3, 'Dog' );
INSERT INTO PetTypes( PetTypeId, PetType )
VALUES( 4, 'Rabbit' );
INSERT INTO Pets( PetId, PetTypeId, OwnerId, PetName, DOB )
VALUES( 1, 2, 3, 'Fluffy', '2020-11-20' );
INSERT INTO Pets( PetId, PetTypeId, OwnerId, PetName, DOB )
VALUES( 2, 3, 3, 'Fetch', '2019-08-16' );
INSERT INTO Pets( PetId, PetTypeId, OwnerId, PetName, DOB )
VALUES( 3, 2, 2, 'Scratch', '2018-10-01' );
INSERT INTO Pets( PetId, PetTypeId, OwnerId, PetName, DOB )
VALUES( 4, 3, 3, 'Wag', '2020-03-15' );
INSERT INTO Pets( PetId, PetTypeId, OwnerId, PetName, DOB )
VALUES( 5, 1, 1, 'Tweet', '2020-11-28' );
INSERT INTO Pets( PetId, PetTypeId, OwnerId, PetName, DOB )
VALUES( 6, 3, 4, 'Fluffy', '2020-09-17' );
INSERT INTO Pets( PetId, PetTypeId, OwnerId, PetName )
VALUES( 7, 3, 2, 'Bark' );
INSERT INTO Pets( PetId, PetTypeId, OwnerId, PetName )
VALUES( 8, 2, 4, 'Meow' );
Забележете, че попълнихме Pets
маса последна. Има причина за това.
Ако се бяхме опитали да вмъкнем данни в Pets
таблица, преди да попълним другите две, щяхме да получим грешка, поради нашето ограничение за външен ключ. И с добра причина. В крайна сметка щяхме да се опитваме да вмъкнем стойности в колоните с външния ключ, които все още не съществуват в колоните с първичен ключ в другите таблици. Това е голямо „не не“, когато става въпрос за външни ключове.
Така че като попълните Owners
и PetTypes
първо таблици, ние се уверихме, че подходящите стойности вече са в колоните с първичен ключ, преди да попълним колоните за външен ключ в Pets
таблица.
Вижте SQL INSERT за начинаещи за повече примери за вмъкване на данни в таблици.
Проверете нашите данни
фу! Най-накрая можем да започнем да изпълняваме заявки към нашата база данни.
Нека проверим данните във всичките ни таблици.
SELECT * FROM Pets;
SELECT * FROM PetTypes;
SELECT * FROM Owners;
Резултат:
+---------+-------------+-----------+-----------+------------+ | PetId | PetTypeId | OwnerId | PetName | DOB | |---------+-------------+-----------+-----------+------------| | 1 | 2 | 3 | Fluffy | 2020-11-20 | | 2 | 3 | 3 | Fetch | 2019-08-16 | | 3 | 2 | 2 | Scratch | 2018-10-01 | | 4 | 3 | 3 | Wag | 2020-03-15 | | 5 | 1 | 1 | Tweet | 2020-11-28 | | 6 | 3 | 4 | Fluffy | 2020-09-17 | | 7 | 3 | 2 | Bark | NULL | | 8 | 2 | 4 | Meow | NULL | +---------+-------------+-----------+-----------+------------+ (8 rows affected) +-------------+-----------+ | PetTypeId | PetType | |-------------+-----------| | 1 | Bird | | 2 | Cat | | 3 | Dog | | 4 | Rabbit | +-------------+-----------+ (4 rows affected) +-----------+-------------+------------+----------------+-------------------+ | OwnerId | FirstName | LastName | Phone | Email | |-----------+-------------+------------+----------------+-------------------| | 1 | Homer | Connery | (308) 555-0100 | [email protected] | | 2 | Bart | Pitt | (231) 465-3497 | [email protected] | | 3 | Nancy | Simpson | (489) 591-0408 | NULL | | 4 | Boris | Trump | (349) 611-8908 | NULL | +-----------+-------------+------------+----------------+-------------------+ (4 rows affected)
Страхотно, така че изглежда, че данните са били вмъкнати успешно.
Изберете конкретни колони
Обикновено се счита за лоша практика да се избират всички редове и всички колони от таблица (както направихме в предишния пример), освен ако наистина не е необходимо. Това може да повлияе на производителността на вашия сървър на база данни, особено ако има много редове в таблицата.
Това не е проблем, когато използвате малки набори от данни, каквито сме тук, или ако сте в среда за разработка или подобна. В противен случай обикновено е по-добре да изберете само колоните, от които се нуждаете.
Следователно, ако искаме личните документи, имената и датите на раждане на всички домашни любимци, бихме могли да направим това:
SELECT PetId, PetName, DOB
FROM Pets;
Резултат:
+---------+-----------+------------+ | PetId | PetName | DOB | |---------+-----------+------------| | 1 | Fluffy | 2020-11-20 | | 2 | Fetch | 2019-08-16 | | 3 | Scratch | 2018-10-01 | | 4 | Wag | 2020-03-15 | | 5 | Tweet | 2020-11-28 | | 6 | Fluffy | 2020-09-17 | | 7 | Bark | NULL | | 8 | Meow | NULL | +---------+-----------+------------+
Ако искаме идентификационните номера и датата на раждане на всички домашни любимци на име Fluffy, бихме могли да използваме това:
SELECT PetId, DOB
FROM Pets
WHERE PetName = 'Fluffy';
Резултат:
+---------+------------+ | PetId | DOB | |---------+------------| | 1 | 2020-11-20 | | 6 | 2020-09-17 | +---------+------------+
Можете също да използвате SELECT
изявление за връщане на данни без таблица. Тоест може да връща данни, които не се съхраняват в таблица. Вижте SQL SELECT
Изявление за начинаещи, за да видят пример.
Сортиране
SQL предоставя ORDER BY
клауза, която ни позволява да сортираме данни.
Можем да добавим ORDER BY
клауза към предишния ни пример, така че домашните любимци да бъдат сортирани по имената си:
SELECT PetId, PetName, DOB
FROM Pets
ORDER BY PetName ASC;
Резултат:
+---------+-----------+------------+ | PetId | PetName | DOB | |---------+-----------+------------| | 7 | Bark | NULL | | 2 | Fetch | 2019-08-16 | | 1 | Fluffy | 2020-11-20 | | 6 | Fluffy | 2020-09-17 | | 8 | Meow | NULL | | 3 | Scratch | 2018-10-01 | | 5 | Tweet | 2020-11-28 | | 4 | Wag | 2020-03-15 | +---------+-----------+------------+
ASC
част означава възходящ . Когато използвате ORDER BY
клауза, по подразбиране е възходяща, така че можете да пропуснете ASC
част, ако желаете.
За да го сортирате в низходящ поръчка, използвайте DESC
.
SELECT PetId, PetName, DOB
FROM Pets
ORDER BY PetName DESC;
Резултат:
+---------+-----------+------------+ | PetId | PetName | DOB | |---------+-----------+------------| | 4 | Wag | 2020-03-15 | | 5 | Tweet | 2020-11-28 | | 3 | Scratch | 2018-10-01 | | 8 | Meow | NULL | | 1 | Fluffy | 2020-11-20 | | 6 | Fluffy | 2020-09-17 | | 2 | Fetch | 2019-08-16 | | 7 | Bark | NULL | +---------+-----------+------------+
Можете също да сортирате резултатите, като използвате множество колони. Той ще сортира по първата посочена колона, след което ако има дубликати в тази колона, ще сортира тези дубликати по посочената втора колона и т.н.
SELECT PetId, PetName, DOB
FROM Pets
ORDER BY PetName DESC, DOB ASC;
Резултат:
+---------+-----------+------------+ | PetId | PetName | DOB | |---------+-----------+------------| | 4 | Wag | 2020-03-15 | | 5 | Tweet | 2020-11-28 | | 3 | Scratch | 2018-10-01 | | 8 | Meow | NULL | | 6 | Fluffy | 2020-09-17 | | 1 | Fluffy | 2020-11-20 | | 2 | Fetch | 2019-08-16 | | 7 | Bark | NULL | +---------+-----------+------------+
Вижте как двамата Fluffys са разменили позициите си.
Ако не използвате ORDER BY
клауза, няма гаранция в какъв ред ще бъдат резултатите ви. Въпреки че може да изглежда както вашата база данни сортира резултатите по определена колона, това всъщност може да не е така. Като цяло, без ORDER BY
клауза, данните ще бъдат сортирани в реда, в който са били заредени в таблицата. Ако обаче редовете са били изтрити или актуализирани, редът ще бъде повлиян от начина, по който СУБД използва повторно възстановено пространство за съхранение.
Следователно, не разчитайте на СУБД да сортира резултатите в някакъв смислен ред.
Долен ред:Ако искате резултатите ви да бъдат сортирани, използвайте ORDER BY
.
Вижте SQL ORDER BY
Клауза за начинаещи за още примери.
Пребройте редовете в набор от резултати
Можете да използвате COUNT()
агрегатна функция за преброяване на редовете, които ще бъдат върнати в заявка.
SELECT COUNT(*) AS Count
FROM Pets;
Резултат:
+---------+ | Count | |---------| | 8 | +---------+
Това ни казва, че в таблицата има 8 реда. Знаем това, защото избрахме всички редове и всички колони.
Можете да използвате COUNT()
на всяка заявка, например заявки, които използват WHERE
клауза за филтриране на резултатите.
Можете също така да посочите конкретна колона за броене. COUNT()
функцията отчита само не-NULL
резултати, така че ако посочите колона, която съдържа NULL
стойности, тези стойности няма да бъдат отчетени.
Ето пример, за да демонстрирам какво имам предвид.
SELECT COUNT(DOB) AS Count
FROM Pets;
Резултат:
+---------+ | Count | |---------| | 6 | +---------+ Warning: Null value is eliminated by an aggregate or other SET operation.
Може би си спомняте, че Pets
таблицата съдържа две NULL
стойности в DOB
колона (два домашни любимци не са посочили датата си на раждане) и така COUNT(DOB)
връща 6 вместо 8, когато използвахме COUNT(*)
. Причината COUNT(*)
върна всички редове, защото тези два реда направиха има данни в другите колони.
В моя пример моята СУБД също върна предупреждение за това. Може да получите или да не получите предупреждение, в зависимост от вашата СУБД и конкретната ви конфигурация.
Вижте SQL COUNT
за начинаещи за още примери.
Други агрегатни функции включват:AVG()
, SUM()
, MIN()
и MAX()
.
Групиране по
Друга полезна клауза е GROUP BY
клауза. Това прави почти това, което обещава името му. Позволява ви да групирате резултатите по дадена колона.
SELECT
PetTypeId,
COUNT(PetTypeId) AS Count
FROM Pets
GROUP BY PetTypeId
ORDER BY Count DESC;
Резултат:
+-------------+---------+ | PetTypeId | Count | |-------------+---------| | 3 | 4 | | 2 | 3 | | 1 | 1 | +-------------+---------+
В този пример броим колко домашни любимци имаме за всеки тип домашен любимец, след което ги сортираме в низходящ ред (с най-висок брой в горната част).
Вижте SQL GROUP BY
Клауза за начинаещи за още примери.
HAVING
Клауза
Можем да използваме HAVING
клауза за филтриране на резултатите в GROUP BY
клауза. HAVING
клаузата връща редове, където обобщените стойности отговарят на определени условия.
Ето един пример.
SELECT
PetTypeId,
COUNT(PetTypeId) AS Count
FROM Pets
GROUP BY PetTypeId
HAVING COUNT(PetTypeId) > 2
ORDER BY Count DESC;
Резултат:
+-------------+---------+ | PetTypeId | Count | |-------------+---------| | 3 | 4 | | 2 | 3 | +-------------+---------+
В този случай върнахме данни само за видовете домашни любимци, които имат повече от 2 домашни любимци, присвоени към този тип.
Вижте SQL HAVING
Клауза за начинаещи за още примери.
Присъединява се
В SQL, присъединяване е мястото, където изпълнявате заявка, която комбинира данни от множество таблици.
Предишните два примера са ОК, но би било по-добре, ако върнат действителните типове домашни любимци (напр. котка, куче, птица и т.н.), а не идентификатора (напр. 1, 2, 3 и т.н.).
Единственият проблем е Pets
таблицата не съдържа тези данни. Тези данни са в PetTypes
таблица.
За наше щастие можем да направим свързване между тези две таблици. Ето пример, който използва LEFT JOIN
:
SELECT
PetTypes.PetType,
COUNT(Pets.PetTypeId) AS Count
FROM Pets
LEFT JOIN PetTypes
ON Pets.PetTypeId = PetTypes.PetTypeId
GROUP BY PetTypes.PetType
ORDER BY Count DESC;
Резултат:
+-----------+---------+ | PetType | Count | |-----------+---------| | Dog | 4 | | Cat | 3 | | Bird | 1 | +-----------+---------+
Този набор от резултати е много по-лесен за четене от предишните. По-лесно е да разберете колко от всеки тип домашен любимец има в таблицата.
Синтаксисът използва типа на присъединяване (в този случай LEFT JOIN
), последвано от първата (лява) таблица, последвана от ON
, последвано от условието за присъединяване.
Нека използваме INNER JOIN
за да върне всички имена на домашни любимци със съответните им типове домашни любимци.
SELECT
Pets.PetName,
PetTypes.PetType
FROM Pets
INNER JOIN PetTypes
ON Pets.PetTypeId = PetTypes.PetTypeId;
Резултат:
+-----------+-----------+ | PetName | PetType | |-----------+-----------| | Fluffy | Cat | | Fetch | Dog | | Scratch | Cat | | Wag | Dog | | Tweet | Bird | | Fluffy | Dog | | Bark | Dog | | Meow | Cat | +-----------+-----------+
Присъединяванията наистина отварят нашите опции, защото вече можем да вземем данни от множество таблици и да ги представим, сякаш са една таблица.
Ще забележите, че в примерите за присъединяване ние квалифицираме имената на колоните си с имената на таблиците. Причината да правим това е, за да избегнем неясноти относно имената на колоните на колоните между таблиците. И двете таблици могат да имат колони с едно и също име (както в нашия пример) и в такива случаи СУБД няма да знае коя колона имате предвид. Поставянето на префикс на имената на колоните с имената на техните таблици гарантира, че препращате към дясната колона и предотвратява всякакви грешки, които биха могли да възникнат от неяснота относно това коя колона имате предвид.
Вижте моя урок за SQL Joins за повече примери и обяснение на различните типове присъединяване.
Псевдоними
Можем да отидем още по-далеч и да зададем псевдоним към всяко име на таблица и име на колона.
SELECT
p.PetName AS Pet,
pt.PetType AS "Pet Type"
FROM PetTypes pt
LEFT JOIN Pets p
ON p.PetTypeId = pt.PetTypeId;
Резултат:
+---------+------------+ | Pet | Pet Type | |---------+------------| | Tweet | Bird | | Fluffy | Cat | | Scratch | Cat | | Meow | Cat | | Fetch | Dog | | Wag | Dog | | Fluffy | Dog | | Bark | Dog | | NULL | Rabbit | +---------+------------+
Това доведе до нови заглавки на колони, плюс кодът е по-сбит.
Псевдонимът ви позволява временно да присвоите друго име на таблица или колона за продължителността на SELECT
запитване. Това може да бъде особено полезно, когато таблици и/или колони имат много дълги или сложни имена.
Псевдонимът се присвоява чрез използването на AS
ключова дума, въпреки че тази ключова дума не е задължителна, така че можете спокойно да я пропуснете. Имайте предвид, че Oracle не поддържа AS
ключова дума за псевдоними на таблици (но го прави за псевдоними на колони).
В горния пример включих AS
ключова дума при присвояване на псевдоними на колоните, но я пропусна при присвояване на псевдоними на таблицата.
Името на псевдоним може да бъде каквото и да е, но обикновено се запазва кратко за целите на четливостта.
В нашия случай променихме двете таблици на p
и pt
и имената на колоните към Pets
и Pet Type
. Обърнете внимание, че заобиколих Pet Type
в двойни кавички. Направих това, защото има място в името. За псевдоними без интервали не е необходимо да правите това. В SQL Server можете алтернативно да използвате квадратни скоби ([]
) вместо двойни кавички (въпреки че поддържа и двойни кавички).
Практиката за използване на интервали в колони и псевдоними като цяло не се препоръчва, тъй като може да причини всякакви проблеми с някои клиентски приложения.
Имайте предвид, че все още трябва да използваме пълните имена на колони, когато ги препращаме в обединението (след ON
ключова дума).
Трябва да отбележа, че присвояването на псевдоним всъщност не преименува колоната или таблицата.
Вижте Обяснение на SQL псевдоним за повече примери.
Актуализиране на данните
Можете да използвате UPDATE
изявление за актуализиране на данните във вашите таблици.
Основният синтаксис е доста прост:
UPDATE Owners
SET LastName = 'Stallone'
WHERE OwnerId = 3;
В този пример актуализираме LastName
колона да има нова стойност на Stallone
където OwnerId
е 3
.
За да актуализирате няколко колони, използвайте запетая, за да разделите всяка двойка колона/стойност.
Но каквото и да правите, не забравяйте WHERE
клаузата (освен ако всъщност не възнамерявате да актуализирате всеки ред в таблицата със същата стойност).
Вижте SQL UPDATE
за начинаещи за повече примери и по-подробно обяснение.
Изтриване на данни
Можете да използвате DELETE
изявление за изтриване на данни от вашите таблици.
Основният синтаксис е дори по-прост от UPDATE
изявление:
DELETE FROM Owners
WHERE OwnerId = 5;
Тук изтриваме номер на собственик 5 от Owners
таблица.
Както при UPDATE
изявление, не забравяйте WHERE
клаузата (освен ако не възнамерявате да изтриете всеки ред в таблицата ).
Вижте SQL DELETE
за начинаещи за повече примери и подробно обяснение.
Изпускане на обекти
While we’re on the subject of deleting things, when you delete a database object (such as a table, view, stored procedure, etc), it’s said that you “drop” that object. For example, if you no longer need a table, you “drop it”.
The syntax is extremely simple, and it goes like this:
DROP TABLE Customers;
Those three words completely obliterated a table called Customers
. The table and all its data is now gone.
As you can imagine, this can be a very dangerous statement, and should be used with extreme caution.
The same syntax can be used for other object types, except you would replace table
with the object type (for example DROP VIEW vPets
drops a view called vPets
).
If you try to drop a table that is referenced by a foreign key, you’ll probably get an error. In this case, you’ll need to either drop the foreign key (using the ALTER TABLE
statement) or the child table itself.
SQL Operators
In SQL, an operator is a symbol specifying an action that is performed on one or more expressions.
Operators manipulate individual data items and return a result. Елементите от данни се наричат операнди или аргументи . In SQL, operators are represented by special characters or by keywords.
We’ve already seen some operators in action. Some of our previous example queries had a WHERE
clause that included the Equals operator (=
). We also ran a query that used the Greater Than operator (>
). These are both comparison operators – they compare two expressions.
See 12 Commonly Used Operators in SQL for examples of operators that you’re likely to need when working with SQL.
You can also use this list of SQL Operators as a reference for the operators available in SQL.
SQL Views
In SQL, a view is a query that’s saved to the database as a database object (just like a table). The term can also be used to refer to the result set of a stored query. Views are often referred to as virtual tables .
To create a view, you write a query, then save it as a view. You do this using the CREATE VIEW
синтаксис.
Here’s an example of creating a view:
CREATE VIEW vPetTypeCount AS
SELECT
PetTypes.PetType,
COUNT(Pets.PetTypeId) AS Count
FROM Pets
LEFT JOIN PetTypes
ON Pets.PetTypeId = PetTypes.PetTypeId
GROUP BY PetTypes.PetType;
Running that code creates the view and stores it as an object in the database.
We can now query the view, just like we’d query a table.
Резултат:
SELECT * FROM vPetTypeCount;
+-----------+---------+ | PetType | Count | |-----------+---------| | Bird | 1 | | Cat | 3 | | Dog | 4 | +-----------+---------+
So we get the same result as we would have got if we’d run the original query, but saving it in a view made it a lot easier to query.
This benefit would become greater, the more complex the query is.
Views and the ORDER BY Clause
One thing I should point out is that the original query had an ORDER BY
clause, but I didn’t include that in the view. The SQL standard does not allow the ORDER BY
clause in any view definition. Also, most RDBMSs will raise an error if you try to include an ORDER BY
клауза.
This isn’t a problem though, because you can sort the results when you query the view. Therefore, we can do something like this:
SELECT * FROM vPetTypeCount
ORDER BY Count DESC;
Резултат:
+-----------+---------+ | PetType | Count | |-----------+---------| | Dog | 4 | | Cat | 3 | | Bird | 1 | +-----------+---------+
Most RDBMSs also include a large set of system views that you can use to retrieve information about the system.
For more about views, see What is a View?
Stored Procedures
A stored procedure is a series of SQL statements compiled and saved to the database. Stored procedures are similar to views in some respects, but very different in other respects.
One of the benefits of stored procedures is that they allow you to store complex scripts on the server. Stored procedures often contain conditional programming such as IF... ELSE
statements, for example. Stored procedures can also accept parameters.
Here’s an example of creating a simple stored procedure in SQL Server to get pet information from our database:
CREATE PROCEDURE uspGetPetById
@PetId int
AS
SET NOCOUNT ON;
SELECT
p.PetName,
p.DOB,
pt.PetType,
CONCAT(o.FirstName, ' ', o.LastName) AS OwnerName
FROM Pets p
INNER JOIN PetTypes pt
ON p.PetTypeId = pt.PetTypeId
INNER JOIN Owners o
ON o.OwnerId = p.OwnerId
WHERE p.PetId = @PetId;
This stored procedure accepts a parameter called @PetId
. This means that when you call the procedure, you need to pass the ID of the pet that you’d like information about. The procedure then selects data from various tables and returns it.
To call the stored procedure, use the EXECUTE
изявление. You can alternatively shorten it to EXEC
. In PostgreSQL, use the CALL
изявление.
EXEC uspGetPetById @PetId = 3;
Резултат:
+-----------+------------+-----------+-------------+ | PetName | DOB | PetType | OwnerName | |-----------+------------+-----------+-------------| | Scratch | 2018-10-01 | Cat | Bart Pitt | +-----------+------------+-----------+-------------+
In this case I was interested in pet number 3, and so that’s the info that I got.
I should mention that the syntax for creating stored procedures can differ quite significantly between DBMSs (as well as their implementations of various SQL statements and commands that you’d use inside a procedure), so I would suggest that you look at the documentation for your particular DBMS if you want to create a stored procedure.
Most RDBMSs also include a large set of system stored procedures that you can use to perform various administration tasks, and to retrieve information about the system.
For a basic overview of stored procedures, including their benefits, see What is a Stored Procedure?
Also, if you’re interested, see How to Create a Stored Procedure in SQL Server to see another example of creating a stored procedure in SQL Server. That example includes some screenshots.
SQL Triggers
A trigger is a special type of stored procedure that automatically executes when an event occurs in the database server.
Most major RDBMSs support DML triggers, which execute when a user tries to modify data through a data manipulation language (DML) event. DML events are INSERT
, UPDATE
, or DELETE
изявления.
Some DBMSs (such as SQL Server and PostgreSQL) allow triggers to be associated with both tables and views. Others only allow triggers to be associated with tables.
SQL Server also supports DDL triggers and logon triggers.
DDL triggers execute in response to DDL events, such as CREATE
, ALTER
, and DROP
statements, and certain system stored procedures that perform DDL-like operations.
Logon triggers are fired in response to the LOGON
event that’s raised when a user’s session is being established.
Here are some articles explaining how to do various things with triggers in SQL Server:
- Create a DML Trigger in SQL Server
- Create a “last modified” column
- Automatically send an email when someone tries to delete a record
- Update a column’s value whenever another column is updated
- Update a column’s value whenever certain other columns are updated
SQL Transactions
SQL transactions are an important part of transactional databases, where data consistency is paramount.
A transaction manages a sequence of SQL statements that must be executed as a single unit of work. This is to ensure that the database never contains the results of partial operations.
When a transaction makes multiple changes to the database, either all the changes succeed when the transaction is committed, or all the changes are undone when the transaction is rolled back.
Transactions help maintain data integrity by ensuring that a sequence of SQL statements execute completely or not at all.
A classic example of a transaction is to move money from one bank account to another. You wouldn’t want money to be deducted from the first bank account, but not appear in the second bank account.
Therefore, you could use a transaction which goes along the lines of this:
START TRANSACTION
Debit account 1
Credit account 2
Record transaction in transaction journal
END TRANSACTION
You could write conditional logic inside that transaction that rolls back the transaction if anything goes wrong.
The end result is that, either the transaction is completed in its entirety, or it’s not completed at all. It’s never half-done.
See my SQL Transactions Tutorial for examples of SQL transactions.
SQL Functions
A function is a routine that can take parameters, perform calculations or other actions, and return a result.
Most DBMSs provide you with the ability to create your own functions, while also providing a range of inbuilt functions.
User-Defined Functions
A user-defined function (UDF) is a function that you create for a specific purpose, and save to the database. You would create such a function for tasks that aren’t catered for by an inbuilt function.
See Introduction to User-Defined Functions in SQL Server for an overview. Although that article is written for SQL Server, most of the general concepts also apply to other DBMSs.
Inbuilt Functions
Most DBMSs have a large range of inbuilt functions that you can use in your SQL queries. For example, there are functions that return the current date and time, functions that format dates and numbers, functions that convert data from one data type to another, and more.
The range of inbuilt functions can be pretty extensive, and depend on the DBMS in use, so I won’t go over them in this SQL tutorial. But I would encourage you to try to find out what inbuilt functions your DBMS supports.
To get you started, the following articles contain some of the most commonly used functions in SQL programming.
SQL Server
- SQL Server String Functions
- SQL Server Mathematical Functions
- SQL Server Date &Time Functions
MySQL
- MySQL String Functions
- MySQL Mathematical Functions
PostgreSQL
- PostgreSQL Date &Time Functions
- PostgreSQL Math Functions
SQLite
- SQLite Aggregate Functions
- SQLite Date &Time Functions