2009-08-16 86 views
0

我們也有類似如下的Java代碼:PreparedStatement的是SQL Server上的prepareStatement執行

PreparedStatement stmt = connection.prepareStatement("drop login tmp"); 
int result = stmt.executeUpdate(); 

當通過調試運行,似乎正在執行的第一線後我們的SQL語句執行,甚至在第二行執行之前。當第二行執行時,刪除SQL再次執行,並且導致錯誤,因爲用戶名tmp不再存在。

這隻發生在SQL Server上,而不是針對Oracle和Postgres的類似刪除SQL查詢。

這是一個已知的問題?除了轉移到Statement而不是PreparedStatement之外,是否有一個常見的解決方法?

+1

那麼,你的陳述不包括任何變量,所以實際上沒有什麼需要「準備」。你有沒有試過只用一個陳述? – 2009-08-16 14:43:30

+0

我同意drop不是一個準備好的陳述的好候選人,事實上,我們切換到陳述並解決問題。 但是,這是一個庫代碼,我們可能需要將它用於不同的查詢,所以我想找到問題的根源。 – splintor 2009-08-17 06:41:44

回答

1

我認爲您最好的選擇是對測試數據庫運行SQL Server Profiler,並在運行此代碼時查看真正觸及服務器的內容。使用C#編寫的語句,您會看到類似於

declare @p1 int 
set @p1=-1 
exec sp_prepexec @p1 output, N'@param, varchar(100)', ... 
select @p1 

Java或您的SQL客戶端庫可能使用不同的技術。

話雖如此,準備好的語句僅用於緩存和參數化重複的,可參數化的類似語句。這個想法是保存重新編譯SQL語句。如果你沒有發佈很多重複的類似的語句,那麼準備好的語句不會對你有利,並且緩存SQL是沒有用的。就我個人而言,我無法想象如何使用'drop login'來緩存會有所幫助。

最重要的是,我不認爲DROP LOGIN語句可以在T-SQL中使用參數。

+0

我同意,放棄不是一個準備好的陳述的好候選人,事實上,我們切換到陳述,問題就解決了。 但是,這是一個庫代碼,我們可能需要將它用於不同的查詢,所以我想找到問題的根源。 – splintor 2009-08-17 06:40:21

0

當您創建PreparedStatement時,查詢將發送到服務器進行預編譯(Source)。

猜測,SQLServer發現沒有佔位符,只是執行查詢。

從評論中判斷,您已經知道修復方法是創建Statement