معلمات SQL التي يمكن أن تكون اختيارية
سؤال
لديّ هذه المشكلة حيث أحتاج إلى تعيين معلمات "اختيارية" لإجراءتي المخزنة للعمل بشكل جيد. على سبيل المثال ، لدي هذا:
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.