# پایگاه‌های داده > SQL Server > T-SQL >  store procedure

## rezaeyan

سلام
من یک store procedure برای گزارشم دارم که می خوام شرط store procedure به عنوان پارامتر از برنامه ارسال بشه. علت این کار اینه که یک گزارش ترکیبی دارم و تعداد شرطها بستگی به انتخاب کاربر داره.
کسی نظری داره؟ :اشتباه:

----------


## baktash.n81@gmail.com

سلام

می تونید از Dynamic TSQL استفاده کنید ... برای دستور exec جستجو نمایید ...

----------


## Galawij

سلام،
شما می تونید داخل SP همه شرطها را لحاظ کنید ولی بسته به انتخاب کاربر شرطتتون عمل کنه.
مثلا به همه پارامترهای ورودی مقدار اولیه صفر بدید بعد قسمت Where روال هم به این صورت درمیاد:
WHERE	((@IdContract=0)OR(dbo.TbContract.IdContract=@IdCo  ntract)) 				
					And
					((@UserId='00000000-0000-0000-0000-000000000000')OR(dbo.aspnet_Users.UserId=Convert(u  niqueidentifier,@UserId)))
این حالت خیلی انعطاف پذیره و کاربردی مخصوصا برای گزارشات برنامه.

----------


## desatir7316

> کسی نظری داره؟



داینامیک سرعتتو میاره پایین
اگه برات مهمه می تونی به این هم توجه کنی

----------


## ali_kolahdoozan

شما میتونی یک String را بفرستی داخل sp و بعد آنرا exec کنی . نگران performance نباش . اگر طراحی database صحیح باشه و بقیه قسمتها استاندارد باشد ، نوشتن یک query داینامیک فقط برای یک یا چند گزارش مشکلی ایجاد نمیکنه . باز هم اگر مشکلی بود لطفا concept را درست توضیح بدهید تا ببینیم بهترین انتخاب چی میتونه باشه . 

ضمننا کم کم نگاهی به Linqtosql و EF هم داشته باشید. (این به معنی حذف SP نیست . شما میتوانید از هسته linq یا ef استفاده کنید ولی همه پروژه خود را مبتنی بر sp بنویسید، در این صورت یک جاهایی مثل مورد الان دستورات داینامیک ef با lingtosql میتونه نجاتت بده ).

----------


## rezaeyan

> شما میتونی یک String را بفرستی داخل sp و بعد آنرا exec کنی .


در مورد این موضوع بیشتر توصیح میدین

----------


## ali_kolahdoozan

سلام 

ببین الان این چیزی که برات میزارم رو ببین . فقط کافی است string رو در سطح application بسازی و شوت کنی اینجا و خلاص

Create Proc StringQuery
@Strinput nvarchar(max)
As
EXEC sp_executesql @Strinput



Declare @str nvarchar(max)
set @str='Your Dynamic Query'
Exec StringQuery @str

----------


## ASKaffash

سلام
بخش کندی Dynamic SQL کجاست ؟




> داینامیک سرعتتو میاره پایین
> اگه برات مهمه می تونی به این هم توجه کنی

----------


## ali_kolahdoozan

> سلام
> بخش کندی Dynamic SQL کجاست ؟


لطفا واضحتر توضیح بفرمائید.

پ ن : در اینکه بهتر است در یک پروژه از SP ها و البته اخیرا تکنولوژیهایی مثل Linq یا EF استفاده بشه شکی نیست ، اما گاهی دیگر امکان پذیر نیست و باید از Query های داینامیک استفاده بشه که ایرادی هم ایجاد نمیکنه . (شاید نظر شما این بوده).

----------


## rezaeyan

> Create Proc StringQuery
> @Strinput nvarchar(max)
> As
> EXEC sp_executesql @Strinput
>  
>  
>  
> Declare @str nvarchar(max)
> set @str='Your Dynamic Query'
> Exec StringQuery @str


 بیشتر در باره این کدها توضیح میدین

----------


## ASKaffash

سلام
برادر خودت می پرس خودت هم نتیجه گیری می کنی واقعا عجیب است . جواب من شفاف است ادعا شده که Dynamic SQL کند است من هم پرسیدم که کجای عمل Dynamic SQL کند است ؟ چون مطمئن هستم ادعا اشتباه است شاید *desatir7316* دلیلی داشته باشند که من نمی دانم.

----------


## hamid-nic

من از Dynamic SQL در  پروژه هام استفاده کردم و مشکلی باهاش نداشتم .
اتفاقاً خیلی خوب جواب داد .

----------


## حمیدرضاصادقیان

سلام.
Dynamic SQL نسبت به Static Query کندتر میشه دلیلش هم اینه که هر دفعه SQL Server مجبور میشه یک  Plan برای اون ایجاد کنه که همین Plan باعث کندی اون خواهد شد. البته نه اینقدر محسوس که کاربر احساس کنه! به همین خاطر پیشنهاد میشه حتی المقدور در SP ها از Query های ثابت به جای Dynamic استفاده  بشه. دومین مورد در مورد استفاده از Dynamic Query ها این هست که باید به مسائل امنیتی دقت کافی رو بکنید تا کدتون مستعد SQL Injection نباشه.به همین خاطر باید اونها رو از سمت Client به سمت Server و درون Sp ها جای داده و از Parameter ها استفاده کرد که بازم باید دقت کرد و مسائلی رو رعایت کرد.
خیلی از راهکارها اگر دقیقتر بررسی بشه میتوان بدون استفاده از Dynamic Query مشکل رو حل کرد.

----------


## ASKaffash

سلام
زمان کامپایل شدن یک Dynamic SQL در عمل زیر یک ثانیه است که اصلا معنی کندی نخواهد داد با فرض رعایت اصول امنیتی که بسیار مهم است مواردی استفاده از Dynamic SQL برای بالابردن سرعت و کارائی یک اجبار است اگر ابهامی باشد حاضرم سر موقع یک مثال بزنم (وقتی که می خواهیم شرایط پویا ایجاد کنیم و قرار است دستور Select در سمت DB باشد)

----------


## حمیدرضاصادقیان

ممنون جناب کفاش. اگر با مثال بیان کنید خیلی عالی میشه.منم سعی میکنم در زمینه Compile شدن و بحثهای دیگه مواردی رو مطرح کنم تا دوستان با این موارد با جزئیات آَشنا بشن.

----------


## صادق صدقی

سلام
من هم یک تاپیک گذاشتم البته اول این تاپیک رو ندیدم

لینک

من دیدم که میشه Where رو داینامیک کرد
اینطوری دیگه نیازی هم به ترجمه نداره سرور

فقط بحث این میمونه که چطوری پارامتر هارو بررسی کنیم و به where بچسبونبم

تاپیک منوهم یک نگگاه بندازید
ممنون میشم

----------


## ASKaffash

سلام
خوب من برای شروع از یک جدول کالاها بنام Goods شروع میکنم برای موضوع امنیت که بعدا بحث میکنیم عمدا فیلد کد کالا را کاراکتری میگیرم بنام C_Goods و طبقه کالا را یک int بنام GTID می گیرم حال منطق ذیل را برای دریافت فیلدهای متغیر و شرایط متغییر اینطوری می نویسم دوستان مطالعه کنند تا بحث فنی را شروع کنیم : (حتما به حالتهای متفاوت دقت کنید)


--Declare @C_Goods1 VarChar(16)='1250000000000000',@C_Goods2 VarChar(16)='1260000000000000',@GTID int=11251121
--Declare @C_Goods1 VarChar(16)='1250000000000000',@C_Goods2 VarChar(16)=null,@GTID int=11251121
--Declare @C_Goods1 VarChar(16)=null,@C_Goods2 VarChar(16)='1260000000000000',@GTID int=11251121
--Declare @C_Goods1 VarChar(16)=null,@C_Goods2 VarChar(16)=null,@GTID int=11251121
--Declare @C_Goods1 VarChar(16)=null,@C_Goods2 VarChar(16)=null,@GTID int=null
Declare @C_Goods1 VarChar(16)='1250000000000000',@C_Goods2 VarChar(16)='1260000000000000',@GTID int=null
Declare @FieldList VarChar(4000)='*,Col1=GTID*2,Col2=Len(C_Goods)'
Declare @DSQL VarChar(1000)='',@DWhere VarChar(3000)=''
Set @DSQL+=' Select '+@FieldList+' From Goods'
if @C_Goods1 IsNull
 Begin
    if Not @C_Goods2 IsNull
       Set @DWhere='C_Goods<='''+@C_Goods2+Char(39)
 End
Else
 Begin
    if Not @C_Goods2 IsNull
       Set @DWhere='C_Goods Between '''+@C_Goods1+''' and '''+@C_Goods2+Char(39)
    else
       Set @DWhere='C_Goods>='''+@C_Goods1+Char(39)
End
if Not @GTID IsNull
 Set @DWhere+=(Case @DWhere When''Then''Else' and 'End)+'GTID='+Convert(VarChar(10),@GTID)
if @DWhere<>''
 Set @DSQL+=' Where '+@DWhere
Select @DSQL --Show
ExEc(@DSQL)--Run

برای مواردی که متن خوب مشاهده نشود تصویر سورس را هم قرار میدهم :

----------

