نمایش نتایج 1 تا 22 از 22

نام تاپیک: آموزش T-SQL 2008

  1. #1

    Post آموزش T-SQL 2008

    قصد دارم مطالب مفید و به روزی را درباره SQL Server و به خصوص نسخه تازه به بازار آمده آن یعنی 2008 بیان کنم. امیدوارم بتوانم تجربیات خودم را برای دوستان محترم و علاقه مند بیان کنم تا شاید بشود که کمکی به پیشبرد صنعت IT در ایران داشته باشم.
    لطفا با نظرات خود مرا یاری کنید.

  2. #2

    نقل قول: آموزش T-SQL 2008

    عملگرهای ترکیبی


    عملگرهای ترکیبی مثل += و -= و *= و ... در این نسخه به امکانات زبان افزوده شده است.


    DECLARE @price AS MONEY = 10.00;
    SET @price += 2.00;
    SELECT @price;
    آخرین ویرایش به وسیله masoud.ramezani : شنبه 15 فروردین 1388 در 12:01 عصر

  3. #3

    نقل قول: آموزش T-SQL 2008

    سازنده Table Value

    سازنده Table Value که در عبارت VALUES استفاده میشود. این بدین معنیست که میتوان فقط از یک عبارت Values برای ساخت چندین سطر استفاده کرد.

    USE tempdb;
    IF OBJECT_ID('dbo.Customers', 'U') IS NOT NULL DROP TABLE dbo.Customers;
    CREATE TABLE dbo.Customers
    (
    custid INT NOT NULL,
    companyname VARCHAR(25) NOT NULL,
    phone VARCHAR(20) NOT NULL,
    address VARCHAR(50) NOT NULL,
    CONSTRAINT PK_Customers PRIMARY KEY(custid)
    );
    INSERT INTO dbo.Customers(custid, companyname, phone, address)
    VALUES
    (1, 'cust 1', '(111) 111-1111', 'address 1'),
    (2, 'cust 2', '(222) 222-2222', 'address 2'),
    (3, 'cust 3', '(333) 333-3333', 'address 3'),

    (4, 'cust 4', '(444) 444-4444', 'address 4'),

    (5, 'cust 5', '(555) 555-5555', 'address 5');

    توجه داشته باشید که اگر یکی از سطرها نتواند وارد شود کل عملیات fail میشود.
    یک سازنده table value میتواند برای تعریف عباراتی مثل جداول مشتق شده استفاده شود مثل :

    SELECT *
    FROM
    (VALUES
    (1, 'cust 1', '(111) 111-1111', 'address 1'),
    (2, 'cust 2', '(222) 222-2222', 'address 2'),
    (3, 'cust 3', '(333) 333-3333', 'address 3'),
    (4, 'cust 4', '(444) 444-4444', 'address 4'),
    (5, 'cust 5', '(555) 555-5555', 'address 5')
    ) AS C(custid, companyname, phone, address);

    مثال بالا از query داخلی استفاده کرده و به عنوان 5 سطر در جدول C استفاده میکند.
    آخرین ویرایش به وسیله masoud.ramezani : شنبه 15 فروردین 1388 در 12:00 عصر

  4. #4

    نقل قول: آموزش T-SQL 2008

    توابع تبدیل ارتقا یافته


    توابع تبدیل نوعهای مختلف به یکدیگر ارتقا یافته است. شما میتوانید به عنوان سومین آرگومان سبک و شیوه تبدیل را تعیین کنید. شیوه 0 (صفر) همان چیزیست که در نسخه های قبل انجام میشد. این شیوه رشته ها را به کد اسکی باینری معادل ترجمه میکند و همچنین بالعکس.
    شیوه های 1 و 2 انواع جدیدی هستند. این شیوه ها رشته های در مبنای 16 را به معادل مقدار باینری که معادل ارقام در مبنای 16 است تبدیل میکند و بالعکس. وقتی شما از شیوه 1 استفاده کنید رشته ورودی باید دارای پیشوند 0x باشد و اگر شیوه 2 را استفاده کنید نباید اینگونه باشد. این اتفاق در هنگامی که یک مقدار باینری را به کاراکتر تبدیل میکنید هم اتفاق می افتد. به مثالهای زیر دقت نمایید:

    SELECT
    CONVERT(VARCHAR(12) , 0x49747A696B , 1) AS [Bin to Char 1],
    CONVERT(VARBINARY(5), '0x49747A696B', 1) AS [Char to Bin 1],
    CONVERT(VARCHAR(12) , 0x49747A696B , 2) AS [Bin to Char 2],
    CONVERT(VARBINARY(5), '49747A696B' , 2) AS [Char to Bin 2];

    این کد خروجی زیر را خواهد داشت:

    Bin to Char 1 Char to Bin 1 Bin to Char 2 Char to Bin 2
    ------------- ------------- ------------- -------------
    0x49747A696B 0x49747A696B 49747A696B 0x49747A696B
    آخرین ویرایش به وسیله masoud.ramezani : شنبه 15 فروردین 1388 در 11:58 صبح

  5. #5

    نقل قول: آموزش T-SQL 2008

    انواع داده ای Date و Time


    یکی از مواردی که خیلی از طرف توسعه دهندگان مورد نیاز بود این بود که نوع DateTime در نسخه های قبل به صورت دو نوع مجزا در نسخه جدید آورده شودکه اینگونه هم شد. در نسخه جدید 4 نوع جدید برای این کار در نظر گرفته شده است که عبارتند از Date ، Time، DateTime2 و DATETIMEOFFSET
    در جدول زیر مشخصات این انواع جدید آورده شده است:

    نوع داده
    ذخیره سازی (bytes)
    دامنه تاریخ
    دقت
    فرمت پیشنهادی تارخ و مثال
    DATE
    3
    January 1, 0001, through December 31, 9999 (Gregorian calendar)
    1 day
    'YYYY-MM-DD'
    '2009-02-12'
    TIME
    3 to 5

    100 nanoseconds
    'hh:mm:ss.nnnnnnn'
    '12:30:15.1234567'
    DATETIME2
    6 to 8
    January 1, 0001, through December 31, 9999
    100 nanoseconds
    'YYYY-MM-DD hh:mm:ss.nnnnnnn'
    '2009-02-12 12:30:15.1234567'
    DATETIMEOFFSET
    8 to 10
    January 1, 0001, through December 31, 9999
    100 nanoseconds
    'YYYY-MM-DD hh:mm:ss.nnnnnnn [+|-]hh:mm'
    '2009-02-12 12:30:15.1234567 +02:00'



    به مثال زیر نیز توجه کنید :
    DECLARE
    @d AS DATE = '2009-02-12',
    @t AS TIME = '12:30:15.1234567',
    @dt2 AS DATETIME2 = '2009-02-12 12:30:15.1234567',
    @dto AS DATETIMEOFFSET = '2009-02-12 12:30:15.1234567 +02:00';

    SELECT @d AS [@d], @t AS [@t], @dt2 AS [@dt2], @dto AS [@dto];
    این انواع جدید در ODBC و ADO.NET و OLE DB هم حمایت شده است جدول زیر معادل هر نوع را در Visual Studio 2008 نمایش میدهد :
    SQL
    ODBC
    OLE DB
    ADO.NET
    DATE
    SQL_TYPE_DATE/
    SQL_DATE
    DBTYPE_DBDATE
    DateTime
    TIME
    SQL_TIME/
    SQL_SS_TIME2
    DBTYPE_DBTIME/
    DBTYPE_DBTIME2
    TimeSpan
    DATETIMEOFFSET
    SQL_SS_TIMESTAMPOFFSET
    DBTYPE_DBTIMESTAMPOFFSET
    DateTimeOffset
    DATETIME2
    SQL_TYPE_TIMESTAMP
    SQL_TIMESTAMP
    DBTYPE_DBTIMESTAMP
    DateTime
    آخرین ویرایش به وسیله masoud.ramezani : شنبه 15 فروردین 1388 در 11:59 صبح

  6. #6

    نقل قول: آموزش T-SQL 2008

    توابع جدید و ارتقا یافته مربوط به زمان



    با توجه به انواع جدید تاریخ و زمان توابع جدیدی تعریف شده است به شرح زیر : SYSDATETIME ، SYSUTCDATETIME ،SYSDATETIMEOFFSET، SWITCHOFFSETوTODATETIMEOFFSET این توابع تاریخ کنونی را در فرمتهای مختلف به عنوان خروجی میدهد. برای گرفتن زمان و یا تاریخ کنونی میتوانید از توابع زیر استفاده کنید :

    SELECT
    CAST(SYSDATETIME() AS DATE) AS [current_date],
    CAST(SYSDATETIME() AS TIME) AS [current_time];

    با استفاده از کد زیر میتوانید time zone مربوط را عوض کنید مثلا مثال زیر time zone را به GMT +05:00 خواهد برد :

     SELECT SWITCHOFFSET(SYSDATETIMEOFFSET(), '-05:00');


    یک سری از توابع به طوری تغییر یافته اند که میتوان ازآنها روی انواع مربوط به زمان و تاریخ استفاده کرد.

    Type conversion functions (CAST and CONVERT)
    Set and aggregate functions (such as MAX, MIN)
    Metadata functions (such as TYPEPROPERTY, COLUMNPROPERTY)
    System functions (such as DATALENGTH, IS_DATE)
    آخرین ویرایش به وسیله masoud.ramezani : شنبه 15 فروردین 1388 در 11:57 صبح

  7. #7

    نقل قول: آموزش T-SQL 2008

    UDT های بزرگ

    در نسخه های قبلی انواع تعریف شده توسط کاربر (user defined type) دارای محدودیت از لحاظ طول بود یعنی CLR های با طول بیش از 8000 بایت نمیشد که ساخته شود ولی در نسخه جدید این محدودیت حذف شده است و این محدودیت تا 2 گیگابایت افزایش یافته است. دو نوع جدید GEOMETRY و GEOGRAPHY از این نوع هستند که در SQL Server 2008 به صورت built in افزوده شده اند. این دو برای نگهداری موقعیت جغرافیایی مناسبند. مشخصه ای برای تعیین طول موجود است که عبارت است از : SqlUserDefinedTypeAttribute.MaxByteSize اگر مقدار آن روی 1- تنظیم شده باشد یعنی تا 2 گیگا بایت میتواند افزایش حجم یابد. کلاینتهای قدیمی 2000 و 2005 این UDT های با حجم زیاد را با نوع VARBINARY(MAX) و IMAGEجایگزین میکند.

  8. #8

    نقل قول: آموزش T-SQL 2008

    نوع داده جدید HIERARCHYID (استراتژی های Indexing)


    این یک CLR UDT است که برای نگهداری و دستکاری سلسله مراتب و وراثت استفاده میشود. این نوع به صورت داخلی در مقدار VARBINARY ذخیره میشود که اطلاعات گره کنونی را در سلسله مراتب (به صورت پدر و فرزند و همچنین به صورت همنیا) نگهداری میکند. برای درک این مطلب باید استراتژی Indexing و Insert گره های جدید را متوجه شویم.


    این مورد شامل چند بخش است :

    ١- استراتژی های Indexing :
    کد زیر نحوه استفاده از نوع جدید HIERARCHYID را نمایش میدهد به ستون hid دقت کنید :

    USE tempdb;
    IF OBJECT_ID('dbo.Employees', 'U') IS NOT NULL DROP TABLE dbo.Employees;
    CREATE TABLE dbo.Employees
    (
    empid INT NOT NULL,
    hid HIERARCHYID NOT NULL,
    lvl AS hid.GetLevel() PERSISTED,
    empname VARCHAR(25) NOT NULL,
    salary MONEY NOT NULL,
    CONSTRAINT PK_Emploees PRIMARY KEY NONCLUSTERED(empid)
    );

    به استفاده از متد GetLevel() توجه کنید، دراین ستون یعنی lvl شماره سطح این گره در سلسله مراتب به دست آمده و نگهداری میشود. این تضمین میکند که تمام گره های فرزند پایینتر از گره های والد است. به این دلیل اگر از اندیس استفاده کنیم به صورت خودکار با افزایش صعودی اندیس، این سلسله مراتب هم به صورت خودکار افزایش میابد درست مثل درختی که شاخ و برگهای آن افزایش میابد. دو نوع استراتژی موجود است 1- عمقی اول (depth first) 2- ردیفی اول (breadth first)
    در استراتژی دوم گره های هم سطح دارای اندیس نزدیک به هم هستند. در کد های زیر هر دو نوع اندیس گذاری معرفی شده :

    CREATE UNIQUE CLUSTERED INDEX idx_depth_first ON dbo.Employees(hid);
    CREATE UNIQUE INDEX idx_breadth_first ON dbo.Employees(lvl, hid);

  9. #9

    نقل قول: آموزش T-SQL 2008

    نوع داده جدید HIERARCHYID (وارد کردن (Insert) گره های جدید )

    برای وارد کردن یک گره در یک ساختار درختی ابتدا باید یک مقدار HIERARCHYID برای آن ساخته شود. از متد HIERARCHYID::GetRoot() برای تولید یک مقدار برای گره root استفاده کنید. از متد GetDescwndant برای تولید مقدار زیر یک گره داده شده استفاده کنید. این متد دو مقدار ورودی HIERARCHYID را به صورت اختیاری دریافت کرده که این دو ورودی جایی را بین خودشان برای گره جدید مشخص میکنند.
    توجه داشته باشید که متد بالا تضمین نمیکند که مقدار تولید شده برای HIERARCHYID یکه باشد. برای اجبار کردن تولید یکه باید حتما روی ستون مربوطه یک primary key ، unique constraint و یا unique index تعریف کنید.
    به عنوان مثال کد زیر یک stored procedure برای اضافه کردن یک گره به ساختار درختی میسازد :

    IF OBJECT_ID('dbo.usp_AddEmp', 'P') IS NOT NULL DROP PROC dbo.usp_AddEmp;
    GO
    CREATE PROC dbo.usp_AddEmp
    @empid AS INT,
    @mgrid AS INT = NULL,
    @empname AS VARCHAR(25),
    @salary AS MONEY
    AS

    DECLARE
    @hid AS HIERARCHYID,
    @mgr_hid AS HIERARCHYID,
    @last_child_hid AS HIERARCHYID;

    IF @mgrid IS NULL
    SET @hid = HIERARCHYID::GetRoot();
    ELSE
    BEGIN
    SET @mgr_hid = (SELECT hid FROM dbo.Employees WHERE empid = @mgrid);
    SET @last_child_hid =
    (SELECT MAX(hid) FROM dbo.Employees
    WHERE hid.GetAncestor(1) = @mgr_hid);
    SET @hid = @mgr_hid.GetDescendant(@last_child_hid, NULL);
    END

    INSERT INTO dbo.Employees(empid, hid, empname, salary)
    VALUES(@empid, @hid, @empname, @salary);
    GO

    کد بالابه اندازه کافی گویا هست که احتیاج به توضیح نداشته باشد. با استفاده از کد پایین میتوانید چندین گره به جدول اضافه کنید :


    EXEC dbo.usp_AddEmp @empid = 1, @mgrid = NULL, @empname = 'David' , @salary = $10000.00;
    EXEC dbo.usp_AddEmp @empid = 2, @mgrid = 1, @empname = 'Eitan' , @salary = $7000.00;
    EXEC dbo.usp_AddEmp @empid = 3, @mgrid = 1, @empname = 'Ina' , @salary = $7500.00;
    EXEC dbo.usp_AddEmp @empid = 4, @mgrid = 2, @empname = 'Seraph' , @salary = $5000.00;
    EXEC dbo.usp_AddEmp @empid = 5, @mgrid = 2, @empname = 'Jiru' , @salary = $5500.00;
    EXEC dbo.usp_AddEmp @empid = 6, @mgrid = 2, @empname = 'Steve' , @salary = $4500.00;
    EXEC dbo.usp_AddEmp @empid = 7, @mgrid = 3, @empname = 'Aaron' , @salary = $5000.00;
    EXEC dbo.usp_AddEmp @empid = 8, @mgrid = 5, @empname = 'Lilach' , @salary = $3500.00;
    EXEC dbo.usp_AddEmp @empid = 9, @mgrid = 7, @empname = 'Rita' , @salary = $3000.00;
    EXEC dbo.usp_AddEmp @empid = 10, @mgrid = 5, @empname = 'Sean' , @salary = $3000.00;
    EXEC dbo.usp_AddEmp @empid = 11, @mgrid = 7, @empname = 'Gabriel', @salary = $3000.00;
    EXEC dbo.usp_AddEmp @empid = 12, @mgrid = 9, @empname = 'Emilia' , @salary = $2000.00;
    EXEC dbo.usp_AddEmp @empid = 13, @mgrid = 9, @empname = 'Michael', @salary = $2000.00;
    EXEC dbo.usp_AddEmp @empid = 14, @mgrid = 9, @empname = 'Didi' , @salary = $1500.00;


  10. #10

    نقل قول: آموزش T-SQL 2008

    نوع داده جدید HIERARCHYID (جستجو زدن روی سلسله مراتب)

    گر شما روی hid جستجو کنید خروجی به صورت binary است و اطلاعات با معنایی برای شما ندارد. برای اینکه به شکل منطقی تری دست پیدا کنید از متد ToString استفاده کنید. اگر این کار را کنید مسیری از سطوح را به شما میدهد که با اسلش از هم جدا شده است. به عنوان مثال کد زیر هر دو نوع binary و معادل منطقی آن را به شما میدهد :

    SELECT hid, hid.ToString() AS path, lvl, empid, empname, salary
    FROM dbo.Employees
    ORDER BY hid;

    فراخوانی HIERARCHYID یک مرتب سازی topological را میسازد و از متد GetLevel برای بدست آوردن سطح میتوانید استفاده کنید. با استفاده از این میتوانید یک ترسیم گرافیکی از ساختار سلسله مراتبی بدست آورید. به راحتی بر اساس hid مرتب سازی کنید و مانند زیر بر اساس lvl مقدار تورفتگی را بدست آورید:

    SELECT
    REPLICATE(' | ', lvl) + empname AS emp,
    hid.ToString() AS path
    FROM dbo.Employees
    ORDER BY hid;

    برای گرفتن یک زیر درخت از employee، شما میتوانید از متد IsDescendantOf کمک بگیرید. این متد اگریک گره به عنوان نواده گره مورد نظر باشد مقدار یک (1) را بر میگرداند. به مثال زیر دقت کنید:

    SELECT C.empid, C.empname, C.lvl
    FROM dbo.Employees AS P
    JOIN dbo.Employees AS C
    ON P.empid = 3
    AND C.hid.IsDescendantOf(P.hid) = 1;

    از کد زیر برای بدست آوردن تمامی مدیران یک employee (افراد بالای سری) استفاده میشود:

    SELECT P.empid, P.empname, P.lvl
    FROM dbo.Employees AS P
    JOIN dbo.Employees AS C
    ON C.empid = 14
    AND C.hid.IsDescendantOf(P.hid) = 1;

    از متد GetIncestor برای بدست آوردن والد یک گره استفاده کنید. این متد یک عدد را که آن را n میخواند به عنوان ورودی میگیرد و یک HIERARCHYID که مربوط به گره والد با n سطح بالاتر آن است را میدهد. به عنوان مثال کد زیر یک زیر درخت با یک سطح پایینتر از employee با شماره 9 را میدهد:

    SELECT C.empid, C.empname
    FROM dbo.Employees AS P
    JOIN dbo.Employees AS C
    ON P.empid = 9
    AND C.hid.GetAncestor(1) = P.hid;

  11. #11

    نقل قول: آموزش T-SQL 2008

    نوع داده جدید HIERARCHYID (متدهای مربوط)

    شما میتوانید از چندین متد دیگر برای دستکاری در نوع داده HIERARCHYID استفاده کنید. از جمله Parse، GetReparentedValue،Read و Write.
    با استفاده از متد HIERARCHYID::Parse میتوانید یک رشته با فرمت درست را به یک HIERARCHYID تبدیل کنید درست مثل تابع CAST.
    با استفاده از متد GetReparentedValue میتواند گره والد یک گره تغییر داد. این متد دو آرگومان ورودی دارد، یکی @old_root و دیگری @new_root. فرض کنید مقدار منطقی و مسیر گره فعلی به صورت روبرو باشد /1/1/2/3/2/ و مقدار old_root /1/1/ باشد و مقدار new_root برابر /2/1/4/ باشد، در این صورت این متد مقدار /2/1/4/2/3/2/ را باز خواهد گرداند. دقت داشته باشید که این متد نیز تضمین نکرده که مقدار برگشتی یکه باشد.
    متدهای Read و Write نیز فقط در CLR قابل استفاده است. از آنها برای خواندن از BinaryReader و نوشتن روی BinaryWriter استفاده کرد. شما میتوانید با استفاده از CAST حتی مقادیر رشته ای معادل HIERARCHYID را به آن تبدیل میکند و بالعکس.

  12. #12

    نقل قول: آموزش T-SQL 2008

    پارامترهای Table Type و Table-Valued

    نسخه جدید SQL Server با معرفی این دو نوع پارامتر کدها را مختصر کرده و کارایی آن را نیز بالا میبرد. Table Type ها اجازه استفاده مجدد آسان تعریف جدول را با متغیر جداول مهیا میسازد و Table Valued اجازه پاس کردن یک table را با استفاده از پارامترها به stored procedure ها و function ها را به ما میدهد.

    1- Table Type ها
    این نوع اجازه میدهد که شما تعریف table را در پایگاه داده ذخیره نمایید و بعدا از آن برای تعریف متغیرهای table و پارامترها به stored procedure ها و function ها استفاده نمایید.به این دلیل که این نوع جدید به شما این امکان را میدهد که از تعریف table دوباره استفاده کنید، آنها پایداری (consistency) و کم کردن احتمال خطا را تامین میکنند.
    شما باید از عبارت CREATE TYPE برای ساخت این نوع جدید استفاده کنید. به عنوان مثال کد زیر یک Table Type جدید بهپایگاه داده AdventureWork می افزاید :

    USE AdventureWorks;
    GO
    CREATE TYPE dbo.OrderIDs AS TABLE
    ( pos INT NOT NULL PRIMARY KEY,
    orderid INT NOT NULL UNIQUE );

    و در کد زیر از آن پس از تعریف استفاده شده است :

    DECLARE @T AS dbo.OrderIDs;
    INSERT INTO @T(pos, orderid) VALUES(1, 51480),(2, 51973),(3, 51819);
    SELECT pos, orderid FROM @T ORDER BY pos;


    برای دیدن اطلاعات metadata مربوط به table typeها روی view با نام sys.table_types یک Query بزنید.

    2- پارامترهای Table-Valued
    شما اکنون دیگر میتوانید از table type ها به عنوان یک type برای پارامترهای ورودی Stored procedure ها و function ها استفاده نمایید. در حال حاضر پارامترهای table-valued به صورت read only هستند و شما باید در هنگام تعریف آنها را با کلمه کلیدی READONLY مشخص کنید.
    سناریویی که در آن این پارامترها بسیار مفید هستند پاس کردن یک آرایه از کلیدها به stored procedure است. قبل از این نسخه راه حلی که برای این کار موجود بود استفاده از متد split بود که یک رشته را میتوانست تکه تکه کند. البته تکنیکهای دیگری نیز مثل استفاده از xml بود. استفاده از Dynamic SQL ریسک حملات SQL Injection را بالا میبرد. استفاده از split و xml هم بسیار پیچیده بود.
    در این نسخه جدید با این نوع پارامترها کار بسیار ساده شده است. دیگر احتمال SQL Injection وجود ندارد و اجازه استفاده مجدد و مفید را از طرحهای اجرا را به ما میدهد. به عنوان مثال stored procedure زیر یک پارامتر از نوع مورد نظر را گرفته و خروجیهای مناسب را تولید میکند :

    CREATE PROC dbo.usp_getorders(@T AS dbo.OrderIDs READONLY)
    AS
    SELECT O.SalesOrderID, O.OrderDate, O.CustomerID, O.TotalDue
    FROM Sales.SalesOrderHeader AS O
    JOIN @T AS T
    ON O.SalesOrderID = T.orderid
    ORDER BY T.pos;
    GO


    تکه کد زیر نیز این stored procedure را صدا میزند:

    DECLARE @MyOrderIDs AS dbo.OrderIDs;
    INSERT INTO @MyOrderIDs(pos, orderid)
    VALUES(1, 51480),(2, 51973),(3, 51819);
    EXEC dbo.usp_getorders @T = @MyOrderIDs;

    توجه کنید که وقتی شما مقداری را به عنوان پارامتر پاس نکنید به صورت پیش فرض یک جدول خالی به عنوان ورودی ارسال میشود. همچنین دقت داشته باشید که شما نمیتوانید متغیرها و پارامترهای table type را به صورت NULL پر کنید.
    SQL Server 2008 همچنین Client API ها را برای تعریف و پر کردن پارامترهای table valued بهبود بخشیده است. پارامترهای table valued به صورت داخلی مانند متغیرهای table کار میکنند. این نوع پارامترها در بعضی موارد از جداول موقت (temporary table) و راه حلهای دیگر بهتر است :

    • آنها strong type هستند.
    • SQL Server برای اینها آماری از distribution نگه نمیدارد. به همین دلیل باعث recompilation نمیشود.
    • اینها با transaction rollback تحت تاثیر قرار نمیگیرند.
    • آنها یک مدل برنامه نویسی ساده را تهیه کرده اند.

  13. #13

    نقل قول: آموزش T-SQL 2008

    عبارت Merge در SQL Server 2008

    این عبارت جدید یک عبارت استاندارد است که سه عمل INSERT و UPDATE و DELETE را ترکیب کرده و بر اساس یک منطق شرطی یک عملیات تجزیه ناپذیر را انجام میدهد. استفاده از این عملیات تجزیه ناپذیر بهینه تر از استفاده همزمان از سه عملیات بالا به صورت مجزاست.
    عبارت به دو جدول اشاره میکند: یک جدول هدف که در عبارت MERGE INTO مشخص میشود و جدول دیگر که جدول منبع است و در عبارت USING استفاده میشود. جدول هدف، هدفیست برای تغییرات و اصلاحات، و جدول منبع میتواند برای اصلاح هدف مورد استفاده قرار بگیرد.
    سیمنتیک عبارت merge شبیه یک outer join است. شما با استفاده عبارت ON مشخص میکنید که کدام سطر از جدول هدف با کدام جدول منبع مطابقت دارد و کدام مطابقت ندارد. شما یک عبارت برای هر مورد دارید که تعیین میکند کدام عملیات انجام شود :

    WHEN MATCHED THEN
    WHEN NOT MATCHED [BY TARGET] THEN
    WHEN NOT MATCHED BY SOURCE THEN

    دقت کنید که شما احتیاج ندارید که هر سه عبارت را مشخص کنید، بلکه فقط یک مورد نیاز است.
    به همان اندازه که دیگر عبارات تغییر، عبارت MERGE نیز عبارت OUTPUT را حمایت میکند،‌که به شما این امکان را میدهد که مقادیری را از سطرهای تغییر یافته باز گرداند. به عنوان قسمتی از عبارت OUTPUT شما میتوانید متد $action را فراخوانی کنید تا عملیاتی که باعث تغییر سطر شده را مشخص کنید.( 'INSERT', 'UPDATE', 'DELETE')
    به عنوان مثال کد زیر طریقه استفاده از عبارت MERGE را مشخص میکند. این کد دو جدول Customers و CustomersStage را در tempdb ساخته و آنها را با داده هایی پر میکند:

    USE tempdb;
    IF OBJECT_ID('dbo.Customers', 'U') IS NOT NULL DROP TABLE dbo.Customers;
    CREATE TABLE dbo.Customers
    (
    custid INT NOT NULL,
    companyname VARCHAR(25) NOT NULL,
    phone VARCHAR(20) NOT NULL,
    address VARCHAR(50) NOT NULL,
    CONSTRAINT PK_Customers PRIMARY KEY(custid)
    );
    INSERT INTO dbo.Customers(custid, companyname, phone, address)
    VALUES
    (1, 'cust 1', '(111) 111-1111', 'address 1'),
    (2, 'cust 2', '(222) 222-2222', 'address 2'),
    (3, 'cust 3', '(333) 333-3333', 'address 3'),
    (4, 'cust 4', '(444) 444-4444', 'address 4'),
    (5, 'cust 5', '(555) 555-5555', 'address 5');

    IF OBJECT_ID('dbo.CustomersStage', 'U') IS NOT NULL
    DROP TABLE dbo.CustomersStage;
    CREATE TABLE dbo.CustomersStage
    (
    custid INT NOT NULL,
    companyname VARCHAR(25) NOT NULL,
    phone VARCHAR(20) NOT NULL,
    address VARCHAR(50) NOT NULL,
    CONSTRAINT PK_CustomersStage PRIMARY KEY(custid)
    );
    INSERT INTO dbo.CustomersStage(custid, companyname, phone, address)
    VALUES
    (2, 'AAAAA', '(222) 222-2222', 'address 2'),
    (3, 'cust 3', '(333) 333-3333', 'address 3'),
    (5, 'BBBBB', 'CCCCC', 'DDDDD'),
    (6, 'cust 6 (new)', '(666) 666-6666', 'address 6'),
    (7, 'cust 7 (new)', '(777) 777-7777', 'address 7');

    عبارت MERGE زیر از جدول Customers به عنوان هدف برای تغییرات و از CustomerState به عنوان منبع استفاده میکند. شرط MERGE مشخصه custid را در دو جدول بر هم منطبق میکند. وقتی یک تطابق در هدف یافت شد مشخصه های هدف Customer با مشخصه های منبع Customer، overwrite میشود. وقتی یک تطابق در هدف یافت نشود، یک سطر جدید در جدول هدف با استفاده از مشخصه جدول منبع insert میشود. وقتیکه یک تطابق در در جدول منبع یافت نشود، سطر customer هدف delete میشود.

    MERGE INTO dbo.Customers AS TGT
    USING dbo.CustomersStage AS SRC
    ON TGT.custid = SRC.custid
    WHEN MATCHED THEN
    UPDATE SET
    TGT.companyname = SRC.companyname,
    TGT.phone = SRC.phone,
    TGT.address = SRC.address
    WHEN NOT MATCHED THEN
    INSERT (custid, companyname, phone, address)
    VALUES (SRC.custid, SRC.companyname, SRC.phone, SRC.address)
    WHEN NOT MATCHED BY SOURCE THEN
    DELETE
    OUTPUT
    $action, deleted.custid AS del_custid, inserted.custid AS ins_custid;

    این عبارت سطرهای 2 و 3 و 5 را update کرده، سطرهای 6 و 7 را insert و سطرهای 1 و 4 را delete میکند.

  14. #14

    نقل قول: آموزش T-SQL 2008

    Grouping Sets در sql server 2008



    این نسخه از SQL Server چندین پسوند برای Group By معرفی کرده که به شما این امکان را میدهد که به صورت همزمان چندین عملیات Grouping روی یک query داشته باشید. این پسوندها عبارتند از Grouping Sets و CUBE و ROLLUP که زیرعبارتهایی از عبارت Group By و توابع GROUPING_ID هستند. پسوندهای جدید استاندارد هستند و نباید با option های غیراستاندارد و قدیمی CUBE و ROLLUP اشتباه گرفته شوند.

    زیر عبارات GROUPING SETS و CUBE و ROLLUP
    برای نمایش و معرفی این عبارات اجازه دهید به چند تکه کد اشاره کنیم:

    USE tempdb;
    IF OBJECT_ID('dbo.Orders', 'U') IS NOT NULL DROP TABLE dbo.Orders;
    CREATE TABLE dbo.Orders
    (
    orderid INT NOT NULL,
    orderdate DATETIME NOT NULL,
    empid INT NOT NULL,
    custid VARCHAR(5) NOT NULL,
    qty INT NOT NULL,
    CONSTRAINT PK_Orders PRIMARY KEY(orderid)
    );
    INSERT INTO dbo.Orders (orderid, orderdate, empid, custid, qty)
    VALUES
    (30001, '20060802', 3, 'A', 10), (10001, '20061224', 1, 'A', 12),
    (10005, '20061224', 1, 'B', 20), (40001, '20070109', 4, 'A', 40),
    (10006, '20070118', 1, 'C', 14), (20001, '20070212', 2, 'B', 12),
    (40005, '20080212', 4, 'A', 10), (20002, '20080216', 2, 'C', 20),
    (30003, '20080418', 3, 'B', 15), (30004, '20060418', 3, 'C', 22),
    (30007, '20060907', 3, 'D', 30);

    بدون پسوندها یک query به صورت نرمال فقط یک Grouping Set در عبارت Group By تعریف میکند. اگر شما بخواهید یک aggregate را روی چندین مجموعه از گروهها اعمال کنید شما به چندینquery نیاز خواهید داشت. و برای اینکه نتیجه را به صورت یکجا داشته باشید مجبور هستید که از UNION ALL استفاده نمایید.
    با زیرعبارت جدید Grouping Sets شما به سادگی میتوانید تمام گروههایی را که میخواهید لیست کنید. به صورت منطقی شما دارید همان کار قدیم را انجام میدهید و نتیجه چندین query را یکی میکنید. البته شما با این روش دسترسی به داده و میزان محاسبات را بهینه میکنید. این بدین دلیل است که SQL SERVER به ازای هر مجموعه نیاز ندارد که داده ها را پیمایش کند، به علاوه در برخی موارد آن یک aggregate سطح بالاتر را بر اساس یک aggregate سطح پایینتر محاسبه میکند به جای اینکه دوباره داده های پایه را محاسبه کند.
    به عنوان مثال، query زیر روی چهار مجموعه عملیات aggregate را انجام میدهد :

    SELECT custid, empid, YEAR(orderdate) AS orderyear, SUM(qty) AS qty
    FROM dbo.Orders
    GROUP BY GROUPING SETS (
    ( custid, empid, YEAR(orderdate) ),
    ( custid, YEAR(orderdate) ),
    ( empid, YEAR(orderdate) ),
    () );

    چهار سطر آخر مجموعه های تعریف شده هستند. آخرین آنها یعنی () یا مجموعه خالی جایگزین ALL یعنی همه میشود. این مانند یک aggregate query بدون عبارت GROUP BY است که شما با تمام جدول مانند یک گروه واحد رفتار کردید.
    دو زیر عبارت جدید دیگر باید به عنوان مخفف در زیر عبارت Grouping Sets به کار روند. زیرعبارت CUBE یک مجموعه قدرتمند از مجموعه المانهای لیست شده در پرانتزها تولید میکند. به عبارت دیگر، این تمام مجموعه گروههای ممکن که میتوان با عناصر لیست شده در پرانتزها ساخته شود را تولید میکند که شما مجموعه خالی نیز میشود. به عنوان مثال استفاده زیر از CUBE :

    CUBE(a,b,c)

    منطقا معادل است با :

    GROUPING SETS((a),(b),(c),(a, b),(a, c),(b, c),(a, b, c),())

    برای n عنصر CUBE به ادازه 2 به توان n مجموعه گروه میسازد.

    خارج از عناصر لیست شده در پرانتزها، زیرعبارت ROLLUP تنها مجموعه گروههایی را تولید میکند که دارای business value باشند، وراثت و سلسله مراتب را بین عناصر فرض کنید. به عنوان مثال استفاده زیر از ROLLUP :

    ROLLUP( country, region, city )

    منطقا معادل است با :

    GROUPING SETS((country, region, city),(country, region),(country),())

    دقت کنید مواردی که دارای business value نیستند، سلسله مراتب را بین عناصر فرض کنید- مانند (city) تولید نشده اند.ممکن است چندین شهر با یک نام در دنیا موجود باشد حتی ممکن است در یک کشور شهر همنام موجود باشد بنابراین هیچ business value برای اینکه آنها را مجتمع کنیم موجود نیست.

  15. #15

    نقل قول: آموزش T-SQL 2008

    جبر مجموعه های گروه بندی در SQL Server 2008



    شما محدود نشده اید که تنها از یک زیرعبارت در عبارت GROUP BY استفاده کنید. شما میتوانید چندین زیرعبارت را با استفاده از کاما مشخص کنید. کاما به عنوان اپراتور حاصلضرب استفاده میشود، بدین معنی که شما حاصلضرب دکارتی مجموعه ها را خواهید داشت. به عنوان مثال، کد زیر جایگزین حاصلضرب دکارتی بین دو مجموعه از زیرعبارات میشود:

    GROUPING SETS ( (a, b), (c, d) ), GROUPING SETS ( (w, x), (y, z) )

    این کد به صورت منطقی معادل است با :

    GROUPING SETS ( (a, b, w, x), (a, b, y, z), (c, d, w, x), (c, d, y, z) )

    شما میتوانید همچنین از زیرعبارات CUBE و ROLLUP به عنوان قسمتی از ضرب دکارتی استفاده نمایید.

  16. #16

    نقل قول: آموزش T-SQL 2008

    تابع GROUPING_ID


    این تابع به شما اجازه میدهد که مجموعه هایی را مشخص کنید که هر کدام از سطور نتایج متعلق به آنهاست. به عنوان ورودی شما تمام مشخصه هایی را که در هر مجموعه دسته بندی شرکت دارند مهیا میکند. تابع یک نتیجه integer که یک bitmap (نقشه بیتی) است را تولید میکند، که در آن هر بیت جایگزین یک مشخصه متفاوت میشود. در این راه تابع یک عدد صحیح یکه برای هر مجموعه دسته بندی تولید میکند.
    Query زیر یک مثال از استفاده این تابع را نمایش میدهد:

    SELECT
    GROUPING_ID(
    custid, empid,
    YEAR(orderdate), MONTH(orderdate), DAY(orderdate) ) AS grp_id,
    custid, empid,
    YEAR(orderdate) AS orderyear,
    MONTH(orderdate) AS ordermonth,
    DAY(orderdate) AS orderday,
    SUM(qty) AS qty
    FROM dbo.Orders
    GROUP BY
    CUBE(custid, empid),
    ROLLUP(YEAR(orderdate), MONTH(orderdate), DAY(orderdate));

    توجه کنید که در خروجی، که در اینجا به صورت مختصر نمایش داده شده، هر مجموعه با یک عدد صحیح یکه جایگزین شده است:

    grp_id custid empid orderyear ordermonth orderday qty
    ------- ------ ----------- ----------- ----------- ----------- -----------
    0 C 3 2006 4 18 22
    16 NULL 3 2006 4 18 22
    24 NULL NULL 2006 4 18 22
    25 NULL NULL 2006 4 NULL 22
    0 A 3 2006 8 2 10
    16 NULL 3 2006 8 2 10
    24 NULL NULL 2006 8 2 10
    25 NULL NULL 2006 8 NULL 10
    0 D 3 2006 9 7 30
    16 NULL 3 2006 9 7 30
    ...
    به عنوان مثال، عدد 25 جایگزین مجموعه دسته بندی (orderyear, ordermonth) شده است. بیتهای جایگزین عناصری که قسمتی از مجموعه گروه بندی در آن غیر فعال است (ordermonth – 2 و orderyear – 4)، و بیتهایی جایگزین عناصری که قسمتی از مجموعه دسته بندی که فعال هستند، نیستند (orderday – 1, empid – 8, custid – 16) میشوند. عدد 25 از جمع مقادیر جایگزین بیتهایی که فعال هستند به دست می آید یعنی 1+8+16 = 25. این ویژگی مخصوصا وقتی مفید است که شما نیاز دارید که به aggregate ها صورت خارجی بخشید و سپس فقط روی مجموعه های خاص query بزنید. شما میتوانید جدول را با مشخصه grp_id دسته بندی (cluster) کنید که این به SQL Server این امکان را میدهد که به صورت موثر و مفید یک درخواست برای یک مجموعه دسته بندی ویژه را انجام دهد.

  17. #17

    نقل قول: آموزش T-SQL 2008

    ساختن template برای گزارشات در Reporting Service


    شاید برای خیلی ها که با SQL Server Reporting Server کار میکنند این سوال پیش آمده باشد که چگونه میتوان برای گزارشات یک قالب از پیش تعیین شده ساخت؟ این دقیقا شبیه Master Page برای صفحات ASP .NET است. پاسخ این سوال به شرح زیر است:

    ۱- گزارش مورد نظر خود را بسازید. این گزارش باید شامل قسمتهایی باشد که در تمام گزارشات شما تکرار میشود. مثلا اگر در تمام گزارشات شما Header و Footer مورد نیاز است، میتوانید این کار را در قالب خود طراحی کنید.
    ۲- فایل rdl ساخته شده را با نام مورد نظر در آدرس زیر کپی کنید:
    D:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\PrivateAssemblies\ProjectItems\Rep ortProject
    ۳- Visual Studio را باز کنید و یک پروژه Report بسازید.
    ۴- پس از ساخته شدن پروژه روی پوشه Reports راست کلیک کنید و گزینه Add و سپس New Item را انتخاب کنید. در دیالوگ باز شده باید یک قالب با نام موردنظر خود ببینید. آن راانتخاب کنید.
    در گزارش جدید باید تغییراتی که از قبل داده اید را ببینید.

    نکته - از این روش شما برای ساختن قالب برای Data Source ها هم میتوانید استفاده کنید.

  18. #18

    نقل قول: آموزش T-SQL 2008

    سلام دوست عزیز
    از مطالب آموزند ه ات بسیار ممنون .
    ببخشید من یک سوال داشتم اگه داده ها داخل یک جدول را بصورت صفحه به صفحه بخوهیم انتخاب کنیم باید چه کنیم منظور من عمل پیجینگ است در سمت sql server لطفا یک نمونه کد برای من قرار دهید . باتشکر

  19. #19

    نقل قول: آموزش T-SQL 2008

    چگونه عملیات صفحه بندی (paging) را در sql server انجام دهیم؟

    در خیلی مواقع ملاحظه میشود که برای نمایش تعدادی از رکوردهای یک جدول در پایگاه داده کل مقادیر موجود درآن توسط یک دستور select به دست می‌آید و صفحه‌بندی خروجی به کنترلهای موجود سپرده میشود. اگر پایگاه داده ما دارای تعداد زیادی رکورد باشد آن موقع است که ما دچار مشکل میشویم. فرض کنید به طور همزمان ۵ نفر (که تعداد زیادی نیستند) از برنامه ما که شامل ۱۰۰۰۰۰ سطر داده میباشد استفاده کنند و در هر صفحه ما ۱۰ رکورد نمایش داده شود و صفحه‌بندی ما از نوع معقولی نباشد در این صورت به جای اینکه ما با ۵×۱۰ رکورد داده را بارگزاری کنیم، ۵×۱۰۰۰۰۰ رکورد یعنی ۵۰۰۰۰۰ رکورد را برای به دست آوردن ۵۰ رکورد بارگزاری میکنیم. در زیر روشی شرح داده میشود که سربار اضافه از روی برنامه و سرورهای مربوطه حذف شود. به stored procedure و توضیحات مربوط به آن توجه فرمایید :

    CREATE PROCEDURE sp_PagedItems
    (
    @Page int,
    @RecsPerPage int
    )
    AS

    -- We don't want to return the # of rows inserted
    -- into our temporary table, so turn NOCOUNT ON
    SET NOCOUNT ON


    --Create a temporary table
    CREATE TABLE #TempItems
    (
    ID int IDENTITY,
    Name varchar(50),
    Price currency
    )


    -- Insert the rows from tblItems into the temp. table
    INSERT INTO #TempItems (Name, Price)
    SELECT Name,Price FROM tblItem ORDER BY Price

    -- Find out the first and last record we want
    DECLARE @FirstRec int, @LastRec int
    SELECT @FirstRec = (@Page - 1) * @RecsPerPage
    SELECT @LastRec = (@Page * @RecsPerPage + 1)

    -- Now, return the set of paged records, plus, an indiciation of we
    -- have more records or not!
    SELECT *,
    MoreRecords =
    (
    SELECT COUNT(*)
    FROM #TempItems TI
    WHERE TI.ID >= @LastRec
    )
    FROM #TempItems
    WHERE ID > @FirstRec AND ID < @LastRec


    -- Turn NOCOUNT back OFF
    SET NOCOUNT OFF
    در این کد دو پارامتر از نوع integer تعریف میکنیم. اول پارامتر @Page که مربوط به شماره صفحه‌ای میباشد که قصد دارید آن را بارگزاری نمایید. دومین پارامتر با نام @RecsPerPage تعداد رکوردهایی است که هر بار میخواهید بارگزاری شوند مثلا اگر میخواهید هر بار ۱۵ عدد از رکوردها را نمایش دهید این مقدار را باید برابر ۱۵ قرار دهیم.در مرحله بعد یک جدول موقت با نام #TempItems ساخته شده است که به طور موقت مقادیری را در حافظه نگه میدارد و هیچ فضای فیزیکی روی هارد دیسک اشغال نمیکند. نکته کلیدی که جلوتر از آن استفاده شده ستون با نام ID است که از نوع auto-increment است و روی جدول موقت تعریف شده است. این ستون شناسه هر سطر را در خود نگه میدارد که به صورت اتوماتیک بالا میرود و جزء لاینفکی از این نوع paging میباشد. پس از آن جدول موقت را توسط رکوردهای جدول واقعی با نام tblItem توسط دستور select پر میکنیم.
    در مرحله بعد شماره اولین و آخرین سطر مورد نظر را بر اساس پارامترهای ورودی محاسبه کرده و در متغیرهای @FirstRec و @LastRec بریزیم.
    برای استفاده از این کد فقط کافیست که پارامترهای ورودی را مقداردهی نمایید. مثلا اگر میخواهید در یک کنترل Grid از آن استفاده کنید باید ابتدا یک کوئری داشته باشید که تعداد کل سطرها را به شما بدهد و بر اساس این مقدار تعداد صفحات مورد نظر را به دست آورید. پس از آن با کلیک روی هر کدام از شماره صفحات آن را به عنوان مقدار به پارامتر مورد نظر بفرستید و از آن لذت ببرید.
    آخرین ویرایش به وسیله masoud.ramezani : یک شنبه 21 تیر 1388 در 16:28 عصر

  20. #20

    نقل قول: آموزش T-SQL 2008

    توسعه و بهبود DDL برای Trigger



    در sql server 2008، تریگرها طوری تغییر کرده اند که از آنها به عنوان DDL میشود استفاده کرد مثلا یک table جدید در آن ساخته شود. با این تغییر انعطاف بسیار بالایی به trigger ها داده شده است. شمای XML برای رخدادها به عنوان بخشی از database engine در مسیر
    C:\Program Files\Microsoft SQL Server\100\Tools\Binn\schemas\sqlserver\2006\11\ev ents\events.xsd
    نصب شده و همچنین از آدرس زیر قابل دریافت است.
    خیلی از stored procedure ها اعمال تعریف داده(DDL) انجام میدهند. قبل از sql server 2008 ، شما نمیتوانستید با یک trigger ساختار داده ای جدیدی تعریف کنید. اکنون شما میتوانید رویدادهایی را راه اندازی کنید که درآنها کارهایی شبیه PROCEDURE انجام دهید. به عنوان مثال، stored procedure با نام sp_rename یک trigger را که در رویداد RENAME جدید ساخته شده است راه اندازی و اجرا میکند. برای نمایش این نوع از trigger، کد زیر یک database با نام testdb و در آن یک trigger روی رویداد RENAME برای چاپ منبع و جزییات هدف را جهت تست میسازد.


    USE master;
    GO
    IF DB_ID('testdb') IS NOT NULL DROP DATABASE testdb;
    CREATE DATABASE testdb;
    GO
    USE testdb;
    GO
    CREATE TRIGGER trg_testdb_rename ON DATABASE FOR RENAME
    AS
    DECLARE
    @SchemaName AS SYSNAME =
    EVENTDATA().value('(/EVENT_INSTANCE/SchemaName)[1]', 'sysname'),
    @TargetObjectName AS SYSNAME =
    EVENTDATA().value('(/EVENT_INSTANCE/TargetObjectName)[1]', 'sysname'),
    @ObjectName AS SYSNAME =
    EVENTDATA().value('(/EVENT_INSTANCE/ObjectName)[1]', 'sysname'),
    @NewObjectName AS SYSNAME =
    EVENTDATA().value('(/EVENT_INSTANCE/NewObjectName)[1]', 'sysname');
    DECLARE
    @msg AS NVARCHAR(1000) =
    N'RENAME event occurred.
    SchemaName: ' + @SchemaName + N'
    TargetObjectName: ' + @TargetObjectName + N'
    ObjectName: ' + @ObjectName + N'
    NewObjectName: ' + @NewObjectName;
    PRINT @msg;
    GO

    برای تستtrigger کد زیر یک table با نام dbo.T1 با یک ستون که col1 نامیده میشود میسازد و sp_rename را برای تغییر نام ستون به col2 اجرا میکند :


    CREATE TABLE dbo.T1(col1 INT);
    EXEC sp_rename 'dbo.T1.col1', 'col2', 'COLUMN';

    Trigger روی رویداد RENAME فراخوانی شده و پیام زیر را چاپ میکند :

    RENAME event occurred.
    SchemaName: dbo
    TargetObjectName: T1
    ObjectName: col1
    NewObjectName: col2

  21. #21

    نقل قول: آموزش T-SQL 2008

    ستونهای پراکنده، ستونهایی هستند که برای ذخیره سازی 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) هستند. این خصیصه در بخش بعدی توضیح داده خواهد شد.

  22. #22
    کاربر دائمی آواتار mostafarastin239
    تاریخ عضویت
    شهریور 1387
    محل زندگی
    مرکز ایران
    سن
    36
    پست
    136

    نقل قول: آموزش T-SQL 2008

    سلام مهندس
    دست گلت درد نکنه. می تونم خواهش کنم که ی دی اف این آموزش ها را قرار بدی تا بتونیم دانلود کرده و داشته باشیم.
    با تشکر

برچسب های این تاپیک

قوانین ایجاد تاپیک در تالار

  • شما نمی توانید تاپیک جدید ایجاد کنید
  • شما نمی توانید به تاپیک ها پاسخ دهید
  • شما نمی توانید ضمیمه ارسال کنید
  • شما نمی توانید پاسخ هایتان را ویرایش کنید
  •