S databßzφ zatφm komunikujeme p°es SQL p°φkazy stylem "Dej mi ty a ty data" - "Tady jsou". Mezi po₧adavky kladen²mi na databßzov² systΘm vÜak pat°φ takΘ vysokß rychlost provßd∞nφ dotaz∙, kterß je dosahovßna vhodnou indexacφ dat a dalÜφmi mechanismy. P°esto by mo₧nß bylo vhodnΘ, aby se databßze mohla n∞jak p°ipravit na monot≤nnφ po₧adavky na nφ kladenΘ.
Ulo₧enΘ procedury nßm umo₧≥ujφ programovat sled dotaz∙ p°φmo v SQL serveru. Vzpomφnßte-li si na dßvkovΘ soubory v prost°edφ MS-DOS (*.bat), naleznete jistou paralelu, p°esto₧e jsou tyto proceduru o n∞co slo₧it∞jÜφ. Majφ n∞kolik v²hod:
- Rychlost jejich provßd∞nφ je vysokß. Databßze znß celou posloupnost p°φkaz∙ a m∙₧e vytvo°it tzv. plßn provßd∞nφ, kter² zajistφ vyÜÜφ efektivitu prßce s nφ.
- Odd∞luje k≤d pro prßci s daty. V²slednΘ zdrojovΘ texty jsou p°ehledn∞jÜφ, nebo¥ v ASP.NET nßm staΦφ zavolat danou proceduru s v²sti₧n²m nßzvem. Zßrove≥ je pak snazÜφ prßce vφce programßtor∙.
Jak² programovacφ jazyk je pou₧φvßn pro zadßvßnφ ulo₧en²ch procedur? Jak v kterΘm systΘmu. V∞tÜinou jde o SQL + dalÜφ jazyk. V novΘ verzi MS SQL Serveru (codename Yukon) bude mo₧nΘ vytvß°et ulo₧enΘ proceduru v jazyku b∞₧φzφm v CLR (tedy VB.NET, C#...), zatφm se musφme smφ°it se stßvajφcφm prost°edkem zvan²m T-SQL.
Chceme-li vytvo°it ulo₧enou proceduru, musφme nejd°φve spustit n∞jakΘ administraΦnφ rozhranφ databßze, v naÜem p°φpad∞ p∙jde o WebMatrix. Spustφme ho a ve stromovΘ struktu°e na kart∞ Data otev°eme naÜi databßzi a klikneme na pole Stored Procedures. Zatφm jsme ₧ßdnou nevytvo°ili, avÜak m∙₧eme kliknutφm na ikonku Add Database Object vytvo°it novou - po zadßnφ jejφho jmΘna se objevφ editaΦnφ okno pro zadßnφ T-SQL programu.
Tento jazyk nenφ case-senstive - podobn∞ jako ve VB.NET nezßvisφ na velikosti pou₧it²ch znak∙. Stejn∞ tak nenφ t°eba ukonΦovat p°φkazy jak²mkoliv znakem.
Je mo₧nΘ voln∞ pou₧φvat obyΦejnΘ p°φkazy jazyka SQL. SELECT, INSERT atp.
Na zaΦßtku deklarace uvedeme klauzuli "CREATE PROCEDURE" nßsledovanou jmΘnem novΘ procedury. Nßsleduje seznam vstup∙ ve tvaru @prom∞nnß typ, @dalÜφProm∞nnß typ, atd. Aby procedura mohla vracet data, m∙₧eme u jednΘ z prom∞nn²ch po urΦenφ datovΘho typu uvΘst slovo OUTPUT. Nßsleduje sl∙vku AS a vlastnφ t∞lo procedury.
Deklaraci prom∞nn²ch v dalÜφm toku provßdφme p°φkazem DECLARE, po nφ₧ uvedeme nßzev prom∞nnΘ (musφ zaΦφnat znakem '@') a jejφ typ. Mezi zßkladnφ pat°φ INT a CHAR. Vφce prom∞nn²ch m∙₧eme deklarovat jedin²m pou₧itφm tohoto p°φkazu, pokud je odd∞lφme Φßrkou (a p°idßme jejich typ).
K p°i°azenφ hodnoty do prom∞nnΘ nestaΦφ uvΘst nßzev prom∞nnΘ = novß hodnota, ale p°ed tφm jeÜt∞ klφΦovΘ slovo SET.
GOTO je muzeßlnφ p°φkaz, kter² se v minulosti hojn∞ pou₧φval ke skok∙m v programu. Proto₧e nenφ T-SQL pou₧φvßn k slo₧it∞jÜφm algoritm∙m, tak se obΦas hodφ. Vy₧aduje jeden parametr, kter² udßvß nßv∞stφ. To musφ b²t uvedeno na jinΘm mφst∞ v k≤du nßsledovßno dvojteΦkou. Po zavolßnφ p°φkazu GOTO se zaΦne zpracovßvat k≤d uveden² za znaΦkou nßv∞stφ.
P°φkaz IF mß standardnφ syntaxi - po klφΦovΘm slov∞ if zadßme podmφnku standardnφho formßtu nßslednovanou k≤dem, kter² se mß vykonat v p°φpad∞ spln∞nφ, dßle p°φpadn∞ slovem ELSE se z°ejm²m v²znamem.
Blok p°φkaz∙ se uvozuje klφΦov²mi slovy BEGIN a END. Poka₧dΘ, kdy chceme na zßklad∞ vyhodnocenφ podmφnky vykonat vφce p°φkaz∙, musφme uvΘst i tato slova.
Cyklus WHILE zde najdeme op∞t ve z°ejmΘ syntaxi - WHILE podmφnka blokP°φkaz∙. Dokud platφ podmφnka, budou se p°φkazy provßd∞t. VyskoΦit z cyklu WHILE (a vlastn∞ i z jakΘhokoliv bloku uvozenΘho p°φkazy BEGIN a END) je mo₧nΘ pomocφ slova BREAK.
Ukß₧eme si primitivnφ ulo₧enou proceduru, je₧ bude vracet mail v tabulce Auto°i na zßklad∞ jmΘna na vstupu.
CREATE PROCEDURE mailUzivatele @jmeno varchar, @mail varchar OUTPUT AS SELECT @jmeno = jmeno FROM Autori WHERE mail = @mail
Procedura, kterß vlo₧φ do databßze p∞t stejn²ch zßznam∙:
CREATE PROCEDURE plnitel AS DECLARE @i int SET @i = 0 WHILE @i < 5 BEGIN SET @i = @i + 1 INSERT INTO Autori (Jmeno, Mail) VALUES ('TomᚠSrb', 'tomas.srb@kdjkaf.cz') END
T-SQL nabφzφ pom∞rn∞ hodn∞ mo₧nostφ - p∞kn² serißl o tΘto technologii se jmenuje T-SQL Programming.
Tak₧e proceduru umφme vytvo°it. Jak jφ vÜak zavolßme a p°edßme hodnoty z naÜφ webovΘ aplikace? Op∞t velice jednoduÜe - staΦφ ji zavolat jako jin² SQL p°φkaz. Musφme ovÜem nastavit parametr objektu SqlCommand CommandType na CommandType.StoredProcedure. StruΦn² p°φklad:
Dim conn As SqlConnection(connString) Dim comm As SqlCommand = New SqlCommand("mailUzivatele 'TomᚠSrb'", conn) comm.CommandType = CommandType.StoredProcedure
DalÜφ velmi rozÜφ°enou vymo₧enostφ modernφch databßzφ jsou tzv. transakce. P°edstavte si situaci, kdy pot°ebujete zabezpeΦit, aby dv∞ zm∞ny v databßzi zaruΦen∞ ob∞ prob∞hly nebo p°i nejhorÜφm byly ob∞ odmφtnuty. Nesmφ nastat situace, aby se jedna z nich provedla a druhß nap°φklad kv∙li pßdu serveru ne, nebo¥ by to mohlo ohrozit vaÜi pracn∞ budovanou strukturu databßze.
K tomu slou₧φ transakce. Dovolujφ jistou sadu operacφ provΘst zßrove≥ a pokud se n∞jakß z nich nezda°φ, vrßtφ data do p∙vodnφho stavu. Implementace v ASP.NET je v∞cφ okam₧iku, prostudujte si tento zdrojov² k≤d:
Dim conn As SqlConnection(connString) conn.Open() Dim tran As SqlTransaction = conn.BeginTransaction() try Dim comm As SqlCommand = New SqlCommand("INSERT INTO Autori (Jmeno, Mail) VALUES ('TomᚠSrb','tomas.srb@kdjkaf.cz')", conn, tran) comm.ExecuteNonQuery() comm.CommandText = "DELETE FROM Autori WHERE Jmeno = 'Tomas Srb'" comm.ExecuteNonQuery() tran.Commit() catch tran.RollBack() end try
Zavedli jsme nov² objekt SqlTransaction, kter² zφskßme z objektu SqlConnection metodou BeginTransaction. Mß dv∞ d∙le₧itΘ metody - Commit potvrdφ ·pravy databßze, zatφmco RollBack je zamφtne.
V minulΘm dφle jsme se dostali jenom k serverovΘmu ovlßdacφmu prvku jmΘnem DataList. To vÜak nenφ vÜe - do sbφrky nßm chybφ ten nejmocn∞jÜφ, DataGrid, kter² nabφzφ dalÜφ mo₧nosti.
Z nßzvu tohoto prvku vypl²vß, ₧e se bude standardn∞ zobrazovat jako tabulka, m°φ₧ka. Pokud svß₧eme tento prvek s objektem DataTable, nemusφme prakticky nic psßt a tabulka bude zobrazena automaticky. M∙₧eme ovÜem ruΦn∞ definovat, kterΘ sloupce chceme nechat zobrazit a jak²m zp∙sobem. Zp∙sob zobrazenφ m∙₧e b²t jeden z t∞chto:
- BoundColumn je klasickΘ zobrazenφ obyΦejn²m v²pisem obsahu pole.
- ButtonColumn umφstφ do polφΦka tlaΦφtko s popiskem dan²m obsahem bu≥ky, akci po kliknutφ lze definovat pomocφ atributu CommandName.
- EditCommandColumn vlo₧φ prvek INPUT TYPE="text", kter² umo₧nφ modifikaci obsahu.
- HyperLinkColumn zobrazφ odkaz s popiskem dan²m obsahem a cφlem dle atributu NavigateUrl.
- KoneΦn∞ TemplateColumn nechßvß pln∞ na programßtorovi aplikace chovßnφ v²slednΘho prvku - je mo₧nΘ definovat Üablonu.
SchΘma takovΘ aplikace pak m∙₧e vypadat takto:
<%@ Page Language="VB" Debug="true" %> <%@ Import Namespace="System.Data" %> <%@ Import Namespace="System.Data.SqlClient" %> <script runat="server"> Sub Page_Load() Dim conn As SqlConnection = new SqlConnection("Data source=lanska;initial catalog=chip;user id=sa;password=modinumeriordines") conn.Open() Dim adap As SqlDataAdapter = new SqlDataAdapter("SELECT * FROM autori ORDER BY id", conn) Dim ds As DataSet = new DataSet() adap.Fill(ds, "autori") DaGr.DataSource = ds.Tables("autori") DataBind() End Sub Sub DaGr_Delete(obj As Object, e As DataGridCommandEventArgs) DaGr.DataBind() End Sub Sub DaGr_Edit(obj As Object, e As DataGridCommandEventArgs) DaGr.EditItemIndex = e.Item.ItemIndex DaGr.DataBind() End Sub Sub DaGr_Cancel(obj As Object, e As DataGridCommandEventArgs) DaGr.EditItemIndex = -1 DaGr.DataBind() End Sub Sub DaGr_Update(obj As Object, e As DataGridCommandEventArgs) DaGr.EditItemIndex = -1 DaGr.DataBind() End Sub </script> <form runat="server"> <asp:DataGrid id="DaGr" runat="server" width="760" AutoGenerateColumns="false" OnDeleteCommand="DaGr_Delete" OnEditCommand="DaGr_Edit" OnCancelCommand="DaGr_Cancel" OnUpdateCommand="DaGr_Update" > <Columns> <asp:BoundColumn HeaderText="ID" DataField="id" /> <asp:BoundColumn HeaderText="JmΘno autora" DataField="jmeno" /> <asp:BoundColumn HeaderText="Mailovß adresa" DataField="mail" /> <asp:ButtonColumn HeaderText="Smazat" Text="Sma₧" CommandName="delete" /> <asp:EditCommandColumn EditText="Edit" CancelText="Storno" UpdateText="Aktualizace" HeaderText="Edit" /> </Columns> </asp:DataGrid> </form>
Ke sprßvnΘ funkci je t°eba umφstit do ubsluh udßlostφ k≤d, kter² zajistφ vlastnφ akci. Tak₧e jde v∞tÜinou o dotaz SQL nebo zßpis do XML souboru. K≤d je pak ale velmi dlouh² a stejn∞ bych pouze opisoval p°φklad z MSDN, kter² vÜe podstatnΘ vysv∞tluje.
JeÜt∞ jedna poznßmka - parametr AutoGenerateColumn zajiÜ¥uje automatickΘ vygenerovßnφ sloupeΦku s obsahem. Pokud bysme uvedli true v naÜem p°φpad∞, sloupce by se p°ipojily za nßmi nadefinovanΘ.
Na dneÜnφ dφl jsem vßm sliboval vytvo°enφ diskusnφho f≤ra. Tomuto slibu bohu₧el nedostojφm, nebo¥ bych rßd poΦkal na zvlßdnutφ technologie XML, kterß nßm umo₧nφ za°adit mezi schopnosti tohoto nßstroje pro mezilidskou komunikaci nap°φklad RSS. Rßd bych v∞noval tomuto f≤ru cel² dvanßct² dφl, nebo¥ bude zahrnovat praktickΘ vyu₧itφ vÜech zatφm nauΦen²ch dovednostφ.
P°φÜt∞ se podφvßme na formßt XML, kter² je poslednφ dobou ve velkΘ oblib∞ mnoha programßtor∙. .NET pro n∞j poskytuje skv∞lou podporu, tak₧e se m∙₧ete t∞Üit na XPath dotazy a XSLT transformace.
VeÜkerΘ nßm∞ty, dotazy a p°ipomφnky piÜte na adresu lansky@czech-ware.net.