Microsoft SQL Server Samouczek
Rozpoczęcie pracy z Microsoft SQL Server
Szukaj…
Uwagi
Jest to zestaw przykładów podkreślających podstawowe użycie SQL Server.
Wersje
Wersja | Data wydania |
---|---|
SQL Server 2016 | 01.06.2016 |
SQL Server 2014 | 18.03.2014 |
SQL Server 2012 | 2011-10-11 |
SQL Server 2008 R2 | 01.04.2010 |
SQL Server 2008 | 2008-08-06 |
SQL Server 2005 | 01.11.2005 |
SQL Server 2000 | 2000-11-01 |
INSERT / SELECT / UPDATE / DELETE: podstawy języka manipulacji danymi
D ata M anipulation L Anguage (w skrócie DML) obejmuje operacje takie jak INSERT
, UPDATE
i DELETE
:
-- Create a table HelloWorld
CREATE TABLE HelloWorld (
Id INT IDENTITY,
Description VARCHAR(1000)
)
-- DML Operation INSERT, inserting a row into the table
INSERT INTO HelloWorld (Description) VALUES ('Hello World')
-- DML Operation SELECT, displaying the table
SELECT * FROM HelloWorld
-- Select a specific column from table
SELECT Description FROM HelloWorld
-- Display number of records in the table
SELECT Count(*) FROM HelloWorld
-- DML Operation UPDATE, updating a specific row in the table
UPDATE HelloWorld SET Description = 'Hello, World!' WHERE Id = 1
-- Selecting rows from the table (see how the Description has changed after the update?)
SELECT * FROM HelloWorld
-- DML Operation - DELETE, deleting a row from the table
DELETE FROM HelloWorld WHERE Id = 1
-- Selecting the table. See table content after DELETE operation
SELECT * FROM HelloWorld
W tym skrypcie tworzymy tabelę, aby zademonstrować podstawowe zapytania.
Poniższe przykłady pokazują, jak wyszukiwać tabele:
USE Northwind;
GO
SELECT TOP 10 * FROM Customers
ORDER BY CompanyName
wybierze pierwsze 10 rekordów tabeli Customer
, uporządkowanych według kolumny CompanyName
z bazy danych Northwind
(która jest jedną z przykładowych baz danych Microsoft, można ją pobrać stąd ):
Pamiętaj, że Use Northwind;
zmienia domyślną bazę danych dla wszystkich kolejnych zapytań. Nadal możesz odwoływać się do bazy danych, używając w pełni kwalifikowanej składni w postaci [Baza danych]. [Schemat]. [Tabela]:
SELECT TOP 10 * FROM Northwind.dbo.Customers
ORDER BY CompanyName
SELECT TOP 10 * FROM Pubs.dbo.Authors
ORDER BY City
Jest to przydatne, jeśli przeszukujesz dane z różnych baz danych. Zauważ, że dbo
, określone „pomiędzy” nazywa się schematem i musi zostać określone przy użyciu w pełni kwalifikowanej składni. Możesz myśleć o tym jak o folderze w bazie danych. dbo
jest domyślnym schematem. Domyślny schemat można pominąć. Wszystkie pozostałe schematy zdefiniowane przez użytkownika muszą zostać określone.
Jeśli tabela bazy danych zawiera kolumny o nazwach podobnych do słów zastrzeżonych, np. Date
, należy zawrzeć nazwę kolumny w nawiasach, jak poniżej:
-- descending order
SELECT TOP 10 [Date] FROM dbo.MyLogTable
ORDER BY [Date] DESC
To samo dotyczy sytuacji, gdy nazwa kolumny zawiera spacje w nazwie (co nie jest zalecane). Alternatywną składnią jest stosowanie podwójnych cudzysłowów zamiast nawiasów kwadratowych, np .:
-- descending order
SELECT top 10 "Date" from dbo.MyLogTable
order by "Date" desc
jest równoważne, ale nie jest tak często używane. Zwróć uwagę na różnicę między podwójnymi cudzysłowami i pojedynczymi cudzysłowami: W przypadku ciągów znaków używane są pojedyncze cudzysłowy
-- descending order
SELECT top 10 "Date" from dbo.MyLogTable
where UserId='johndoe'
order by "Date" desc
jest poprawną składnią. Zauważ, że T-SQL ma prefiks N
dla typów danych NChar i NVarchar, np
SELECT TOP 10 * FROM Northwind.dbo.Customers
WHERE CompanyName LIKE N'AL%'
ORDER BY CompanyName
zwraca wszystkie firmy posiadające nazwę firmy zaczynającą się od AL
( %
to symbol wieloznaczny, użyj go tak, jakbyś używał gwiazdki w wierszu poleceń DOS, np. DIR AL*
). W przypadku LIKE
istnieje kilka symboli wieloznacznych, spójrz tutaj, aby uzyskać więcej informacji.
Łączy się
Połączenia są przydatne, jeśli chcesz wyszukiwać pola, które nie istnieją w jednej tabeli, ale w wielu tabelach. Na przykład: Chcesz wykonać zapytanie do wszystkich kolumn z tabeli Region
w bazie danych Northwind
. Ale zauważasz, że potrzebujesz również RegionDescription
, który jest przechowywany w innej tabeli Region
. Jednakże, istnieje wspólny klucz, RgionID
których można użyć, aby połączyć te informacje w jednym zapytaniu następująco ( Top 5
prostu zwraca pierwszych 5 wierszy, pomijają to, aby wszystkie wiersze):
SELECT TOP 5 Territories.*,
Regions.RegionDescription
FROM Territories
INNER JOIN Region
ON Territories.RegionID=Region.RegionID
ORDER BY TerritoryDescription
pokaże wszystkie kolumny z Territories
oraz kolumnę RegionDescription
z Region
. Wynik jest uporządkowany według TerritoryDescription
.
Aliasy tabel
Gdy zapytanie wymaga odwołania do dwóch lub więcej tabel, przydatne może być użycie aliasu tabeli. Aliasy tabel to skrócone odniesienia do tabel, które mogą być używane zamiast pełnej nazwy tabeli i mogą ograniczyć pisanie i edycję. Składnia użycia aliasu to:
<TableName> [as] <alias>
Gdzie as
jest opcjonalnym słów kluczowych. Na przykład poprzednie zapytanie można przepisać jako:
SELECT TOP 5 t.*,
r.RegionDescription
FROM Territories t
INNER JOIN Region r
ON t.RegionID = r.RegionID
ORDER BY TerritoryDescription
Aliasy muszą być unikalne dla wszystkich tabel w zapytaniu, nawet jeśli użyjesz tej samej tabeli dwa razy. Na przykład, jeśli tabela pracowników zawiera pole SupervisorId, możesz użyć tego zapytania, aby zwrócić pracownika i nazwisko jego przełożonego:
SELECT e.*,
s.Name as SupervisorName -- Rename the field for output
FROM Employee e
INNER JOIN Employee s
ON e.SupervisorId = s.EmployeeId
WHERE e.EmployeeId = 111
Związki
Jak widzieliśmy wcześniej, Join dodaje kolumny z różnych źródeł tabeli. Ale co, jeśli chcesz połączyć wiersze z różnych źródeł? W takim przypadku możesz użyć UNII. Załóżmy, że planujesz przyjęcie i chcesz zaprosić nie tylko pracowników, ale także klientów. Następnie możesz uruchomić to zapytanie, aby to zrobić:
SELECT FirstName+' '+LastName as ContactName, Address, City FROM Employees
UNION
SELECT ContactName, Address, City FROM Customers
Zwróci nazwiska, adresy i miasta od pracowników i klientów w jednym stole. Zauważ, że zduplikowane wiersze (jeśli powinny istnieć) są automatycznie eliminowane (jeśli nie chcesz tego, użyj UNION ALL
). Numer kolumny, nazwy kolumn, kolejność i typ danych muszą być zgodne we wszystkich instrukcjach select, które są częścią unii - dlatego pierwszy SELECT łączy FirstName
i LastName
od pracownika w ContactName
.
Zmienne tabelowe
Przydaje się, gdy trzeba poradzić sobie z danymi tymczasowymi (szczególnie w procedurze przechowywanej), aby użyć zmiennych tabeli: Różnica między tabelą „rzeczywistą” a zmienną tabeli polega na tym, że istnieje ona w pamięci do tymczasowego przetwarzania.
Przykład:
DECLARE @Region TABLE
(
RegionID int,
RegionDescription NChar(50)
)
tworzy tabelę w pamięci. W takim przypadku przedrostek @
jest obowiązkowy, ponieważ jest zmienną. Możesz wykonać wszystkie wyżej wymienione operacje DML, aby wstawić, usunąć i wybrać wiersze, np
INSERT INTO @Region values(3,'Northern')
INSERT INTO @Region values(4,'Southern')
Ale zwykle wypełnia się go w oparciu o prawdziwy stół
INSERT INTO @Region
SELECT * FROM dbo.Region WHERE RegionID>2;
który odczytuje przefiltrowane wartości z prawdziwej tabeli dbo.Region
i wstawia ją do tabeli pamięci @Region
- gdzie można go wykorzystać do dalszego przetwarzania. Na przykład możesz użyć go do łączenia
SELECT * FROM Territories t
JOIN @Region r on t.RegionID=r.RegionID
które w tym przypadku zwrócą wszystkie terytoria Northern
i Southern
. Bardziej szczegółowe informacje można znaleźć tutaj . Tabele tymczasowe są omawiane tutaj , jeśli chcesz przeczytać więcej na ten temat.
UWAGA: Firma Microsoft zaleca stosowanie tylko zmiennych stołowych jeśli liczba wierszy danych w zmiennej tabeli są mniej niż 100. Jeśli będziesz pracować z większymi ilościami danych, należy użyć tabeli tymczasowej lub temp tabeli, zamiast.
WYDRUKOWAĆ
Wyświetl komunikat w konsoli wyjściowej. Za pomocą SQL Server Management Studio będzie to wyświetlane na karcie wiadomości, a nie na karcie wyników:
PRINT 'Hello World!';
Wybierz wszystkie wiersze i kolumny z tabeli
Składnia:
SELECT *
FROM table_name
Korzystanie z operatora gwiazdki *
służy jako skrót do wybierania wszystkich kolumn w tabeli. Wszystkie wiersze zostaną również wybrane, ponieważ ta instrukcja SELECT
nie ma klauzuli WHERE
celu określenia jakichkolwiek kryteriów filtrowania.
Działałoby to również w ten sam sposób, jeśli dodałeś alias do tabeli, na przykład e
w tym przypadku:
SELECT *
FROM Employees AS e
Lub jeśli chcesz wybrać wszystko z określonej tabeli, możesz użyć aliasu + „. *”:
SELECT e.*, d.DepartmentName
FROM Employees AS e
INNER JOIN Department AS d
ON e.DepartmentID = d.DepartmentID
Dostęp do obiektów bazy danych można również uzyskać przy użyciu w pełni kwalifikowanych nazw:
SELECT * FROM [server_name].[database_name].[schema_name].[table_name]
Niekoniecznie jest to zalecane, ponieważ zmiana nazw serwera i / lub bazy danych spowodowałaby, że zapytania wykorzystujące w pełni kwalifikowane nazwy przestałyby być wykonywane z powodu nieprawidłowych nazw obiektów.
Należy zauważyć, że pola przed table_name
można w wielu przypadkach pominąć, jeśli zapytania są wykonywane odpowiednio na jednym serwerze, bazie danych i schemacie. Jednak baza danych ma wiele schematów i w takich przypadkach nazwa schematu nie powinna być pomijana, gdy jest to możliwe.
Ostrzeżenie: użycie SELECT *
w kodzie produkcyjnym lub procedurach przechowywanych może później prowadzić do problemów (gdy nowe kolumny są dodawane do tabeli lub jeśli kolumny są przestawiane w tabeli), szczególnie jeśli kod zawiera proste założenia dotyczące kolejności kolumn, lub liczba zwróconych kolumn. Dlatego bezpieczniej jest zawsze jawnie określać nazwy kolumn w instrukcjach SELECT dla kodu produkcyjnego.
SELECT col1, col2, col3
FROM table_name
Wybierz wiersze pasujące do warunku
Ogólnie składnia jest następująca:
SELECT <column names>
FROM <table name>
WHERE <condition>
Na przykład:
SELECT FirstName, Age
FROM Users
WHERE LastName = 'Smith'
Warunki mogą być złożone:
SELECT FirstName, Age
FROM Users
WHERE LastName = 'Smith' AND (City = 'New York' OR City = 'Los Angeles')
AKTUALIZACJA Określony wiersz
UPDATE HelloWorlds
SET HelloWorld = 'HELLO WORLD!!!'
WHERE Id = 5
Powyższy kod aktualizuje wartość pola „HelloWorld” o „HELLO WORLD !!!” dla rekordu, w którym „Id = 5” w tabeli HelloWorlds.
Uwaga: W instrukcji aktualizacji zaleca się stosowanie klauzuli „gdzie”, aby uniknąć aktualizacji całej tabeli, chyba że wymagania są inne.
AKTUALIZACJA Wszystkie wiersze
Prostą formą aktualizacji jest zwiększenie wszystkich wartości w danym polu tabeli. W tym celu musimy zdefiniować pole i wartość przyrostu
Poniżej znajduje się przykład, w którym zwiększa Score
pola o 1 (we wszystkich rzędach)
UPDATE Scores
SET score = score + 1
Może to być niebezpieczne, ponieważ możesz uszkodzić swoje dane, jeśli przypadkowo wykonasz UPDATE dla określonego wiersza z UPDATE dla wszystkich wierszy w tabeli.
Komentarze w kodzie
Transact-SQL obsługuje dwie formy pisania komentarzy. Komentarze są ignorowane przez silnik bazy danych i są przeznaczone do czytania.
Komentarze są poprzedzone --
i są ignorowane, dopóki nie zostanie napotkany nowy wiersz:
-- This is a comment
SELECT *
FROM MyTable -- This is another comment
WHERE Id = 1;
Komentarze do ukośnika zaczynają się od /*
a kończą na */
. Cały tekst między tymi ogranicznikami jest traktowany jako blok komentarza.
/* This is
a multi-line
comment block. */
SELECT Id = 1, [Message] = 'First row'
UNION ALL
SELECT 2, 'Second row'
/* This is a one liner */
SELECT 'More';
Komentarze w gwiazdkach ukośnika mają tę zaletę, że umożliwiają użytkowanie komentarza, jeśli instrukcja SQL traci nowe znaki wiersza. Może się to zdarzyć, gdy SQL zostanie przechwycony podczas rozwiązywania problemów.
Komentarze gwiazdy ukośnika mogą być zagnieżdżone, a początkowy /*
wewnątrz komentarza ukośnika musi być zakończony znakiem */
aby był prawidłowy. Poniższy kod spowoduje błąd
/*
SELECT *
FROM CommentTable
WHERE Comment = '/*'
*/
Gwiazda ukośnika, mimo że wewnątrz cytatu, jest uważana za początek komentarza. Dlatego należy go zakończyć kolejną ukośną gwiazdą. Prawidłowy sposób byłby
/*
SELECT *
FROM CommentTable
WHERE Comment = '/*'
*/ */
Pobierz podstawowe informacje o serwerze
SELECT @@VERSION
Zwraca wersję MS SQL Server działającą na instancji.
SELECT @@SERVERNAME
Zwraca nazwę wystąpienia MS SQL Server.
SELECT @@SERVICENAME
Zwraca nazwę usługi Windows MS SQL Server działa jako.
SELECT serverproperty('ComputerNamePhysicalNetBIOS');
Zwraca fizyczną nazwę komputera, na którym działa program SQL Server. Przydatne do identyfikacji węzła w klastrze pracy awaryjnej.
SELECT * FROM fn_virtualservernodes();
W klastrze pracy awaryjnej zwraca każdy węzeł, w którym SQL Server może działać. Nic nie zwraca, jeśli nie klaster.
Używanie transakcji do bezpiecznej zmiany danych
Za każdym razem, gdy zmieniasz dane, w poleceniu Data Manipulation Language (DML) możesz zawinąć swoje zmiany w transakcję. DML obejmuje UPDATE
, TRUNCATE
, INSERT
i DELETE
. Jednym ze sposobów, aby upewnić się, że zmieniasz właściwe dane, byłoby skorzystanie z transakcji.
Zmiany DML zablokują dotknięte wiersze. Po rozpoczęciu transakcji musisz zakończyć transakcję, w przeciwnym razie wszystkie obiekty zmieniane w DML pozostaną zablokowane przez tego, kto rozpoczął transakcję. Możesz zakończyć transakcję za pomocą funkcji ROLLBACK
lub COMMIT
. ROLLBACK
przywraca wszystko w transakcji do pierwotnego stanu. COMMIT
umieszcza dane w końcowym stanie, w którym nie można cofnąć zmian bez kolejnej instrukcji DML.
Przykład:
--Create a test table
USE [your database]
GO
CREATE TABLE test_transaction (column_1 varchar(10))
GO
INSERT INTO
dbo.test_transaction
( column_1 )
VALUES
( 'a' )
BEGIN TRANSACTION --This is the beginning of your transaction
UPDATE dbo.test_transaction
SET column_1 = 'B'
OUTPUT INSERTED.*
WHERE column_1 = 'A'
ROLLBACK TRANSACTION --Rollback will undo your changes
--Alternatively, use COMMIT to save your results
SELECT * FROM dbo.test_transaction --View the table after your changes have been run
DROP TABLE dbo.test_transaction
Uwagi:
- To jest uproszczony przykład, który nie obejmuje obsługi błędów. Ale każda operacja na bazie danych może się nie powieść i dlatego zgłasza wyjątek. Oto przykład, jak może wyglądać taka wymagana obsługa błędów. Nigdy nie należy używać transakcji bez procedury obsługi błędów , w przeciwnym razie możesz pozostawić transakcję w nieznanym stanie.
- W zależności od poziomu izolacji transakcje blokują dane, które są wyszukiwane lub zmieniane. Należy upewnić się, że transakcje nie są uruchomione przez długi czas, ponieważ będą blokować rekordy w bazie danych i mogą prowadzić do impasu w przypadku innych równoległych transakcji. Utrzymuj operacje zamknięte w transakcjach tak krótkie, jak to możliwe i minimalizuj wpływ dzięki ilości blokowanych danych.
Usuń wszystkie wiersze
DELETE
FROM Helloworlds
Spowoduje to usunięcie wszystkich danych z tabeli. Tabela nie będzie zawierać wierszy po uruchomieniu tego kodu. W przeciwieństwie do DROP TABLE
, zachowuje to samą tabelę i jej strukturę i możesz nadal wstawiać nowe wiersze do tej tabeli.
Innym sposobem usunięcia wszystkich wierszy w tabeli jest obcięcie go w następujący sposób:
TRUNCATE TABLE HelloWords
Różnice między operacją DELETE są następujące:
- Operacja obcięcia nie zapisuje się w pliku dziennika transakcji
- Jeśli istnieje pole
IDENTITY
, zostanie ono zresetowane - TRUNCATE można zastosować do całej tabeli, a nie do jej części (zamiast polecenia
DELETE
można skojarzyć klauzulęWHERE
)
Ograniczenia TRUNCATE
- Nie można TRUNCATE tabeli, jeśli istnieje odwołanie do
FOREIGN KEY
- Jeśli tabela jest
INDEXED VIEW
- Jeśli tabela zostanie opublikowana przy użyciu
TRANSACTIONAL REPLICATION
lubMERGE REPLICATION
- Nie uruchomi żadnego wyzwalacza zdefiniowanego w tabeli
TABELA ŚCIEŻKI
TRUNCATE TABLE Helloworlds
Ten kod usunie wszystkie dane z tabeli Helloworlds. Obcięta tabela jest prawie podobna do Delete from Table
kodu Delete from Table
. Różnica polega na tym, że nie można używać klauzul where w programie Truncate. Tabela obcięcia jest uważana za lepszą niż usuwanie, ponieważ wykorzystuje mniej przestrzeni dzienników transakcji.
Zauważ, że jeśli kolumna tożsamości istnieje, jest ona resetowana do początkowej wartości początkowej (na przykład automatycznie zwiększany identyfikator zostanie zrestartowany od 1). Może to prowadzić do niespójności, jeśli kolumny tożsamości zostaną użyte jako klucz obcy w innej tabeli.
Utwórz nową tabelę i wstaw rekordy ze starej tabeli
SELECT * INTO NewTable FROM OldTable
Tworzy nową tabelę o strukturze starej tabeli i wstawia wszystkie wiersze do nowej tabeli.
Niektóre ograniczenia
- Nie można określić zmiennej tabeli lub parametru o wartości tabeli jako nowej tabeli.
- Nie można użyć opcji WYBIERZ… INTO, aby utworzyć partycjonowaną tabelę, nawet jeśli tabela źródłowa jest podzielona na partycje. WYBIERZ ... INTO nie używa schematu partycji tabeli źródłowej; zamiast tego nowa tabela jest tworzona w domyślnej grupie plików. Aby wstawić wiersze do tabeli podzielonej na partycje, należy najpierw utworzyć tabelę podzieloną na partycje, a następnie użyć instrukcji INSERT INTO ... SELECT FROM.
- Indeksy, ograniczenia i wyzwalacze zdefiniowane w tabeli źródłowej nie są przenoszone do nowej tabeli, ani nie można ich określić w instrukcji SELECT ... INTO. Jeśli te obiekty są wymagane, możesz je utworzyć po wykonaniu instrukcji SELECT ... INTO.
- Określenie klauzuli ORDER BY nie gwarantuje, że wiersze zostaną wstawione w określonej kolejności. Gdy rzadka kolumna znajduje się na liście wyboru, właściwość rzadkiej kolumny nie jest przenoszona do kolumny w nowej tabeli. Jeśli ta właściwość jest wymagana w nowej tabeli, zmień definicję kolumny po wykonaniu instrukcji SELECT ... INTO, aby uwzględnić tę właściwość.
- Gdy kolumna obliczeniowa znajduje się na liście wyboru, odpowiednia kolumna w nowej tabeli nie jest kolumną obliczaną. Wartości w nowej kolumnie są wartościami obliczonymi w momencie wykonania instrukcji SELECT ... INTO.
[ sic ]
Uzyskiwanie liczby wierszy tabeli
Poniższy przykład może być użyty do znalezienia całkowitej liczby wierszy dla określonej tabeli w bazie danych, jeśli table_name
jest zastąpiona przez tabelę, którą chcesz zapytać:
SELECT COUNT(*) AS [TotalRowCount] FROM table_name;
Możliwe jest również uzyskanie liczby wierszy dla wszystkich tabel, łącząc się ponownie z partycją tabeli na podstawie HEAP tabel (id_indeksu = 0) lub indeksu klastrowego klastra (id_indeksu = 1) przy użyciu następującego skryptu:
SELECT [Tables].name AS [TableName],
SUM( [Partitions].[rows] ) AS [TotalRowCount]
FROM sys.tables AS [Tables]
JOIN sys.partitions AS [Partitions]
ON [Tables].[object_id] = [Partitions].[object_id]
AND [Partitions].index_id IN ( 0, 1 )
--WHERE [Tables].name = N'table name' /* uncomment to look for a specific table */
GROUP BY [Tables].name;
Jest to możliwe, ponieważ każda tabela jest zasadniczo jedną tabelą partycji, chyba że zostaną do niej dodane dodatkowe partycje. Zaletą tego skryptu jest to, że nie ingeruje w operacje odczytu / zapisu w wierszach tabel.