2017-03-16 252 views
0

我想通過java將數據插入到SQL服務器中的表中。 第一個是ID,第二個是nvarchar名稱,第三個是xml類型(我將它作爲字符串插入)。java.sql.SQLException:錯誤的參數數量錯誤

我有一個數據庫管理類,管理查詢執行本身(包括連接到數據庫)。

插入代碼:

stmt = String.format("INSERT INTO [dbo].[WorkflowFull] ([ID], [Name], [Workflow]) VALUES (%d, N'%s', N'%s')", workflowID, fileNameForDB, fileContent); 
     try{ 
      dbManager.insert(stmt); 
     } catch (SQLException e){ 
      System.out.println("Problem adding workflow " + fileName + " to DB"); 
      e.printStackTrace(); 
      continue; 
     } 

我得到的錯誤:

java.sql.SQLException: Wrong number of parameters: expected 3, was given 0 Query: INSERT INTO [dbo].[WorkflowFull] ([ID], [Name], [Workflow]) VALUES (1, N'testWorkflow', N'<Workflow name="NetMonitorTester" start="atomic"> 
<atomic name="atomic" startingPoint="monitor" hostType="PC" multiplicity="1"> 
    <activity package="MonitorNetwork" name="monitor" input="null" stopCondition="never"> 
     <filter query="regex:GET.+(.{10,})\1{10,}"/> 
     <resultQuery retrieve="SELECT * FROM PUBLIC.TCP_PACKETS"/> 
    </activity> 
</atomic> 
</Workflow>') Parameters: [] 
at org.apache.commons.dbutils.AbstractQueryRunner.rethrow(AbstractQueryRunner.java:392) 
at org.apache.commons.dbutils.QueryRunner.insert(QueryRunner.java:610) 
at org.apache.commons.dbutils.QueryRunner.insert(QueryRunner.java:516) 
at org.bgu.ddms.utils.dbutils.DbManager.insert(DbManager.java:165) 
at org.bgu.ddms.cnc.CNC.populateWorkflows(CNC.java:289) 
at org.bgu.ddms.cnc.CNC.populateDB(CNC.java:244) 
at org.bgu.ddms.cnc.Main.main(Main.java:108) 

當我運行在SSMS完全相同的查詢,一切工作正常

+0

這是什麼意思'N'% s''? –

+0

注意:我不是你正在使用的框架的專家('[dbo]'等等,看起來不像舊的sql),但是'String.format(...)'看起來很像容易受SQL注入影響。您應該_never_直接將可能不受信任的值連接到查詢中。既然你使用了JDBC標籤,我建議使用'PreparedStatement'來代替(或者你的框架公開了)。 – Thomas

+1

結合我上面的評論,我會懷疑將未轉義的XML,尤其是包含查詢本身的XML直接轉換爲查詢字符串是您遇到的問題。這可能會通過使用'PreparedStatement'來解決,您可以在其中調用'setParameter(3,yourXmlString)'而不是將它連接到查詢中。 – Thomas

回答

2

第一是一個ID,第二個是nvarchar名稱,第三個是xml類型(我將它作爲字符串插入)。

你的方法可能會導致一個語法錯誤,像你現在,壞事SQL Injection所以要避免這一點,你必須使用PreparedStatement代替,例如:

String query = "INSERT INTO [dbo].[WorkflowFull] ([ID], [Name], [Workflow]) VALUES (?, ?, ?)"); 
PreparedStatement preparedStatement = connection.prepareStatement(query); 
preparedStatement.setInt(1, workflowID); 
preparedStatement.setString(2, fileNameForDB); 
preparedStatement.setString(3, fileContent); 
+0

我會對'PreparedStatement'產生更多興趣,因爲這樣可以解決問題(setXXX方法可以避免這個問題)並且更安全。 – AxelH

+0

你是什麼意思@AxelH我已經把一個例子說明如何使用PreparedStetement?你想讓我把'setInt'改成'setXXX'還是什麼? –

+1

那麼,我已經在編輯過程中評論過添加示例,所以這正是我的意思;) – AxelH