VERİ TABANI KURTARMA İŞLEMLERİ
Bir şirket içinde bulunan veri tabanına ait veriler fonksiyonelliğini kaybedebilirler.
Bu gibi durumlarda büyük sorunlar yaşamamak için birinci altın; kural mutlaka yedekli
olarak çalışmaktır.
İşte bu konumuzda bunun nasıl yapılacağını ve kullanabileceğimiz diğer
yöntemleri inceleyeceğiz.
DA TABASE SNAPSHOTS:
Database Snapshots ile veri tabanının sağlam ve read-only(sadece okunabilir)
bir görünümünü oluşturarak, sistem yöneticilerinin kullanımına sunabiliriz.
Veri tabanının bir andaki görünümünü içeren bu yapıyı test amaçlı veya basit
raporlama için tercih edebiliriz.
Komple bir veri tabanının kopyasını almak yerine, fiziksel disk alanının üzerinde
NTFS dosya sisteminde kısımsal olarak tutabiliriz. Bunun için kaynak veri tabanında
bir değişikliğin olması gerekmektedir.
Hızlı kurtarma sağladığı için tercih edebileceğimiz bir yöntem olabilir.
DATABASE SNAPSHOTS YÖNETİMİ:
Database Snapshots oluşturmak için CREATE DATABASE ifadesi ile beraber
AS SNAPSHOT cümleciğini kullanabiliriz.
Snapshot mutlaka aynı SQL Server instance üzerinde kaynak veri tabanı gibi
oluşturulmalıdır ve oluşturulacak dosyanın bulunacağı hedef klasör mutlaka olmadır.
Ayrıca ON ifadesi her veri dosyası için bir dosya içermelidir. SİZE, MAXSIZE ve
FILEGROVVTH parametrelerini kullanmamak gerekir. NTFS olmasına dikkat edelim. Aşağıdaki örnek ile NTFS dosya sistemine sahip F sürücüsü içinde daha önce
var olan snap isimli klasörün içinde burak isimli veri tabanımın SNAPSHOT dosyasını oluşturuyorum.
F sürücüsünü açarak, snap klasörünün içini kontrol edebiliriz.
Oluşturulan snapshot o anki zamana ait veri tabanı bilgileri içerdiği için, SQL
Server Agent kullanılarak istenilen bir zamana ait snapshot bilgisi otomatik olarak
depolanabilir. Ayrıca bir veri tabanı için birden fazla snapshot bilgisi olabileceğinden
verdiğiniz isim; bu zamanı temsil etmelidir ki şaşırmayın.
Bir veri tabanında eğer çok fazla değişiklik oluyorsa snapshot dosyası çok
genişleyebilir. Eğer bir zamanlama ile oluşumu otomatikleştirmiş iseniz zamanlama
işi olarak eski snapshot sürümlerinin silinmesini ayarlamanız gerekmektedir.
Not: Bir veri tabanı snapshot yapısı için kaynak veri tabanlarını bulmak,
sorgulamak amaçlı sys.databases içinden source_database_id sütununu
kullanabilirsiniz
Oluşturulan bir snapshot yapısını kullanmak için;
1) Aşağıdaki yazılım prestige tablosu içindeki tüm kayıtları listelemek için
kullanılır.
Aynı şekilde Object Explorer kullanılarak da görüntüleme yapılabilir. Bunun
için Databasesklasörü altında bulunan Database Snapshots klasörünü açmak
yeterlidir.
2) Bu snapshot yapısında hiçbir değişiklik ve yeni kayıt ekleme
yapamazsınız. Ancak orijinal veri tabanında yeni kayıt eklediğiniz ve
boyuta etki eden değişiklik yaptığınız zaman bu, snapshot dosyasına
yansır.
3) Silmek için ise DROP DATABASE snapsot_adı ifadesi kullanılır.
Ancak silme yapabilmek için veri tabanının aktif olmaması gerekir
Ayrıca master, model veya tempdb verh tabanlarının snapshot'u alınamaz.
Yedekleme- Geri yükleme (Backup^ Restore), İliştirme- İlişiği sökme (Attach-
Deattach) işlemleri yapılamaz. Orijinal veri tabanı silinmeden önce mutlaka
snapshot silinmelidir.
DATABASE SNAPSHOT ile VERİKURTARMA:
Her ne kadar Backup- Restore mekanizması kadar güçlü bir veri kurtarma
yöntemi olmasa da , yine de veri kurtarmada kullanabileceğimiz yöntemlerden
biridir. Ancak siz Backup- Restore mekanizmasından bu yönteme güvenerek
kesinlikle vazgeçmeyin.
Bir veri tabanı dosyasının silinmesi, bir satırda meydana gelen silinme, hata,
değişiklik gibi olaylarda Backup-Restore mekanizmasına göre daha hızlı olduğu
için bu yöntemi tercih edebilirsiniz.
Bunu, bir senaryo üzerinde göstermeye çalışalım;
1) İlk olarak aşağıdaki komutla, orijinal tablomuz içindeki tüm kayıtları silelim.
2) Ardından snapshot içinde bulunan aynı tablodan tüm kayıtları
kurtararak, tekrar ana tablomuzu eski haline getirelim.
3) Ana tablomuz içindeki kayıtların kurtulduğunu, aşağıdaki ifade ile görebiliriz.
BACKUP-RESTORE (YEDFKLEME- GERİ YÜKLEME):
Veri tabanı üzerinde gerekli kurtarmaları yapmak için, bir veri taba.ni
yöneticisinin temel olarak kullanacağı strateji Backup- Restore olmalıdır. Bu kısımda
bu yapıyı detaylı olarak inceleyeceğiz.
BACKUP(YEDEKLEME):
SQL Server 2008 içinde çeşitli yedekleme seçenekleri vardır.
Bunlar;
*** Full: Veri tabanı içinde bulunan veri dosyalarının tamamının yedeğini alır.
Ayrıca Transaction log dosya kısmının yedeğini alır.
*** Differential: En son Full Backup alınan yerden itibaren değişikliğe uğrayan
verilerin yedeğini alır.
*** Partial: Full Backup gibidir. Ancak Tüm dosya gruplarını içermez.
"* Transaction Log: Veri tabanı içinde oluşan herhangi bir değişikliği
kaydeder.
*** Tail-Log: Geri yükleme(Restore) yapmadan önce alınması gereken bir
uzantı log yedeklemesidir.
*** File/ FileGroup: Bir veri tabanı içindeki belli bir dosya veya dosya grubunun
yedeklemesi için kullanılır.
"* Copy-only: Diğer yedeklemeler gibi değildir. Veri tabanı ve log bilgilerini
barındırır.
Üç tane de kurtarma modeli vardır;
*** Simple: Küçük veri tabanları için tercih edilir.
*** Full: Tam kurtarma modelidir.
*** Bulk-Logged: Veri tabanını yeniden oluşturmak için veri tabanı ve log
yedeklerini kullanır.
SQL Server 2005'den itibaren BACKUP yapısında çeşitli değişiklikler gelmiştir.
Eski sürümlerde olan BACKUP LOG WITH NO_LOG ve BACKUP LOG WITH
TRUNCATE_ONLY seçeneklerine destek vermemektedir.
Aşağıdaki ifade ile veri tabanı bütünlüğünü kontrol edebiliriz.
Basit olarak veri tabanını ve log dosyasını yedeklemek için kullanılan Full
Backup yazılımını verecek olursak;
İlk ifade veri tabanını, ikinci ifade ise log dosyasını yedekler.
Aşağıdaki yazılım burak isimli veri tabanının C: sürücüsünde yedek isimli
klasöre burakk.bkf adıyla yedeklemesini gösterir. Burada yedekleme_aygıtı olarak
fiziksel bir disk yeri belirledik. Ancak bu bir medya aygıtı da olabilir.O zaman Disk
ifadesini kullanmadan bu aygıtın ismini yazmak gerekir.
En son Full yedek aldıktan sonra sadece değişenleri yedeklemek için ise aşağıdaki ifade kullanılır.
Log yapılarını yedeklemek için ise aşağıdaki ifadeden yararlanılır;
Aynı işlemleri Object Explorer içinden yapmak için ise;
1) Yedeği alınacak veri tabanı üzerinde sağ tuşa basılarak gelen listeden
Tasks/ Back Up seçeneğine tıklanır.
2) Gelen yedekleme iletişim kutusundan gerekli ayarlamalar ve yedekleme aygıtı belirtilerek yedek alınır. Kısımsal yedekleme yapılarak süre kısaltılabilir.
READ_WRITE_FILEGROUPS seçeneği ile bu sağlanabilir.
Diğer bir özellik ise COPY-ONLY cümleciğidir. Bu cümlecikle alınan yedekleme,
genelde test gibi özel amaçlı yedeklemedir. Burada Full, differential ve
transaction log gibi normal sıra düzenlemesine izin vermez.
Buraya kadar aldığımız tüm yedekler, klasörün içinde şekildeki gibi görünecektir.
RESTORE (GERİ YÜKLEME)
Muhtemel geri yükleme aşağıdaki adımları içerir;
Data Copy: Bu adımda tüm veri, log ve index sayfaları yedek setinden
yüklenir.
Redo(Roll Forward): Yedek setinden Logged transaction
uygulamasını gerçekleştirir.
Undo(Roll Back): Uncommitted transaction verilerinde kullanılır.
SQL Server 2005' den itibaren Online Restore işlemi yapılabilmektedir. Online
Restore işlemi herhangi bir kullanıcı hareketine ihtiyaç duymadan, otomatik olarak
gerçekleşir.
Ayrıca daha önceden de belirttiğimiz gibi snapshot yapısından kurtarma
yapılabilir.
Eski versiyonda olduğu gibi RESTORE ifadesi ile yedeklenen bilgiler geri
yüklenebilir. Yeni özelliklerinden birisi RESTRICTEDJJSER seçeneğidir. Bu
seçenekle geri yükleme sadece db_ower, dbcreator ve sysadmin rolleri ile
gerçekleşebilir. SQL Server 2000 yapısında bu seçeneğin yerine DBO_ONLY ifadesi
kullanılmaktaydı.
Geri yükleme işlemi sadece eski versiyonlardan SQL Server 7.0 ve SQL
Server 2000'den yapılabilir. Daha eski yedek setlerine destek vermez.
Not1: Eğer bir veri tabanının snapshot'u varsa geri yükleme işlemi çalışmaz.
Bunun için ilk olarak bu veri tabanına ait snapshot silinmeli ardından geri yükleme
işlemi gerçekleştirilmelidir.
Ayrıca geri yükleme yapılırken master veri tabanı aktif olmamalıdır.
Not2: Bu kısımda değineceğimiz yedekleme Offline olarak çalışmaktadır.
Online geri yükleme çeşidi de yeni bir özellik olup sadece SQL Server 2005
Enterprise Edition sürümünde çalışır. Tabiki yedeklemenin de bu sürümde
yapılması gerekir. Zamandan kazanma temel prensibidir.
Management Studio kullanılarak geri yükleme işlemi gerçekleştirilebilir.
CHECKSUM:
Backup- Restore stratejisini tercih ettiğinizde herşey güllük güllüstanlık
olmayabilir© Örneğin; yedekleme aygıtında olabilecek bir hata geri yüklemede
sorunlara yol açabilir.
İşte bu hatalarda kullanabileceğimiz ifadelerden biri CHECKSUM ifadesidir. Bu
ifade ile yedekleme aygıtına yazılmadan tüm veriler kontrol edilir ve ondan sonra
yazılır. Bu da geçerli verinin yedek setine yazılmasını sağlar.
MIRROR:
Eğer verileriniz çok önemli ise biraz daha maliyetli bir işlem
gerçekleştirebilirsiniz. Bunun için kullanacağınız MIRROR ifadesi ile yedeğini bir
kopyasını da almış olursunuz. Eğer bu ifade ile yedek alacaksanız mutlaka WITH
FORMAT cümleciğini eklemeniz gerekir.
Ben aynı yere farklı isimler ile yedekledim. Ama gerçeğinde farklı ortamlarda
olması gerekir ki işe yarasın.
Ayrıca bir disk alanını sanki bir tape aygıtı gibi algılatabiliriz. Bunun yazılımı ve
kullanımı aşağıdaki gibidir.
.NET CLR
NET CLR VE SOL SERVER:
SQL Server 2008 içindeki veri tabanı objelerini yönetmek için .NET
CLR(Common Language Runtime) ile yazılmış program kodları kullanılabilir.
Böylelikle .NET Framework yapısı, veri tabaınna güçlü, sağlam ve daha güvenli özellikler kazandırmış olur.
Runtimes yeni bir program değildir. Bir çok program dili Runtimes kullanır. Örneğin; Microsoft Visual Basic, Visual C# ve Jscript gibi. Ayrıca ilaveten SmallTalk, Perl ve Java gibi üçüncü yazılım dillerini de destekler.
Burada .NET Framevvork yapısının rolü oldukça kritik ve önemlidir. Çünkü diğer Runtimes yapılarından, tüm programlama dillerinde ortak bileşenleri kullandığı için ayrılır.
Bünyesinde bulunan bir bileşen çalışırken CLR; hafıza yönetimi, işlemlerin başlaması ve durdurulması, güvenlik ayarları ve diğer komponentlerle olan ilişkilerinden sorumludur. Bunları hep kontrol eder.
Ayrıca SQL Server içine CLR yapısının direkt dahil edilmesi sağlanabilir. Çağrılan kütüphaneler yardımı ile gerekli kodlar uygulanır. Bu bir stored procedure çağırmak gibi oldukça basit bir olaydır. Ancak geleneksel stored procedure yapısından çok daha güçlü ve sağlamdır.
Buraya CLR yapısından kod çağırma ve kullanma olayına assembly denir. Karmaşık programlama durumlarında .NET Framework'ün içinde bulunan bir kütüphaneyi kullanmak ihtiyacı duyduğumuzda ve işlemciyi (CPU) daha performanslı kullanmak istediğimizde tercih edeceğimiz bir yöntemdir.
CREATE ASSEMBLY:
Assembly kodları ile SQL Server 2008 içinde çalışmak için mutlaka veri tabanına kayıt etmek gerekir. Bunun için kullanılacak CREATE ASSEMBLY
ifadesinde izlenecek
adımlar;
*** Assembly için veri tabanı nesnesinin adının atanması.
*** Bulunduğu dosya yolunun belirtilmesi.
*** Güvenlik izinlerinin atanması.
Kullanım Şekli;
Eğer kayıt olmuş bir Assembly'nin kaydı silinmek istenirse DROP ASSEMBLY ifadesi kullanılır.
Assembly_ad: Assembly için veri tabanı nesnesinin adıdır. Bu ismi stored procedure gibi veri tabanı nesneleri ile bağlantı kurmak istediğimiz zaman kullanırız. Bu isimin geçerli bir SQL Server adı ve veri tabanı içinde tek olması gerekir. Assembly dosya adı ile aynı olması zorunludur. Eğer bu ismi yazmazsak SQL Server uygun bir isim ataması bizim yerimize yapar.
CREATE ASSEMBLY [assembly_ad] [AUTHORIZATION owner_ad ] FROM {assembly_dosya_yolu\ assembly_bits[,…n]}
[WITH PERMISSION_SET=(SAFE\EXTERNAL_ACCESS\UNSAFE}]
Assembly_dosya_yolu: Kullanılacak Assembly'nin bulunduğu fiziksel yoldur. Burada istenirse bir netvvork yolu da UNC kullanmak sureti ile
verilebilir. Assembly yalnızca bir dosya içerebilir, çünkü SQL Server 2008 çoklu Assembly yapısına destek vermez. Eğer bu Assembly'nin bağlı bulunduğu dosyalar varsa ve aynı yol üzerinde değilse işlem gerçekleşmez. Aşağıdaki yazılım bir netvvork ortamından alınan Assembly'nin nasıl kayıt edildiğini göstermektedir. İsimlerin aynı olduğuna dikkat edin.
WITH_PERMISSION_SET: Kod için açma yetkisi vermek istediğimizde
kullanacağımız cümleciktir.
Burada bulunan seçenekler.
SAFE En kısıtlayıcı ve varsayılan ayardır. Özel bir durum olmadıkça değiştirmemek
gerekir. Böylelikle dış sistem kaynakları tarafından erişilmesi önlenir.
EXTERNAL ACCESS Bazı sistem kaynakları tarafından erişimine izin verilir. Bu kaynaklar; içerdiği
dosyalar, netvvork, environment ve registry değerleri. Önüne gelen açar.Ancak bu izinle Assembly oluşturmak için mutlaka sysadmin
grubunun üyesi olmak gerekir.
Aşağıdaki kod, kayıt edilen Assembly için verilen izni göstermektedir.
Kod yazmadan oluşturmak için ise Management Studio içinden Object Explorer altında bulunan veri tabanımızı açarak, Programmability klasörünün altındaki Assemblies klasörü üzerinde sağ tuş ile New Assembly komutunu çalıştırırız. Gelen iletişim kutusundan kolaylıkla kayıt işlemini gerçekleştirebiliriz.
CREATE ASSEMBLY feneryener FROM ‘\\GORYUK\kutuphane\feneryener.dll’
CREATE ASSEMBLY feneryener
FROM 'C:\superlig\feneryener.dll' WITH PERMISSION_SET = EXTERNAL_ ACCESS
EXTERNAL NAME: Bu çağrılan kütüphaneyi (Assembly Kaydı) kullanarak SQL Server içinde
oluşturabileceğimiz birçok veri tabanı objesi vardır.
Burada kullanılacak iadeler;
*** CREATE PROCEDURE
*** CREATE TRIGGER
*** CREATE FUNCTION
*** CREATE TYPE
*** CREATE AGGREGATE
CREATE ifadelerinde kullanım şekli, standart kullanım şeklindeki AS cümlesine kadar aynıdır. Bundan sonra kullanılan EXTERNAL NAME cümleciği ile çağırmış olduğumuz kütüphaneyi ilişkilendiririz.
EXTERNAL NAME cümleciğinin kullanım şekli;
Proje adı ile ana namespace Visual Basic .Net yapısında aynıdır. Ancak Visuai C# varsayılan ismi koymadığı için bunu eklememiz gerekir. Bunun anlamı bu iki dilde hazırlanan yapıların EXTERNAL NAME ile kullanımı farklılık gösterir.
Aşağıdaki yazılım CREATE ASSMBLY ile daha önce SQL Server içine kaydedilmiş feneryener isimli Asemmbly'nin içindeki futbol class'ı fb namespace'i içindedir. Bunun içinde de brezilya isimli bir fonksiyon bulunmaktadır.
Eğer bir namespace içermese idi isim yazılımı aşağıdaki gibi olacaktı.
Oluşturduktan sonra çalıştırması geleneksel şekilde gerçekleştirilir.
UYGULAMA: 1-) Yeni bir Visual Studio .NET projesinde Class Library kalıbını seçerek Location kısmında C:\ sürücüsü seçili iken Name kısmına feneryener yazalım. Ardından OK butonuna basalım.
EXTERNAL NAME AssemblyName.[[Namespace].ClassName].MetrıodName
CREATE PROCEDURE yuksel.puantablo AS
EXTERNAL NAME feneryener.[fb.futbol].brezilya
2) İçindeki tüm kodlan silerek, yerine aşağıdaki kodlan yazalım.
C#
using System; using System.Collections.Generic; using System.Text; using System.Data.Sql; using System.Data.SqlTypes; namespace feneryener { public class futbol
{ public static Sqllnt32 brezilya()
{ retum 5;
} }}
VB
Imports System
Imports System.Data.Sql
Imports System.Data.SqlTypes
Public Class futbol Public Shared Function brezilya() As Sqllnt32
Return 5 End Function
End Class
3) Build menüsünden Build Solution komutunu çalıştırarak projemizi derleyelim
4) Başarı ile derlediğimizde kaydettiğimiz yer olan C:\ sürücüsü altındaki feneryener klasörü içinde bin\debug klasörleri içinde feneryener.dll isimli bir dosyanın oluşması gerekir..
5) Oluşturduğumuz kütüphaneyi SQL Server ile ilişkilendirmek için SQL Server 2008 içinde Query bölümünde aşağıdaki kodu yazalım.
6) İşlem başarı ile tamamlandığı zaman Assembly klasörü altında görebilirsiniz 7) Assembly oluştuktan sonra bunu bir stored procedure içine
aşağıdaki şekilde yerleştirebiliriz.
CREATE ASSEMBLY feneryener FROM ‘C:\feneryener\feneryener\bin\debug\feneryener.dll’
CREATE PROCEDURE dbo.azvar AS EXTERNAL NAME feneryener. [feneryener . futbol] .brezilya
Not: Eğer NET ortamında oluşturduğunuz fonksiyon bir string değer döndürecek ise, bu değeri yakalamak için aşağıdaki gibi bir fonksiyon oluşturabilirsiniz.
CREATE FUNCTION k2 () RETURNS nvarchar(20) AS EXTERNAL NAME feneryener.[feneryener.futbol].brezilya GO select dbo.k2()
8) Sonucu görebilmek için ilk olarak aşağıdaki ayarları yapmamız gerekir. Bunu bir kez yaptıktan sonra iptal edene kadar her zaman için SQL Server yapısında geçerli olacaktır. İfadeyi Query Analyzer içine yazıyoruz.
Bunun sonucunda aşağıdaki ifadeyi görmemiz gerekir.
9) Son olarak gelen değeri görmek için aşağıdaki kod yazılır
Sonuç şekildeki gibi olacaktır.
SYSTEM.DATA.SQLSERVER:
.NET platformu ile ilişki kurup SQL Server içinde nesne oluştururken en yaygın kullanacağımız namespace yapısı sqlaccess.dll içinde bulunan Sysytem.Data.SqlServer'dır.
Veri tabanını hızlı açmak ve istediğimiz işlemleri yapmak için bu namespace
Sp_configure ‘clr enabled’,1
GO
RECONFIGURE
Declare @a int Exec @a=azvar Select @a
altında bulunan Class'ları bilmemiz gerekir.
Şimdi bunları inceleyelim;
SqlContext: Durum içeriğini almak için kullanılır. Örneğin o anki veri tabanı bağlantısı veya transaction durumu gibi.
SqlConnection: Herhangi bir veri sorgulaması yapmadan önce veri tabanına bağlanmak için kullanılır. Eğer aynı veri tabanına bir nesne
oluşturmak için tekrar bağlantıya geçmemek ihtiyacı duyarsak SqlContext ile beraber aşağıdaki gibi kullanılabilir.
SqlCommand: Veri tabanına Transact-SQL komutlarını göndermek ve bir
stored procedure veya fonksiyon çağırmak için kullanılır.
Burada kullanılan ExecuteNonQuery methodu Transact-SQL ifadesinin çalıştırılarak SQL Server üzerine gönderilmesini sağlar. Döndürdüğü değer etkilenen kayıt sayısıdır.
Eğer kayıt seçimi yapılacak ise ExecuteReader methodu sadece okunabilir özelliğine sahip olan SqlDataReader ile beraber kullanılır. Server cursor yapısına girerek kaydırma ve güncelleme yapmak için ise ExecuteResultSet methodu kullanılır. Döndürdüğü değer ise IsdlResultSet nesnesidir.
SqlParameter: Bu class ile SqlCommand nesnesine parametre ekleme imkanı sağlarız. Örneğin bir stored procedure içinde tanımlı olan parametrelere değer yollamak gibi.
VB
Dim c as SqlConnection = SqlContext.GetConnection();
C#
SqlConnection c = SqlContext.GetConnection();
Dim co As New SqlCommand co.Connection=c co.CommandText = "DELETE kitap WHERE kitapno = 5" Dim sonuc As Integer = co.ExecuteNonQuery()
C#
SqlCommand co = new SqlCommand(); Co. Connection=c; Co.CommandText="DELETE kitap WHERE kitapno=5"; int sonuc=co. ExecuteNonQuery;
Bu temel yapılar dışında diğer class'ları kısaca açıklayacak olursak;
SqlPipe: Client uygulamaları direkt sonuç veya mesaj yollamak için kullanılır.
SqlDataReader: Veri tabanından dönen kayıtları yakalamak için kullanılır.
SqlTransaction: Veri tabanı içindeki transaction yapısını günceliemek için kullanılır.
SqlTriggerContext: Aktif Trigger yapıları hakkında bilgi edinmek için kullanılır.
VB
Dim c As New SçIConnection Dim co As New
SqlCommand Co.Connection = c
co.CommandText = "Sil"
co.CommandType = CommandType.StoredProcedure
Dim p As New SqlParameter()
p.SourceColumn = "Kitapno"
p.Direction = ParameterDirection.Input p.SçIDbType = SqlDbType.lnt p. Value = 5 co. Parameters.Add(p) co. ExecuteNonQuery()
C#
SqlCommand co = new SqlCommand(); Co. Connection=c; co.CommandText = "Sil"; co.CommandType = CommandType.StoredProcedure;
SqlParameter p = new SqlParameter();
p.SourceColumn = "Kitapno";
p.Direction = ParameterDirection.Input;
p.SqlDbType = SqlDbType.lnt;
p. Value = 5;
co.Parameters.Add(p);
co. ExecuteNonOuery();
Not: Bu class'iarı kullanmak için .NET platformunda kod kısmına imports veya using ifadelerini kullanarak, aşağıdaki
namespace'leri tanımlamak gerekir.
System.Data.Sql System.Data System.Data.SqlClient Microsoft.SqlServer Microsoft.SglServer.Server
CLR ile STORED PROCEDURE:
CLR stored procedure oluşturma, eski versiyonlardaki stored procedure yapılarına göre çok daha sağlam ve güvenilirdir.
Oluşum için aşağıdaki adımların takip edilmesi gerekir.
1) Bir public class yapısı içinde Visual C# .NET için static, Visual Basic .NET için shared fonksiyon oluşturulur.
2) Fonksiyon içine SqlProcedure özellikleri ile eklenir. Bir class içinde birden fazla stored procedure fonksiyonu bulunabilir. Yani her stored procedure için ayrı bir class oluşturmaya gerek yoktur.
3) Gerekli kodlar yazılır. Şimdi bu üç yapıyı örnekleyelim;
UYGULAMA:
1) Bu uygulamamızda ciro tablosunu kullanacağız. Bu tablo tasarımı ve içindeki kayıtlar şekildeki gibidir.
2) Bu uygulamamızı ilk olarak klasik yolla yapacağız, ardından yapacağımız uygulama ile daha basit bir yol izleyeceğiz. Bunun için C sürücüsü içinde yazar isimli bir Class Library oluşturalım.
3) İçine aşağıdaki kodları yazalım. Sonraki uygulamada direkt
yapacağımızdan C# kodlarını vermeye gerek duymadım. 4) Derledikten sonra SOL Server 2008 içindeki Ouery bölümüne aşağıdaki
kodları yazarak; hem Assembly oluşturalım, hem de Storede procedure.
Irnports System.Data.Sql Imports System.Data İmports System.Data.SqlClient Imports Microsoft.SqlServer imports Microsoft.SqlServer.Server Public Class Class1 Public Shared ReadOnly s As String = "Server=fb1\yuk2008;database=yuksel3;lntegrated Security=SSPI;"
Public Shared Function hepsigel() As Integer Dim c As New SqlConnection c.ConnectionString = s Dim co As New SqlCommand co.Connection = c c.Open() co.CommandText = "select count(urunad) from ciro” Dim i As Integer = co.ExecuteScalar c.Close() Return i
End Function
End Class
CREATE ASSEMBLY yazar FROM ' C: \yazar \yazar \bin\Debug\yazar.dll WITH PERMISSION_SET – EXTERNAL_ACCESS
GO CREATE PROCEDURE dbo.gel AS EXTERNAL NAME yazar.[yazar.Class1].hepsigel
5) Aşağıdaki kodu Ouery bölümüne yazarak, test edelim. 6) Çalıştırınca şekildeki gibi toplam kayıt sayısı görüntülenecektir.
UYGULAMA:
1)Bu uygulamadan itibaren daha basit bir yapı üzerinde duracağız ve bundan sonraki tüm CLR ile SOL Server nesneleri oluşturmada bu tekniği kullanacağız.
2)Yeni bir proje oluşturma seçeneğinde karşımıza gelen iletişim kutusunda; sol
taraftan yazılım yapacağımız dilin altından Database, sağ taraftan ise SOL Server Project kalıbını seçip yazar2 ismini vererek OK butonuna basalım.
Declare @a int
Exec @a=gel
Select @a
3) İlk bağlantımızda gerekli tanıtımları yapmak için gelen iletişim kutusunda; eğer veri tabanımız yoksa, alt kısımda bulunan Add New Reference ile ekliyoruz.
OK ve YES butonları ile işlemi sonlandıralım.
4) Oluşturduğumuz bu yeni proje üzerinde sağ tuşa basarak Add seçeneğinden Stored Procedure seçeneğine tıklayalım.
Gelen iletişim kutusunda direkt Add butonuna basalım. Karşımıza şekildeki gibi hazır yapı gelecektir. Eğer yoksa üste
System.Data.Sq I Client namespace'ini ilave edelim.
5) Buradaki kodları aşağıdaki şekilde değiştirelim. Sadece olmayanları îiave ediniz. Burada context connection=true ifadesi ile aktif bağlantı özeliklerini kullanıyorum. Ve sonucu yollamak içinse SqlPipe yapısından yararlanıyorum.
VB Imports System Imports System.Data Imports System.Data.Sql Imports System.Data.SqlCiient Imports System.Data.SqlTypes Imports Microsoft.SqlServer.Server
Partial Public class StoredProcedures Shared ReadOnly c As New SqlConnection(“context connection=true") <SqlProcedure(Name:="gel22")>_ Public Shared Sub hepsigel() Dim co As New SqlCommand co.Connection = c c.Open() co.CommandText = "select * from ciro" Dim rdr As SqlDataReader = co.ExecuteReader() Dim sp As SqlPipe=SqlContext.Pipe Sp.Send(rdr) Sp.send(“merhaba”) c.close() end sub End class
6) Ardından proje adı üzerinde sağ tuşa basarak Deploy seçeneğine tıklayalım.
Böylelikle bir önceki uygulamada SQL Server içinde yaptıklarımıza hiç gerek kalmadı. Otomatik olarak yazar2 isimli bir Assembly ve gel22 isimli bir Stored Procedure oluşmuş oldu. Gidip SQL Server içinden kontrol ediniz. Herşey çok pratik oldu.
C#
using System;
using System.Data;
using System.Data.Sql;
using System.Data.SqlTypes;
using Microsoft. Sq I Server. Server;
using System.Data.SqlClient;
public partial class StoredProcedures
{ [Microsoft.SqlServer.Server.SqlProcedure(Name = "ge!22")] public static void hepsige!2()
{
using (SqlConnection c = new SqlConnection("context connection=true"))
{ c.Open(); SqlCommand cmd = new SqlCommand("seIect * from ciro", c); SqlDataReader r = cmd.ExecuteReader(); SqlContext.Pipe.Send(r); SqlContext.Pipe.Send("merhaba");
c.Close(); }
}
}
}
7) SQL Server içinden sadece aşağıdaki kodu yazarak sonucu görebilirsiniz. Sonuçta, Results bölümünde tüm kayıtlar görünecek ve Messages kısmında da merhaba yazacaktır.
UYGULAMA:
1) Bu uygulamamızda da oluşturacağımız stored procedure içinde XML yapısını kullanacağız.
2) Yeni bir SQL Server projesini .NET ortamında oluşturalım.
3) Gelen iletişim kutusundan veri tabanımızı seçerek OK butonuna basalım.
4) Projemize Stored Procedure dahil edelim.
5) Üst tarafa System.Xml namespace'ini ekleyelim.
6) Aşağıdaki adımları uygulayarak projemizde namespace yapısını yapılandıralım. Gerçi burada gerek yok, ama nasıl olduğunu bilmek açısından ileride işinize yarayabilir.
VB.NET için;
Proje adı üzerinde sağ tuşa basarak Properties seçeneğine tıklayalım. Gelen ayarlar iletişim kutusundan Application bölümünde Root namespace kısmına namespace adı olacak yüksel ifadesini yazalım.
C#.NETiçin;
Using ifadelerinden sonraki kodları aşağıdaki blok içine alalım.
namespace yüksel { }
7) Class yapımız içindeki tüm kodları aşağıdaki hale getirelim.
VB Imports System Imports System.Data Imports System.Data.Sql Imports System.Data.SqlTypes Imports Microsoft.SqlServer.Server Imports System.XmI
Partial Public Class StoredProcedures
<SqlProcedure(Name:="kitap3")> _
Public Shared Sub SaveXML(ByVal x As SqlXml, ByVal f As SqlString) Dim d As New XmlDocument()
d.LoadXml(x.Value)
d.Save(f.Value)
End Sub
End Class
C# using System; using System. Data; using System.Data.Sql; using System.Data.SqlTypes; using Microsoft. SqlServer. Server; using System.Xml;
namespace yüksel
{ public partial class StoredProcedures
{ [SqlProcedure(Name = "kitap3")] public static void SaveXML (SqlXml x,SalString f)
{
XmlDocument d = new XmlDocument(); d.LoadXml(x.Value); d.Save(f.Value);
}
}; }
8) Projemizi derledikten sonra proje adı üzerinde sağ tuşa basarak Deploy seçeneği ile SQL Server'a yollayalım. Hem Assembly, hem de Stored Procedure otomatik olarak oluşsun.
9) SQL Server içinde oluşan Assembly üzerinde sağ tuşa basarak Properties seçeneğine tıklayalım.
10) Permission set kısmından External access seçeneğini seçerek OK butonuna basalım.
Eğer sahiplikle ilgili bir hata mesajı çıkarsa; veri tabanımızın özelliklerine girerek Properties kısmından o an bağlandığınız kullanıcıya sahiplik verebilirsiniz.
11) C sürücüsünde ciro isimli bir klasör oluşturalım ve aşağıdaki yazılımı Query
bölümüne yazarak, yapımızı test edelim. 12) Bunun sonucunda C: sürücüsü içinde oluşturduğumuz ciro klasöründe
ciro.xml isimli bir dosya oluşacaktır ve içine ciro tablosundaki tüm kayıtları yerleştirecektir
Declare @kitapliste xml SET @kiyapliste=(SELECT * FROM ciro ciroyolla FOR XML AUTO ,ROOT(‘kitap’),TYPE) EXEC dbo.kitap3 @kitapliste, ‘C:\\ciro\\ciro.xml
Dosyayı açtığımızda görüntü, şekildeki gibi olacaktır;
CLR İLE FUNCTION:
Oluşum kademeleri stored procedure oluşturma ile aynıdır. Hem scalar hem tabular olarak oluşturulabilir. Döndürülecek veri tipi System.Data.SqlTypes namespace'i kullanılarak doğru tanımlanmalıdır.
Opsiyonel DataAccess argümanı ile veri okunabilir ve DataAccessKind.Read değeri atanabilir. Veri tabanı dışında dosya ve normal veriler üzerinde de çalışılabilir.
Eğer table-valued fonksiyon oluşturulacaksa ve döndüreceği değer bir veri tablosundaki satırlar olacak ise mutlaka lsqlReader kullanılmalıdır.
UYGULAMA:
1) Yeni bir .NET SqlServer projesi açarak, veri tabanımızı seçelim.
2) User-Defined Function seçeneği ile bir fonksiyon tanımlama sayfası ekleyelim.
3) İçindeki kodları aşağıdaki gibi değiştirelim.
VB
Imports System
Imports System.Data
Imports System.Data.Sql
Imports System.Data.SqlTypes
Imports Microsoft.SqIServer.Server
Partial Public Class UserDefinedFunctions <Microsoft.SqlServer.Server.SqlFunction(Name:="tarih")>_
Public Shared Function Function"! (ByVal t As SqlDateTime) As SqISt ring
Return t.Value.ToLongDateString()
End Function
End Class
using System;
using System.Data;
using System.Data.Sql;
using System.Data.SçITypes;
using Microsoft.SqlServer.Server;
public partial class UserDefinedFunction
{
[SqlFunction(Name="tarih")]
public static SqlString GetLongDate(SqlDateTime t)
{
return t. Value. ToLongDateString();
}
};
4) Derledikten sonra proje üzerinde sağ tuşa basarak; seçeceğimiz Depioy komutu ile SQL Server içine yollayalım.
5) SQL Server içinde Query kısmını açarak aşağıdaki kodu yazıp fonksiyonumuzun çalıştığını test edelim. Tarih girerken ay/gün/yıl formatında giriyoruz.
Sonuç;şekildeki gibi olacaktır.
CLR ile AGGREGATE:
Kullanıcı tanımlı Aggregate oluşturmak için kullanılır. SOL Server içinde kümeleme işlemlerini gerçekleştiren birçok hazır Aggregate bulunmaktadır. (Örneğin MAX,MIN,SUM)
Oluşturmak için;
1) Bir Structure veya Class tanımlanır.
2) Class'a Serializable ve SqiUserDefinedAggregate özellikleri kazandırılır. Serializable; geçici çalışma tablosu için biçimi belirlerken, diğer özellik ise SQL Server içinde en performanslı şekilde tutulması gerekli olan ayarları tutar. Bu yapıda kullanılacak Format seçeneği ile kullanıcı biçimi serDefined cümleciği ile istediği gibi belirleyebilir veya Native cümleciği ile otomatik ayarlanabilir. Bu tür bilgiler için ayrılacak en fazla boyut miktarı için ise MaxByteSize kullanılır.
3) Aşağıdaki methotlar oluşturularak, gerekli kodlar yazılır;
Irıit: Sorgu işlemcisi; her bir grup için bu methodu bir kez çağırır. Lokal değişkenleri sıfırlamak için gerekli temizleme kodlarının buraya yazılması gerekmektedir.
Accumulate: Kullanılacak değerin alacağı yeni şekil belirlenir. Örneğin;
Select dbo.tarih(‘08/02/2001’)
arkasına çeşitli karakterler bu bölümde ilave edilir.
Merge: Yapıları birleştirmek için kullanılır.
Terminate: Sonucu döndürmek için kullanılır.
Eğer bir Class olarak tanımlarsanız ve IbinarySerilaze ile Implement etmek ihtiyacı duyarsanız; aşağıdaki methotları da eklemeniz gerekir.
UYGULAMA:
1) Yeni bir SOL Server kalıbını .NET içinden ekleterek üzerinde sağ tuşa basıp Add seçeneğinden Aggregate seçeneğine tıklayalım.
İçindeki kodları aşağıdaki şekilde değiştirelim. Bu, seçilen değerin başına üç yıldız koyacaktır. Eğer seçilen değer boş ise üç nokta koyacaktır. Kod'a dikkat ediniz, gelen yapıyı Class olarak değiştirip IbinarySerialize ile Implement
Overridable Sub Read(ByVal r As BinaryReader) Implements IBinarySerialize.Read Overridable Sub rite(ByVal w As BinaryWriter) Implements IBinarySerialize.Write End Sub
VB
Imports System imports System.Data Imports System.Data.Sql İmports System.Data.SqlTypes İmports Microsoft.SqlServer.Server İmports System.Text 'Biz ekledik İmports System.10 'Biz ekledik <Serializable()>_ <Microsoft.SqlServer.Server.SqlUserDefinedAggregate(Format.User Defined,_
lslnvariantToNulls:=True, lslnvariantToDuplicates:=False, _ IslnvariantToOrder:=False, MaxByteSize:=8000, Name.="yildiz")> _ Public Class yildiz1 Implements IBinarySerialize Dim sonuc As StringBuilder Public Sub Init()
Sonuc=New stringBuilder() End Sub Public Sub Accumulate(ByVaI value As SqlString) If value.lsNull Then sonuc.Append("...") Else sonuc.Append("***" & value.ToString) End lf End Sub
Public Sub Merge(ByVal gelen As yildizl) sonucAppend(gelen.sonuc) End Sub Public Function Terminate() As SqlString Dim gelen As String = String.Empty If (sonuç.Length > 0) Then gelen = sonuc.ToString(0, sonuc.Length -1) Retum New SqlString(gelen) Endlf
End Function Overridable Sub Read(ByVal r As BinaryReader) Implements
IBinarySerialize.Read sonuc = New StringBuilder(r.ReadString()) End Sub
Overridable Sub rite(ByVal w As BinaryVVriter) Implements IBinarySerialize.VVrite w.Write(sonuc.ToString()) End Sub End Class
3) Test etmek için aşağıdaki ifadeyi SQL Server içinden yazalım.
4) Çalıştırdığımızda görüntü, şekildeki gibi olur.
C# using System; using System.Data; using System.Data.Sql; using System.Data.SqlTypes; using Microsoft. SglServer. Server; using System.Text;//'Biz ekledik using System.lO;//'Biz ekledik [Serializable] [SqlUserDefinedAggregate( Format.UserDefined,lslnvahantToNulls=true, lslnvariantToDuplicates=false,lslnvahantToOrder=false, MaxByteSize=8000, Name="yiİd iz") ] public class yildizl: IBinarySerialize { private StringBuilder sonuç; public void lnit( ) { sonuç = new StringBuilder(); } public void Accumulate(SqlString value) { if(value.lsNull) { retum; } sonuc.Append(value. Value). Append(‘,'); } public void Merge(yildiz1 gelen) { sonuc.Append(gelen. sonuç); } public SqlString Terminate() { string gelen = String.Empty; if (sonuc! null && sonuc.Length > 0) gelen = sonuc.ToString(0, sonuc.Length-1); retum new SqlString(gelen); } public void Read(BinaryReader r) ' { sonuç = new StringBuilder(r.ReadString()); public void Write(BinaryWriter w) { w. Write(sonuc. ToString()); } }
Select personelad ,dbo.yildiz(urunad) as sattiklari from ciro Group by personel ad
CLR İLE USER DEFİNE DATA TYPE:
Kullanıcı tanımlı veri tipi (UTDs) oluşturmak mümkündür. Burada izlenecek adımlar;
1)Class veya Structure oluşturulur. Bunlara Serializable ve
SqlUserDefinedType özellikleri kazandırılır.
2)Boş(Null) değerler tanıtılır.
3)Veri tipleri string dönüşümü yapılır.(Parse veya Tostring)
4)Public özelliklerinin Private özellikleri açması sağlanır. (GeL.Set)
UYGULAMA:
1) Yeni bir SQL Server kalıbı ile .NET projesi oluşturalım. Proje adı üzerinde sağ tuşa basarak Add seçeneğinden User-Defined Type alt seçeneğine tıklayarak; gelen iletişim kutusunu "tarihayir" adı ile onaylayalım
2) İçindeki kodları, aşağıdaki şekilde düzenleyelim.
VB
Imports System
Imports System.Data
Imports System.Data.Sql Imports System.Data.SqlTypes
Imports Microsoft.SqlServer.Server <Serializable()> _ <Microsoft.SqlServer.Server.SqlL)serDefinedType(Format.Native)>_ Public Structure tarihayir Implements INullable
Private bos As Boolean
Private m_a As Double
Private m_b As Double
Private m_c As Double Public Overrides Function ToString() As String
If Me.lsNull Then
Retum "NULL"
Else
Return m_a.ToString & "." & m_b.ToString & ".’' & m_c.ToString End lf
End Function Public ReadOniy Property lsNull() As Boolean Implements INullable.lsNull
Get
Return bos End Get
End Property Public Shared ReadOniy Property Null() As tarihayir Get
Dim t As New tarihayir()
t.bos = True
Return t
End Get
End Property Public Shared Function Parse(ByVal s As SqlString) As tarihayir
If s.lsNull Then Return tarihayir.Null
Else Dim t As New tarihayir() ,Dim str As String = Convert.ToString(s),Dim ab() As String =
str.Split("/".ToCharArray()) t.A = Double. Parse(ab(0)),t.B = Double.Parse(ab(1)).t.C = Double.Parse(ab(2))
Retum t End lf End Function
Public Property A() As Double
Get
Return m_a
End Get Set(ByVal value As Double)
m_a = value
End Set End Property Public Property B() As Double
Get Return m_b
End Get Set(ByVal value As Double)
m_b = value End Set End Property
Public Property C() As Double
Get Return m_c
End Get Set(ByVal value As Double)
m_c = value
End Set End Property
Public Function unvan() As String
Return "Tarih: " + Me.ToString()
End Function End Structure
C#
using System; using System. Data. Sql; using System.Data.SqlTypes; using System. Text; using Microsoft. SqlServer. Server;
namespace tarihler
{ [Serializabie] [SqlUserDefinedType(Format.Native)] public struct tarihayir: INullable
i private bool bos; private double m_a; private double m_b; private double m_c;
public override string ToString() { if (this.lsNull)
{
Return ‘’NULL’’;
} else {
return m_a + "." + m_b + "." + m_c;
} }
public bool IsNull
{ get { return bos;
} }
public static tarihayir Null { get
{ tarihayir tarih = new tarihayir();
tarih.bos = true; return tarih;
} }
public static tarihayir Parse(SqlString s) { if (s. IsNull)
{ return tarihayir.Null;
} else
{ tarihayir tarih = new tarihayir();
String str = Convert. ToString(s); / String[]ab = str. Split(‘’/’’. ToCharArray()); tarih. A = double.Parse(ab[0]); tarih.B = double.Parse(ab[1]); tarih.C = double. Parse(ab[2]);
return tarih; }
}public Double A { get { retum m_a; } set { m_a = value;
} } public Double B{get { retum m_b; } set{ m_b = value;
} }public Double C { get { retum m_c; } set { m_c =
value;} } public Strirtg unvan(){ retum "Tarih:" + this.
ToString();
} }}
3) Projeyi derleyerek Deploy edelim.
4) Bunu, bir tabloda kullanalım.
5)Bunun sonucunda tarih girerken arada / işareti kullanmak zorunlu olacaktır. Onun dışında girilen tarih veya başka bir değerde şekildeki gibi hata verecektir.
CLR ile TRİGGER:
Diğer oluşturacağımız SOL Server nesnesi de çok kullanılan Trigger nesnesidir.
Takip edilecek adımlar;
1) Class oluşturulur.
2) İşlemleri kolaylaştırmak için SqlTrigger özelliği eklenir.
3) Gerekli Trigger kodları yazılır.
UYGULAMA:
1) Yeni bir .NET projesini SQL Server kalıbı ile oluşturalım.
2) Proje adı üzerinde sağ tuşa basarak Add/ Triggers seçeneğine şekildeki gibi tıklayalım.
3) Aşağıdaki gibi kodları uygulayalım.
VB
Imports System
Imports System.Data
Imports System.Data.Sql
Imports System.Data.SqlTypes
Imports Microsoft.SqlServer.Server
Imports System.Data.SqlClient
Partial Public Class Triggers Shared ReadOnly c As New SqlConnection("context connection=true") <SqlTrigger(Name:="silvb", Target:="Ciro", Event:="FOR INSERT")> _
Public Shared Sub silvb()
Dim hareket As SqlTriggerContext
Dim p As SgIPipe = SqlContext.Pipe hareket = SqlContext.TriggerContext() If (hareket.TriggerAction = TriggerAction.Insert) Then Dim co As New SqlCommand co.Connection = c c.Open() co.CommandText = "SELECT satisno FROM INSERTED"
Dim r As SqlDataReader = co.ExecuteReader()
While (r.Read())
p.Send("Yeni Kaydın Numarası: " & r("satisno").ToString)
End While
Endlf
End Sub
End Class