執行SQL語句的方式


JDBC不僅可執行查詢,也可以執行DDL,DML等SQL語句,從而允許通過JDBC最大限度地控制數據庫。

使用executeUpdate或者使用executeLargeUpdate方法來執行DDL和DML語句:

 編寫程序,通過executeUpdate方法在mysql當前數據庫下創建一個數據庫表 示范:

public class JDBC {
    String driver;
    String url;
    String user;
    String password;
    
    //查詢該數據庫是否有對應的表,有則返回ture,沒有返回false
    public boolean tableIsExists(String tableName){
        try{
            Connection conn =DriverManager.getConnection(url,user,password);
            Statement statement =conn.createStatement();
            String sql = "select table_name from information_schema.tables where table_schema='test'";
            ResultSet resultSet = statement.executeQuery(sql);
            while(resultSet.next()){
                String queryTableName = resultSet.getString(1);
                System.out.println(queryTableName);
                if(queryTableName.equals("tb_test")){
                    return true;
                }
            }
        }catch(Exception e){}
        return false;
    }
    
    public void createTableJDBC(String tableName){
        try{
            Connection conn =DriverManager.getConnection(url,user,password);
            Statement statement =conn.createStatement();
            if(!tableIsExists(tableName)){
                System.out.println("當前數據庫沒有"+tableName+"表格,將創建"+tableName+"數據庫表");
                String sql = "create table "+tableName+"("
                        + "test_id int auto_increment primary key,"
                        + "test_name varchar(255),"
                        + "test_desc text)";
                int result = statement.executeUpdate(sql);
            }else{
                System.out.println("當前數據庫有"+tableName+"表格,不創建"+tableName+"數據庫表");
            }
            
        }catch(Exception e){}
    }
    
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        JDBC jdbc = new JDBC();
        
        jdbc.initParam("mysql.properties");
        jdbc.createTableJDBC("tb_test");
    }
}

 第一次運行結果如下:

tb_adminuser
tb_user
當前數據庫沒有tb_test表格,將創建tb_test數據庫表

 第二此運行結果如下(假如沒有操作mysql數據的話):

tb_adminuser
tb_test
當前數據庫有tb_test表格,不創建tb_test數據庫表

 

 編寫程序,對上述新增表添加數據:

public class JDBC {
    String driver;
    String url;
    String user;
    String password;
    public void initParam(String paramFile){
        try{
            Properties props = new Properties();
            props.load(new FileInputStream(paramFile));
            driver = props.getProperty("driver");
            url = props.getProperty("Url");
            user = props.getProperty("user");
            password = props.getProperty("password");
            
        }catch(Exception e){}
    }
    
    public void addData(String table,String sql){
        try{
            Connection conn =DriverManager.getConnection(url,user,password);
            Statement statement =conn.createStatement();
            int resultRow = statement.executeUpdate(sql);
            System.out.println("對"+table+"表添加了1條數據,該表受影響行數為"+resultRow);
        }catch(Exception e){}
    }
    
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        JDBC jdbc = new JDBC();

        jdbc.initParam("mysql.properties");
        String table = "tb_test";
        String sql = "insert into "+table+"(test_name,test_desc) values('hjl','0');";
        jdbc.addData(table, sql);
    }
}

 運行的效果為:

對tb_test表添加了1條數據,該表受影響行數為1

 通過兩個代碼進行測試可以得知,使用executeUpdate(String sql) 是可以對數據庫進行DML語句與DDL語句操作的,不同的是,DDL語句因為不是對表中內容進行操作,因此返回的值為0;而DML語句是對表格內容進行操作的,因此返回影響表格內容的行數。

 

使用execute方法執行SQL語句:

 Statement的execute()方法幾乎可以執行任何SQL語句,但它執行SQL語句時比較麻煩,通常都是使用executeQuery()方法或者executeUpdate()方法來執行SQL語句;只有不清楚SQL語句的類型,為了保證不出錯,最好是用execute()方法來執行該SQL語句。

 使用execute()的返回值是boolean,那么如何來獲取執行查詢語句獲得的ResultSet對象,以及如何獲取執行DDL或者DML語句獲得的int數值呢?針對這種情況,Statement提供了如下兩個方法:

  1.getResultSet(): 該方法返回Statement執行查詢語句所返回的ResultSet對象。

  2. getUpdateCount():該方法返回statementDDL,DML語句所影響的記錄行數。

 下面程序示范了使用Statment的execute()方法來執行任意的SQL語句。

public class JDBC {
    
    //使用execute方法進行對表查詢
    public void queryByExecuteMethod(String table){
        try{
            String sql = "select * from "+table;
            boolean b = statement.execute(sql);
            if(b){
                System.out.println("execute方法返回"+b);
                ResultSet result = statement.getResultSet();
                int count = 0;
                while(result.next()){
                    count++;
                }
                System.out.println("一共查詢了"+count+"條記錄");
            }else{System.out.println("execute方法返回"+b);}
        }catch(Exception e){}
    }
    
    //使用execute方法進行DML刪除該表的內容
    public void deleteDataByExecuteMethod(String table){
        try{
            String sql = "delete from "+table;
            boolean b = statement.execute(sql);
            if(!b){
                System.out.println("execute方法返回"+b);
                System.out.println(table+"受影響行數為:"+statement.getUpdateCount());
            }else{System.out.println("execute方法返回"+b);}
        }catch(Exception e){}
    }
    
    //使用execute方法進行DDL刪除該表
    public void dropTableByExecuteMethod(String table){
        try{
            String sql = "drop table "+table;
            boolean b = statement.execute(sql);
            if(!b){
                System.out.println("execute方法返回"+b);
                System.out.println(table+"受影響行數為:"+statement.getUpdateCount());
            }else{System.out.println("execute方法返回"+b);}
        }catch(Exception e){}
    }
    
    Connection conn = null;
    Statement statement = null;
    public JDBC(String paramFile){
        try{
            Properties props = new Properties();
            props.load(new FileInputStream(paramFile));
            String driver = props.getProperty("driver");
            String url = props.getProperty("Url");
            String user = props.getProperty("user");
            String password = props.getProperty("password");
            conn =DriverManager.getConnection(url,user,password);
            statement =conn.createStatement();
            
        }catch(Exception e){}
    }
    
    public static void main(String[] args) {
        // TODO Auto-generated method stub

        String table = "tb_test";
        JDBC jdbc_2 = new JDBC("mysql.properties");
        jdbc_2.queryByExecuteMethod(table);
        jdbc_2.deleteDataByExecuteMethod(table);
        jdbc_2.dropTableByExecuteMethod(table);
    }
}

 上述程序中,使用了execute()方法執行了三種SQL語句,分別是查詢語句,DML語句與DDL語句,其中查詢語句返回的是True值,根據true值從Statement對象中獲取ResultSet對象,而根據false值,從Statement對象中獲取getUpdateCount()方法的值,其運行效果為:

execute方法返回true
一共查詢了2條記錄
execute方法返回false
tb_test受影響行數為:2
execute方法返回false
tb_test受影響行數為:0

 

使用PreparedStatement執行SQL語句:

 如果在程序中有經常反復執行一條結構相似的SQL語句,例如下面兩句:

insert into tb_test values(null,'張三',1);
insert into tb_test values(null,'李四',2);

 對於上述兩句,它們的結構基本相似,值時執行插入時的值不同而已。對於這種情況,可以使用帶占位符(?)參數的SQL語句來代替它們,即:

insert into tb_test values(null,?,?)

 但Statement執行的SQL語句是不允許使用問號占位符參數,而且這個問號占位符參數必須獲得值后才可以執行。為了滿足這種情況,JDBC提供了PreparedStatement接口,該接口是Statement接口的子接口,它可以預編譯SQL語句,預編譯后的SQL語句被存儲到PreparedStatement對象中,然后可以使用該對象對此高效地執行該語句。

 PreparedStatement接口也實現了Statement接口的execute,executeQuery,executeUpdate方法,不過都沒有帶參數,因為SQL語句早已經在PreparedStatement對象里。若要執行PreParedStatement對象里預編譯的SQL語句,需要為問號占位符參數傳入參數值,PrepatedStatement提供了一系列的setXxx(int index,Xxx value)方法傳入參數值。(若不清楚傳入值的數據類型,可以使用Object來代替)。

 下面使用Statement以及PrepareStatement分別對tb_test表插入10條數據,並作對比:

public class JDBC {

   String driver;
     String url;
   String user;
   String password;

public void addDatas(String table,boolean insertType){
        try{
            String sql =null;int result = 0;
            System.out.println("開始對"+table+"表插入數據");
            if(insertType){
                sql = "insert into "+table+" values(null,?,?)";
                System.out.println(sql);
                PreparedStatement prepareStatement = conn.prepareStatement(sql);
                for(int i=0;i<5;i++){
                    prepareStatement.setString(1, "name_HJL"+i);
                    prepareStatement.setString(2,"desc_"+i);
                    result = prepareStatement.executeUpdate();
                    System.out.println(table+"受影響行數為:"+result);
                }
            }else{
                for(int i=0;i<5;i++){
                    sql = "insert into "+table+" values(null,'HJL"+i+"','"+i+"')";
                    System.out.println(sql);
                    result = statement.executeUpdate(sql);
                    System.out.println(table+"受影響行數為:"+result);
                }
            }
            System.out.println("插入數據完畢!");        
        }catch(Exception e){}
    }
    
    Connection conn = null;
    Statement statement = null;
    public JDBC(String paramFile){
        try{
            Properties props = new Properties();
            props.load(new FileInputStream(paramFile));
            driver = props.getProperty("driver");
            url = props.getProperty("Url");
            user = props.getProperty("user");
            password = props.getProperty("password");
            conn =DriverManager.getConnection(url,user,password);
            statement =conn.createStatement();
            
        }catch(Exception e){}
    }
    
    public static void main(String[] args) {
        JDBC jdbc_2 = new JDBC("mysql.properties");
        String table = "tb_test";
        
        jdbc_2.addDatas(table,true);
        jdbc_2.addDatas(table,false);
    }
}

 根據上述的代碼,我們可以看到使用Statement來編寫SQL語句是比較麻煩的,不僅僅要區分雙引號還有單引號,有時候是因為這個錯誤才導致程序執行不下去,同時編程時是沒有提示說該sql是錯誤的,只有等到運行為止才知道。

 運行結果如下:

開始對tb_test表插入數據
insert into tb_test values(null,?,?)
tb_test受影響行數為:1
tb_test受影響行數為:1
tb_test受影響行數為:1
tb_test受影響行數為:1
tb_test受影響行數為:1
插入數據完畢!
開始對tb_test表插入數據
insert into tb_test values(null,'HJL0','0')
tb_test受影響行數為:1
insert into tb_test values(null,'HJL1','1')
tb_test受影響行數為:1
insert into tb_test values(null,'HJL2','2')
tb_test受影響行數為:1
insert into tb_test values(null,'HJL3','3')
tb_test受影響行數為:1
insert into tb_test values(null,'HJL4','4')
tb_test受影響行數為:1
插入數據完畢!
View Code

 總體來看,PreparedStatement比使用Statement有以下的優勢:

  1.PreparedStatement預編譯SQL語句,性能更好

  2.PreparedStatement無須“拼接”SQL語句,編程更簡單

  3.PreparedStatement可以放置SQL注入,安全性更好

 

使用CallableStatement調用存儲過程:

 在JDBC中,若想編寫存儲過程,是使用CallableStatement對象,該對象是由Connection的perpareCall(String sql)方法來創建,調用存儲過程的SQL語句總是這種格式:{call 存儲過程名稱(?,?,?.....)},其中的問號作為存儲過程參數的占位符。例如:

delimiter //
create procedure add_pro(a int, b int,out sum int)
begin
set sum = a+b;
end;
//

 上述代碼是數據庫存儲過程的SQL語句,下面是將上述的SQL語句,變成perpareCall()方法使用對應格式的存儲過程SQL格式:

Connection.prepareCall("call add_pro(?,?,?)");

 存儲過程的參數既有傳入參數,也有傳出參數。所謂傳入參數就是Java程序必須為這些參數傳入值,可以通過CallableStatement的setXxx()方法為傳入參數設置值;所謂傳出參數就是Java可以通過該參數獲取存儲過程里的值,CallableStatement需要調用registerOutParameter(int index,int SQLTypes)方法來注冊該參數,第二個參數是直接調用Types的類屬性便可。

 當設置完傳入參數以及傳出參數后,便可以調用CallableStatement的execute()方法來執行存儲過程了,執行結束后,通過CallableStatement對象的getXxx(int index)方法來獲取指定傳出參數值。

 下面根據上述的存儲過程SQL來進調用存儲過程:

public class JDBC {

   String driver;
   String url;
   String user;
   String password;

public void callableStatementTest(){
        try{
            String sql = "call add_pro(?,?,?)";
            CallableStatement callableStatement = conn.prepareCall(sql);
            //設置存儲過程的傳入參數與傳出參數
            callableStatement.setInt(1, 4);
            callableStatement.setInt(2, 5);
 callableStatement.registerOutParameter(3,Types.INTEGER);
            
            callableStatement.execute();
            
            //獲取並輸出存儲過程傳出參數的值:
            System.out.println("執行結果是:"+callableStatement.getInt(3));
            
        }catch(Exception e){}
    }
    
    Connection conn = null;
    Statement statement = null;
    public JDBC(String paramFile){
        try{
            Properties props = new Properties();
            props.load(new FileInputStream(paramFile));
            driver = props.getProperty("driver");
            url = props.getProperty("Url");
            user = props.getProperty("user");
            password = props.getProperty("password");
            conn =DriverManager.getConnection(url,user,password);
            statement =conn.createStatement();
            
        }catch(Exception e){}
    }
    
    public static void main(String[] args) {
        JDBC jdbc_2 = new JDBC("mysql.properties");
        jdbc_2.callableStatementTest();
    }
}

 其運行結果為:

執行結果是:9

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM