2015-09-05 1758 views
0

当使用下面的代码尝试向数据库表中插入新闻行时,我得到了完整性约束违规错误。SQLIntegrityConstraintViolationException由于重复键值

public void ExtractBoard() throws IOException, SQLException { 
    int rows = 0; 
    String sqlInser = "INSERT INTO APP.SUBSCRIBERBR (subID, boardno)"+"VALUES (?,?)"; 
    PreparedStatement stmt = conn.prepareStatement(sqlInser, Statement.RETURN_GENERATED_KEYS); 
    String[] AryFiles2 = rf.OpenFile(); 
    int i,j; 
    String p1 = "", p2 = ""; 
    for (i=0; i<AryFiles2.length; i++) { 
     if (AryFiles2[i].contains("ADD VSBR")) { 
      String[][] parts = this.LineParts(); 
      Scanner in = new Scanner(parts[i][0]).useDelimiter("[^0-9]+"); 
      int intst = in.nextInt(); 
      p1 = String.valueOf(intst); 
      for (j=0; j<parts[1].length; j++) { 
       if (parts[i][j].contains("MN")) { 
        Scanner inn = new Scanner(parts[i][j]).useDelimiter("[^0-9]+"); 
        int intstr = inn.nextInt(); 
        p2 = String.valueOf(intstr); 

       } 
      } 
     } 
     if(p1 != null && p2 != null){ 
      stmt.setString(1, p1); 
      stmt.setString(2,p2); 
      rows = stmt.executeUpdate(); 
     } 
     else { 
      throw new SQLException("Null parameters"); 
     } 
    } 
} 

这是我收到的错误消息。

java.sql.SQLIntegrityConstraintViolationException:语句被放弃,因为它会造成一个独特的或主键约束或通过在“SUBSCRIBERBR”定义“SQL150827011836400”标识的唯一索引中的重复的键值。

我该如何解决这个问题?

+0

这将是一个有点帮助,如果你可以发布数据库表的方案。但是,异常本身已经告诉你,你试图将一个值作为主键(或者至少是一个唯一的列)插入到数据库中,该值已经存在。所以您还应该检查您从中读取值的文件的内容。 – sleepy42

回答

0

你的subID变量似乎是重复的。 (有一个在你的表相同的subID另一条记录)

可能的原因是:

  1. 文件的阅读方法是错误的,你最终会读你的输入文件是错误的。

  2. 您的输入文件已包含重复键。

  3. 一切正常,但是您正试图在不清洗的情况下针对同一数据库运行您的代码,因此您最终将从上次运行中找到具有此子ID的记录。

+0

我认为该文件有重复的键。我想获得一些关于如何添加代码行来跳过已插入的键的帮助,使用sql关键字'EXISTS'或其他。 – AAJ

+0

首先你应该验证你的假设。 *然后*作为一个可能的解决方案(因为你正在寻找一些简单的东西),我会建议简单地捕获SQLIntegrityConstraintViolationException并跳过违规行。 –

+0

询问数据库是否已写入密钥更容易(且比异常处理更便宜)。你可以使用一个简单的选择,比如'从APP.SUBSCRIBERBR中选择subID,其中subID =?'。如果你没有行,你可以插入。 –

0

你从未p1p2为空,所以如果if声明是在第一次迭代假的,你插入"", "",如果if语句是在随后的迭代假的,你插入相同值如前面的迭代所做的那样。

+0

如果他会插入值“”,“”他应该得到一个非空约束违规或类型违规,因为'subID'是类型编号/ int的主键,我猜。 –

+0

@ dev.null你是对的,但也有这样的情况,*那么*这些代码有很多错误,我甚至不会解决关于未显示的事情的假设问题,比如列的数据类型,直到远远低于名单。相反,我选择专注于保证重复错误的逻辑的一部分,这就是问题所在,而没有对输入数据的明确了解。 ---让我们来看看....是的,可能会有一行或两行代码,我没有问题。更多的是,如果你用末端大括号来统计线条。 – Andreas

0

我想你读了错误的int,所以你最终得到错误的值并生成重复的键,这违反了约束条件。

你的主键来自parts[i][0](在0 i开始)在行:

Scanner in = new Scanner(parts[i][0]).useDelimiter("[^0-9]+"); 

但是,为什么你使用相同的值关于第二个SQL参数? p2设置为parts[i][j]在行

Scanner inn = new Scanner(parts[i][j]).useDelimiter("[^0-9]+"); 

(记住:j从0开始,太)见行

for (j=0; j<parts[1].length; j++) { 

所以你读parts[i][0]两次。

第二个问题可能是for循环变量j的上限:您将其设置为parts[1].length。不应该这部分[i] .length?

你怎么解决它?看看你的价值p1p2,也许你可以登录它。这些是你预期的价值吗? 你有哪些限制?只有主键或boardno也有约束或唯一索引(请参阅错误消息)?

你可以尝试这样的事情:

try { 
    rows = stmt.executeUpdate(); 
} catch (Exception e) { 
    logger.error("p1="+p1+" p2="+p2+" catched="+e); 
} 
+0

我没有读取两个sql参数的相同值。请注意,在if(parts [i] [j] .contains(“MN”))“ ”之后有一个if语句 和 '我知道在我正在使用的文件中,包含字符串“MN”的部分从不在第一列(即部分[i] [0])中。 我在表中使用其他输入文件正确的值。它只是这个文件给我的错误。 – AAJ

+0

你能告诉我们你的输入文件的内容吗? –

+0

对不起,我不能。 Compagny政策。 – AAJ