MySQL基本的增删改查


JDBC MySQL的连接

使用工具:Eclipse and Visual Studio 2019

这里其实无论是使用Java还是C++,使用的都是jdBC的操作。当然这里的Java相对来说更加的正宗一点,C++中的jdBC库我用了关于string那一块还有bug,兼容性还不行。所以这里就使用eclipse Java来举例吧。至于如何连接MySQL,这个倒是简单的很,也是不必再说了。

Driver的初始化

try {
    //Class.forName是把这个类加载到JVM中,加载的时候,就会执行其中的静态初始化块,完成驱动的初始化的相关工作。 
    // 首先加载驱动包 com.mysql.cj.jdbc.Driver
    Class.forName("com.mysql.cj.jdbc.Driver");
} catch (ClassNotFoundException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}
mysql::MySQL_Driver* driver;
driver = sql::mysql::get_mysql_driver_instance();

Connection连接数据库, 初始化 Statement

// 连接的地址 localhost就是127.0.0.1就是本机的地址 world 代表的是要使用的数据库的名字
String url = "jdbc:mysql://localhost:3306/sher?useUnicode=true&characterEncoding=UTF8&useSSL=false&serverTimezone=UTC";
// 建立和数据库的连接 url account password
try {
    con = DriverManager.getConnection(url,"root","root");
    stmt = con.createStatement();
} catch (SQLException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

其实上面的变量的声明都在类中的静态变量中,为了方便以后数据库的关闭

static ResultSet rs = null;
static Statement stmt = null;
static Connection con = null;
static PreparedStatement pstmt = null;
Connection* con;
Statement* state;
ResultSet* result;
const char* accout = "root";
const char* passwd = "root";
con = driver->connect("tcp://127.0.0.1:3306", accout, passwd);
state = con->createStatement();

这里C++代码中要注意一个问题,account和passwd不能直接写driver->connect中,而且也不可以使用string类,不然会出现莫名其妙的bug,我也是求助了好长时间才知道这个地方出了问题,我也是醉了。

数据库的关闭

private static void close() {
    try {
        if (rs!=null) {
            rs.close();
        }
        if (stmt!=null) {
            stmt.close();
        }
        if (con!=null) {
            con.close();
        }
        if (pstmt!=null) {
            pstmt.close();
        }
    } catch (SQLException e) {
        e.printStackTrace();
    }    
}

C++代码当中没有使用异常处理的机制,而且C++代码中异常处理也不是很好,反正使用体验极差。不过C++11中对于异常机制的改良,我也没学过不知道怎么样。

数据库的增删改查

数据库增加数据

private static void addData(int id, String username, String passwd) throws SQLException {
    String sql = String.format("insert into shertable(id, username, passwd) values('%d', '%s', '%s')", id, username,passwd);
    stmt.execute(sql);
}

上面定义的时候我们使用了两种Statement。Statement和 PreparedStatement,这两种之间有什么区别呢?其实是建议使用PreparedStatement的,Statement容易被SQL注入,是不怎么安全的,不过为了介绍这里就都使用了。

stmt.execute(sql) 一般这种insert语句还有用的就是executeUpdate()。还有一个是executeQuery().这三者是有区别的

  1. ResultSet executeQuery(String sql); 执行SQL查询,并返回ResultSet 对象
  2. int executeUpdate(String sql); 可执行增,删,改,返回执行受到影响的行数
  3. boolean execute(String sql); 可执行任何SQL语句,返回一个布尔值,表示是否返回ResultSet

不过这个execute也不是万能的。

如果 SQL 语句中有 ? 占位符,那么在设置好占位符中的值后,必须使用 executeUpdate() 执行。

至于这个?占位符是PreparedStatement中使用的,等到下面再说。

数据库查询数据

private static void queryData(String sql) throws SQLException {
    rs = stmt.executeQuery(sql);
    while (rs.next()){
        System.out.println("Id: "+rs.getInt("id")+" Username: "+rs.getString("username")+" Password: "+rs.getString("passwd"));
    }
    System.out.println();
}
state->execute("use world");
// 查询
result = state->executeQuery("select * from city order by id desc limit 10");
// 输出查询
    cout << endl;
    cout << setw(15) << "" << "======================================================================" << endl;
    cout << setw(15) << "";
    cout << left << setw(15) << "Id" << setw(15) << "Name" << setw(15) << "CounryCode"
        << setw(15) << "District" << setw(15) << "Population" << endl;
    cout << setw(15) << "" << "======================================================================" << endl;
    while (result->next())
    {
        int id = result->getInt("id");
        // 关于getString()这一块这个写的真的是全都是bug, 不过现在好像已经可以运行了。
        string name = result->getString("name").c_str();
        string countrycode = result->getString("countrycode").c_str();
        string district = result->getString("district").c_str();
        int population = result->getInt("population");
        cout << setw(15) << "" << setw(15) << id << setw(15) << name << setw(15) << countrycode
            << setw(15) << district << setw(15) << population << endl;
    }
    cout << setw(15) << "" << "======================================================================" << endl;
    delete state;
    delete con;

看这个Java和C++中jdBC的操作基本上都是一样的。不过这里C++代码需要注意一下,我又被坑惨了。在使用result->getString()之后要加上.c_str()使其变成C风格的字符串。都说了string类在jdBC for C++中真的全是bug。C++其实也有C风格的MySQL数据库连接的库,不过那个已经不在这次介绍的范围之内了。

PreparedStatement 添加数据

private static void setPstmtSql(int id, String username, String passwd) throws SQLException {
    pstmt = con.prepareStatement("insert into shertable(id, username, passwd) values(?,?,?)");
    pstmt.setInt(1, id);
    pstmt.setString(2, username);
    pstmt.setString(3, passwd);

    pstmt.executeUpdate();
}

这里就是pstmt的代码的使用。我们先使用占位符来创建一个SQL语句,然后使用setInt(),setString()的方法,来填入占位符中的内容,这是既简便了stmt字符串连接的操作,也可以防止SQL注入,很安全~

注意上面说的:

如果 SQL 语句中有 ? 占位符,那么在设置好占位符中的值后,必须使用 executeUpdate() 执行。

数据库删除数据

private static void delData(int id) throws SQLException{
    pstmt = con.prepareStatement("delete from shertable where id=?");
    pstmt.setInt(1, id);

    pstmt.executeUpdate();
}

数据库修改数据

private static void modifyPasswd(String username, String old_passwd, String new_passwd) throws SQLException{
    pstmt = con.prepareStatement("update shertable set passwd = ? where username = ? and passwd = ?");
    pstmt.setString(1, new_passwd);
    pstmt.setString(2, username);
    pstmt.setString(3, old_passwd);

    int flag = pstmt.executeUpdate();
    if (flag!=0) {
        System.out.println("Successfully!");
    }else {
        System.out.println("Unsuccessfully, please try again!");
    }
}

本列中其他的操作

根据名字查询

private static void queryByName(String name) throws SQLException {
    pstmt = con.prepareStatement("select * from shertable where username = ?");
    pstmt.setString(1, name);

    rs = pstmt.executeQuery();
    if (rs.next())
        System.out.println("Id: "+rs.getInt("id")+"\nUsername: "+rs.getString("username")+"\nPassword: "+rs.getString("passwd"));
    else
        System.out.println("Not Found!");
}

登陆系统

private static void sign(String name, String passwd) throws SQLException{
    pstmt = con.prepareStatement("select * from shertable where username = ? and passwd = ?");
    pstmt.setString(1, name);
    pstmt.setString(2, passwd);

    rs = pstmt.executeQuery();
    if (rs.next()) {
        System.out.println("Sign Up Successfully!");
    }else {
        System.out.println("Worng UserName or Password!");
    }
}

总结

上面都只是MySQL中的基础中的基础中的基础的操作,作为从来没有学过MySQL的看看基本就行了。对于MySQL中进阶一点的操作,SQL命令的更加高阶的使用可以下次写写看,现在暂时MySQL用得还是比较少滴,不急着学。


一枚小菜鸡