2017-03-16 324 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