ASP.NET pro zaΦßteΦnφky
9. PokroΦilΘ databßze
MENU
Ulo₧enΘ procedury

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:

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.

StruΦn² p°ehled syntaxe T-SQL

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ßzky ulo₧en²ch procedur

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.

P°φstup k ulo₧en²m procedurßm z ASP.NET

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
Transakce

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.

DataGrid

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:

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Θ.

Diskusnφ f≤rum

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φ.

Zßv∞rem

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.

LukßÜ Lßnsk²
VeÜkerΘ nßm∞ty, dotazy a p°ipomφnky piÜte na adresu lansky@czech-ware.net.