SQL SERVER 2008

تجارب من در رابطه با SQL SERVER

چند Script خوب در رابطه با تعریف Job
ساعت ٥:٤۸ ‎ب.ظ روز ۱۳۸٧/۱٠/٢٤  کلمات کلیدی: sql server 2008 ، job ، automatic backup ، پشتیبانگیری خودکار

برای انجام کارها در SQL SERVER به صورت خودکار باید JOB تعریف کرد. این کار میتواند به صورت دستی از داخل برنامه انجام شود یا اینکه برای آن Script نوشت و آن را اجرا کرد. یکی سوالات متداول این است که چگونه میتوانیم به صورت خودکار از SQL SERVER پشتیبانگیری کنیم، این کار با JOB ها قابل انجام است. در زیر چند Job کاربردی برای نمونه آورده شده است:

Back up به صورت کامل : کد مثال برای تمام Job ها یک دایرکتوری به ازای هر پایگاه داده خواهد ساخت و از آن پشتیبانگیری میکند :

DECLARE @basePath varchar(300);
SET @basePath = N'M:\Program Files\Microsoft SQL Server\MSSQL10.MSSQLSERVER\MSSQL\Backup\';

DECLARE @db sysname;
DECLARE user_db_cursor CURSOR FOR
      SELECT name FROM sys.databases WHERE name NOT IN ('master', 'model', 'msdb', 'tempdb')
OPEN user_db_cursor
FETCH NEXT FROM user_db_cursor
INTO @db

WHILE @@FETCH_STATUS = 0
BEGIN
      DECLARE @backupPath varchar(1000);
      SET @backupPath = @basePath + @db + '\';

      DECLARE @backupName varchar(1000);
      DECLARE @time datetime2;
      SET @time = SYSDATETIME();
      SET @backupName = @db + '_backup_' + REPLACE(REPLACE(REPLACE(CONVERT(varchar, @time, 20),'-','_'),':',''),' ','_')
      + '_' +  CAST(DATEPART(NANOSECOND, @time)/100 as varchar)

      --Create sub-directory
      EXECUTE master.dbo.xp_create_subdir @backupPath
     
      DECLARE @backupFileName varchar(1000);
      SET @backupFileName = @backupPath + @backupName + '.bak';
     
      --Backup database
      BACKUP DATABASE @db TO DISK=@backupFileName
            WITH RETAINDAYS=14, NOFORMAT, NOINIT, NAME=@backupName ,
            SKIP, REWIND, NOUNLOAD, STATS=10

CLOSE user_db_cursor
DEALLOCATE user_db_cursor

پشتیبان Differential :

DECLARE @basePath varchar(300);
SET @basePath = N'M:\Program Files\Microsoft SQL Server\MSSQL10.MSSQLSERVER\MSSQL\Backup\';

DECLARE @db sysname;
DECLARE user_db_cursor CURSOR FOR
 SELECT name FROM sys.databases WHERE name NOT IN ('master', 'model', 'msdb', 'tempdb')
OPEN user_db_cursor
FETCH NEXT FROM user_db_cursor
INTO @db

WHILE @@FETCH_STATUS = 0
BEGIN
      DECLARE @backupPath varchar(1000);
      SET @backupPath = @basePath + @db + '\';

      DECLARE @backupName varchar(1000);
      DECLARE @time datetime2;
      SET @time = SYSDATETIME();
      SET @backupName = @db + '_backup_' + REPLACE(REPLACE(REPLACE(CONVERT(varchar, @time, 20),'-','_'),':',''),' ','_')
      + '_' + CAST(DATEPART(NANOSECOND, @time)/100 as varchar)

      --Create sub-directory
      EXECUTE master.dbo.xp_create_subdir @backupPath
     
      DECLARE @backupFileName varchar(1000);
      SET @backupFileName = @backupPath + @backupName + '.bak';
     
      --Backup database
      BACKUP DATABASE @db TO DISK=@backupFileName
            WITH DIFFERENTIAL, RETAINDAYS=14, NOFORMAT, NOINIT, NAME=@backupName ,
            SKIP, REWIND, NOUNLOAD, STATS=10
      
CLOSE user_db_cursor
DEALLOCATE user_db_cursor

پشتیبان  Transaction Log :

DECLARE @basePath varchar(300);
SET @basePath = N'M:\Program Files\Microsoft SQL Server\MSSQL10.MSSQLSERVER\MSSQL\Backup\';

DECLARE @db sysname;
DECLARE user_db_cursor CURSOR FOR
      SELECT name FROM sys.databases WHERE name NOT IN ('master', 'model', 'msdb', 'tempdb')
OPEN user_db_cursor
FETCH NEXT FROM user_db_cursor
INTO @db

WHILE @@FETCH_STATUS = 0
BEGIN
      DECLARE @backupPath varchar(1000);
      SET @backupPath = @basePath + @db + '\';

      DECLARE @backupName varchar(1000);
      DECLARE @time datetime2;
      SET @time = SYSDATETIME();
      SET @backupName = @db + '_backup_' + REPLACE(REPLACE(REPLACE(CONVERT(varchar, @time, 20),'-','_'),':',''),' ','_')
      + '_' +  CAST(DATEPART(NANOSECOND, @time)/100 as varchar)

      --Create sub-directory
      EXECUTE master.dbo.xp_create_subdir @backupPath
     
      DECLARE @backupFileName varchar(1000);
      SET @backupFileName = @backupPath + @backupName + '.trn';
     
      --Backup database
      BACKUP LOG @db TO DISK=@backupFileName
            WITH RETAINDAYS=14, NOFORMAT, NOINIT, NAME=@backupName ,
            SKIP, REWIND, NOUNLOAD, STATS=10
      
CLOSE user_db_cursor
DEALLOCATE user_db_cursor

اجرای Job Agent Task در SQL SERVER :

EXEC msdb.dbo.sp_start_job '<job name>';

نکته : این عملیات به کمک SQL Server Agent انجام میشود. اطمینان حاصل کنیدکه سرویس مربوط به آن run است.


 
ستونهای پراکنده (Sparse)
ساعت ٩:٢٧ ‎ب.ظ روز ۱۳۸٧/۱٠/۱٦  کلمات کلیدی: sql server 2008 ، sparse column

ستونهای پراکنده، ستونهایی هستند که برای ذخیره سازی NULL ها بهینه شده اند. برای تعریف یک ستون به عنوان Sparse ، مشخصه های آن را به عنوان بخشی از تعریف ستون مشخص کنید. Sparse ها هیچ فضایی را برای NULL مصرف نمیکنند، مطابق با انواع با طول ثابت; اگرچه وقتی یک ستون به عنوان sparse مشخص میشود، ذخیره مقادیر غیر Null از همیشه پر هزینه تر میشود. بنابراین شما فقط باید زمانی یک ستون را از نوع Sparse تعریف کنید که درصد زیادی از اطلاعات آن Null باشد. کتابهای online مربوط به SQL Server پیشنهاداتی در این زمینه دارد که چه مقدار از داده ها از هر نوع باید null باشد تا استفاده از sparse برای آن ستون مفید باشد.
Query زدن و پر کردن ستونهای sparse مانند ستونهای معمولیست با یک تفاوت که در جلوتر بیان خواهد شد. به عنوان مثال کد زیر یک جدول با نام T1 در tempdb (برای تست) میسازد، سه تا از ستونها با مشخصه sparse علامت گذاری میشوند، یک زوج از سطرها در آن insert میشوند و روی جدول  query زده میشود :


USE tempdb;
IF OBJECT_ID('dbo.T1', 'U') IS NOT NULL DROP TABLE dbo.T1;
CREATE TABLE dbo.T1
(
  keycol INT                   NOT NULL PRIMARY KEY,
  col1   VARCHAR(20)           NOT NULL,
  col2   INT            SPARSE     NULL,
  col3   CHAR(10)       SPARSE     NULL,
  col4   NUMERIC(12, 2) SPARSE     NULL
);
INSERT INTO dbo.T1(keycol, col1, col2) VALUES(1, 'a', 10);
INSERT INTO dbo.T1(keycol, col1, col4) VALUES(2, 'b', 20.00);
 
SELECT keycol, col1, col2, col3, col4
FROM dbo.T1;

محدودیتهای زیادی برای استفاده از ستونهای Sparse موجود است که بحث در رابطه با آنها در اینجا نمیگنجد.
SQL Server 2008 به شما این اجازه را میدهد که مجموعه ای از ستونها که تمامی ستونهای sparse یک جدول را در یک ستون XML واحد ترکیب میکند تعریف کنید. شما ممکن است که بخواهید به این گزینه، وقتیکه تعداد زیادی از ستونهای sparse را در جدولتان دارید (بیشتر از ۱۰۲۴)  فکر کنید و کار کردن روی آنها به صورت شخصی ممکن است طات فرسا باشد.
برای تعریف یک مجموعه از ستونها(column set)، عبارت زیر را به عنوان بخشی از عبارت CREATE TABLE مشخص کنید:


<column_set_name> XML column_set FOR ALL_SPARSE_COLUMNS


به عنوان مثال، کد زیر جدول T1 را مجددا با یک مجموعه ستون با نام cs میسازد:


IF OBJECT_ID('dbo.T1', 'U') IS NOT NULL DROP TABLE dbo.T1;
CREATE TABLE dbo.T1
(
  keycol INT                   NOT NULL PRIMARY KEY,
  col1   VARCHAR(20)           NOT NULL,
  col2   INT            SPARSE     NULL,
  col3   CHAR(10)       SPARSE     NULL,
  col4   NUMERIC(12, 2) SPARSE     NULL,
  cs     XML column_set FOR ALL_SPARSE_COLUMNS
);

شما همچنین میتوانیداز کد مشابهی که قبلتر استفاده شده برای insert سطرها در جدول و query زدن روی آن استفاده کنید :


INSERT INTO dbo.T1(keycol, col1, col2) VALUES(1, 'a', 10);
INSERT INTO dbo.T1(keycol, col1, col4) VALUES(2, 'b', 20.00);

SELECT keycol, col1, col2, col3, col4
FROM dbo.T1;

اما شما میتوانید روی column set با استفاده از اعمال XML به جای اعمال رابطه ای  کار کنید. به عنوان مثال، کد زیر یک سطر با استفاده از column set در جدول درج میکند :


INSERT dbo.T1(keycol, col1, cs)
  VALUES(3, 'c', '<col3>CCCCCCCCCC</col3><col4>30.00</col4>');


NULL برای ستونی که در مقدار XML نیامده است در نظر گرفته میشود که در این مثال col2 است.
دقت کنید که اگر شما یک column set در جدول تعریف کنید، SELECT * مقادیر مشابه SELECT که در آن تمام ستونها به صورت واضح نام برده شده اند را بر نمیگرداند. SELECT * تمام ستونهای sparse را به عنوان یک مقدار XML در column set برمیگرداند. برای نمایش این، کد زیر را اجرا کنید :


SELECT * FROM dbo.T1;


این کد خروجی زیر را برمیگرداند:


keycol      col1       cs
----------- ---------- ------------------------------------------
1           a          <col2>10</col2>
2           b          <col4>20.00</col4>
3           c          <col3>CCCCCCCCCC</col3><col4>30.00</col4>

اگر شما به صورت صریح ستونها را در عبارت SELECT لیست کنید، تمام ستونهای نتیجه به عنوان مقادیر رابطه ای باز گردانده میشوند.
خصیصه جدید دیگری که میتوانند در مقارنه با ستونهای sparse استفاده شوند اندیسهای فیلتر شده (filtered index) هستند. این خصیصه در بخش بعدی توضیح داده خواهد شد.


 
خطا در چاپ گزارش در SQL Server Reporting Service
ساعت ۳:٤٧ ‎ب.ظ روز ۱۳۸٧/۱٠/۱۱  کلمات کلیدی: reporting service ، ssrs 2008 ، report viewer ، client print

چند روزی بود که درگیر مشکلی با SSRS برای چاپ گزارش در روی Client بودیم. جدیداگزارشات نرم افزار خودمان را روی RS 2008پیاده سازی کرده بودیم.خطای موجود به شکل زیر بود : 

SSRS: Unable to Load Client Print Control error

 

 دلیل این خطا یکی از موارد زیر است : 

۱) اگر جدیدا ویندوز شما Update شده باید یک patch امنیتی با عنوان KB956391 نصب شده باشد. نصب این patch باعث مشکل در client print  در Reporting Service میشود و دیگر اجازه دانلود به ActiveX مربوط داده نمیشود. برای حل این مشکل میتوانید patch باعنوان KB954606  را نصب کنید. سپس MS Report Viewer Distribute Package 2008 SP1 را نصب کنید. احتمالا مشکل شما حل خواهد شد.

۲) مورد دیگر این است که شاید گزارشات و RS را به ۲۰۰۸ ارتقا داده باشید ولی کنترل ReportViewer شما یک کنترل مربوط به VS 2005 باشد. اگر کنترل را با کنترل موجود در VS 2008 جایگزین کنید این مشکل حل خواهد شد.