سؤال

لديّ هذه المشكلة حيث أحتاج إلى تعيين معلمات "اختيارية" لإجراءتي المخزنة للعمل بشكل جيد. على سبيل المثال ، لدي هذا:

CREATE PROCEDURE [dbo].[Search]
(
 @StartTime datetime = NULL,
 @EndTime datetime = NULL,
 @CustomerEmail nvarchar(255) = NULL,
 @OrderStatusID int
)

الآن ، في موقع الويب الخاص بي .NET لدي مثل مثال ، يرجى الأخذ في الاعتبار أنه يمكن أن يكون هناك معلمة واحدة فقط أو قد يكون هناك جميعًا:

commAdvanced.Parameters.Add("@StartTime", SqlDbType.DateTime).Value = startDate;
commAdvanced.Parameters.Add("@EndTime", SqlDbType.DateTime).Value = endDate;
commAdvanced.Parameters.Add("@CustomerEmail", SqlDbType.nvarchar).Value = null;
commAdvanced.Parameters.Add("@OrderStatusID", SqlDbType.Int).Value = null;

وهذا هو الاستعلام:

SELECT * FROM Order 
WHERE CreatedOn > CAST(@StartTime as datetime) 
  AND CreatedOn < CAST(@EndTime as datetime)
  AND Order.OrderStatusID = @OrderStatusID 
  AND Order.CustomerEmail = @PaymentStatusID

لا أحصل على أي سجلات عندما أفعل ذلك ، هل يمكن لشخص ما مساعدتي ماذا أحتاج إلى التغيير.

هل كانت مفيدة؟

المحلول

وفقًا لسؤالك ، من بين 4 معلمات ، يمكن نقل واحد أو جميع المعلمات إلى الإجراء الخاص بك. ويحتوي استعلامك على جميع الأعمدة التي تم فحصها في الفقرة. لذلك إذا فهمت لك بشكل صحيح ، حاليًا ، فلن تحصل على أي سجلات حتى يتم تمرير جميع المعلمات الأربعة باستخدام بيانات صالحة.

جرب هذا ، أنا ببساطة أقوم ببناء استعلام ثم تنفيذه. أتحقق من كل من المعلمات الخاصة بـ Nulls وفقط قيم المعلمة غير الفارغة يتم تضمينها في الفقرة.

declare @sqlstring varchar(1000)

set @sqlstring = 'SELECT * FROM Order WHERE 1=1 '

if @StartTime <> null OR @StartTime <> '' 
BEGIN 
set @sqlstring = @sqlstring + 'AND CreatedOn > CAST(@StartTime as datetime) ' 
END 

if @EndTime <> null OR @EndTime <> '' 
BEGIN 
set @sqlstring = @sqlstring + 'AND CreatedOn < CAST(@EndTime as datetime) ' 
END 

if @OrderStatusID <> null OR @OrderStatusID <> '' 
BEGIN 
set @sqlstring = @sqlstring + 'AND OrderStatusID = @OrderStatusID ' 
END 

if @CustomerEmail <> null OR @CustomerEmail <> '' 
BEGIN 
set @sqlstring = @sqlstring + 'AND CustomerEmail > @CustomerEmail ' 
END 

print @sqlstring
Exec(@sqlstring)

نصائح أخرى

على افتراض وجود خطأ مطبعي في استعلام SELECT ربما حاول

AND Order.CustomerEmail = ISNULL(@CustomerEmail, CustomerEmail)
And OrderStatusID = ISNULL(@OrderStatusID, OrderStatusID)

كما أنك لست بحاجة إلى إلقاء startTime وما إلى ذلك إلى DateTime. هم بالفعل من هذا النوع ، لا؟

تحتاج إلى المرور DBNull.Value لتلك المعلمة التي تريد تركها فارغة (وليس فقط .NET null) :

commAdvanced.Parameters.Add("@CustomerEmail", SqlDbType.nvarchar).Value = DBNull.Value;
commAdvanced.Parameters.Add("@OrderStatusID", SqlDbType.Int).Value = DBNull.Value;

هذا ينبغي أن تفعل خدعة.

أيضًا: إذا حددت معلمة من النوع varchar أو nvarchar, ، أود أن أوصي دائماً حدد طوله.

أعتقد أن هذا هو Simpy إلى استفسارك غير صحيح.

دعنا نأخذ مثال توفير @فقط. سيقوم استفسارك بتقييم:

SELECT * FROM Order  
WHERE CreatedOn > CAST(@StartTime as datetime)  
  AND CreatedOn < null
  AND Order.OrderStatusID = null
  AND Order.CustomerEmail = null

على افتراض أن ANSI nulls قيد التشغيل ، لا توجد قيمة عند مقارنتها بإرجاع نتيجة حقيقية ، وبالتالي مجموعة النتائج الفارغة.

أعتقد أن إجابة نويل الأقرب - أود أن أقترح:

SELECT * FROM Order  
WHERE (@StartTime is null or CreatedOn > @StartTime)
  AND (@EndTime is null or CreatedOn < @EndTime)
  AND Order.OrderStatusID = isnull(@OrderStatusID, Order.OrderStatusID)
  AND Order.CustomerEmail = isnull(@CustomerEmail, Order.CustomerEmail)

MARC_S صحيح أيضًا - إذا كنت ترغب صراحة في تعيين قيمة @ المعلمة على SQL NULL ، فقم بتعيينها كـ

commAdvanced.Parameters.Add("@CustomerEmail", SqlDbType.nvarchar).Value = DBNull.Value;          
commAdvanced.Parameters.Add("@OrderStatusID", SqlDbType.Int).Value = DBNull.Value;   

ومع ذلك ، نظرًا لأنك قدمت قيمًا افتراضية لـ NULL في بروك المخزنة الخاص بك (باستثناء orstatusid - خطأ مطبعي؟), ، لا تحتاج فعلاً إلى إضافة هذه المعلمات إلى الأمر على الإطلاق.

كن حذرًا: قد لا يكون الحل الأفضل للصيانة جيدًا للأداء وقابلية التوسع (ولاحظ أن مجال اللعب قد تغير منذ SQL Server 2008).

هذا موضوع كبير وأوصيك بقراءة ظروف البحث الديناميكية في T-SQL بواسطة erland Sommarskog.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top