📖 Izvan teksta i brojeva
U realnim sistemima, morate čuvati PDF ugovore, slike profila, video tutorijale, Word dokumente, Excel fajlove,
slike proizvoda, audio zapise i mnoge druge nestrukturirane podatke. Ovi podaci se nazivaju
BLOB (Binary Large Objects) - binarni objekti velikih razmjera. SQL Server nudi tri nivoa
njihovog čuvanja: direktno u tabeli pomoću VARBINARY(MAX), na fajl sistemu preko baze
(FILESTREAM) ili kao eksterni folder sa Windows integracijom (FileTable).
💡 Šta su BLOB podaci?
BLOB (Binary Large Object) je termin koji se koristi za bilo koji binarni podatak koji ne može biti efikasno predstavljen kao tekst ili numerička vrijednost. Primjeri uključuju:
- Dokumenti: PDF, Word (.docx), Excel (.xlsx), PowerPoint prezentacije
- Slike: JPEG, PNG, GIF, BMP, TIFF
- Video: MP4, AVI, MOV
- Audio: MP3, WAV, FLAC
- Arhive: ZIP, RAR, 7Z
- Izvršni fajlovi: EXE, DLL
- Baze podataka: SQLite, Access (.mdb)
Za razliku od strukturiranih podataka (brojevi, datumi, tekst), BLOB podaci nemaju unutrašnju strukturu koju SQL Server može direktno razumjeti. Oni se čuvaju kao "crna kutija" - SQL Server zna gdje su, ali ne zna šta je unutra bez dodatnih alata.
📦 VARBINARY(MAX): Skladištenje unutar baze
Šta je VARBINARY(MAX)?
VARBINARY(MAX) je SQL Server tip podataka koji može čuvati binarne podatke do maksimalno
2 GB po koloni. Riječ "VAR" znači "variable" (promjenjiva) - kolona može čuvati različite
veličine podataka, od 0 bajtova do 2 GB.
Kako VARBINARY(MAX) radi interno?
SQL Server koristi LOB (Large Object) storage mehanizam za VARBINARY(MAX) podatke:
- Do 8000 bajtova: Podaci se čuvaju direktno u red tabele (in-row storage)
- Preko 8000 bajtova: SQL Server koristi LOB pointer u redu tabele, a stvarni podaci se čuvaju u posebnim LOB stranicama (out-of-row storage)
- LOB stranice: Specjalne 8KB stranice koje mogu čuvati do 8040 bajtova podataka po stranici
-- Primjer: Tabela za čuvanje slika profila
CREATE TABLE Users.ProfilePictures (
ProfilePictureID INT IDENTITY(1,1) PRIMARY KEY,
UserID INT NOT NULL,
PictureData VARBINARY(MAX) NOT NULL,
FileName NVARCHAR(255),
ContentType NVARCHAR(100), -- npr. 'image/jpeg', 'image/png'
FileSize BIGINT, -- veličina u bajtovima
UploadDate DATETIME2 DEFAULT SYSDATETIME()
);
GO
-- Primjer: Tabela za dokumente
CREATE TABLE Documents.Contracts (
ContractID INT IDENTITY(1,1) PRIMARY KEY,
ContractNumber NVARCHAR(50) UNIQUE,
Title NVARCHAR(200) NOT NULL,
DocumentContent VARBINARY(MAX) NOT NULL,
DocumentType NVARCHAR(50), -- 'PDF', 'DOCX', 'XLSX'
CreatedDate DATETIME2 DEFAULT SYSDATETIME(),
CreatedBy NVARCHAR(100)
);
GO
Prednosti VARBINARY(MAX)
- ACID transakcije: Podaci su dio transakcije - ako se transakcija rollback-uje, podaci se vraćaju
- Backup i restore: Automatski uključeni u backup baze
- Sigurnost: Podaci su zaštićeni SQL Server sigurnosnim mehanizminma
- Jednostavnost: Nema potrebe za konfiguracijom fajl sistema
- Integritet: Foreign key i druge constraint-e rade normalno
Nedostaci VARBINARY(MAX)
- Performanse na velikim fajlovima: Fajlovi veći od 1 MB mogu usporiti bazu
- Veličina baze: Povećava veličinu baze podataka
- Backup vrijeme: Veliki backup fajlovi traju duže
- Memorija: Čitanje velikih BLOB-ova može zauzeti puno memorije
- Nema direktnog pristupa: Ne možete otvoriti fajl direktno iz Windows Explorer-a
-- Metoda 1: Umetanje iz fajla pomoću OPENROWSET (zahtijeva permisije)
INSERT INTO Documents.Contracts (Title, DocumentContent, DocumentType)
SELECT
'Ugovor o radu',
BulkColumn,
'PDF'
FROM OPENROWSET(BULK 'C:\Documents\Contract.pdf', SINGLE_BLOB) AS Document;
GO
-- Metoda 2: Umetanje iz aplikacije (C#, Python, itd.)
-- Aplikacija čita fajl u byte array i šalje kao parametar
-- INSERT INTO Documents.Contracts (Title, DocumentContent)
-- VALUES (@Title, @DocumentBytes);
-- Metoda 3: Konverzija iz string-a (za male podatke)
DECLARE @SmallImage VARBINARY(MAX) = CONVERT(VARBINARY(MAX), 'Binary data here');
GO
⚠️ Važno za VARBINARY(MAX)
- Preporučena veličina: Koristite VARBINARY(MAX) za fajlove manje od 1 MB
- Granica: Maksimalna veličina je 2 GB po koloni
- Performanse: Za fajlove veće od 1 MB, razmotrite FILESTREAM
- Memorija: Čitanje velikih BLOB-ova može zauzeti puno RAM-a
💾 FILESTREAM: Najbolje od oba svijeta
Šta je FILESTREAM?
FILESTREAM je SQL Server tehnologija koja kombinuje ACID transakcije baze podataka sa performansama fajl sistema. Kada koristite FILESTREAM:
- Metadata (ID, naziv, datum) se čuva u SQL Server tabeli
- Stvarni fajlovi se čuvaju na NTFS fajl sistemu
- Transakcije su potpuno podržane - ako se transakcija rollback-uje, fajl se briše
- Backup uključuje i fajlove (ako koristite backup sa WITH FILESTREAM)
Kako FILESTREAM radi?
FILESTREAM koristi poseban FILESTREAM filegroup koji mapira SQL Server strukture na NTFS folder. Kada umetnete podatak u FILESTREAM kolonu:
- SQL Server kreira GUID identifikator za fajl
- Fajl se čuva u FILESTREAM folderu na disku
- U tabeli se čuva samo pointer (GUID) na fajl
- Windows File System API se koristi za čitanje/pisanje (brže od SQL Server I/O)
Konfiguracija FILESTREAM-a
FILESTREAM se mora omogućiti na nivou SQL Server instance prije korištenja:
-- Korak 1: Omogućiti FILESTREAM na SQL Server instance nivou
-- Ovo se radi kroz SQL Server Configuration Manager ili T-SQL:
EXEC sp_configure filestream_access_level, 2;
RECONFIGURE;
GO
-- Vrijednosti:
-- 0 = FILESTREAM onemogućen
-- 1 = Omogućen samo za Transact-SQL pristup
-- 2 = Omogućen za T-SQL i Windows file I/O pristup (preporučeno)
-- Korak 2: Kreirati FILESTREAM filegroup u bazi
ALTER DATABASE MyDatabase
ADD FILEGROUP FileStreamFG CONTAINS FILESTREAM;
GO
-- Korak 3: Dodati FILESTREAM fajl u filegroup
ALTER DATABASE MyDatabase
ADD FILE (
NAME = 'FileStreamData',
FILENAME = 'C:\SQLData\FileStreamData' -- Folder gdje će se čuvati fajlovi
)
TO FILEGROUP FileStreamFG;
GO
-- Napomena: Folder mora postojati, ali SQL Server će ga kreirati ako ne postoji
-- FILENAME mora biti putanja do foldera, ne fajla
-- Važno: FILESTREAM tabele MORAJU imati UNIQUEIDENTIFIER kolonu sa ROWGUIDCOL
CREATE TABLE Legal.Contracts (
ContractID UNIQUEIDENTIFIER ROWGUIDCOL PRIMARY KEY DEFAULT NEWID(),
ContractNumber NVARCHAR(50) UNIQUE NOT NULL,
Title NVARCHAR(200) NOT NULL,
Document VARBINARY(MAX) FILESTREAM NULL, -- FILESTREAM kolona
FileName NVARCHAR(255),
FileSize BIGINT,
UploadDate DATETIME2 DEFAULT SYSDATETIME(),
CreatedBy NVARCHAR(100)
);
GO
-- Napomena:
-- - ROWGUIDCOL označava kolonu koja čuva GUID za FILESTREAM
-- - FILESTREAM kolona može biti NULL
-- - Maksimalna veličina fajla je ograničena samo disk prostorom (ne 2 GB kao VARBINARY)
Rad sa FILESTREAM podacima
-- Metoda 1: Umetanje iz fajla pomoću OPENROWSET
INSERT INTO Legal.Contracts (ContractNumber, Title, Document, FileName, FileSize)
SELECT
'CONTRACT-2024-001',
'Ugovor o radu',
BulkColumn,
'Contract.pdf',
DATALENGTH(BulkColumn)
FROM OPENROWSET(BULK 'C:\Documents\Contract.pdf', SINGLE_BLOB) AS Document;
GO
-- Metoda 2: Umetanje iz aplikacije (preporučeno)
-- Aplikacija koristi SqlFileStream klasu (.NET) ili slično za direktan pristup
-- Ovo omogućava streaming bez kopiranja cijelog fajla u memoriju
-- Metoda 3: Umetanje praznog FILESTREAM-a i kasnije popunjavanje
INSERT INTO Legal.Contracts (ContractNumber, Title, Document)
VALUES ('CONTRACT-2024-002', 'Novi ugovor', 0x); -- 0x = prazan BLOB
GO
-- Čitanje FILESTREAM podataka
SELECT
ContractID,
ContractNumber,
Title,
Document, -- Vraća VARBINARY(MAX)
FileName,
FileSize
FROM Legal.Contracts
WHERE ContractID = '12345678-1234-1234-1234-123456789012';
GO
-- Za eksport u fajl, koristite aplikaciju koja čita VARBINARY(MAX) i piše u fajl
-- Ili koristite bcp utility ili SQL Server Integration Services (SSIS)
Prednosti FILESTREAM-a
- Performanse: Windows File System API je brži za velike fajlove
- Skalabilnost: Fajlovi nisu ograničeni na 2 GB (samo disk prostor)
- ACID transakcije: Potpuna transakcijska podrška
- Backup: Fajlovi se mogu backup-ovati zajedno sa bazom
- Memorija: Ne zauzima toliko RAM-a kao VARBINARY(MAX)
- Streaming: Mogućnost streaming-a velikih fajlova
Nedostaci FILESTREAM-a
- Kompleksnost: Zahtijeva dodatnu konfiguraciju
- Filegroup: Mora kreirati poseban FILESTREAM filegroup
- GUID zahtjev: Tabela mora imati UNIQUEIDENTIFIER sa ROWGUIDCOL
- Backup kompleksnost: Backup mora uključivati FILESTREAM filegroup
- Nema direktnog pristupa: Ne možete direktno pristupiti fajlovima iz Windows Explorer-a (osim kroz FileTable)
🔑 Kada koristiti šta?
| Kriterij | VARBINARY(MAX) | FILESTREAM |
|---|---|---|
| Veličina fajla | < 1 MB | > 1 MB |
| Maksimalna veličina | 2 GB | Ograničeno samo disk prostorom |
| Performanse | Brzo za male fajlove | Brzo za velike fajlove |
| Kompleksnost | Jednostavno | Zahtijeva konfiguraciju |
| Backup | Automatski u backup baze | Mora eksplicitno uključiti FILESTREAM |
| Windows pristup | Nema | Moguć kroz FileTable |
📂 FileTable: SQL Server kao Windows folder
Šta je FileTable?
FileTable je nadogradnja FILESTREAM-a koja omogućava da SQL Server tabele izgledaju i ponašaju se kao Windows folder. Sa FileTable-om možete:
- Kopirati fajlove direktno u Windows folder, a SQL Server ih automatski "vidi" i dodaje u tabelu
- Otvoriti fajlove direktno iz Windows Explorer-a
- Koristiti Windows API-je za pristup fajlovima
- Integrirati sa aplikacijama koje rade sa fajlovima (npr. Word, Excel)
Kako FileTable radi?
FileTable koristi FILESTREAM tehnologiju u pozadini, ali dodaje:
- Hierarhijsku strukturu: Fajlovi i folderi se organizuju u hijerarhiju
- Windows kompatibilnost: Fajlovi su vidljivi kroz Windows File System
- Automatsku sinhronizaciju: Promjene u Windows folderu se automatski reflektuju u SQL tabeli
- File attributes: Čuva Windows file attributes (read-only, hidden, itd.)
Konfiguracija FileTable-a
-- Korak 1: Omogućiti FILESTREAM (kao što je prikazano ranije)
EXEC sp_configure filestream_access_level, 2;
RECONFIGURE;
GO
-- Korak 2: Kreirati FILESTREAM filegroup (ako već nije kreiran)
ALTER DATABASE MyDatabase
ADD FILEGROUP FileStreamFG CONTAINS FILESTREAM;
GO
ALTER DATABASE MyDatabase
ADD FILE (
NAME = 'FileStreamData',
FILENAME = 'C:\SQLData\FileStreamData'
)
TO FILEGROUP FileStreamFG;
GO
-- Korak 3: Omogućiti non-transacted access (potrebno za FileTable)
ALTER DATABASE MyDatabase
SET FILESTREAM (NON_TRANSACTED_ACCESS = FULL, DIRECTORY_NAME = 'MyFileTableShare');
GO
-- NON_TRANSACTED_ACCESS = FULL omogućava Windows pristup fajlovima
-- DIRECTORY_NAME je ime Windows share-a koji će biti kreiran
-- Kreiranje FileTable-a
CREATE TABLE Documents.DocumentStore AS FileTable
WITH (
FileTable_Directory = 'DocumentStore', -- Ime foldera u Windows share-u
FileTable_Collate_Filename = database_default
);
GO
-- FileTable automatski kreira sljedeće kolone:
-- - stream_id (UNIQUEIDENTIFIER, ROWGUIDCOL) - jedinstveni ID
-- - file_stream (VARBINARY(MAX), FILESTREAM) - stvarni fajl
-- - name (NVARCHAR(255)) - ime fajla
-- - path_locator (HIERARCHYID) - pozicija u hijerarhiji
-- - parent_path_locator (HIERARCHYID) - parent folder
-- - file_type (NVARCHAR(255)) - ekstenzija fajla
-- - cached_file_size (BIGINT) - veličina fajla
-- - creation_time (DATETIME2) - vrijeme kreiranja
-- - last_write_time (DATETIME2) - vrijeme zadnje izmjene
-- - last_access_time (DATETIME2) - vrijeme zadnjeg pristupa
-- - is_directory (BIT) - da li je folder
-- - is_archive (BIT) - archive atribut
-- - is_hidden (BIT) - hidden atribut
-- - is_readonly (BIT) - read-only atribut
-- - is_offline (BIT) - offline atribut
-- - is_system (BIT) - system atribut
-- - is_temporary (BIT) - temporary atribut
Pristupanje FileTable-u
Nakon kreiranja FileTable-a, možete mu pristupiti na nekoliko načina:
-- Metoda 1: Kroz Windows Explorer
-- Putanja: \\ServerName\MyFileTableShare\DocumentStore\
-- Možete kopirati, brisati, i mijenjati fajlove direktno iz Windows-a
-- Metoda 2: Kroz T-SQL (kao običnu tabelu)
SELECT
name,
file_type,
cached_file_size,
creation_time,
file_stream
FROM Documents.DocumentStore
WHERE is_directory = 0; -- Samo fajlovi, ne folderi
GO
-- Metoda 3: Umetanje fajla kroz T-SQL
INSERT INTO Documents.DocumentStore (name, file_stream)
SELECT
'MyDocument.pdf',
BulkColumn
FROM OPENROWSET(BULK 'C:\Temp\MyDocument.pdf', SINGLE_BLOB) AS Document;
GO
-- Metoda 4: Kreiranje foldera
INSERT INTO Documents.DocumentStore (name, is_directory)
VALUES ('MyFolder', 1);
GO
Prednosti FileTable-a
- Windows integracija: Fajlovi su vidljivi kao obični Windows folderi
- Jednostavnost: Korisnici mogu raditi sa fajlovima bez znanja SQL-a
- Hijerarhija: Podrška za folder strukturu
- File attributes: Čuva Windows file attributes
- Transakcije: I dalje podržava SQL transakcije
Nedostaci FileTable-a
- Kompleksnost: Najkompleksnija opcija od tri
- Sigurnost: Zahtijeva pažljivo podešavanje Windows permisija
- Performanse: Može biti sporiji za neke operacije zbog Windows integracije
- Ograničenja: Neki SQL Server features ne rade sa FileTable-om
🔍 Full-Text Search (FTS): Lingvistička pretraga
Šta je Full-Text Search?
Standardni LIKE '%tekst%' operator je prespor jer ne koristi indekse i mora skenirati
svaki red u tabeli. Na milionima redova, ovo može trajati minute ili čak sate.
Full-Text Search (FTS) je napredna SQL Server tehnologija koja:
- Kreira poseban indeks koji razumije strukturu jezika
- Razumije morfologiju - pronalazi riječi u različitim oblicima (trčanje, trčao, trčati)
- Podržava više jezika - bosanski, hrvatski, srpski, engleski, itd.
- Razumije sinonime i povezane pojmove
- Rangira rezultate po relevantnosti
Kako Full-Text Search radi?
FTS koristi Full-Text Engine koji:
- Tokenizira tekst: Razbija tekst na riječi (tokens)
- Primjenjuje word breaker: Razumije granice riječi (npr. "SQL Server" = 2 riječi)
- Primjenjuje stemmer: Redukuje riječi na korijen (npr. "trčanje" → "trč")
- Kreira invertirani indeks: Mapira svaku riječ na redove gdje se pojavljuje
- Čuva pozicije: Zna gdje se riječ pojavljuje u dokumentu
Konfiguracija Full-Text Search-a
-- Korak 1: Kreirati Full-Text Catalog
-- Catalog je kontejner za Full-Text indekse
CREATE FULLTEXT CATALOG ft_ProductCatalog
WITH ACCENT_SENSITIVITY = ON
AS DEFAULT; -- Ovo čini katalog default-om za bazu
GO
-- ACCENT_SENSITIVITY = ON znači da razlikuje "č" od "c"
-- ACCENT_SENSITIVITY = OFF tretira "č" i "c" isto
-- Važno: Tabela MORA imati jedinstveni indeks (obično PRIMARY KEY)
-- Prije kreiranja Full-Text Index-a, provjerite da tabela ima unique index
-- Kreiranje Full-Text Index-a na koloni ReviewBody
CREATE FULLTEXT INDEX ON dbo.ProductReview (
ReviewBody LANGUAGE 'Bosnian' -- Specifikacija jezika
)
KEY INDEX PK_ProductReview -- Jedinstveni indeks na tabeli
ON ft_ProductCatalog -- Catalog gdje će se čuvati
WITH (
CHANGE_TRACKING AUTO, -- Automatsko praćenje promjena
STOPLIST = SYSTEM -- Koristi sistem stop listu (riječi koje se ignoriraju)
);
GO
-- LANGUAGE opcije:
-- 'Bosnian', 'Croatian', 'Serbian' - za našu regiju
-- 'English' - za engleski
-- 0 ili 'Neutral' - bez jezičke analize
-- CHANGE_TRACKING opcije:
-- AUTO - automatsko praćenje promjena (preporučeno)
-- MANUAL - ručno ažuriranje sa ALTER FULLTEXT INDEX ... START UPDATE POPULATION
-- OFF - bez praćenja promjena
Full-Text Search Funkcije
1. CONTAINS - Precizna pretraga
CONTAINS omogućava preciznu pretragu sa podrškom za:
- Riječi:
CONTAINS(column, 'riječ') - Fraze:
CONTAINS(column, '"tačna fraza"') - Wildcards:
CONTAINS(column, 'prog*')- naći će "program", "programiranje", itd. - Boolean operatore: AND, OR, NOT
- Blizina:
NEAR- pronalazi riječi blizu jedna drugoj
-- Pronalaženje riječi
SELECT Title, ReviewBody
FROM dbo.ProductReview
WHERE CONTAINS(ReviewBody, 'kvalitet');
GO
-- Pronalaženje tačne fraze
SELECT Title, ReviewBody
FROM dbo.ProductReview
WHERE CONTAINS(ReviewBody, '"odličan proizvod"');
GO
-- Boolean operatori (AND, OR, NOT)
SELECT Title, ReviewBody
FROM dbo.ProductReview
WHERE CONTAINS(ReviewBody, 'kvalitet AND cijena');
GO
SELECT Title, ReviewBody
FROM dbo.ProductReview
WHERE CONTAINS(ReviewBody, 'kvalitet OR performanse');
GO
SELECT Title, ReviewBody
FROM dbo.ProductReview
WHERE CONTAINS(ReviewBody, 'kvalitet AND NOT skup');
GO
-- Wildcard pretraga (mora biti na kraju)
SELECT Title, ReviewBody
FROM dbo.ProductReview
WHERE CONTAINS(ReviewBody, 'prog*'); -- Naći će "program", "programiranje", "programer"
GO
-- NEAR - pronalazi riječi blizu jedna drugoj
SELECT Title, ReviewBody
FROM dbo.ProductReview
WHERE CONTAINS(ReviewBody, 'NEAR((kvalitet, cijena), 5)');
-- Pronalazi redove gdje su "kvalitet" i "cijena" unutar 5 riječi jedna od druge
GO
-- Weighted pretraga (rangiranje)
SELECT
Title,
ReviewBody,
KEY_TBL.RANK AS RelevanceScore
FROM dbo.ProductReview
INNER JOIN CONTAINSTABLE(dbo.ProductReview, ReviewBody,
'ISABOUT(kvalitet WEIGHT(0.8), cijena WEIGHT(0.2))') AS KEY_TBL
ON dbo.ProductReview.ReviewID = KEY_TBL.[KEY]
ORDER BY KEY_TBL.RANK DESC;
GO
2. FREETEXT - Inteligentna pretraga
FREETEXT je "pametnija" pretraga koja:
- Razumije morfologiju: Ako tražite "trčanje", naći će i "trčao", "trčati", "trkač"
- Razumije sinonime: Ako tražite "auto", naći će i "automobil", "vozilo"
- Ignorira stop riječi: Ignoriše česte riječi kao "i", "ili", "je", "su"
- Rangira rezultate: Vraća rezultate sortirane po relevantnosti
-- Inteligentna pretraga - razumije različite oblike riječi
SELECT Title, ReviewBody
FROM dbo.ProductReview
WHERE FREETEXT(ReviewBody, 'trčanje');
-- Naći će: "trčanje", "trčao", "trčati", "trkač", itd.
GO
-- Pretraga sa više riječi
SELECT Title, ReviewBody
FROM dbo.ProductReview
WHERE FREETEXT(ReviewBody, 'kvalitet proizvoda i cijena');
-- FTS će razumjeti da tražite dokumente o kvalitetu, proizvodima i cijeni
GO
-- FREETEXT sa rangiranjem
SELECT
Title,
ReviewBody,
KEY_TBL.RANK AS RelevanceScore
FROM dbo.ProductReview
INNER JOIN FREETEXTTABLE(dbo.ProductReview, ReviewBody,
'kvalitet proizvoda i cijena') AS KEY_TBL
ON dbo.ProductReview.ReviewID = KEY_TBL.[KEY]
ORDER BY KEY_TBL.RANK DESC;
GO
CONTAINSTABLE i FREETEXTTABLE
Ove funkcije vraćaju tabelu sa rangiranim rezultatima, što omogućava:
- Rangiranje: Rezultati su sortirani po relevantnosti
- JOIN sa drugim tabelama: Možete join-ovati sa drugim tabelama
- Fleksibilnost: Više kontrolnih opcija
-- CONTAINSTABLE vraća tabelu sa KEY i RANK kolonama
SELECT
pr.ReviewID,
pr.Title,
pr.ReviewBody,
ct.RANK AS RelevanceScore
FROM dbo.ProductReview pr
INNER JOIN CONTAINSTABLE(dbo.ProductReview, ReviewBody,
'kvalitet AND cijena', 10) AS ct -- Top 10 rezultata
ON pr.ReviewID = ct.[KEY]
ORDER BY ct.RANK DESC;
GO
-- Napredna pretraga sa više kolona
SELECT
pr.ReviewID,
pr.Title,
pr.ReviewBody,
ct.RANK
FROM dbo.ProductReview pr
INNER JOIN CONTAINSTABLE(dbo.ProductReview,
(Title, ReviewBody), -- Pretraga u više kolona
'kvalitet', 20) AS ct
ON pr.ReviewID = ct.[KEY]
WHERE ct.RANK > 50 -- Samo relevantni rezultati
ORDER BY ct.RANK DESC;
GO
Stop Liste (Stopwords)
Stop liste su liste riječi koje se ignoriraju tokom Full-Text pretrage jer su previše česte i ne nose značenje. Primjeri: "i", "ili", "je", "su", "na", "u", itd.
-- Kreiranje custom stop liste
CREATE FULLTEXT STOPLIST MyCustomStoplist;
GO
-- Dodavanje riječi u stop listu
ALTER FULLTEXT STOPLIST MyCustomStoplist
ADD 'riječ1' LANGUAGE 'Bosnian';
ALTER FULLTEXT STOPLIST MyCustomStoplist
ADD 'riječ2' LANGUAGE 'Bosnian';
GO
-- Korištenje custom stop liste u Full-Text Index-u
ALTER FULLTEXT INDEX ON dbo.ProductReview
SET STOPLIST MyCustomStoplist;
GO
-- Vraćanje na sistem stop listu
ALTER FULLTEXT INDEX ON dbo.ProductReview
SET STOPLIST SYSTEM;
GO
💡 Best Practices za Full-Text Search
- Ispravan jezik: Uvijek specificirajte jezik u Full-Text Index-u za bolje rezultate
- CHANGE_TRACKING AUTO: Koristite AUTO za automatsko ažuriranje indeksa
- Stop liste: Koristite stop liste za bolje performanse
- Kombinacija sa WHERE: Kombinujte FTS sa običnim WHERE klauzulama za bolje performanse
- Rangiranje: Koristite CONTAINSTABLE/FREETEXTTABLE za rangirane rezultate
🎯 Praktične Vježbe
Vježba 1: Full-Text Search Engine za Recenzije Proizvoda
Imate tabelu ProductReview sa hiljadama dugih recenzija. Korisnici žele
brzo pretraživati recenzije po ključnim riječima sa podrškom za morfološku pretragu.
Korak 1: Kreirajte tabelu za recenzije i Full-Text Catalog.
-- Kreirati tabelu za recenzije
CREATE TABLE dbo.ProductReview (
ReviewID INT IDENTITY(1,1) PRIMARY KEY,
ProductID INT NOT NULL,
CustomerName NVARCHAR(100),
ReviewTitle NVARCHAR(200),
ReviewBody NVARCHAR(MAX) NOT NULL, -- Kolona za Full-Text Search
Rating INT CHECK (Rating BETWEEN 1 AND 5),
ReviewDate DATETIME2 DEFAULT SYSDATETIME(),
IsVerified BIT DEFAULT 0
);
GO
-- Kreirati Full-Text Catalog
CREATE FULLTEXT CATALOG ft_ProductCatalog
WITH ACCENT_SENSITIVITY = ON
AS DEFAULT;
GO
Korak 2: Kreirajte Full-Text Index nad kolonom ReviewBody.
-- Kreirati Full-Text Index
CREATE FULLTEXT INDEX ON dbo.ProductReview (
ReviewBody LANGUAGE 'Bosnian'
)
KEY INDEX PK__ProductReview__ReviewID
ON ft_ProductCatalog
WITH (
CHANGE_TRACKING AUTO,
STOPLIST = SYSTEM
);
GO
-- Provjera statusa Full-Text Index-a
SELECT
OBJECT_NAME(object_id) AS TableName,
fulltext_catalog_id,
is_enabled,
change_tracking_state_desc
FROM sys.fulltext_indexes;
GO
Korak 3: Umetnite test podatke i testirajte različite tipove pretrage.
-- Umetanje test podataka
INSERT INTO dbo.ProductReview (ProductID, CustomerName, ReviewTitle, ReviewBody, Rating)
VALUES
(1, 'Amar Selimović', 'Odličan proizvod',
'Ovaj proizvod ima izuzetan kvalitet. Cijena je pristupačna i vrijedi svake marke. Preporučujem svima!', 5),
(1, 'Lejla Hasanović', 'Zadovoljna sam',
'Kvalitet proizvoda je na visokom nivou. Brza dostava i dobra komunikacija sa prodavcem.', 4),
(2, 'Emir Kovačević', 'Može bolje',
'Proizvod je dobar, ali cijena je previsoka za ono što dobijate. Performanse su solidne.', 3);
GO
-- Čekati da se Full-Text Index popuni
WAITFOR DELAY '00:00:05';
GO
-- Test 1: CONTAINS pretraga
SELECT ReviewTitle, ReviewBody, Rating
FROM dbo.ProductReview
WHERE CONTAINS(ReviewBody, 'kvalitet');
GO
-- Test 2: FREETEXT pretraga (razumije različite oblike)
SELECT ReviewTitle, ReviewBody, Rating
FROM dbo.ProductReview
WHERE FREETEXT(ReviewBody, 'kvalitet');
GO
-- Test 3: Rangirana pretraga
SELECT
pr.ReviewID,
pr.ReviewTitle,
pr.ReviewBody,
pr.Rating,
ct.RANK AS RelevanceScore
FROM dbo.ProductReview pr
INNER JOIN CONTAINSTABLE(dbo.ProductReview, ReviewBody,
'kvalitet AND cijena', 10) AS ct
ON pr.ReviewID = ct.[KEY]
ORDER BY ct.RANK DESC;
GO
Vježba 2: FILESTREAM Sistem za Dokumente
Kreirajte kompletan sistem za upravljanje dokumentima koji koristi FILESTREAM za čuvanje PDF, Word i Excel fajlova.
-- 1. Omogućiti FILESTREAM
EXEC sp_configure filestream_access_level, 2;
RECONFIGURE;
GO
-- 2. Kreirati bazu sa FILESTREAM filegroup-om
CREATE DATABASE DocumentManagement;
GO
USE DocumentManagement;
GO
ALTER DATABASE DocumentManagement
ADD FILEGROUP DocumentFileStreamFG CONTAINS FILESTREAM;
GO
ALTER DATABASE DocumentManagement
ADD FILE (
NAME = 'DocumentFileStreamData',
FILENAME = 'C:\SQLData\DocumentFileStream'
)
TO FILEGROUP DocumentFileStreamFG;
GO
-- 3. Kreirati tabelu sa FILESTREAM kolonom
CREATE SCHEMA Documents;
GO
CREATE TABLE Documents.DocumentStore (
DocumentID UNIQUEIDENTIFIER ROWGUIDCOL PRIMARY KEY DEFAULT NEWID(),
DocumentNumber NVARCHAR(50) UNIQUE NOT NULL,
Title NVARCHAR(200) NOT NULL,
DocumentContent VARBINARY(MAX) FILESTREAM NULL,
FileName NVARCHAR(255) NOT NULL,
FileExtension NVARCHAR(10),
FileSize BIGINT,
CreatedDate DATETIME2 DEFAULT SYSDATETIME(),
CreatedBy NVARCHAR(100)
);
GO
-- 4. Umetanje dokumenta
INSERT INTO Documents.DocumentStore (
DocumentNumber, Title, DocumentContent, FileName, FileExtension, FileSize, CreatedBy
)
SELECT
'DOC-2024-001',
'Ugovor o radu',
BulkColumn,
'Contract_2024_001.pdf',
'PDF',
DATALENGTH(BulkColumn),
'admin'
FROM OPENROWSET(BULK 'C:\Documents\Contract.pdf', SINGLE_BLOB) AS Document;
GO
✅ Zaključak Modula 4
Završili smo specijalizovano skladištenje. Vaša baza sada može čuvati sve:
- ✅ In-Memory za brzine mjerene u mikro-sekundama.
- ✅ XML za kompleksne hijerarhije i šeme.
- ✅ Spatial za geografske i GIS aplikacije.
- ✅ FILESTREAM i FTS za sisteme upravljanja dokumentima (DMS).
📚 Modul 5: Konkurentnost i Sigurnost
U sljedećem modulu prelazimo na kritične operacije. Naučićete kako rješavati Deadlock situacije, koristiti Always Encrypted za zaštitu podataka i podesiti Audit za potpuni mir.