在sql中执行insert语句之前或之后获取记录的插入id

Posted

技术标签:

【中文标题】在sql中执行insert语句之前或之后获取记录的插入id【英文标题】:Get the inserted id of the record before or after execute the insert statement in sql 【发布时间】:2018-11-04 10:58:54 【问题描述】:

我的 DAO 类中有这个方法可以将记录插入到名为 idea 的表中,这是我的方法:

    public long  addIdea(AddIdeaDto addIdeaDto, int userId) 

    Connection connection = null;

    PreparedStatement preparedStatement = null;
    try 
        connection = getConnection();



        preparedStatement = connection.prepareStatement(
                "INSERT INTO IDEA ( IDEA.I_ID,IDEA.I_NO,IDEA.I_APPROVER_NAME_CODE, IDEA.I_TITLE,IDEA.I_DESCRIPITION, IDEA.I_CREATED_DATE,IDEA.I_STATUS_CODE, "
                        + "IDEA.I_IS_CODE, IDEA.I_CONTRIBUTION_CODE, IDEA.I_POSITIVE_IMPACT, IDEA.I_SECOND_MEMBER_ID,IDEA.I_THIRD_MEMBER_ID,IDEA.I_FOURTH_MEMBER_ID,"
                        + "IDEA.I_FIFTH_MEMBER_ID, IDEA.I_POINTS,IDEA.I_CREATED_USER_ID)"
                        + " VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)");


        preparedStatement.executeQuery("SELECT IDEA_SEQ.nextval FROM DUAL");

        // Set parameters
        preparedStatement.setObject(1, Types.NUMERIC);
        preparedStatement.setObject(2, Types.NUMERIC);

        preparedStatement.setObject(3, addIdeaDto.getApproverNameCode());

        preparedStatement.setString(4, addIdeaDto.getTitle());

        preparedStatement.setString(5, addIdeaDto.getDescription());
        preparedStatement.setDate(6, addIdeaDto.getCreatedDate() == null ? null
                : new java.sql.Date(addIdeaDto.getCreatedDate().getTime()));

        preparedStatement.setObject(7, addIdeaDto.getStatusCode());
        preparedStatement.setObject(8, addIdeaDto.getIsNewCode());

        preparedStatement.setObject(9, addIdeaDto.getContributionCode());

        preparedStatement.setString(10, addIdeaDto.getPositiveImpact());
        preparedStatement.setObject(11, addIdeaDto.getSecondMemberName());
        preparedStatement.setObject(12, addIdeaDto.getThirdMemberName());
        preparedStatement.setObject(13, addIdeaDto.getFourthMemberName());
        preparedStatement.setObject(14, addIdeaDto.getFifthMemberName());

        preparedStatement.setObject(15, addIdeaDto.getPoints());
        preparedStatement.setInt(16, userId);

        preparedStatement.executeQuery();
        return addIdeaDto.getIdeaId();

     catch (Exception e) 
        throw new RuntimeException(e);
     finally 
        try 
            preparedStatement.close();
         catch (SQLException e) 
            throw new RuntimeException(e);
        
    

实际上我想要的是在插入语句之后或之前我想要获取 id (IDEA_SEQ.nextval) 并将其保存在一个值中,以便将其用作插入到另一个表中的输入。

例如,我插入这条记录:id = 1,no = 1,approver code = 2,title = 'test'......

我希望这个值 id = 1 用于插入表 A,A_id = 33,IDEA.I_ID = 1,A_name ='testing'

我怎样才能以适当的方式实现它?

我根据收到的 cmets 更新了代码,但我没有实现它

【问题讨论】:

看看这个:***.com/questions/1915166/… 【参考方案1】:

通常需要重用的 ID 可以使用先前的单独 SQL 查询来处理

 previousPreparedStatement = connection.prepareStatement(
            "select IDEA_SEQ.nextval as nextval from dual");

根据传递给现有插入语句的列(numbervarchar)将结果保存为intString 参数:

(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)");

另请注意answer from DBA forum

您将无法使用纯 SQL 来克服此限制:您将需要一些 PL/SQL

【讨论】:

它会像:String id = "select IDEA_SEQ.nextval as nextval from dual" 和preparedStatement.setObject(1, id); 谢谢,我设置参数的时候会设置成字符串 我将不得不语句选择和插入 @wadhaalketbi 或 int,根据 oracle 列 varchar 或 number 两者都是 int 但我会将第一个语句 (select) 保存为 int 然后当我设置第二个语句的参数时,我将放置这个变量?【参考方案2】:

处理这个问题的更好方法是RETURNING INTO 子句,它使用单个原子语句:

INSERT INTO mytable (id, col1, col2)
VALUES ( seq_id.nextval, c1, c2 )
RETURNING id INTO myval;

【讨论】:

我添加返回到我的查询它给我缺少关键字 returning into 只能在 PL/SQL 块中使用,不能在 SQL 查询中使用。 我认为处理这个问题的最好方法是把它变成一个返回新 id 的函数。请参阅 Twitter 上的#SmartDB。别写SQL了! (见 Feuerstein)【参考方案3】:

您可以使用PreparedStatement.getGeneratedKeys() 来获取生成的值。无需单独声明:

您也不能在INSERT 语句的列列表中使用表名作为列名的前缀。

String insert = 
     "INSERT INTO IDEA ( I_ID,I_NO,I_APPROVER_NAME_CODE, I_TITLE,I_DESCRIPITION, I_CREATED_DATE,I_STATUS_CODE, "
   + "I_IS_CODE, I_CONTRIBUTION_CODE, I_POSITIVE_IMPACT, I_SECOND_MEMBER_ID,I_THIRD_MEMBER_ID,I_FOURTH_MEMBER_ID,"
   + "I_FIFTH_MEMBER_ID, I_POINTS,I_CREATED_USER_ID)"
   + " VALUES (idea_seq.nextval,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";


preparedStatement = connection.prepareStatement(insertSql, new String[] "I_ID");
preparedStatement.setInt(1, ???); // don't know where the value for I_NO comes from
preparedStatement.setString(2, addIdeaDto.getApproverNameCode());
preparedStatement.setString(3, addIdeaDto.getTitle());
... other parameters
preparedStatement.executeUpdate();
ResultSet rs = preparedStatement.getGeneratedKeys();
long newId = -1;

if (rs.next()) 
  newId = rs.getLong("I_ID");


... use the NewId ...

prepareStatement() 调用的参数new String[] "I_ID" 告诉 JDBC 驱动程序返回为该列生成的值。该值可以通过getGeneratedKeys() 检索,它返回一个ResultSet,其中包含每个插入行的一行(在这种情况下正好是一行)。然后可以使用常用的getLong()(或getInt())方法从ResultSet 中提取ID 值。

【讨论】:

以上是关于在sql中执行insert语句之前或之后获取记录的插入id的主要内容,如果未能解决你的问题,请参考以下文章

sql server 用INSERT语句添加数据时 语句中若有中文或英文字母 执行时就报错 是怎么回事?

求一条插入并返回的SQL语句

触发器

SQL语句replace怎么替换?

MySQL-08-笔记

如何得到JDBC Insert 语句执行后插入Oracle 数据库记录的主键