【问题标题】:How to insert and select from mysql simultaneously如何同时从mysql中插入和选择
【发布时间】:2013-11-29 17:16:36
【问题描述】:

我有一个要求,当且仅当号码不存在时,我需要在 mysql 中插入手机号码。因此,为此我首先使用 select 查询检查 mysql 中是否存在号码。如果号码不存在然后 insert.Following 是我的代码

PreparedStatement pt1=con.prepareStatement("select * from registerSmsUsers where mobile='"+mobile+"'");
PreparedStatement pt=con.prepareStatement("insert into registerSmsUsers values(?,?,?)");
        pt.setString(1, name);
        pt.setString(2, email);
        pt.setString(3, mobile);
ResultSet rs1=pt1.executeQuery();
        if(rs1.next())

{pt.executeUpdate();}

我不知道这是否是一种有效的方法。请给我一个比这个更好的方法

【问题讨论】:

    标签: java mysql sql jdbc


    【解决方案1】:

    我认为最好创建一个存储过程,然后在该存储过程中,您可以先使用IF NOT EXISTS 子句使用select 语句检查用户是否存在。如果用户不存在,您可以insert 数据库中的用户。

    类似这样的:

    IF NOT EXISTS(SELECT 1 FROM `registerSmsUsers` WHERE mobile= @mobile) THEN
        BEGIN
        INSERT INTO 
            `registerSmsUsers`
            (
                //column names
            ) 
            VALUES 
            (
                //values
            );
        END;
    END IF;
    

    还有一个INSERT IGNORE 语句,您可以这样使用:

    insert ignore into registerSmsUsers values(?,?,?)
    

    【讨论】:

    【解决方案2】:
    if not exists(select * from registerSmsUsers where mobile='232323') <-- will check your mobile no
    begin
     insert into registerSmsUsers values(?,?,?)
    end
    

    这也是一种检查您的方法是否正常工作的有效方法,但也可以这样做 看到不同的是你在这里只有一个查询 希望对你有帮助 谢谢

    [编辑]

    您的问题回答

    是的,您和我的查询之间存在执行 时间差异,它取决于 数据库大小 如果您使用的是 小型数据库(可能有 1000 人) 那么您不会看到您的查询和我的查询之间有任何差异,但是如果您使用的是十万用户,那么您将遇到性能问题检查,包括 mysql 中的执行计划,您将获得两者之间的实时差异

    【讨论】:

    • 感谢您的回答,+1 的帮助。您能告诉我如何知道上述方式比我的方式更好。我们能知道执行时间或其他任何事情吗
    • 我是这样做的 if not exists(select * from registerSmsUsers where mobile='232323') -&gt; begin -&gt; insert into registerSmsUsers values(?,?,?) -&gt; end; 错误是You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'if not exists(select * from registerSmsUsers where mobile='232323') begin inse' at line 1
    • 您使用的是哪个版本?
    【解决方案3】:

    mysql 中最简单的方法可能是:

    insert ignore into registerSmsUsers values(?,?,?)
    

    假设您在移动设备上拥有唯一密钥

    您可以在这里查看:How to 'insert if not exists' in MySQL?

    或在这里:http://dev.mysql.com/doc/refman/5.6/en/insert.html

    【讨论】:

    • 它可能不是主键。但以这种方式使用它应该是唯一的关键
    【解决方案4】:

    许多建议的解决方案(包括您的解决方案)都有可能导致主键或唯一约束违规的竞争条件。您的代码还可能通过连接 SQL 而不是使用准备好的语句参数来进行 SQL 注入攻击。使用 SELECT...进行更新。

    PreparedStatement ps = con.prepareStatement("SELECT name, email, mobile FROM registerSmsUsers WHERE mobile=? FOR UPDATE",
                                                ResultSet.TYPE_FORWARD_ONLY,
                                                ResultSet.CONCUR_UPDATABLE);
    ps.setString(1, mobile);
    ResultSet rs = ps.executeQuery();
    if (rs.next()) { // it exists already
       rs.moveToCurrentRow();
       rs.updateString(3, mobile);
       rs.updateRow();
    } else { // it does NOT exist
       rs.moveToInsertRow();
       rs.updateString(1, name);
       rs.updateString(2, email);
       rs.updateString(3, mobile);
       rs.insertRow();
    }
    rs.close();
    ps.close();
    

    编辑:只要确保您在 registerSmsUsers 上有一个索引。

    CREATE INDEX registerSmsUsers_mobile_ndx ON registerSmsUsers(mobile)
    

    或唯一的约束(隐式创建索引):

    ALTER TABLE registerSmsUsers ADD CONSTRAINT registerSmsUsers_mobile_unq UNIQUE (mobile)
    

    使用索引,即使有数百万条记录,更新/插入也基本上是即时的。

    EDIT2:添加了光标/结果集选项。

    【讨论】:

    • 感谢您的回答+1,我需要知道哪种方式会更快。假设如果我有大约 1000000 条记录,那么插入一条记录它将检查 1000000 条。
    • 是的,如果registerSmsUsers 已经在创建声明mobile 唯一的,那么会有一个现有的索引,它应该非常快。当你发现它有效时,请接受这个答案。
    • 看到我发现你的答案很有用,所以已经投了赞成票,请给我一些时间在我的应用中实现你的想法。
    • 这将是 rs.setString(1, name); rs.setString(2, email); rs.setString(3, mobile); rs.updateString() 而不是 setString,对吧?
    • 我刚刚将您的代码复制到 eclipse。在 eclipse 中它给出了编译错误并建议使用 rs.setString() 到 rs.UpdateString()(此错误显示在 else 循环中)
    【解决方案5】:

    根据要求,这是我对 brettw 答案的调整版本:

    import java.sql.*;
    
    public class MySQLtest {
    
        public static void main(String[] args) {
            Connection con;
            try {
                con = DriverManager.getConnection(
                        "jdbc:mysql://192.168.1.3/zzzTest?" +
                        "useUnicode=yes&characterEncoding=UTF-8" +
                        "&user=root&password=whatever");
                String newName = "Gord";
                String newEmail = "gord@example.com";
                String newMobile = "416-555-1212";
                String sql = 
                        "SELECT " +
                            "id, " +
                            "name, " +
                            "email, " +
                            "mobile " +
                        "FROM registerSmsUsers " +
                        "WHERE mobile = ? " +
                        "FOR UPDATE";
                PreparedStatement pst = con.prepareStatement(
                        sql, 
                        ResultSet.TYPE_FORWARD_ONLY, 
                        ResultSet.CONCUR_UPDATABLE);
                pst.setString(1, newMobile);
                ResultSet rs = pst.executeQuery();
                if (rs.next()) {
                    rs.moveToCurrentRow();
                    rs.updateString("name", newName);
                    rs.updateString("email", newEmail);
                    rs.updateRow();
                    System.out.println("Existing row updated.");
                }
                else {
                    rs.moveToInsertRow();
                    rs.updateString("name", newName);
                    rs.updateString("email", newEmail);
                    rs.updateString("mobile", newMobile);
                    rs.insertRow();
                    System.out.println("New row inserted.");
                }
            } catch (SQLException ex) {
                ex.printStackTrace();
            }
        }
    
    }
    

    注意id 是表的主键:int(11) NOT NULL AUTO_INCREMENT

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-11
      • 1970-01-01
      • 1970-01-01
      • 2019-08-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多