Tworzenie baz danych i tabel Wprowadzenie SQL (ang. Structured Query Language strukturalny język zapytań używany do tworzenia, modyfikowania baz danych oraz do umieszczania i pobierania danych z baz danych. SQL został opracowany w latach 70. w firmie IBM. Stał się standardem w komunikacji z serwerami relacyjnych baz danych. Wiele współczesnych systemów relacyjnych baz danych używa do komunikacji z użytkownikiem SQL, dlatego potocznie mówi się, że korzystanie z relacyjnych baz danych to korzystanie z SQL-a. Pierwszą firmą, która włączyła SQL do swojego produktu komercyjnego, był Oracle. Dalsze wprowadzanie SQL-a, w produktach innych firm, wiązało się nierozłącznie z wprowadzaniem modyfikacji pierwotnego języka. Wkrótce utrzymanie dalszej jednolitości języka wymagało wprowadzenia standardu. Użycie SQL, zgodnie z jego nazwą, polega na zadawaniu zapytań do bazy danych. Zapytania można zaliczyć do jednego z trzech głównych podzbiorów: SQL DML (ang. Data Manipulation Language język manipulacji danymi, SQL DDL (ang. Data Definition Language język definicji danych. SQL DCL (ang. Data Control Language język kontroli nad danymi. Instrukcje SQL w obrębie zapytań tradycyjnie zapisywane są wielkimi literami, jednak nie jest to obowiązkowe. W standardzie, zapytania SQL kończone są średnikiem (;, ale niw we wszystkich implementacjach jest to obowiązkowe (np. w TransactSQL firmy Microsoft. Dodatkowo, niektóre programy do łączenia się z silnikiem bazy danych (np. psql w przypadku PostgreSQL, używają swoich własnych instrukcji, spoza standardu SQL, które służą np. do połączenia się z bazą, wyświetlenia dokumentacji itp. Tworzenie bazy danych IF DB_ID('NazwaBazy' IS NULL CREATE DATABASE NazwaBazy -- Jeśli baza nie istnieje to -- utwórz bazę danych Usuwanie bazy danych IF DB_ID('NazwaBazy' IS NOT NULL -- Jeśli baza istnieje to DROP DATABASE NazwaBazy -- usuń bazę danych Tworzenie tabel Dane w relacyjnej bazie danych przechowywane są w tabelach, które są dwuwymiarowymi macierzami. Tabele zostały wybrane jako logiczna struktura do przechowywania danych ze względu na łatwość uzyskiwania i wyświetlania danych, jak również manipulowania nimi. Tabele tworzy się za pomocą polecenia: CREATE TABLE. IF OBJECT_ID('Baza.Właściciel.NazwaTabeli','U' IS NULL -- Jeśli tabela nie istnieje CREATE TABLE Baza.Właściciel.NazwaTabeli ( -- to utwórz tabelę nazwa_atrybutu typ [ograniczenie], nazwa_atrybutu typ [ograniczenie],... UWAGI: 1. Podawanie nazwy bazy nie jest obowiązkowe np. CREATE TABLE Właściciel.NazwaTabeli Tabela będzie wówczas zakładana w bieżącej (aktualnej bazie danych. BAD210 Strona 1
2. Podawanie właściciela również nie jest konieczne np. CREATE TABLE NazwaTabeli. Automatycznie właścicielem tabeli będzie użytkownik, który ją zakłada. 3. Jeśli tabela ma być dostępna dla wielu użytkowników, jako właściciela należy podać dbo (database owner, tzn. CREATE TABLE dbo.nazwatabeli. Pamiętajmy, że tworząc zapytania będziemy musieli odwoływać się do atrybutów tabel. Dlatego warto nadawać im takie nazwy, które niosą informację o zawartych w nich danych. Typy danych Typy danych charakteryzują daną komórkę w wierszu. Określają, jakiego rodzaju informacje możemy umieścić w danej kolumnie. Przykładowo innego typu danych użyjemy, gdy będziemy chcieli przechowywać imię użytkownika, innego dla daty jego urodzin, a jeszcze innego, gdy będziemy chcieli przechowywać jego zdjęcie. Poszczególne typy danych można zakwalifikować do rożnych grup, według funkcjonalności jaką mogą spełniać: Dane tekstowe: CHAR, VARCHAR, NCHAR, NTEXT, NVARCHAR Liczbowe: INT, SMALLINT, BIGINT, TINYINT, FLOAT, REAL, DECIMAL, NUMERIC Data i czas: DATETIME, SMALLDATETIME Binarne: BINARY, VARBINARY Waluta: MONEY, SMALLMONEY Specjalne: TEXT, IMAGE, XML, BIT Dokładną definicję oraz wyjaśnienie zastosowania danego typu można znaleźć w pomocy dołączonej do MS SQL Server. Ograniczenia Poszczególne atrybuty w tworzonej tabeli mogą posiadać ograniczenia co do dopuszczalnych danych: PRIMARY KEY ograniczenie definiujące klucz podstawowy dla relacji FOREIGN KEY ograniczenie definiujące e dany atrybut jest kluczem obcym w relacji (przykład użycia poniżej NOT NULL zastosowanie tego ograniczenia wymusi aby w każdej krotce wartość atrybutu była nie pusta CHECK sprawdzenie czy wartość atrybutu jest z dopuszczalnego zakresu UNIQUE wymagania unikalnej wartości atrybutu W poniższej deklaracji dla atrybutu nazwa ustalamy, że ma być wartością tekstową dla której rezerwujemy 30 znaków, pole to nie może przyjmować wartości NULL oraz jest kluczem głównym relacji: IF OBJECT_ID('Przedmioty','U' IS NULL CREATE TABLE Przedmioty (nazwa VARCHAR(30 NOT NULL PRIMARY KEY -- Jeśli tabela nie istnieje Przykłady instrukcji tworzących (rożne tabele: IF OBJECT_ID('Nauczyciele','U' IS NULL -- Jeśli tabela nie istnieje CREATE TABLE Nauczyciele( id INT NOT NULL PRIMARY KEY, nazwisko VARCHAR(30 CHECK (nazwisko LIKE '[A-Z]%', dyzur VARCHAR(30 CHECK (dyzur in ('pon', 'wt', 'sr', 'czw', 'pt', BAD210 Strona 2
zarobek FLOAT CHECK (zarobek >= 1000 IF OBJECT_ID('Studenci','U' IS NULL -- Jeśli tabela nie istnieje CREATE TABLE Studenci( id INT IDENTITY(1,1 PRIMARY KEY, imie VARCHAR(10, id_wydz INT REFERENCES Wydzialy(id_wydz, rodzaj VARCHAR(7 CHECK (rodzaj in ('dzienny', 'zaoczny' DEFAULT 'dzienny', rok_studiow INT Modyfikacja tabeli Istniejącą tabelę możemy zmodyfikować - dodając bądź usuwając atrybuty, a także dodając do nich ograniczenia. Wykorzystujemy do tego polecenie alter. IF OBJECT_ID('NazwaTabeli','U' IS NULL -- Jeśli tabela nie istnieje ALTER TABLE NazwaTabeli <operacja> [, <operacja> ]; gdzie <operacja> = ADD <definicja atrybutu> - dodanie nowego atrybutu(kolumny ADD <ograniczenie> - dodanie ograniczenia ALTER [COLUMN] <definicja atrybutu> - modyfikacja atrybutu DROP nazwa atrybutu - usunięcie atrybutu DROP CONSTRAINT nazwa ograniczenia - usunięcie ograniczenia UWAGA: Przed dodaniem, usunięciem lub modyfikacją kolumny należy sprawdzić, czy dana kolumna istnieje! Sposób użycia (dodanie to tabeli nauczyciele atrybutu DataUrodz: IF COL_LENGTH('Nauczyciele','DataUrodz' IS NULL -- Jeśli kolumna nie istnieje ALTER TABLE Nauczyciele ADD DataUrodz SMALLDATETIME -- dodaj kolumnę Usuwanie tabeli Aby usnąć tabele (wraz z danymi które się w niej znajdują należy zastosować polecenie: IF OBJECT_ID('NazwaTabeli','U' IS NOT NULL DROP TABLE NazwaTabeli -- Jeśli tabela istnieje -- usuń tabelę Przykład użycia (w efekcie zostanie usunięta tabela nauczyciele: IF OBJECT_ID('Nauczyciele','U' IS NOT NULL -- Jeśli tabela istnieje DROP TABLE Nauczyciele -- usuń tabelę Należy pamiętać, że nie możemy usunąć tabeli do której istnieją powiązania bez uprzedniego usunięcia powiązań (kluczy obcych w innych tabelach lub całych tabel które zawierają odwołania do usuwanej tabeli. Tworzenie automatycznego identyfikatora Bardzo często definiując tabele chcemy aby identyfikator krotek był automatycznie tworzony przez silnik bazy danych. W ten sposób wstawiając dane do tabeli nie musimy sprawdzać, czy wartość identyfikatora krotki, którą chcemy dodać jest unikalna. W przypadku MS SQL aby uzyskać automatyczne tworzenie identyfikatora tabeli wystarczy, że w definicji tabeli przy polu, które chcemy BAD210 Strona 3
aby było kluczem głównym dodamy ograniczenie IDENTITY(START,KROK gdzie parametr START określa od jakiej wartości chcemy rozpocząć numerowanie, KROK określa o jaką wartość zwiększane będą wartości atrybutu w kolejnych krotkach. IF OBJECT_ID('Studenci','U' IS NULL -- Jeśli tabela nie istnieje CREATE TABLE Studenci( id INT IDENTITY(1,1 PRIMARY KEY, -- Automatycznie zwiększaj wartość imie VARCHAR(10, id_wydz INT REFERENCES Wydzialy(id_wydz, rodzaj VARCHAR(7 CHECK (rodzaj in ('dzienny', 'zaoczny' DEFAULT 'dzienny', rok_studiow INT Wprowadzanie danych do tabeli INSERT INTO NazwaTabeli [(atrybut, atrybut,... ] VALUES (wartosc, wartosc,... Przykłady: INSERT INTO Autorzy VALUES (1, 'Marciniak', 'Polska' INSERT INTO Studenci (pesel, imie, wydzial, rok VALUES ('11111111111', 'Jakub',1, 2 UWAGA: Możemy nie podawać nazw kolumn, ale musimy wtedy podać wartości dla wszystkich kolumn w odpowiednim porządku (pierwszy przykład. Jeżeli nie chcemy podawać wszystkich wartości, bo są one np. domyślne, generowane automatycznie to musimy podać nazwy kolumn dla których wprowadzone będą wartości (drugi przykład. Klucze własne i obce oparte o kilka kolumn Przykład tabeli z kluczem własnym opartym o dwie kolumny IF OBJECT_ID('InvoiceLines','U' IS NULL -- Jeśli tabela nie istnieje CREATE TABLE InvoiceLines ( ID INT IDENTITY(1,1, InvoiceNr VARCHAR(10 NOT NULL, -- element klucza własnego --(Klucz główny tabeli InvoiceHeaders LineNr INT NOT NULL, -- element klucza własnego ItemCode VARCHAR(20,..., PRIMARY KEY (InvoiceNr, LineNr, -- definicja klucza własnego FOREIGN KEY InvoiceNr REFERENCES InvoiceHeaders(InvoiceNr Łączenie innej tabeli z tabelą InvoiceLines po kluczu składającym się z dwóch kolumn: IF OBJECT_ID('InvoiceLineDetails','U' IS NULL -- Jeśli tabela nie istnieje CREATE TABLE InvoiceLineDetails ( ID INT IDENTITY(1,1, InvoiceNr VARCHAR(10 NOT NULL, -- elem. klucza własnego (i obcego LineNr INT NOT NULL, -- elem. klucza własnego (i obcego PropertyID VARCHAR(10 NOT NULL, -- elem. klucza własnego Value VARCHAR(10, PRIMARY KEY (InvoiceNr, LineNr, PropertyID, -- definicja klucza własnego FOREIGN KEY (InvoiceNr, LineNr REFERENCES InvoiceLines(InvoiceNr, LineNr -- definicja klucza obcego BAD210 Strona 4
Kopiowanie zawartości tabeli 1. Kopiowanie do tabeli, która już istnieje Tworzenie tabeli IF OBJECT_ID('InvoiceHistory','U' IS NULL CREATE TABLE InvoiceHistory ( ID INT IDENTITY(1,1, InvoiceNr VARCHAR(10 NOT NULL, ClientNr VARCHAR(10 NOT NULL,... -- Jeśli tabela nie istnieje Kopiowanie danych INSERT INTO InvoiceHistory (InvoiceNr, ClientNr SELECT (InvoiceNr, ClientNr FROM Invoices WHERE... 2. Kopiowanie danych z jednoczesnym tworzeniem tabeli SELECT (InvoiceNr, ClientNr INTO InvoiceHistory2 FROM Invoices WHERE... InvoiceHistory2 -- i wstaw dane z tabeli Invoices BAD210 Strona 5
Zadania W poniższych zadaniach kolorem czerwonym zaznaczono kolumnę, która ma być kluczem własnym tabeli. UWAGA: Przed nazwą tabel nie wstawiaj dbo. 1. Utwórz tabelę: SZKOLY (ID_szkola, Nazwa, Miasto IF OBJECT_ID(...,'U' IS NULL CREATE TABLE (..., PRIMARY KEY... 2. Utwórz tabelę: NAUCZYCIELE (ID_nauczyciel, Nazwisko, Imie, Data_urodzenia, Stawka 3. Utwórz tabelę: PRZEDMIOTY (ID_przedmiot, nazwa, ID_szkola, ID_nauczyciel, ID_szkola i ID_nauczyciel są kluczami obcymi do utworzonych wcześniej tabel. 4. Utwórz tabelę: DZIALY (ID_dzial, Nazwa, Adres identyfikator ma się nadawać automatycznie 5. Utwórz tabelę: ETATY(ID_etat, Placa_min, Placa_max, Placa _max mniejsza od Placa_min Wskazówka: Dodaj warunek (CHECK po utworzeniu tabeli. 6. Utwórz tabelę: KADRY (ID_pracownik, Nazwisko, ID_etat, Szef, Zatrudniony, ID_dzial, ID_etat jest kluczem obcym do tabeli ETATY, ID_dzial jest kluczem obcym do tabeli DZIALY. 7. Dodaj kolumnę 'Wymagania' (pole tekstowe do 255 znaków do tabeli ETATY IF OBJECT_ID(...,'U' IS NOT NULL -- Jeśli tabela istnieje IF COL_LENGTH(...,'Wymagania' IS NULL -- Jeśli kolumna nie istnieje ALTER TABLE... ADD... -- dodaj kolumnę 8. Dodaj kolumnę 'Pesel' w tabeli KADRY VARCHAR(11 9. Dodaj ograniczenie na kolumnę 'Pesel' w tabeli KADRY by akceptowane były tylko liczby Wskazówka: (Pesel LIKE '[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]' IF OBJECT_ID(...,'U' IS NOT NULL -- Jeśli tabela istnieje IF COL_LENGTH(...,'Wymagania' IS NULL -- Jeśli kolumna nie istnieje ALTER TABLE... ADD CONSTRAINT CT_Pesel CHECK (... 10. Usuń kolumnę Wymagania w tabeli KADRY IF OBJECT_ID(...,'U' IS NOT NULL -- Jeśli tabela istnieje IF COL_LENGTH(...,'Wymagania' IS NOT NULL -- Jeśli kolumna istnieje ALTER TABLE... 11. Wprowadź przykładowe dane do tabel DZIALY, ETATY, KADRY korzystając z tabel ODDZIALY, STANOWISKA, PRACOWNICY i zapytań SELECT INSERT INTO DZIALY (... SELECT... FROM Oddzialy INSERT INTO ETATY (... SELECT... FROM STANOWISKA INSERT INTO KADRY (... SELECT... FROM PRACOWNICY BAD210 Strona 6