Sayfalar

Translate

7 Haziran 2015 Pazar

SQL Server - EXEC Management

Bir SP miz var. Bu SP nin kontrollü çalışmasını istiyoruz. Örneğin SP miz çalışmaya başlayınca yaklaşık 1 saat boyunca çalışıyor olsun. SP mizi EXEC ettik, çalışması bitene kadar yanlışlıkla tekrar EXEC edilse bile çalışmasını istemiyoruz.

Bunun için aşağıdaki gibi bir şablon kullanabiliriz;


1- ExecInfoTable Tablosu:


CREATE TABLE ExecInfoTable(
      SpName VARCHAR(64) NOT NULL,
      LastSessionID INT NOT NULL
)

Bu tabloda istediğimiz SP mizin anlık çalışma bilgisini saklıyor olacağız.

Her oluşturduğumuz SP için ExecInfoTable tablosuna bir kayıt insert ederiz. Bizim örneğimizde SP mizin ismi sp_ExecManagementTest olacak.

INSERT INTO ExecInfoTable(SpName, LastSessionID) VALUES('sp_ExecManagementTest', 0)

SP miz çalışmaya başladığında SessionID sini @@SPID distem değişkeninden alarak ExecInfoTable tablosuna kaydedeceğiz



2- SessionID Aktiflik Kontolü:


SQL Server in çalışmakta olan Exec işlemlerinin SessionID lerini sakladığı bir sistem tablosu var. Bu tablonun ismi sys.dm_exec_requests dir.

Aşağıdaki sorgu ile sistemde aktif çalışan Exec işlemlerinin SessionID lerini görebiliriz.

SELECT session_id FROM sys.dm_exec_requests WHERE status IN ('running', 'suspended', 'pending', 'runnable')




3- EXEC Management Şablonu:

SP mize aşağıdaki şablonu uygulayarak, kontrollü çalışmasını sağlamış oluyoruz:

CREATE PROCEDURE sp_ExecManagementTest
AS
BEGIN
      DECLARE @LastSessionID INT = 0
     
      SELECT @LastSessionID = LastSessionID FROM ExecInfoTable WITH(NOLOCK) WHERE SpName = 'sp_ExecManagementTest'
     
      IF EXISTS(SELECT 1 FROM sys.dm_exec_requests WHERE status IN ('running', 'suspended', 'pending', 'runnable') AND session_id = @LastSessionID)
      BEGIN
            PRINT 'sp_ExecManagementTest bitmeden tekrar çalýþtýrýlamaz!'
            GOTO SPEnd
      END
      ELSE
            UPDATE ExecInfoTable SET LastSessionID = @@SPID WHERE SpName = 'sp_ExecManagementTest'
     
      -- Bu noktadan sonra SP mizin asıl kodları başlar
      WAITFOR DELAY '00:00:10'
      PRINT 'sp_ExecManagementTest çalışmas bitti'
   
SPEnd:
   
END


4- Test:

SP mizi farklı pencerelerde(farklı session lar altında) çalıştırmayı denersek sonuç aşağıdaki gibi olacaktır:




6 Haziran 2015 Cumartesi

SQL Server Management Studio (SSMS) - Find And Replace Ayarları

SQL Server Management Studio(SSMS) kullanırken editörde ki script in içerisinde arama yaptığımız durumlar sık sık oluyor.



Kelime arama işi bittiğinde ekranımıza bunu bildiren aşağıdaki mesajın geldiğini biliyoruz.



Eğer bu mesaj kutusundaki "Always show this message" tikini yanlışlıkla yada bi anlık ihtiyaç sebebiyle kaldırırsak çok can sıkıcı bir durum ortaya çıkıyor.

Çok uzun bir script te arama yaparken ve oradan oraya atlanarak kelimeler bulunurken, script in sonuna gelindiğinde artık bu mesaj çıkmayacağı için, arama en baştan devam ediyor ve bunu anlamak için scrollbar ı takip etmek zorunda kalıyoruz.



Ne yazık ki bu durumu eski haline çevirmek için SSMS nun ayarları arasında Find and Replace yada Alert mesajları ile ilgili bir seçenek bulunmuyor. Google da arattığımız da ise genellikle Find and Replace de Regex i kullanarak nasıl daha profesyonel aramalar yapabileceğimiz ile ilgili bilgiler buluyoruz. Ama en sonunda aradığımız bilgiyi de bulabiliyoruz tabi. Bu kadar çok uğraşmaya gerek kalmaması amacıyla bu paylaşımı çoğaltmak istiyorum.

Find and Replace, ayarlarını regedit ten okunuyor. SSMS 2008 kurulu olan makineler için Find and Replace ayarlarını aşağıdaki path de bulabilirsiniz. Daha eski versiyonlarda kırmızı ile işaretli kısım 100 değil de 90 yada 80 olmaktadır.

HKEY_CURRENT_USER\Software\Microsoft\Microsoft SQL Server\100\Tools\Shell
Aramanın sonuna gelindiğini bildiren mesajın gösterilip gösterilmemesi ile ilgili ayarın tutulduğu key, ShowEndOfSearch Key idir. Diğer Key ler Find and Replace ekranının diğer ayarlarıdır. Şu an için onlarla işimiz yok.
 Regedit te ki ShowEndOfSearch ayarı 1 olarak tanımlı iken, "Always show this message" tikini kaldırdığımızda  aşağıdaki gibi 0 olarak atanıyor.


SSMS yu kapatarak ShowEndOfSearch Key ini yeniden 1 olarak değiştirir isek canımızı sıkan bu sorunumuz da hallolmuş oluyor.

20 Mayıs 2015 Çarşamba

SQL Server - ISNUMERIC

Sql de bazen bir değerin Integer olup olmadığını doğrulamak isteriz. Bunun için internette farklı fonksiyonların yazıldığını görebiliyoruz. Yalnız daha basit bir çözüm için ISNUMERIC fonksiyonunu kullanabiliriz. Tabi dikkat etmemiz gereken şey ISNUMERIC fonksiyonunun sadece integer değil float, decimal hatta Scientific Expressions ları da destekliyor olması...

yani aşağıdaki sorgulardan da ISNUMERIC 1 dönecektir.

SELECT ISNUMERIC('123D3')


SELECT ISNUMERIC('123E3')


ISNUMERIC in sadece Integer kontrolü yapmasını aşağıdaki şekilde sağlayabiliriz. Değişkenin sonuna .0e0 ifadesini ekleyerek ISNUMERIC in Değişken sadece integer olduğunda 1 dönmesini sağlıyoruz.

ISNUMERIC(@Degisken + '.0e0')

8 Mayıs 2015 Cuma

SQL Server - Uncommittable Transaction

Hata: Uncommittable transaction is detected at the end of the batch. The transaction is rolled back.

Bu hata mesajı TRANSACTION içerisinde ERROR vermiş bir işlemin COMMIT lenmeye çalışılması ile oluşuyor.

Bir TRANSACTION başlatıldığında, TRY içerisinde hata oluşursa, mevcut TRANSACTION, Uncommittable Transaction olarak işaretleniyor ve bu TRANSACTION için COMMIT komutu çalıştırılamaz hale geliyor.

Çözüm: Error Handling yaparak COMMIT komutunun çalışmasını engelleyerek bu hatadan kurtulabiliyoruz.

Kaynak: https://msdn.microsoft.com/en-us/library/ms175976.aspx

1 Mayıs 2015 Cuma

C# - 32 bit Uygulama ile 64 bit Registry Okuma

Windows 64 bit İşletim Sistemlerinde Registry ikiye ayrılmış. Biri x84 uygulamalar için diğer x64 uygulamalar için. Registry e bir bilgi koyuyoruz ve C# x86 uygulamamızı o bilgiyi okuyacak şekilde kodluyoruz.
















Yalnız uygulamamızı çalıştırdığımızda Key bulunamadı hatası alıyor. Bunun sebebi bizim regedit ekranını kullanarak oluşturduğumuz Key in x64 Registry de oluşuyor olması ve x86 uygulamaların buraya erişiminin olmamasıdır.

Bu gibi durumlar için Microsoft x64 Registry e aşağıdaki dizini koymuş:

"HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node"

Biz kodumuza okuması için "HKEY_LOCAL_MACHINE\SOFTWARE\DenemeKey" path ini verdiğimizde C# kodumuz işletim sistemi tarafından "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\DenemeKey" path ine yönlendirilmekte.

Yani, 64 bit işletim sistemi üzerinde 86 bit olarak derlenmiş C# kodu ile registry den bilgi okumak istediğimizde bu bilgileri aşağıdaki path altında oluşturmamız gerekiyor.

"HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node"

Kaynak: https://dotnetgalactics.wordpress.com/2010/05/10/accessing-64-bit-registry-from-a-32-bit-process/

27 Nisan 2015 Pazartesi

SQL Server - (NOLOCK) ve WITH(NOLOCK) Farkı

Bu iki komut ta aynı işi yapıyor. Görev olarak hiç bir farkları yok.  Özellik olarak benim karşılaştığım bir fark oldu.

Eğer yazdığımız sorguda bir tabloya link server ile bağlanıyor isek (NOLOCK) kulanırsak sorgu hata alıyor ama WITH(NOLOCK) hatasız çalışıyor.

Ek olarak, Microsoft, WITH(NOLOCK) ın kullanılmasını öneriyor.

24 Nisan 2015 Cuma

SQL Server - REMOTE JOIN - Performans

Bir tabloyu(Tablo1) Arsiv deki başka bir tablo(Tablo2History) ile JOIN lemek istiyoruz. Ana makinedeki Tablo1 de 1000 kayıt olsun. Arsiv Makinesinde bulunan  Tablo2History tablosunda da 10 milyon kayıt olsun. JOIN işleminde Link Server kullanalım ve kullanacağımız Link Server ismi ArsivDB olsun.

Normalde aşağıdaki gibi bir sorgu yazarız. JOIN işleminde Tablo2History deki tablodan sadece birkaç kayıt geleceğini biliyor olalım.

SELECT * FROM Tablo1 T WITH(NOLOCK)
INNER JOIN ArsivDB.dbo.Tablo2History TH WITH(NOLOCK) ON (TH.Tarih = T.Tarih)

Yukardaki sorkuda işleyiş şu şekilde oluyor:

1- Tablo2History tablosunda bulunan 10 milyon kayıt Arşiv Makinasından Ana Makineye taşınıyor.
2- JOIN işlemi Ana Makinede yapılıyor ve eşleşen bir kaç kayıt listeleniyor.

Yani bir kaç kayıt listelemek için 10 milyon kaydı ana makineye taşıyarak çok büyük külfet vermiş ve süreyi çok uzatmış oluyoruz.

Bunun yerine REMOTE komutunu sorguya ekleyerek performansı arttırmış oluruz.
Aşağıdaki gibi bir sorgu yazarsak

SELECT * FROM Tablo1 T WITH(NOLOCK)
INNER REMOTE JOIN ArsivDB.dbo.Tablo2History TH WITH(NOLOCK) ON (TH.Tarih = T.Tarih)

işleyiş şu şekilde oluyor:

1- Tablo1 tablosunda bulunan 1000 kayıt Ana Makinadan Arşiv Makinesine taşınıyor.
2- JOIN işlemi Arşiv Makinesinde yapılıyor ve eşleşen bir kaç kayıt Ana Makineye taşınarak listeleniyor.


REMOTE komutu sorguya şu görevi veriyor: JOIN işlemi sağdaki tablonun bulunduğu remote makinede yapılsın.

SQL Server - CROSS APPLY, OUTER APPLY - Performans

Bir sorguda ikinci bir tabloya JOIN yapmak istiyoruz yalnız o tablodan sadece eşleşen ilk kaydın gelmesini istiyoruz.

INNER JOIN yada LEFT JOIN de TOP 1 koyamıyoruz. CROSS APPLY ve OUTER APPLY yardımımıza yetişiyor.

CROSS APPLY -> INNER JOIN in dengi ve performansları aynı
OUTER APPLY -> LEFT JOIN in dengi ve performansları aynı

Örneğin Müşteri kayıtlarını tuttuğumuz bir tablomuz(Musteriler) ve müşterilerin hareketlerini logladığımız ikinci bir tablomuz(MusteriHareketLog) olsun.

Musteri tablomuzun verileri aşağıdaki gibi osun;

ID  MusteriIsmi
1    Ahmet ASLAN
2    Orhan YILMAZ
3    Sevim KOKMAZ
...

MusteriHareketLog tablomuzun verileri de aşağıdaki gibi osun;

ID  HaraketIsmi MusteriID   TarihSaat
1    Giris               1                   2015-04-20 15:00
2    İşlem1            1                   2015-04-20 15:01
3    Giris               3                   2015-04-21 16:00
4    İşlem2            3                   2015-04-21 16:05
5    Giris               2                   2015-04-23 11:30
6    İşlem3            2                   2015-04-23 11:32

Müşterilerin listesini almak istiyoruz ve bu listede son yaptığı işlemin tarih ve saatini de görmek istiyoruz. Eğer müşteri ve MusteriHareketLog tablolarını JOIN lersek bütün logları listelemiş oluruz. Bu bizim istediğimiz değil, istediğimiz liste için aşağıdaki gibi bir sorgu yazmamız yeterli oluyor


SELECT *  FROM Musteri M WITH(NOLOCK)
CROSS APPLY(
                                SELECT TOP 1 TarihSaat FROM MusteriHareketLog L WITH(NOLOCK)
                                WHERE L.MusteriID = M.ID ORDER BY TarihSaat DESC
                           ) T

SQL Server - CTE (Common Table Expressions) WITH TableName AS - Performans

Bir tabloyu aynı sorguda birden fazla okumamız gerektiğinde, yani recursive erişim gerektiğinde CTE çok kullanışlı olmaktadır.

Örneğin bir Menu tablonuz olsun. Aynı tabloda ana menu ve alt menuler aşağıdaki gibi tutuluyor olsun;

CREATE TABLE Menu(
    ID INT,
    Aciklama VARCHAR(50),
    AnaMenuID INT
)

Bu tablonun verileri aşağıdaki gibi olsun;

ID  Aciklama      AnaMenuID
1    Raporlar         0
2    Alt Rapor1     1
3    Alt Rapor2     1
4    Alt Rapor3     1
5    İşlemler          0
6    Alt İşlem1      5
7    Alt İşlem2      5
8    Alt İşlem3      5
9    Alt İşlem4      5

Biz menu ismini ve ana menü ismini aynı satırda listelemek istersek bu tabloya recursive erişmemiz gerekecek ve bunun için CTE yi aşağıdaki gibi kullanabiliriz;

WITH tempMenuList AS    -- Menu tablosu belleğe alınarak temp tablo oluşturulur
(
    SELECT * FROM Menu WITH(NOLOCK)
)
-- Buradan sonrasında tempMenuList tablosunu istediğimiz gibi kullanabiliriz. Sadece SELECT
--  değil çeşitli ihtiyaçlarda UPDATE, DELETE, INSERT komutları da kullanılabilir.
SELECT M1.ID, M1.Aciklama,  ISNULL(M2.Aciklama, '')  'AnaMenuAciklama'
FROM tempMenuList M1
LEFT JOIN tempMenuList M2 ON (M2.ID = M1.AnaMenuID)

CTE, sorgu sonucundan gelen verileri(bu örneğimizde Menu tablosunu) belleğe alarak recursive erişimde performansı artırmaktadır.

17 Nisan 2015 Cuma

Merhaba Dünya

Ekrana "Merhaba Dünya" yazdırmakla başlayan Yazılım hayatımda karşılaştığım zorlukları ve çözümlerini paylaşmak istediğim bu sayfa benim de bazen açıp ne yapmıştım diye bakma ihtiyacımdan doğmuştur :)