بررسی Multi Statements در SQL SERVER همراه با تشریح تابع Split
  در این مقاله به بررسی دقیق تر Multi Statements در SQL SREVER همراه با تشریح یک مثال عملی ، تابع Split می پردازم .
   SQL Server
   ۳۵۸۵۹
   این مقاله حاوی فایل ضمیمه نمی باشد
   محمد زنگنه
   ۱۳۸۶/۸/۲۳
ارسال لینک صفحه برای دوستان ارسال لینک صفحه برای دوستان  اضافه کردن به علاقه مندیها اضافه کردن به علاقه مندیها   نسخه قابل چاپ نسخه قابل چاپ

 

مقدمه :
در اين مقاله به بررسي دقيق ترتوابع Multi Statements  همراه با شرح يک مثال مي پردازم .

تعريف : Multi Statements توابعي هستند که مقدار برگشتب آنها از نوع Table مي باشد .
اين جمله را شرح مي دهم :
ابتدا ، متغير هايي از نوع Table :

در SQl Server ما مي توانيم متغير هايي از نوع Table  اعلام کنيم . اعلام يک متغير از نوع Table به شکل زير است :


DECLARE @Table TABLE
(
    UserID int NOT NULL,
    UserName NVARCHAR(50)
)

براي مقدار دهي به متغيرهاي از نوع table  نمي توانيم مانند ديگر انواع متغيرها از دستور SET استفاده کنيم .

براي مقدار دهي به اين متغيرها ، همانگونه که از مفهوم منطقي جدول (table) مشخص است ، بايد رکورد به جدول اضافه کنيم . پس ما براي کار کردن با اين متغيرها بايد از دستورات پايگاه داده اي(INSERT,UPDATE,DELETE,SELECT) استفاده کنيم و کلا به اين گونه متغيرها مانند يک جدول نگاه کنيم که ماهيت فيزيکي ندارند .
نمونه اي از مقدار دادن به يک متغير از نوع Table  :


INSERT INTO @Table
(UserID ,UserName)
    VALUES
(1,'MohammadZangeneh')

با اين توضيحات توابع Multi Statements توابعي هستند مانند ساير توابع با اين تفاوت که در داخل آنها ما يک متغير table  را اعلام کرده و آنرا مقدار دهي کرده و آنرا برمي گردانيم .

حال براي جا افتادن مطالب به بررسي يک مثال عملي مي پردازيم که احتمالا کاربرد زيادي در برنامه هاي ما خواهد داشت (من که تو برنامه هام خيلي از اين تابع استفاده کردم ).

ما در برنامه هاي خود گاهي نياز داريم که يک عمل يا فرآيند را روي تعدادي از متغيرها يا موجوديت ها اعمال کنيم ، مانند حذف يا تائيد موجوديت ها بصورت دسته اي و يا دادن نمره هاي دروس مختلف يا دادن ترتيب يا اولويت به يک سري از موجوديت ها ...

در اين مواقع ما مي توانيم براي اين دسته از متغيرها يا موجوديت ها تک تک و هر بار همان عمل را انجام دهيم .به عنوان مثال در مورد حذف 4 موجوديت از جدول بايد هر بار يک دستور حذف روي جدول اجذا کنيم .

راه ديگر اين است که يکباره همه آن موجوديتها (کليدهاي موجوديت ها ) را در رشته اي به هم چسبانده (Concate ) و به وسيله يک کاراکتر جداکننده (Separator)  از هم متمايز کنيم . سپس آنها را به سرور فرستاده و انجام آن فرآيند را بر روي اين دسته از موجوديت ها به SQL Server بسپاريم .

اين روش از کارآيي و سرعت بسيار بالاتري نسبت به روش قبل دارد و استاندارتر هم مي باشد .

تنها مسئله اي که مي ماند اين است که ما کليد اين موجوديت هايي که همگي داخل يک رشته هستند و به وسيله يک کاراکتر جدا کننده از هم متمايز شده اند را از هم جدا کرده يا اصطلاحا قطعه قطعه (Split) کنيم و اين موجوديت ها را از هم جدا کنيم . سپس براي هر يک از آنها عمليات را انجام دهيم .

تابع زير يک رشته ورودي مي گيرد که قرار است آنرا بر اساس کاراکتر جدا کننده اي (Separator) که به آن فرستاده شده است  از هم جدا کند و جدولي را متشکل از قطعه هاي رشته برمي گرداند . شما مي توانيد اين تابع را در Stored Procedure ها يا Function هاي خود به خوبي استفاده کنيد .


-- =============================================
-- Author:        Mohammad Zangeneh
-- alter date: 2007-05-15
-- Description:    For Split String
-- =============================================
CREATE  FUNCTION [dbo].[fn_Spliter]
(
    @str_Source    nvarchar(250),
    @Separator    nvarchar(50)
)
RETURNS
@tbl_Result TABLE (Word NVARCHAR(250) COLLATE Arabic_CI_AS )
AS
BEGIN
    
    DECLARE @tbl_Temp TABLE(Word NVARCHAR(250) COLLATE Arabic_CI_AS )

    DECLARE @str_Temp NVARCHAR(50)

    
    SET @str_Temp = @str_Source

    WHILE (len(@str_Temp)>0)
    BEGIN
        IF    CHARINDEX(@Separator,@str_Temp) <> 0
        BEGIN
            IF SUBSTRING (@str_Temp,1,CHARINDEX(@Separator,@str_Temp)-1) <> ''
                INSERT INTO @tbl_Temp (Word) VALUES (SUBSTRING (@str_Temp,1,CHARINDEX(@Separator,@str_Temp)-1))

            SET @str_Temp = SUBSTRING (@str_Temp,CHARINDEX(@Separator,@str_Temp)+1,len(@str_Temp) - CHARINDEX(@Separator,@str_Temp))

        END

    ELSE
        BREAK
END

IF (len(@str_Temp)>0 )
    INSERT INTO @tbl_Temp (Word) VALUES (@str_Temp)

INSERT @tbl_Result SELECT WORD FROM @tbl_Temp

RETURN
END

در رويه ذخيره شده زير شيوه استفاده از تابع fn_Spliter را مشاهده مي کنيد .
ايت تابع رشته اي متشکل از آدي يک سري از کاربران به همراه امتيازشان فرستاده مي شود و اين SP به هر کاربر امتيازش را تخصيص مي دهد .


CREATE PROCEDURE [dbo].[SP_Usre_AssignRateToUser]
    @str_List    VARCHAR(200)
AS

DECLARE CUR CURSOR FOR SELECT * FROM fn_spliter(@str_List,',')
DECLARE @str_Temp VARCHAR(50)
OPEN CUR
FETCH NEXT FROM CUR INTO @str_Temp
WHILE @@FETCH_STATUS = 0
    BEGIN
        DECLARE @UserID    INT
        SET @UserID = CAST(SUBSTRING (@str_Temp,1,CHARINDEX('_',@str_Temp)-1) AS INT)

        DECLARE @Rate    INT
        SET @Rate = SUBSTRING (@str_Temp,CHARINDEX('_',@str_Temp)+1,len(@str_Temp) - CHARINDEX('_',@str_Temp))
        UPDATE tbl_UsersRate SET
            UserRate = @Rate ,
            Date = GETDATE()
            WHERE UsreID = @UserID

        FETCH NEXT FROM CUR INTO @str_Temp
    END
    
CLOSE CUR
DEALLOCATE  CUR

حال شما با دستور زير مي توانيد به ده ها کاربر سيستم امتياز مناسب را تخصيص دهيد .


EXEC [dbo].[SP_Users_AssignRateToUser] '1_2,2_4,3_10,4_5,6_5'

توضيح ضروري :
من عمدا خصوصيت Collate متغير Table را تنظيم کردم ، چون شما شايد در بعضي از استفاده ها از  Multi Statements  بخواهيد تابع تان را با جدول ديگري JOIN کنيد و ممکن است در برخي موارد به Error در رابطه با عدم تشابه Collate جداول برخورد کنيد .در  اين گونه موارد Collate متغير جدولتان را با Collate مناسب تنظيم کنيد .

ومن الله التوفيق .