8

Tôi đã tạo ra một quy trình với cấu trúc này nhưng nó không hoạt động cho tham số đầu vào datetimeLoại datetime cho tham số đầu vào trong thủ tục

tôi thực hiện truy vấn này nhưng

declare @a datetime 
declare @b datetime 

set @a='2012/04/06 12:23:45' 
set @b='2012/08/06 21:10:12' 

exec LogProcedure 'AccountLog', N'test', @a, @b 

nhưng SQL Server đã cho tôi này lỗi

Chuyển đổi không thành công khi chuyển đổi ngày và/hoặc thời gian từ chuỗi ký tự.

nhưng khi tôi thử nghiệm với truy vấn này nó hoạt động

exec LogProcedure 'AccountLog',N'test' 

mã thủ tục lưu trữ:

alter PROCEDURE LogProcedure 
    @TableName VARCHAR(60), 
    @SearchString NVARCHAR(50), 
    @DateFirst DateTime = '', 
    @DateLast DateTime = '' 
AS 
BEGIN 
    SET NOCOUNT ON 

    DECLARE @FinalSQL  NVARCHAR(MAX) 

    SET @FINALSQL = 'SELECT * FROM [' + @TableName + '] where 1=2 ' 

    IF @DateFirst <> '' and @DateLast <> '' 
     set @FinalSQL = @FinalSQL + ' or convert (Date,DateLog) >=  '''[email protected] + ' and convert (Date,DateLog) <='''[email protected] 

    SELECT 
     @FinalSQL = @FinalSQL + ' or [' + SYSCOLUMNS.NAME + '] LIKE N''%' + @SearchString + '%'' ' 
    FROM SYSCOLUMNS 
    WHERE OBJECT_NAME(id) = @TableName 
    AND TYPE_NAME(SYSCOLUMNS.XTYPE) IN ('VARCHAR','NVARCHAR','CHAR','NCHAR','INT','DECIMAL') 
    ORDER BY COLID 

    EXEC(@FinalSQL) 
END 

Truy vấn này là đúng quá

SELECT * 
FROM AccountLog 
where 1=2 or convert (Date, DateLog) >= '2012/04/06' 
and convert (Date, DateLog) <='2012/08/06' 
+3

Tôi không hiểu StackOverflow nữa, tại sao câu hỏi này lại bị bỏ phiếu? đó là một vấn đề khá chung chung với một lời giải thích về những gì anh ta đã thử. –

Trả lời

21

Bạn nên sử dụng các tiêu chuẩn ISO -8601 định dạng cho chuỗi đại diện của ngày - bất cứ điều gì khác phụ thuộc vào cài đặt ngôn ngữ và định dạng ngày tháng của SQL Server.

Định dạng tiêu chuẩn ISO-8601 cho một DATETIME khi sử dụng chỉ ngày là: YYYYMMDD (không dấu gạch ngang hoặc antyhing!)

Đối với một DATETIME với phần thời gian, đó là YYYY-MM-DDTHH:MM:SS (với dấu gạch ngang, và một T trong giữa các phần ngày và thời gian riêng biệt).

Nếu bạn muốn chuyển đổi chuỗi thành DATE cho SQL Server 2008 hoặc mới hơn, bạn có thể sử dụng YYYY-MM-DD (với dấu gạch ngang) để đạt được kết quả tương tự. Và đừng hỏi tôi tại sao điều này quá mâu thuẫn và khó hiểu - nó chỉ là vậy, và bạn sẽ phải làm việc với điều đó ngay bây giờ.

Vì vậy, trong trường hợp của bạn, bạn nên thử:

declare @a datetime 
declare @b datetime 

set @a = '2012-04-06T12:23:45' -- 6th of April, 2012 
set @b = '2012-08-06T21:10:12' -- 6th of August, 2012 

exec LogProcedure 'AccountLog', N'test', @a, @b 

Hơn nữa - proc lưu trữ của bạn có vấn đề, vì bạn đang concatenating cùng datetime và chuỗi thành một chuỗi, nhưng bạn không chuyển đổi datetime để chuỗi đầu tiên, và cũng có thể, bạn đang quên các dấu ngoặc kép gần trong câu lệnh của bạn sau cả hai ngày.

Vì vậy, thay đổi dòng này ở đây như thế này:

IF @DateFirst <> '' and @DateLast <> '' 
    SET @FinalSQL = @FinalSQL + ' OR CONVERT(Date, DateLog) >= ''' + 
        CONVERT(VARCHAR(50), @DateFirst, 126) + -- convert @DateFirst to string for concatenation! 
        ''' AND CONVERT(Date, DateLog) <=''' + -- you need closing quotes after @DateFirst! 
        CONVERT(VARCHAR(50), @DateLast, 126) + ''''  -- convert @DateLast to string and also: closing tags after that missing! 

Với các thiết lập này, và một khi bạn đã cố định thủ tục lưu trữ của bạn, trong đó có vấn đề ngay bây giờ, nó sẽ làm việc.

1

Trong phần này của SP của bạn:

IF @DateFirst <> '' and @DateLast <> '' 
    set @FinalSQL = @FinalSQL 
     + ' or convert (Date,DateLog) >=  ''' + @DateFirst 
     + ' and convert (Date,DateLog) <=''' + @DateLast 

bạn đang cố gắng nối chuỗi và datetimes.

Như kiểu datetime có ưu tiên cao hơn varchar/nvarchar, các nhà điều hành +, khi nó xảy ra giữa một chuỗi và một datetime, được hiểu như là Thêm vào đó, không phải là nối, và động cơ sau đó cố gắng để chuyển đổi phần chuỗi của bạn (' or convert (Date,DateLog) >= ''' và các giá trị khác) cho giá trị giờ hoặc giá trị số. Và thất bại.

Điều đó không xảy ra nếu bạn bỏ qua hai thông số cuối cùng khi gọi thủ tục, vì điều kiện đánh giá là sai và câu lệnh vi phạm không được thực thi.

Sửa đổi tình hình, bạn cần phải thêm đúc rõ ràng của các biến datetime của bạn để dây:

set @FinalSQL = @FinalSQL 
    + ' or convert (Date,DateLog) >=  ''' + convert(date, @DateFirst) 
    + ' and convert (Date,DateLog) <=''' + convert(date, @DateLast) 

Bạn cũng sẽ cần phải thêm đóng dấu nháy đơn:

set @FinalSQL = @FinalSQL 
    + ' or convert (Date,DateLog) >=  ''' + convert(date, @DateFirst) + '''' 
    + ' and convert (Date,DateLog) <=''' + convert(date, @DateLast) + '''' 
Các vấn đề liên quan