Selamlar... 


Çalıştığım firmada şöyle bir ihtiyacımız oldu. Canlı veritabanın yedeğini her gün bir arşiv sunucusuna yükleyip raporları buradan almamız icabetti.
Şu şekilde bir çözüme gittik.
Bir C# konsol uygulaması yazdık.
Bunu da Windows zamanlanmış görevlere yedeğin ortalama tamamlanma süresinden 1 saat kadar sonraya.
Uygulama şu şekilde çalışıyor:
- Veritabanı yedeği bir NAS cihazında(bir yedekleme sunucusunda).
- Öncelikle o sunucuya kullanıcı adı-şifre doğrulaması ile bağlanıp yedek dosyasını arşiv sunucusuna(uygulamamızın çalıştığı sunucu) alıyoruz.
- Yedekleme sunucusunda çok sayıda yedek olduğundan en güncel yedeği bulup kopyalıyor uygulamamız.
- Sonra yedeği arşiv sunucusuna kopyaladığımız yedek dosyasını veritabanına yüklüyoruz..
- Sonra yedek dosyamızı siliyoruz.
- Son olarak işlem ile ilgili bilgilendirme mesajı atıyoruz.
- Uygulamanın başlangıç ayarlarını normalde bir xml dosyasından alıyorum, ancak burada direkt kodun içinden alacak şekilde yazdım. 


Program.cs
using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlServer.Management.Smo;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;
namespace VtYedekYukleMesajAt
{
    class Program
    {
        private static string _uygulamaDizini = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
        private static string _sunucuAdresi = @"\\192.168.0.101\sqlbackup";
        private static string _sunucudakiYedekDosyaYolu = @"\\Z:\VERITABANI_backup_2015_06_16_020000_8320823.bak";
        private static string _veritabaniAdi = "VERITABANI";
        private static string _yedekDosyaYolu = _uygulamaDizini + "\\VERITABANI_Yedek.bak";
        private static string _sunucuAdi = @"\\192.168.0.55";
        private static string _veritabaniKullaniciAdi = "sa";
        private static string _veritabaniSifre = "123456";
        private static string _sunucuKullaniciAdi = "sqlbackup";
        private static string _sunucuSifre = "123456";
        private static string _fizikselDataDosyasi = "VERITABANI.mdf";
        private static string _fizikselLogDosyasi = "VERITABANI.ldf";
        private static string _mantiksalDataDosyasi = "VERITABANI_Data";
        private static string _mantiksalLogDosyasi = "VERITABANI_Log";
        private static string _sunucuDomain = "firmaismi";
        private static string _agYoluHarfi = "Z:";
        private static string _bilgiEPostaAdresi = "zamkinos@firmaismi.com.tr";
        private static string _smtpAdi = "zamkinos@firmaismi.com.tr";
        private static string _smtpSifresi = "123456";
        private static DateTime _baslangicZamani;
        private static DateTime _bitisZamani;
        static void Main(string[] args)
        {
            try
            {
                _baslangicZamani = DateTime.Now;
   dosyayiKopyala(_sunucuKullaniciAdi, _sunucuSifre);
                yedegiYukle(_veritabaniAdi, _yedekDosyaYolu, _sunucuAdi, _veritabaniKullaniciAdi, _veritabaniSifre);
                dosyayiSil(_yedekDosyaYolu);
                _bitisZamani = DateTime.Now;
                epostaYolla(_sunucudakiYedekDosyaYolu);
            }
            catch (Exception ex)
            {
                hatayiYaz(ex);
            }
        }
        private static void epostaYolla(string sunucudakiYedekDosyaYolu)
        {
            EPosta.EPostaYolla(_bilgiEPostaAdresi, "<br />" + sunucudakiYedekDosyaYolu + " yedek dosyasi basariyla yuklendi.<br />Baslangic Zamani: (" + _baslangicZamani.ToString() + ")<br />Bitiş Zamani: (" + _bitisZamani.ToString() + ")", "Yedek Yukleme Islemi", "sql@firmaismi.com.tr", "Sql Yedek", _smtpAdi, _smtpSifresi, new EPostaEki[] { });
        }
        private static void dosyayiKopyala(string username, string password)
        {
            NetworkConnection objNetworkConnection = new NetworkConnection(_sunucuAdresi, new System.Net.NetworkCredential(_sunucuKullaniciAdi, _sunucuSifre, _sunucuDomain), _agYoluHarfi);
            _sunucudakiYedekDosyaYolu = _sunucuAdresi + "\\" + objNetworkConnection.DosyaYolu;
            File.Copy(_sunucudakiYedekDosyaYolu, _yedekDosyaYolu, true);
        }
        private static void dosyayiSil(string yedekDosyaYolu)
        {
            File.Delete(_yedekDosyaYolu);
        }
        private static void yedegiYukle(String databaseName, String backUpFile, String serverName, String userName, String password)
        {
            ServerConnection conn = new ServerConnection(serverName, userName, password);
            conn.StatementTimeout = int.MaxValue;
            //conn.ServerInstance = serverName;
            Server srv = new Server(conn);
            int satir = 0;
            try
            {
                // Generate new FilePath for both Files.
                string fileMdf = System.IO.Path.Combine(srv.MasterDBPath, _fizikselDataDosyasi);
                string fileLdf = System.IO.Path.Combine(srv.MasterDBLogPath, _fizikselLogDosyasi);
                RelocateFile relocateMdf = new RelocateFile(_mantiksalDataDosyasi, fileMdf);
                RelocateFile relocateLdf = new RelocateFile(_mantiksalLogDosyasi, fileLdf);
                Restore res = new Restore();
                res.Devices.AddDevice(backUpFile, DeviceType.File);
                res.RelocateFiles.Add(relocateMdf);
                res.RelocateFiles.Add(relocateLdf);
                res.Database = databaseName;
                res.NoRecovery = false;
                res.ReplaceDatabase = true;
                satir = 1;
                srv.KillAllProcesses(databaseName); // 26.01.2016.
                satir = 2;
                res.SqlRestore(srv);
                satir = 3;
                conn.Disconnect();
            }
            catch (SmoException ex)
            {
                hatayiYaz(ex);
                throw new SmoException("[SmoException]:" + satir + ex.Message, ex.InnerException);
            }
            catch (IOException ex)
            {
                hatayiYaz(ex);
                throw new IOException("[IOException]:" + satir + ex.Message, ex.InnerException);
            }
            catch (Exception ex)
            {
                hatayiYaz(ex);
                throw new Exception("[Exception]:" + satir + ex.Message, ex.InnerException);
            }
        }
        private static void hatayiYaz(Exception ex)
        {
            StreamWriter file = new StreamWriter(_uygulamaDizini + "\\Hata.txt", true);
            file.WriteLine(Environment.NewLine + "=================");
            file.WriteLine("Tarih:" + DateTime.Now.ToString() + Environment.NewLine);
            file.WriteLine("Ex:(" + ex.Message + "), InnerEx:(" + ex.InnerException + ")");
            file.Close();
        }
    }
}


NetworkConnection.cs
using System;
using System.ComponentModel;
using System.IO;
using System.Net;
using System.Runtime.InteropServices;
namespace VtYedekYukleMesajAt
{
    public class NetworkConnection : IDisposable
    {
        #region Private Members
        private string _networkName;
        [DllImport("mpr.dll")]
        private static extern int WNetAddConnection2(NetResource netResource, string password, string username, int flags);
        [DllImport("mpr.dll")]
        private static extern int WNetCancelConnection2(string name, int flags, bool force);
        #endregion Private Members
        #region Public Members
        /// <summary>
        /// 
        /// </summary>
        public string DosyaYolu;
        #endregion Public Members
        #region Constructor
        /// <summary>
        /// 
        /// </summary>
        /// <param name="networkName"></param>
        /// <param name="credentials"></param>
        public NetworkConnection(string networkName, NetworkCredential credentials, string agYoluHarfi)
        {
            _networkName = networkName;
            var netResource = new NetResource()
            {
                Scope = ResourceScope.GlobalNetwork,
                ResourceType = ResourceType.Disk,
                DisplayType = ResourceDisplaytype.Share,
                RemoteName = networkName
            };
            var userName = string.IsNullOrEmpty(credentials.Domain)
                ? credentials.UserName
                : string.Format(@"{0}\{1}", credentials.Domain, credentials.UserName);
            var result = WNetAddConnection2(
                netResource,
                credentials.Password,
                userName,
                0);
            if (result != 0)
            {
                if (result == 1219) // Zaten baglanti var...
                {
                    System.IO.DriveInfo[] drives = System.IO.DriveInfo.GetDrives();
                    foreach (var drive in drives)
                    {
                        if (drive.Name.Equals(agYoluHarfi.Replace("\\", "").Replace(":", "")) && drive.DriveType == DriveType.Network)
                        {
                            DirectoryInfo hdDirectoryInWhichToSearch = new DirectoryInfo(agYoluHarfi);
                            guncelDosyayiBul(hdDirectoryInWhichToSearch);
                            break;
                        }
                    }
                    if (string.IsNullOrEmpty(this.DosyaYolu))
                    {
                        DirectoryInfo hdDirectoryInWhichToSearch2 = new DirectoryInfo(networkName);
                        guncelDosyayiBul(hdDirectoryInWhichToSearch2);
                    }
                }
                else
                {
                    throw new Win32Exception(result, "Error connecting to remote share");
                }
            }
            else
            {
                DirectoryInfo hdDirectoryInWhichToSearch = new DirectoryInfo(networkName);
                guncelDosyayiBul(hdDirectoryInWhichToSearch);
            }
        }
        #endregion Constructor
        #region Private Methods
        private void guncelDosyayiBul(DirectoryInfo hdDirectoryInWhichToSearch)
        {
            FileInfo[] filesInDir = hdDirectoryInWhichToSearch.GetFiles("*" + "VERITABANI" + "*.bak*");
            DateTime oncekiTarih = DateTime.MinValue;
            foreach (FileInfo foundFile in filesInDir)
            {
                if (oncekiTarih != DateTime.MinValue)
                {
                    if (oncekiTarih < foundFile.CreationTime.Date)
                    {
                        this.DosyaYolu = foundFile.Name;
                        oncekiTarih = foundFile.CreationTime.Date;
                    }
                }
                else
                {
                    oncekiTarih = foundFile.CreationTime.Date;
                    this.DosyaYolu = foundFile.Name;
                }
            }
        }
        #endregion Private Methods
        #region Public Methods
        ~NetworkConnection()
        {
            Dispose(false);
        }
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
        protected virtual void Dispose(bool disposing)
        {
            WNetCancelConnection2(_networkName, 0, true);
        }
        #endregion Public Methods
    }
    /// <summary>
    /// 
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public class NetResource
    {
        /// <summary>
        /// 
        /// </summary>
        public ResourceScope Scope;
        /// <summary>
        /// 
        /// </summary>
        public ResourceType ResourceType;
        /// <summary>
        /// 
        /// </summary>
        public ResourceDisplaytype DisplayType;
        /// <summary>
        /// 
        /// </summary>
        public int Usage;
        /// <summary>
        /// 
        /// </summary>
        public string LocalName;
        /// <summary>
        /// 
        /// </summary>
        public string RemoteName;
        /// <summary>
        /// 
        /// </summary>
        public string Comment;
        /// <summary>
        /// 
        /// </summary>
        public string Provider;
    }
    /// <summary>
    /// 
    /// </summary>
    public enum ResourceScope : int
    {
        /// <summary>
        /// 
        /// </summary>
        Connected = 1,
        /// <summary>
        /// 
        /// </summary>
        GlobalNetwork,
        /// <summary>
        /// 
        /// </summary>
        Remembered,
        /// <summary>
        /// 
        /// </summary>
        Recent,
        /// <summary>
        /// 
        /// </summary>
        Context
    };
    /// <summary>
    /// 
    /// </summary>
    public enum ResourceType : int
    {
        /// <summary>
        /// 
        /// </summary>
        Any = 0,
        /// <summary>
        /// 
        /// </summary>
        Disk = 1,
        /// <summary>
        /// 
        /// </summary>
        Print = 2,
        /// <summary>
        /// 
        /// </summary>
        Reserved = 8
    }
    /// <summary>
    /// 
    /// </summary>
    public enum ResourceDisplaytype : int
    {
        /// <summary>
        /// 
        /// </summary>
        Generic = 0x0,
        /// <summary>
        /// 
        /// </summary>
        Domain = 0x01,
        /// <summary>
        /// 
        /// </summary>
        Server = 0x02,
        /// <summary>
        /// 
        /// </summary>
        Share = 0x03,
        /// <summary>
        /// 
        /// </summary>
        File = 0x04,
        /// <summary>
        /// 
        /// </summary>
        Group = 0x05,
        /// <summary>
        /// 
        /// </summary>
        Network = 0x06,
        /// <summary>
        /// 
        /// </summary>
        Root = 0x07,
        /// <summary>
        /// 
        /// </summary>
        Shareadmin = 0x08,
        /// <summary>
        /// 
        /// </summary>
        Directory = 0x09,
        /// <summary>
        /// 
        /// </summary>
        Tree = 0x0a,
        /// <summary>
        /// 
        /// </summary>
        Ndscontainer = 0x0b
    }
}


EPosta.cs
using System;
using System.IO;
using System.Net.Mail;
using System.Text;
namespace VtYedekYukleMesajAt
{
    public class EPosta
    {
        public static string UygulamaDizini = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
        public static void EPostaYolla(string to, string body, string subject, string fromAddress, string fromDisplay, string credentialUser, string credentialPassword, params EPostaEki[] attachments)
        {
            string host = "mail.firmaismi.com.tr";
            //body = UpgradeEmailFormat(body);
            try
            {
                MailMessage mail = new MailMessage();
                mail.Body = body;
                mail.IsBodyHtml = true;
                mail.To.Add(new MailAddress(to));
                mail.From = new MailAddress(fromAddress, fromDisplay, Encoding.UTF8);
                mail.Subject = subject;
                mail.SubjectEncoding = Encoding.UTF8;
                mail.Priority = MailPriority.Normal;
                foreach (EPostaEki ma in attachments)
                {
                    mail.Attachments.Add(ma.File);
                }
                SmtpClient smtp = new SmtpClient();
                smtp.Credentials = new System.Net.NetworkCredential(credentialUser, credentialPassword);
                smtp.Host = host;
                smtp.Send(mail);
            }
            catch (Exception ex)
            {
                StringBuilder sb = new StringBuilder();
                sb.Append("\nTo:" + to);
                sb.Append("\nbody:" + body);
                sb.Append("\nsubject:" + subject);
                sb.Append("\nfromAddress:" + fromAddress);
                sb.Append("\nfromDisplay:" + fromDisplay);
                sb.Append("\ncredentialUser:" + credentialUser);
                sb.Append("\ncredentialPasswordto:" + credentialPassword);
                sb.Append("\nHosting:" + host);
                sb.Append("\nException:" + ex.Message);
                // Write the string to a file.
                StreamWriter file = new StreamWriter(UygulamaDizini + "\\Hata.txt", true);
                file.WriteLine(Environment.NewLine + "=================");
                file.WriteLine("Tarih:" + DateTime.Now.ToString() + Environment.NewLine);
                file.WriteLine(sb.ToString());
                file.Close();
                //ErrorLog(sb.ToString(), ex.ToString(), ErrorLogCause.EmailSystem);
            }
        }
    }
}


Saygılar...
# Kategoriler : C# Sql Server Veritabanı Yazılım
# Etiketler : Etiket Yok
# Yorumlar : 0 Yorum Yorum Yaz

Selamlar...

Sql Server'da bir tabloda bir değerin hem Rusça, hem de Türkçe karşılığını tutma ihtiyacınız olduğunu varsayalım. İki alan tanımlayalım NVARCHAR türünde, TurkceAciklama ve RuscaAciklama şeklinde.

 

CREATE TABLE TABLOISMI(

[Id] [numeric](10, 0) IDENTITY(1,1) NOT NULL,

[TurkceAciklama] [nvarchar](60) NULL,

[RuscaAciklama] [nvarchar](60) COLLATE Cyrillic_General_CI_AS_KS NULL

)

 

Bu alana değer ataması yaparken de, string ifademizin önüne "N" eklemek gerekiyor.

 

INSERT INTO TABLOISMI VALUES ('Türkçesi', N'Rusçası:я,ё,ю,и,е,ь')

 

Saygılar...

# Kategoriler : Sql Server Veritabanı
# Etiketler : Etiket Yok
# Yorumlar : 0 Yorum Yorum Yaz

Selamlar...

SQL Server'dan e-posta gönderebilmek için aşağıdaki şekilde ayar yapmamız gerekiyor.

Daha sonra bir veritabanı işi oluşturup, bu ayarları kullanarak e-posta gönderebileceğiz.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Saygılar...

# Kategoriler : Sql Server Veritabanı
# Etiketler : Etiket Yok
# Yorumlar : 0 Yorum Yorum Yaz
Selamlar...
Veritabanında e-posta ayarlarını yapmıştık. İlgili yazıya buradan ulaşılabilir. 
Peki bu ayarları nasıl kullanacağız?
Gerçek bir örnek verelim.
Bir firmada çalışıyorsunuz ve o gün doğum günü olan bir çalışan varsa tebrik mesajı atılması gerekiyor.
Adi, Soyadi, Aktif ve DogumTarihi alanlarından oluşan bir PERSONEL tablomuz olsun.
Her gün çalışacak bir veritabanı işi yazalım.
Bu iş o gün doğum günü olanları bulup otomatik doğum günü tebrik mesajı yollayacak.
Burada kritik noktalardan birisi <img src="cid:DogumGunu.jpg" /> ifadesi. Resmin yolunu parametre kısmında veriyoruz. Mesajın içerisinde ise id'sini veriyoruz. Diğer türlü resim gözükmeyebiliyor.
Bir diğer dikkat edilmesi gereken kısım da, isimlerin sonuna eklediğimiz ek. Bütün isimlerin sonuna aynı ek ifadesini eklemek çok hoş olmuyor. Ahmet Yıldız'in, Nurettin Küpür'in,...vs yerine uygun eki buluyoruz.
 
DECLARE @tableHTML NVARCHAR(MAX) ;
DECLARE @gununTarihi DATE ;
DECLARE @personelCursor CURSOR ;
DECLARE @personelAdiSoyadi NVARCHAR(100) = '';
DECLARE @adSoyadTumu NVARCHAR(250) = '';
DECLARE @ekKismi NVARCHAR(3) = '';
DECLARE @sonHarf NVARCHAR(1) = '';
DECLARE @toplamUzunluk INT = 0;
DECLARE @strGecici NVARCHAR(250) = '';
 
SET @gununTarihi = CONVERT(DATE, GETDATE(), 103) 
SET @personelCursor = CURSOR FAST_FORWARD 
    FOR SELECT p.Adi + ' ' + p.Soyadi As PersonelAdiSoyadi
        FROM   dbo.PERSONEL p 
        Where DATEPART(MONTH, p.DogumTarihi) = DATEPART(MONTH, @gununTarihi)
        And DATEPART(DAY, p.DogumTarihi) = DATEPART(DAY, @gununTarihi)
        And p.Aktif = 1
 
    OPEN @personelCursor 
         
    FETCH NEXT FROM @personelCursor INTO @personelAdiSoyadi
 
    WHILE @@FETCH_STATUS = 0 
      BEGIN
        SET @adSoyadTumu = @adSoyadTumu + ', ' + @personelAdiSoyadi
        FETCH NEXT FROM @personelCursor INTO @personelAdiSoyadi
      END
    CLOSE @personelCursor
    DEALLOCATE @personelCursor 
    IF (@adSoyadTumu <> '')
        BEGIN
        Set @adSoyadTumu = SUBSTRING(@adSoyadTumu, 3, LEN(@adSoyadTumu)-2);
        Set @toplamUzunluk = LEN(@adSoyadTumu);
        Set @sonHarf = SUBSTRING(@adSoyadTumu, @toplamUzunluk, 1);
        If (UPPER(@sonHarf) = 'A' Or UPPER(@sonHarf) = 'I') 
            Begin
                Set @ekKismi = 'nın';
            End
        Else If (UPPER(@sonHarf) = 'E' Or UPPER(@sonHarf) = 'İ') 
            Begin
                Set @ekKismi = 'nin';
            End
        Else If (UPPER(@sonHarf) = 'O' Or UPPER(@sonHarf) = 'U') 
            Begin
                Set @ekKismi = 'nun';
            End
        Else If (UPPER(@sonHarf) = 'Ö' Or UPPER(@sonHarf) = 'Ü') 
            Begin
                Set @ekKismi = 'nün';
            End
        Else
            Begin
                Set @strGecici = @adSoyadTumu;
                SET @toplamUzunluk = LEN(@strGecici); 
                WHILE (@toplamUzunluk > 1)
                   BEGIN   
                         SELECT
                            @strGecici = LEFT(@strGecici, @toplamUzunluk - 1); 
                            SET @toplamUzunluk = LEN(@strGecici); 
                            Set @sonHarf = SUBSTRING(@strGecici, @toplamUzunluk, 1);
                            If (UPPER(@sonHarf) = 'A' Or UPPER(@sonHarf) = 'I') 
                                Begin
                                    Set @ekKismi = 'ın';
                                    Break;
                                End
                            Else If (UPPER(@sonHarf) = 'E' Or UPPER(@sonHarf) = 'İ') 
                                Begin
                                    Set @ekKismi = 'in';
                                    Break;
                                End
                            Else If (UPPER(@sonHarf) = 'O' Or UPPER(@sonHarf) = 'U') 
                                Begin
                                    Set @ekKismi = 'un';
                                    Break;
                                End
                            Else If (UPPER(@sonHarf) = 'Ö' Or UPPER(@sonHarf) = 'Ü') 
                                Begin
                                    Set @ekKismi = 'ün';
                                    Break;
                                End
                   END
            End
        SET @tableHTML =
            N'<html><head></head><body>' +
            N'    <table style="width: 100%;">' +
            N'        <tr><td style="text-align:center"><img src="cid:DogumGunu.jpg" /></td></tr>' +
            N'        <tr><td style="text-align:center; font-family:''Monotype Corsiva''; font-size:x-large">' +
            N'            Bugün ' + @adSoyadTumu + '''' + @ekKismi + ' doğum günü...<br />' +
            N'            Doğum gününüzü kutlar,<br />' +
            N'            sevdiklerinizle birlikte<br />' +
            N'          daha nice mutlu yıllar geçirmenizi dileriz...' +
            N'            </td></tr>' +
            N'        <tr><td style="text-align:center; font-size:28.0pt;font-family:''Impact'',sans-serif; color:maroon">' +
            N'            <i>~ İnsan Kaynakları ~</i>' +
            N'            </td></tr>' +
            N'    </table>' +
            N'</body></html>' ;
     
            EXEC msdb.dbo.sp_send_dbmail
            @profile_name = 'otomatik',
            @recipients = 'tumfirma@firmaadi.com.tr',
            @blind_copy_recipients = 'sizinadresiniz@firmaadi.com.tr',
            @body = @tableHTML,
            @body_format = 'HTML',
            @file_attachments = 'c:/VTResim/DogumGunu.jpg',
            @subject = 'Doğum Günü' ;
    END
GO
 

Bu Sql'i her gün çalışacak bir işin için eklemek de çok basit.

 

  

 

 

 

 

 

Saygılar...

# Kategoriler : Sql Server Veritabanı
# Etiketler : Etiket Yok
# Yorumlar : 0 Yorum Yorum Yaz
Selamlar...
Başlığı biraz daha açmak gerekebilir.
Misal MUSTERI isimli bir tablonuz var. Bu tabloyla bağlantılı, aralarında FOREIGN KEY ilişkisi olmayan bir çok tablonuz daha olsun.
MUSTERI tablosundaki bir MusteriNo değeri değiştiğinde ilişkili tablolarda da gerekli güncellemeyi yapmak lazım haliyle.
Peki hangi tabloda bu değer var nasıl buluruz kolayca?
İşte aşağıdaki şekilde bulabiliriz:
DECLARE @kolonAdi NVARCHAR(20);
DECLARE @tabloAdi NVARCHAR(50);
DECLARE @arananDeger NVARCHAR(50);
DECLARE @dinamikSql NVARCHAR(1000);
DECLARE @tabloCursor CURSOR
  
SET @kolonAdi = 'MusteriNo';
SET @arananDeger = '123456789';
  
SET @tabloCursor = CURSOR FAST_FORWARD
FOR SELECT table_name from INFORMATION_SCHEMA.COLUMNS
       WHERE TABLE_CATALOG = '[VeritabaniAdi]'
       AND COLUMN_NAME = @kolonAdi
       AND table_name LIKE '[IstegeBagliTabloOnEki]%'
  
       OPEN @tabloCursor
       FETCH NEXT FROM @tabloCursor INTO @tabloAdi
             WHILE @@FETCH_STATUS = 0
               BEGIN
                    SET @dinamikSql = ' SELECT ''' + @tabloAdi  + ''', tbl.* FROM [' + @tabloAdi + '] tbl'
                    SET @dinamikSql = @dinamikSql + ' WHERE tbl.[' + @kolonAdi + '] = ''' + @arananDeger + ''' ' ;
                          EXEC (@dinamikSql)
                    FETCH NEXT FROM @tabloCursor INTO @tabloAdi
               END
       CLOSE @tabloCursor;
       DEALLOCATE @tabloCursor;
GO
 
Burada diğer tablolarda da alanın adının MusteriNo olduğunu varsaydık.
Dilerseniz kolon adını LIKE ile aratıp içerisinde belirleyeceğimiz ifade geçen kolonları da aratabiliriz.
Bundan sonrası ihtiyaç ve hayal gücünüze kalmış.
 
Saygılar...
# Kategoriler : Sql Server Veritabanı
# Etiketler : Etiket Yok
# Yorumlar : 0 Yorum Yorum Yaz
Selamlar...
Sql Server'da indeksler zamanla parçalanıyor. Bu da okuma ve yazma hızını etkiliyor.   
Bunlara arada sırada bakım yapmak gerekiyor. Ancak bakımın da bazı kriterleri var. 
Misal, hergün indekslere rebuild işlemi uygulamak ve ayrıca tüm indekslere bunu uygulamak da doğru değil.
İnternette araştırdığım kadarıyla genel yaklaşım, indeks'in ortalama bozulma oranı ve sayfa sayısına göre uygun bir çözüm bulmak yönünde. 
Sadece indeks oranı yeterli değil, ReBuild ya da ReOrganize için. Kayıt sayısı da önemli. Kayıt sayısı az olan tablolarda mesela bu değer büyük. 
Ancak  sayfa sayısı 1.000 küçükse işlem yapmaya çok da gerek olmayabilir. (https://technet.microsoft.com/en-us/library/cc966523.aspx)
http://www.turgaysahtiyan.com adresinde bir store prosedür buldum. Parçalanma oranına göre Rebuild ya da ReOrganize yapıyor. Gayet temiz ve iş gören bir script.
Aslında bu işin otoritesi Ola Hallengren diye biri sanırım. İnternette herkes onun hazırladığı bakım scriptinden bahsediyor. 
Hatta http://sqlskills.com/ sitesinden bir yönetici ile yazıştım birkaç soru sormak için, o bile direkt bunu söyledi.
Her şeyi yapıyor, fakat çok karışık. (https://ola.hallengren.com/sql-server-index-and-statistics-maintenance.html). O yüzden ilk script üzerinden gitmeyi tercih ettim.
Bu scripte istatistik, kayıt sayısı kontrolü ve sonuç raporu ile ilgili eklemeler yaptim.
İstatistik de performansı etkileyen bir unsur bazı durumlarda. Bir sorgu çalışmadan evvel SQL Server, kaç kayıt döneceğini hesaplamak için kullanıyor. 
Ona göre tabloyu okuyor. Aslında ReBuild işlemi ilgili indekse ait istatistiği de güncelliyor, fakat burada şunlar aklımıza geliyor:
1- ReOrganize yaptığımız indekslere ait istatistikleri güncellememiz gerekmiyor mu?
2- Rebuild sadece indekslere ait istatistikleri güncelliyor, ya tabloya ait indeks olmayan kolonlara ait istatistikler ne olacak?
Bu sorulara farklı kaynaklardan bulduğum cevapları harmanlayarak scriptte düzenlemeler yaptım.
Öncelikle bozulma oranının yanında sayfa sayısı da önemli olduğundan sayfa sayısı 1.000'den düşük olanlarda indekslere herhangi bir işlem yapmıyorum.
- İndeks ReBuild işleminden sonra istatistikleri güncellemekle ilgili herhangi bir işleme gerek yok.
- İndeks ReOrganize işleminden sonra istatistikleri güncelliyorum.
- Her iki işleme de tabi tutulmamış indeksler için de sadece istatistikleri güncelliyorum.
- İndekslerle ilgili işlem bittikten sonra da içerisinde kayıt olan tüm tabloları dolaşarak, sadece kolon istatistiklerini güncelliyorum.
- Tüm işlemler bittikten sonra da yetkili kişiye e-posta yolluyorum.
Bu işlem çok miktarda RAM tüketiyor. Sql Server'ın ilginç bir özelliği de RAM'i kullandıktan sonra işi bitse de bırakmıyor. Ancak RAM'e ihtiyaç duyan bir
iş çalışırsa işletim sistemi bırakmaya zorluyor. Ancak RAM'in bu şekilde yüksek gözükmesi herhangi bir performans sorununun işareti değil. 
SQL Server sadece alıkoyuyor, kullanmıyor aslında işi bitince.
Bunun haftada bir çalışması yeterli gibi görünüyor başlangıçta. Zaten bir süre sonra işlediği kayıt sayısında azalma olmasını bekleriz en azından indekslerde.
Ancak istatistikleri her hafta güncellemek işlem zamanını çok artırıyor. 
Sql Server veritabanının ayarı da AUTO_CREATE_STATISTICS->on ve AUTO_UPDATE_STATISTICS->on ise istatistikleri her hafta güncellemek çok da elzem değil gibi.
Bu sebeple scripte ayın başı olup olmadığını kontrol etme şartı ekledim.
Eğer script ayın ilk haftası çalışıyorsa istatistikleri de güncelliyor, değilse sadece indekslerle ilgileniyor.
 
IF OBJECT_ID('INDEKS_ISTATISTIK_BAKIMI', 'P') IS NOT NULL
  DROP PROCEDURE INDEKS_ISTATISTIK_BAKIMI 
GO 
 
CREATE PROC [INDEKS_ISTATISTIK_BAKIMI] @DBName VARCHAR(100) 
AS
  BEGIN
      SET NOCOUNT ON; 
      DECLARE @OBJECT_ID            INT, 
              @INDEX_NAME           SYSNAME, 
              @SCHEMA_NAME          SYSNAME, 
              @OBJECT_NAME          SYSNAME, 
              @AVG_FRAG             FLOAT, 
              @FRAG_COUNT           BIGINT, 
              @sqlCommand           NVARCHAR(MAX), 
              @sqlCommandIndex      NVARCHAR(MAX), 
              @sqlCommandStats      NVARCHAR(MAX), 
              @rebuildCount         INT, 
              @reOrganizeCount      INT,
              @indexStatsCount      INT, 
              @kolonStatsCount      INT, 
              @reOrganizeStatsCount INT, 
              @tableName            SYSNAME, 
              @schemaName           SYSNAME, 
              @msgContent           NVARCHAR(MAX),
              @msgHeader            NVARCHAR(MAX),
              @dStart               DATETIME,
              @dFinish              DATETIME,
              @ayinKacinciHaftasi   INT
      CREATE TABLE #tempIM 
        ( 
           [ID]             [INT] IDENTITY(1, 1) NOT NULL PRIMARY KEY, 
           [INDEX_NAME]     SYSNAME NULL, 
           [OBJECT_ID]      INT NULL, 
           [SCHEMA_NAME]    SYSNAME NULL, 
           [OBJECT_NAME]    SYSNAME NULL, 
           [AVG_FRAG]       FLOAT,
           [FRAG_COUNT]     BIGINT
        ) 
      SELECT @rebuildCount = 0, 
             @reOrganizeCount = 0,
             @indexStatsCount = 0,
             @reOrganizeStatsCount = 0,
             @kolonStatsCount = 0;
      SELECT @msgContent = '',
             @sqlCommand = '',
             @sqlCommandIndex = '',
             @sqlCommandStats = '';  
      SET @ayinKacinciHaftasi = (SELECT DATEPART(DAY, DATEDIFF(DAY, 0, GETDATE())/7 * 7) / 7 + 1);
      SELECT @msgHeader = '<html><head><style type="text/css">table.tblMesaj {font-family: verdana,arial,sans-serif;font-size:11px;color:#333333;border-width: 1px;border-color: #666666;border-collapse: collapse;}' ;
      SET @msgHeader = @msgHeader + 'table.tblMesaj th {border-width: 1px;padding: 8px;border-style: solid;border-color: #666666;background-color: #dedede;}' ;  
      SET @msgHeader = @msgHeader + 'table.tblMesaj td {border-width: 1px;padding: 8px;border-style: solid;border-color: #666666;background-color: #ffffff;}</style></head><body>' ;
      SET @msgHeader = @msgHeader + '<table class="tblMesaj"><tr><th colspan="2">İNDEKS - İSTATİSTİK BAKIMI SONUÇLARI</th></tr>' ;
      SET @dStart = GETDATE();
       
      SELECT @sqlCommand = 'USE ' + @DBName + '; INSERT INTO #tempIM (OBJECT_ID, INDEX_NAME, SCHEMA_NAME, OBJECT_NAME, AVG_FRAG, FRAG_COUNT) ';
      SET @sqlCommand = @sqlCommand + ' SELECT ps.object_id, i.name as IndexName, OBJECT_SCHEMA_NAME(ps.object_id) as ObjectSchemaName, OBJECT_NAME (ps.object_id) as ObjectName, ';
      SET @sqlCommand = @sqlCommand + ' ps.avg_fragmentation_in_percent, ps.fragment_count FROM sys.dm_db_index_physical_stats (NULL, NULL, NULL , NULL, ''LIMITED'') ps INNER JOIN sys.indexes i ';
      SET @sqlCommand = @sqlCommand + ' ON i.object_id = ps.object_id and i.index_id = ps.index_id WHERE ps.index_id > 0 and ps.database_id = DB_ID(''' + @DBName + ''') ORDER BY avg_fragmentation_in_percent desc ' ;     
      EXEC(@sqlCommand) ; 
      
      SELECT @sqlCommandIndex = 'USE ' + @DBName + '; ';
      DECLARE c CURSOR FAST_FORWARD FOR
        SELECT OBJECT_ID, 
               INDEX_NAME, 
               SCHEMA_NAME, 
               OBJECT_NAME, 
               AVG_FRAG,
               FRAG_COUNT
        FROM   #tempIM 
      OPEN c 
      FETCH NEXT FROM c INTO @OBJECT_ID, @INDEX_NAME, @SCHEMA_NAME, @OBJECT_NAME, @AVG_FRAG, @FRAG_COUNT 
      WHILE @@FETCH_STATUS = 0 
        BEGIN
            -- Reorganize veya Rebuild İşlemi.
            IF @AVG_FRAG > 30 AND @FRAG_COUNT > 1000 
              BEGIN
                  SET @sqlCommandIndex = @sqlCommandIndex + ' ALTER INDEX [' + @INDEX_NAME + '] ON [' + @SCHEMA_NAME + '].[' + @OBJECT_NAME + '] REBUILD WITH (ONLINE = ON);' ; 
                  SET @rebuildCount = @rebuildCount + 1 ;
              END
            ELSE -- Rebuild index istatistikleri de guncelliyor. Ancak reorganize istatistikleri guncellemiyor.
                IF @AVG_FRAG <= 30 AND @AVG_FRAG > 5 AND @FRAG_COUNT > 1000 
                    BEGIN
                          SET @sqlCommandIndex = @sqlCommandIndex + ' ALTER INDEX [' + @INDEX_NAME + '] ON [' + @SCHEMA_NAME + '].[' + @OBJECT_NAME + '] REORGANIZE;'
                          SET @sqlCommandStats = @sqlCommandStats + ' UPDATE STATISTICS [' + @SCHEMA_NAME + '].[' + @OBJECT_NAME + '] [' + @INDEX_NAME + '] WITH FULLSCAN, NORECOMPUTE;' ;  
                          SET @reOrganizeCount = @reOrganizeCount + 1 ; 
                          SET @reOrganizeStatsCount = @reOrganizeStatsCount + 1 ; 
                    END
                ELSE -- Kalanlari da ekleyelim. 
                    BEGIN
                          SET @sqlCommandStats = @sqlCommandStats + ' UPDATE STATISTICS [' + @SCHEMA_NAME + '].[' + @OBJECT_NAME + '] [' + @INDEX_NAME + '] WITH FULLSCAN, NORECOMPUTE;'; 
                          SET @indexStatsCount = @indexStatsCount + 1 
                    END
            FETCH NEXT FROM c INTO @OBJECT_ID, @INDEX_NAME, @SCHEMA_NAME, @OBJECT_NAME, @AVG_FRAG, @FRAG_COUNT  
        END
      CLOSE c 
      DEALLOCATE c 
      DROP TABLE #tempIM 
      EXEC (@sqlCommandIndex); 
      --PRINT 'indeksler tamamdır.';
-- Son olarak da indeksler haricindeki kolonlarin istatistiklerini guncelleyelim.
      IF (@ayinKacinciHaftasi = 1)
        BEGIN
          CREATE TABLE #tempIST 
            ( 
               [ID]             [INT] IDENTITY(1, 1) NOT NULL PRIMARY KEY, 
               [TABLE_NAME]     SYSNAME NULL, 
               [SCHEMA_NAME]    SYSNAME NULL
            ) 
           
          SELECT @sqlCommand = 'USE ' + @DBName + '; INSERT INTO #tempIST (TABLE_NAME, SCHEMA_NAME) ';
          SET @sqlCommand = @sqlCommand + ' SELECT t.NAME, s.Name FROM sys.tables t INNER JOIN sys.indexes i ON t.OBJECT_ID = i.object_id ';
          SET @sqlCommand = @sqlCommand + ' INNER JOIN sys.partitions p ON i.object_id = p.OBJECT_ID AND i.index_id = p.index_id ';
          SET @sqlCommand = @sqlCommand + ' INNER JOIN sys.allocation_units a ON p.partition_id = a.container_id ';
          SET @sqlCommand = @sqlCommand + ' LEFT OUTER JOIN sys.schemas s ON t.schema_id = s.schema_id ';
          SET @sqlCommand = @sqlCommand + ' WHERE t.NAME NOT LIKE ''dt%'' AND t.is_ms_shipped = 0 AND i.OBJECT_ID > 255 AND a.used_pages > 0 GROUP BY t.Name, s.Name' ;
          EXEC(@sqlCommand) ; 
           
          SELECT @sqlCommandStats = 'USE ' + @DBName + '; ' + @sqlCommandStats;
          DECLARE c2 CURSOR FAST_FORWARD FOR
            SELECT TABLE_NAME, SCHEMA_NAME FROM #tempIST
          OPEN c2 
          FETCH NEXT FROM c2 INTO @tableName, @schemaName 
          WHILE @@FETCH_STATUS = 0 
            BEGIN
                SET @sqlCommandStats = @sqlCommandStats + ' UPDATE STATISTICS [' + @schemaName + '].[' + @tableName + '] WITH FULLSCAN, COLUMNS;'; 
                SET @kolonStatsCount = @kolonStatsCount + 1 ;
                FETCH NEXT FROM c2 INTO @tableName, @schemaName   
            END
          CLOSE c2; 
          DEALLOCATE c2; 
          DROP TABLE #tempIST;
          EXEC (@sqlCommandStats);
          --PRINT 'kolonlar tamamdır.';
        END
         
      SELECT 'İşlem başarılı' AS RESULT ;
       
      SET @dFinish = GETDATE();
      SET @msgContent = @msgHeader + '<tr><td>Başlangıç zamanı</td><td>' + CAST(@dStart AS nvarchar(30)) + '</td></tr>'
                        + '<tr><td>Bitiş zamanı</td><td>' + CAST(@dFinish AS nvarchar(30)) + '</td></tr>'
                        + '<tr><td>Rebuild işlemine tabi tutulmuş indeks sayısı</td><td>' + CAST(@rebuildCount AS VARCHAR(5)) + '</td></tr>'
                        + '<tr><td>Reorganize işlemine tabi tutulmuş indeks sayısı</td><td>' + CAST(@reOrganizeCount AS VARCHAR(5)) + '</td></tr>'
                        + '<tr><td>Reorganize işlemine tabi tutulmuş indekslere ait güncellenen istatistik sayısı</td><td>' + CAST(@reOrganizeStatsCount AS VARCHAR(5)) + '</td></tr>'
                        + '<tr><td>Rebuild/Reorganize işlemine tabi tutulmamış indekslere ait güncellenen istatistik sayısı</td><td>' + CAST(@indexStatsCount AS VARCHAR(5)) + '</td></tr>'
                        + '<tr><td>İndeks olmayan güncellenen kolon istatistik sayısı</td><td>' + CAST(@kolonStatsCount AS VARCHAR(5)) + '</td></tr></table></body></html>'
 
      EXEC msdb.dbo.sp_send_dbmail
            @profile_name = 'bt_noreply',
            @recipients = 'isminiz@firmadi.com.tr',
            @blind_copy_recipients = 'ikinciisim@firmadi.com.tr',
            @body = @msgContent,
            @body_format = 'HTML',
            @subject = 'İndeks-İstatistik Bakım' ;
 
  END
 
Bu prosedürü oluşturduktan sonra her hafta çalışan bir iş tanımlayıp çağırmak yeterli.
EXEC master.dbo.INDEKS_ISTATISTIK_BAKIMI 'VeritabaniAdi'
Saygılar...
# Kategoriler : Sql Server Veritabanı
# Etiketler : Etiket Yok
# Yorumlar : 0 Yorum Yorum Yaz
Selamlar...
Microsoft Dynamics NAV ERP uygulamasının kullandığı veritabanının bir yedeğini de farklı bir sunucuya yükleyerek, bir test sunucusu oluşturabiliriz.
Yedek dosyasını sunucuya yükleme işleminde özel bir durum yok, ancak bu yükleme işleminden sonra Navision uygulamasından veritabanına bağlanamıyoruz.
Çünkü kullanıcıların oluşturulması gerekiyor.
İşte bu ihtiyaç için, gerçek ortamdaki veritabanı sunucusundan kullanıcı bilgilerini alıp test sunucusuna oluşturan bir script yazdım.
Test sunucunuza gerçek ortam ortam sunucunuzu "Linked Server" olarak eklemek gerekiyor öncelikle.
Sonra da bu scripti çalıştırdığınızda, root seviyedeki kullanıcıları varsa silip tekrar oluşturuyor ve NAVISION veritabanına database_owner olarak rol tanımlıyor.
DECLARE @strSql NVARCHAR(MAX);
DECLARE @kullaniciAdi SYSNAME;
DECLARE @kullaniciSifre NVARCHAR(MAX);
DECLARE @kullaniciCursor CURSOR;
 
SET @strSql = '';
SET @kullaniciCursor = CURSOR FAST_FORWARD 
    FOR
        -- Gercek ortamdaki sunucuyu [Server Objects -> Linked Servers] altina ekledik. Oradan guncel kullanici bilgisini aliyoruz.
        SELECT SP.name, CONVERT(NVARCHAR(MAX), SL.password_hash, 1) 
            FROM [GercekNavisionSunucusu].master.sys.server_principals AS SP
                LEFT OUTER JOIN [GercekNavisionSunucusu].master.sys.sql_logins AS SL ON SP.principal_id = SL.principal_id
        WHERE SP.type_desc = 'SQL_LOGIN'
            AND SP.name NOT LIKE '##%##'
            AND SP.name IN ('Kullanici1', 'Kullanici2', 'Kullanici3', 'Kullanici4'); -- Sadece belirli kullanicilari olusturalim.
 
    -- Buldugumuz kullanicilar icinde dolasiyoruz.
    OPEN @kullaniciCursor 
    FETCH NEXT FROM @kullaniciCursor INTO @kullaniciAdi, @kullaniciSifre
 
    WHILE @@FETCH_STATUS = 0 
      BEGIN
        SELECT @strSql =  @strSql + 
            -- Bazi kullanicilara ait semalar var(kullanici adiyla ayni), bu durumda kullaniciyi silemiyor. Once onlarin dbo yapalim.
            ' IF EXISTS (SELECT name FROM sys.schemas WHERE name = N''' + @kullaniciAdi + ''') ' +
            ' BEGIN ALTER AUTHORIZATION ON SCHEMA::' + @kullaniciAdi + ' TO dbo END; ' +
 
            -- Sonra eger varsa, ana seviyedeki kullanicilari silip tekrar guncel sifreleriyle olusturalim.  
            ' IF(SUSER_ID(' + QUOTENAME(@kullaniciAdi, '''') + ') IS NOT NULL) BEGIN DROP LOGIN ' + QUOTENAME(@kullaniciAdi) + ' END;' +
            ' CREATE LOGIN ' + QUOTENAME(@kullaniciAdi) +
            ' WITH PASSWORD = ' + @kullaniciSifre + ' HASHED; ' +
 
            -- Veritabani seviyesindeki kullaniciyi da silelim ve yeniden yukaridaki giris kullanicisiyla eslesmis sekilde olusturalim.
            ' USE NAVISION; IF (EXISTS (SELECT * FROM sys.database_principals WHERE name = N''' + @kullaniciAdi + ''')) BEGIN DROP USER [' + @kullaniciAdi + '] END; ' +
            ' CREATE USER [' + @kullaniciAdi + '] FOR LOGIN [' + @kullaniciAdi + '] WITH DEFAULT_SCHEMA = [dbo]; ' + 
            ' USE NAVISION; EXEC sp_addrolemember N''db_owner'', N''' + @kullaniciAdi + '''; ' + CHAR(10);
        FETCH NEXT FROM @kullaniciCursor INTO @kullaniciAdi, @kullaniciSifre
      END
    CLOSE @kullaniciCursor;
    DEALLOCATE @kullaniciCursor; 
    --PRINT (@strSql);
    IF (@strSql <> '')
        BEGIN
            EXEC(@strSql) ; 
        END
    GO
 
Test sunucusuna NAVISION veritabanını ilk defa yüklüyorsanız, içerisinde 4616 geçen bir hata aldıysanız, öncelikle SQL Server Configuration Manager'dan Startup parametrelerine -4616 parametresini eklemeniz gerekiyor.
Sonra da aşağıdaki scripti çalıştırmanız gerekiyor.
USE [master]
GO
 
/****** Object:  ExtendedStoredProcedure [dbo].[xp_ndo_enumusergroups]    Script Date: 11.04.2015 09:00:41 ******/
EXEC dbo.sp_addextendedproc N'[dbo].[xp_ndo_enumusergroups]'
    ,'C:\Program Files\Microsoft SQL Server\MSSQL11.LOCALDB2\MSSQL\Binn\xp_ndo_x64.dll'
GO
/*========================*/
USE [master]
GO
 
/****** Object:  ExtendedStoredProcedure [dbo].[xp_ndo_enumusersids]    Script Date: 11.04.2015 09:00:52 ******/
EXEC dbo.sp_addextendedproc N'[dbo].[xp_ndo_enumusersids]'
    ,'C:\Program Files\Microsoft SQL Server\MSSQL11.LOCALDB2\MSSQL\Binn\xp_ndo_x64.dll'
GO
/*========================*/
GRANT EXECUTE
    ON [xp_ndo_enumusergroups]
    TO PUBLIC
GO
/*========================*/
GRANT EXECUTE
    ON [xp_ndo_enumusersids]
    TO PUBLIC
GO
 
-- Yukaridaki DLL'e Everyone yetkisi de verdim. Baska bir yerde okudugum bir oneriye istinaden.
-- DLL'lerin ilgili dizinlerde olmasi lazim.
-- SQL Server Configuration Manager acilip, bizim Sql Server sunucusunu secip, Advanced sekmesinde
---- Startup Parameters kismina cift tiklayarak sonuna ";-t4616" ekliyoruz.
 
Saygılar...
# Kategoriler : Navision Veritabanı
# Etiketler : Etiket Yok
# Yorumlar : 0 Yorum Yorum Yaz
Arama
  Ara
Sayfalar
Takvim
<Temmuz 2017>
PSÇPCCP
262728293012
3456789
10111213141516
17181920212223
24252627282930
31123456
Bağlantılar