it-swarm.asia

كيف يتم تضمين معلمة datetime في إجراء مخزن مع استعلام السلسلة؟

الإجراء المخزن الخاص بي على النحو التالي ،

    -- Add the parameters for the stored procedure here 
   @FromDate datetime,
   @ToDate datetime

       --Select query
      DECLARE @query nvarchar(max)

      set @query='SELECT [col1] 
                  FROM [Table1]              
                  WHERE ([col2] BETWEEN '''[email protected]+''' AND'''[email protected]+''')'

       execute sp_executesql @query

يؤدي تنفيذ استعلام السلسلة هذا إلى الخطأ التالي ،

"فشل التحويل عند تحويل التاريخ و/أو الوقت من سلسلة الأحرف."

أي شخص الرجاء مساعدتي في فرز هذا ...

5
Harun

المشكلة الأساسية هي أن TSQL لا يمكنها ضمنيًا تحويل التاريخ والوقت (أو عدد صحيح أو نقطة عائمة) إلى أنواع بيانات الأحرف. إنه في الواقع يتراجع ، يحاول تحويل بيانات الأحرف ضمنيًا إلى وقت التاريخ (قيمة النقطة العائمة/int) بناءً على قواعد أسبقية نوع البيانات. هذا ما تخبرك به رسالة الخطأ الخاصة بك بالمناسبة ، لا يمكن تحويل السلاسل إلى قيم التاريخ. يجب عليك صراحة أن تطلب منه دمج القيم في سلاسل الأحرف.

يوضح هذا المثال الرئيسي بالأعداد الصحيحة حيث يسهل فهم القيم المتوقعة.

DECLARE 
    @stringInt nvarchar(3)
,   @intint int

SELECT
    @stringInt = N'3'
,   @intint = 5

SELECT 
    @stringInt + @intint AS implicit_conversion
,   @stringInt + CAST(@intint AS nvarchar(5)) AS explicit_conversion

تُظهر قيمة التحويل الضمني أنstringint يتم تحويله إلى عدد صحيح أولاً ثم يتم التعامل مع + كإضافة رقمية وينتج عنها 8. يؤدي التحويل الصريح لـintint إلى نوع بيانات حرف في علامة + التي يتم التعامل معها على أنها سلسلة مع سلسلة عائدة من 35

implicit_conversion explicit_conversion
------------------- -------------------
8                   35

لحل مشكلتك المقدمة ، يجب عليك صراحةً تحديد قيم التاريخ والوقت لنوع الحرف بحيث يمكن ربط سلسلة الاستعلام كما هو متوقع.

set @query='SELECT [col1] 
FROM [Table1]              
WHERE ([col2] BETWEEN ''' + CONVERT(nvarchar(24), @FromDate, 121) +''' AND'''+ CONVERT(nvarchar(24), @ToDate, 121) +''')'

ولكن كما هو موضح أعلاه ، فأنت لا ترغب حقًا في القيام بذلك لعدد من الأسباب ، حيث يعد SQL Injection أحد هذه الأسباب. كما أنه يجعل الصيانة أكثر صعوبة عندما تقوم بتقطيع سلسلة استعلام وتقطيعها في TSQL.

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

جدول البيانات والبيانات

CREATE TABLE 
dbo.table1
(col1 int, col2 datetime)

INSERT INTO
    dbo.table1
SELECT
3, '2009-04-06'
UNION ALL SELECT
1, '2001-09-11'

عرض توضيحي لاستخدام المعلمات

DECLARE
    @FromDate datetime,
    @ToDate datetime

SELECT    
    @FromDate = '2005-03-17'
,   @ToDate = current_timestamp

DECLARE
    @query nvarchar(max)
SET @query = N'    
SELECT [col1] 
FROM [Table1]              
WHERE ([col2] BETWEEN @start AND @end)'

-- gratuitous use of parameter assignment here
-- could just as easily used @FromDate and @ToDate
-- in the @query and the parameter list
EXECUTE sp_executesql 
    @query
,   N'@start datetime, @end datetime'
,   @start = @FromDate
,   @end = @ToDate

النتائج

col1
3
11
billinkc

لتجنب هذا الخطأ ، ونقاط الضعف في حقن SQL ، يجب عليك إعادة كتابة الاستعلام الخاص بك على النحو التالي:

@FromDate datetime,
@ToDate datetime

--Select query
 SELECT [col1] 
   FROM [Table1]              
  WHERE [col2] BETWEEN @FromDate AND @ToDate
3
datagod