2013-12-10 15 views
0

儘量簡短。這是我的桌子和SP在SQL Server 2008 R2數據庫:ADO.NET和SSMS以不同方式解釋SP參數或SQL分析器有錯誤?

CREATE TABLE dbo.TEST_TABLE 
(
    ID INT NOT NULL IDENTITY (1,1) PRIMARY KEY, 
    VALUE varchar(23) 
) 
GO 

CREATE PROCEDURE USP_TEST_PROCEDURE 
( 
    @Param1 varchar(23) 
) 
AS 
BEGIN 
    INSERT INTO TEST_TABLE (VALUE) VALUES (@Param1) 
END 
GO 

下面是C#代碼:我特意指定的日期時間@參數1的類型

using (SqlConnection con = GetConection()) 
{ 
    using (var cmd = new SqlCommand("USP_TEST_PROCEDURE", con)) 
    { 
     cmd.CommandType = CommandType.StoredProcedure; 
     cmd.Parameters.Add("@Param1", SqlDbType.DateTime, 23).Value = "2013-12-10 12:34:56.789"; 
     cmd.Connection.Open(); 
     cmd.ExecuteNonQuery(); 
    } 
} 

留意。 現在啓動SQL Server Profiler並運行.NET代碼。完成後,不要停止分析器,只需查看輸出即可。我看到了RPC以下文字:完成事件類:

exec USP_TEST_PROCEDURE @Param1='2013-12-10 12:34:56.790' 

現在這個文本,打開SSMS,粘貼複製到新的查詢窗口,並運行它沒有任何變化。現在停止剖析,並確保在SSMS中產生的探查作爲ADO.NET應用程序相同的文字:

exec USP_TEST_PROCEDURE @Param1='2013-12-10 12:34:56.790' 

現在從TEST_TABLE表中選擇。我看到以下結果:

ID&nbspVALUE 
1 &nbspDec 10 2013 12:34PM 
2 &nbsp2013-12-10 12:34:56.790 

的問題是,爲什麼兩個相同的命令(從SQL Server Profiler的觀點)產生不同的結果?

這似乎是探查器無法正確顯示幕後發生的事情。當我運行.NET應用程序,我預計將看到以下內容:

DECLARE @Param1 Datetime = '2013-12-10 12:34:56.789'; 
exec USP_TEST_PROCEDURE @[email protected] 

在這種情況下,這將是很清楚,爲什麼我有790毫秒,而不是789.這是因爲日期時間類型也不是很準確。它被四捨五入爲.000,.003或.007秒的增量。請參閱:datetime (Transact-SQL)這也將是明確的爲什麼我'2013年12月10日12:34 PM'而不是'2013-12-10 12:34:56.790'。這是因爲datetime被轉換爲字符串時默認使用'mon dd yyyy hh:miAM(或PM)'格式。見CAST and CONVERT (Transact-SQL)下面的例子表明:

DECLARE @Param1 Datetime = '2013-12-10 12:34:56.789'; 
DECLARE @Param1_varchar varchar(23); 

SELECT @Param1 --2013-12-10 12:34:56.790 
SET @Param1_varchar = @Param1; 
SELECT @Param1_varchar; --Dec 10 2013 12:34PM 
GO 

如果我的理解是正確的,那麼我想改寫這個問題:爲什麼SQL Server事件探查顯示了一些奇怪和困惑?有沒有任何方法可以解決這個問題?

回答

0

您的應用程序發送一個日期,但因爲你選擇了一個VARCHAR列,它是隱含在轉換的方式就像什麼用打印情況:

DECLARE @d DATETIME = GETDATE(); 

SELECT @d; -- this is still a datetime 

PRINT @d; -- this is implicitly converted to a string 

如果你不喜歡這種混亂行爲,然後停止混合數據類型。絕對沒有理由將日期時間值存儲在varchar列中。

+0

是的,你是對的 - 我們不應該混合使用數據類型。不過,我想留意一下,我是故意透露這個問題的。事實上,問題是關於SQL Server Profiler的混淆行爲。 – Alex

+0

讓我們想象我有第三方應用程序,並且無法訪問源代碼。所以我不知道SqlDbType分配給SqlParameter的是什麼。也許它有SqlDbType.DateTime或SqlDbType.VarChar。在這種情況下,看看發生了什麼的唯一方法是使用分析器。所以我啓動它並看到以下內容: 'exec USP_TEST_PROCEDURE @Param1 ='2013-12-10 12:34:56。790'' 我如何知道「應用程序正在發送日期時間」,而不是字符串?這並不明顯。探查器中是否有任何參數可以強制探查器顯示此信息? – Alex

+0

@Alex我認爲你錯誤的工作使用了錯誤的工具,我甚至不知道爲什麼。首先,profiler已被棄用,不用擔心它不是爲你正在做的任務而設計的。你可以從執行計劃中獲得更多的信息(參數類型,隱式轉換等),這些信息遠遠超過了探查器。你試圖問出租車司機是誰開車送我去機場的,我什麼時候會到達目的地。 –