`
robinsoncrusoe
  • 浏览: 749193 次
  • 性别: Icon_minigender_2
  • 来自: 深圳
社区版块
存档分类
最新评论

数据插入

    博客分类:
  • JAVA
阅读更多
4.2.4 程序说明

对于上面的例子程序,其实读者应该不难理解。经过第三章的学习,对于建立数据库连接读者肯定是非常熟悉了。通过微软提供的JDBC For SQL Server 2000的驱动程序,连接数据库,取得连接对象con,然后再调用createStatement ()方法,创建了一个Statement对象stmt,利用此对象执行一些SQL操作。这些和第三章介绍的那个例子程序没什么区别,只是有些地方进行了一些简化,比如把记录JDBC运行的Log流取消了。这样更容易看清楚程序结构。

注意:

当用JDBC向数据库中插入数据的时候,如果处理中文有可能出现问题,如产生乱码等。

这个问题的实现通常与各个JDBC Driver的实现有关. 目前大多数JDBC Driver采用本地编码格式来传输中文字符,例如中文字符“0x4271”会被转成“0x42”和“0x71”进行传输. 因此我们需要对JDBC Driver返回的字符以及要发给JDBC Driver的字符进行转换。

当用JDBC Driver向数据库中插入数据时,需要先将Unicode转成Native Code; 当JDBC Driver从数据库中查询数据时,则需要将Native Code转换成Unicode。下面给出了这两种转换的实现,代码如下:

String native2Unicode(String s) {

if (s == null || s.length() == 0) {

return null;

}

byte[] buffer = new byte[s.length()];

for (int i = 0; i s.length(); i++) {

if (s.charAt(i)>= 0x100) {

c = s.charAt(i);

byte []buf = (""+c).getBytes();

buffer[j++] = (char)buf[0];

buffer[j++] = (char)buf[1];

}

else {

buffer[j++] = s.charAt(i);

}

}

return new String(buffer,0,j);

}

除使用以上两个方法之外,有些JDBC Driver如果对JDBC Driver Manager设置了正确的字符集属性,以上2个方法就不需要了,一般的Driver会做说明,否则的话,读者只好自己实验一下了。我们的例子程序中显示部分是通过遍历结果集来进行的,在JDK1.1中,ResultSet类中只定义了next()方法支持数据指针的下移,但在Java 2中,ResultSet类增加了如下方法支持数据指针的移动,包括:

● ResultSet.first() 将数据指针移到结果集的第一行

● ResultSet.last() 将数据指针移到结果集的最后一行

● ResultSet.previous() 将数据指针上移一行

对于结果集会在第四节进行更详细的介绍。这段程序中以前没有做过详细介绍的就是Statement接口的用法,下面对其进行一些介绍。

4.2.5 Statement接口介绍

在此之前已经在很多程序中应用了Statement接口,它也是以后应用必不可少的一个重要接口。Statement对象用于将SQL语句发送到数据库中,实际上有三种 Statement 对象,它们都作为在给定连接上执行SQL语句的包容器:Statement、PreparedStatement(它从 Statement 继承而来)和CallableStatement(它从 PreparedStatement 继承而来)。它们都专用于发送特定类型的SQL语句,其中Statement对象用于执行不带参数的简单SQL语句,PreparedStatement 对象用于执行带或不带IN参数的预编译SQL语句;CallableStatement对象用于执行对数据库已存储过程的调用。

1. Statement接口基本用法

Statement接口提供了执行语句和获取结果的基本方法。PreparedStatement 接口添加了处理 IN 参数的方法,而PreparedStatement添加了处理 OUT 参数的方法。

本书将在本章第10节对PreparedStatement和PreparedStatement接口进行介绍。

一般情况下在建立了到特定数据库的连接之后,就可用该连接发送SQL语句。Statement对象用Connection的方法createStatement创建,如下列代码段中所示:

Connection con = DriverManager.getConnection(url,"sunny","");

Statement stmt = con.createStatement ();

这样就创建了一个Statement对象,下面的任务就是使用该对象执行SQL操作。

(1) 使用Statement对象执行语句

Statement接口提供了三种执行SQL语句的方法:executeQuery、 executeUpdate和execute。使用哪一个方法由SQL语句所产生的内容决定。方法executeQuery用于产生单个结果集的语句,例如SELECT语句。方法executeUpdate用于执行INSERT、UPDATE或DELETE语句以及SQL DDL(数据定义语言)语句,例如CREATE TABLE和DROP TABLE。INSERT、UPDATE或DELETE语句的效果是修改表中零行或多行中的一列或多列。executeUpdate的返回值是一个整数,指示受影响的行数(即更新计数)。对于 CREATE TABLE或DROP TABLE等不操作行的语句,executeUpdate的返回值总为零。

如果不知道要执行的SQL语句是否是查询或者更新,可以用execute()来执行相应的 Statement对象内置的SQL语句,如果返回true,说明该于具有结果集要处理,就应该用ExecuteQuery()方法来执行查询。如果返回 false,哪么就应该用ExecuteUpdate()方法来执行更新,它将返回更新所影响的行数。

此外,方法execute可以用来测试用于执行返回多个结果集、多个更新计数或二者组合的语句。因为多数程序员不会需要使用该高级功能,所以在此不再详细介绍。

Statement对象本身不包含SQL语句,因而必须给Statement. execute方法提供SQL语句作为参数。这些和其他两种不同,PreparedStatement对象并不将SQL语句作为参数提供给这些方法,因为它们已经包含预编译SQL语句。CallableStatement对象继承这些方法的PreparedStatement 形式。对于这些方法的PreparedStatement或CallableStatement版本,使用查询参数将抛出SQLException,所以它们都不返回任何结果集对象。

(2) 语句完成和提交

当连接处于AutoCommit模式时,其中所执行的语句在完成时将自动提交或还原。语句在已执行且所有结果返回时,即认为已完成。可以通过Connection对象的setAutoCommit(boolean autoCommit)方法设定连接的提交模式。

对于返回一个结果集的 executeQuery方法,在检索完ResultSet对象的所有行时该语句完成。对于方法executeUpdate,当它执行时语句即完成。但在少数调用方法execute的情况中,在检索所有结果集或它生成的更新计数之后语句才完成。

有些DBMS将已存储过程中的每条语句视为独立的语句,而另外一些则将整个过程视为一个复合语句。在启用自动提交时,这种差别就变得非常重要,因为它影响什么时候调用Commit方法。在前一种情况中,每条语句单独提交;在后一种情况中,所有语句统一提交。

(3) 关闭Statement 对象

Statement对象将由Java垃圾收集程序自动关闭。而作为一种好的编程风格,应在不需要Statement对象时显式地关闭它们。这将立即释放DBMS资源,有助于避免潜在的内存问题。

以上便是使用Statement接口的整体步骤,读者在以后的编程学习中也一定要按照这种步骤来进行操作,这样肯定会少犯不必要的错误。

2. Statement对象中的SQL转义语法的用法

Statement对象的主要是作为SQL命令的载体,把SQL命令传递给驱动程序再连接数据库,以得到相应的结果。我们知道SQL中有一些通配符来提供更加灵活的操作方式,同样在Statement对象中也同样定义了一些转义语法供程序员使用,下面我们对其进行一些介绍。

Statement支持转义语法,它告诉驱动程序其中的代码应该以不同方式处理。驱动程序将扫描任何转义语法,并将它转换成特定数据库可理解的代码。这使得转义语法与 DBMS 无关,并允许程序员使用在没有转义语法时不可用的功能。下面具体进行介绍。

(1) 转义子句由花括号和关键字界定:

{keyword . . . parameters . . . }

该关键字指示转义子句的类型,首先是escape表示LIKE 转义字符。字符“%”和“_”类似于SQL LIKE子句中的通配符(“%”匹配零个或多个字符,而“_”则匹配一个字符)。为了正确解释它们,应在其前面加上反斜杠(“\”),它是字符串中的特殊转义字符。在查询末尾包括如下语法即可指定用作转义字符的字符:

{escape 'escape-character'}

例如,下列查询使用反斜杠字符作为转义字符,查找以下划线开头的标识符名:

stmt.executeQuery("SELECT name FROM Identifiers

WHERE id LIKE `\_%' {escape `\'});

(2) fn表示标量函数

几乎所有DBMS都具有标量值的数值、字符串、时间、日期、系统和转换函数。要使用这些函数,可使用如下转义语法:关键字fn后跟所需的函数名及其参数。例如,下列代码调用函数concat将两个参数连接在一起:

{fn concat("Hot","Java")};

可用下列语法获得当前数据库用户名:

{fn user()};

标量函数可能由语法稍有不同的DBMS支持,而它们可能不被所有驱动程序支持。各种 DatabaseMetaData方法将列出所支持的函数。例如,方法getNumericFunctions返回用逗号分隔的数值函数列表,而方法 getStringFunctions将返回字符串函数等等。驱动程序将转义函数调用映射为相应的语法,或直接实现该函数。

(3) d、t 和ts表示日期和时间文字

DBMS用于日期、时间和时间标记文字的语法各不相同。JDBC使用转义子句支持这些文字的语法的ISO标准格式。驱动程序必须将转义子句转换成DBMS表示。

例如,可用下列语法在JDBC SQL语句中指定日期:

{d 'yyyy-mm-dd'}

在该语法中,yyyy为年份,mm为月份,而dd则为日期。驱动程序将用等价的特定于DBMS的表示替换这个转义子句。例如,如果'28- MAY-99'符合基本数据库的格式,则驱动程序将用它替换{d 1999-05-28}。

(4) 对于TIME和TIMESTAMP也有类似的转义子句

{t 'hh:mm:ss'}

{ts 'yyyy-mm-dd hh:mm:ss.f . . .'}

TIMESTAMP中的小数点后的秒(.f . . .)部分可忽略。call或? = call表示已存储过程如果数据库支持已存储过程,则可从JDBC中调用它们,语法为:

{call procedure_name [(?,?,. . .)]}

或(其中过程返回结果参数):

{? = call procedure_name [(? ,?,. . .)]}

方括号表示其中的内容是可选的,它们不是语法的必要部分。输入参数可以为文字或参数。

如果不知道数据库是否支持存储过程,那么可以调用方法 DatabaseMetaData. supports StoredProcedures()它会返回一个Boolean类型的值,以此来检查数据库是否支持已存储过程。

(5) oj表示外部连接

外部连接的语法为:

{oj outer-join}

其中outer-join形式为 :

table LEFT OUTER JOIN {table / outer-join} ON search-condition

外部连接属于高级功能。有关它们的解释可参见本章后面的4.9小节。JDBC 提供了三种DatabaseMetaData方法用于确定驱动程序支持哪些外部连接类型:supportsOuterJoins()、 supportsFullOuterJoins()和supportsLimitedOuterJoins()。

Statement支持的转义语法功能默认状态是打开的,也可以通过方法 Statement.setEscape Processing()来打开或关闭转义处理。当性能极为重要时,程序员可能想关闭它以减少处理时间,应该用 Statement.setEscapeProcessing(false)来关闭它。但通常它将处于打开状态。应注意的是,setEscapeProcessing()不适用于PreparedStatement对象,因为在调用该语句前它就可能已被发送到数据库。当然对于CallableStatement对象也是不适合的,因为CallableStatement继承了PreparedStatement接口。

execute方法的使用

在Statement对象中用于提交SQL操作的方法有3个,对于executeQuery()、executeUpdate()这两个方法,都比较容易理解和使用。但是execute()方法的使用却不是很简单,下面用一些篇幅对其进行介绍。

execute()方法应该仅在语句能返回多个ResultSet对象、多个更新计数或 ResultSet对象与更新计数的组合时使用。当执行某个已存储过程或动态执行未知SQL字符串(即应用程序程序员在编译时未知)时,有可能出现多个结果的情况,尽管这种情况很少见。例如,用户可能执行一个已存储过程,并且该存储过程可执行更新,然后执行选择,再进行更新,再进行选择等。通常使用已存储过程的人应知道它所返回的内容。

因为方法execute处理非常规情况,所以获取其结果需要一些特殊处理。例如,假定已知某个过程返回两个结果集,则在使用方法execute执行该过程后,必须调用方法getResultSet获得第一个结果集,然后调用适当的getXXX方法获取其中的值。要获得第二个结果集,需要先调用getMoreResults方法,然后再调用getResultSet方法。如果已知某个过程返回两个更新计数,则首先调用方法getUpdateCount,然后调用getMoreResults,并再次调用getUpdateCount。

对于不知道返回内容,则情况更为复杂。如果结果是ResultSet对象,则方法 execute返回 true;如果结果是Java int,则返回false。如果返回int,则意味着结果是更新计数或执行的语句是DDL命令。在调用方法execute之后要做的第一件事情是调用 getResultSet或 getUpdateCount,调用方法getResultSet可以获得两个或多个ResultSet对象中第一个对象,而调用方法 getUpdateCount可以获得两个或多个更新计数中第一个更新计数的内容。

当SQL语句的结果不是结果集时,则方法getResultSet将返回null,这可能意味着结果是一个更新计数或没有其他结果。在这种情况下,判断null真正含义的惟一方法是调用方法getUpdateCount,它将返回一个整数,这个整数为调用语句所影响的行数,如果为–1 则表示结果是结果集或没有结果。如果方法getResultSet已返回null(表示结果不是ResultSet对象),则返回值–1表示没有其他结果。也就是说,当下列条件为真时表示没有结果(或没有其他结果):

((stmt.getResultSet() == null) && (stmt.getUpdateCount() == –1))

如果已经调用方法getResultSet并处理了它返回的ResultSet对象,则有必要调用方法getMoreResults以确定是否有其他结果集或更新计数。如果getMoreResults返回true,则需要再次调用 getResultSet来检索下一个结果集。如上所述,如果getResultSet返回null,则需要调用getUpdateCount来检查 null是表示结果为更新计数还是表示没有其他结果。

当getMoreResults返回false时,它表示该SQL语句返回一个更新计数或没有其他结果。因此需要调用方法getUpdateCount来检查它是哪一种情况。这时当下列条件为真时表示没有其他结果:

((stmt.getMoreResults() == false) && (stmt.getUpdateCount() == –1))

下面的代码演示了一种用来确认已访问调用方法execute所产生的全部结果集和更新计数的方法。

stmt.execute(queryStringWithUnknownResults);

while (true) {

int rowCount = stmt.getUpdateCount();

if (rowCount > 0) { // 它是更新计数

System.out.println("Rows changed = " + count);

stmt.getMoreResults();

continue;

}

if (rowCount == 0) { // DDL 命令或 0 个更新

System.out.println(" No rows changed or Statement was not DML command");

stmt.getMoreResults();

continue;

}

// 执行到这里,证明有一个结果集或没有其他结果

ResultSet rs = stmt.getResultSet;

if (rs != null) {

. . . // 进行需要的操作,例如取得元数据等

while (rs.next()) {

. . . // 处理结果

stmt.getMoreResults();

continue;

}

break; // 说明没有其他结果gigi_miao
分享到:
评论

相关推荐

    Database system concepts的数据插入

    数据插入是数据库操作中最基础且重要的部分,它涉及到SQL语言中的INSERT语句。在本篇文章中,我们将深入探讨“Database system concepts”的数据插入相关的知识点。 首先,我们需要了解SQL(Structured Query ...

    mysql大批量数据插入

    MySQL 大批量数据插入优化方法 MySQL 大批量数据插入是指在短时间内将大量数据插入到 MySQL 数据库中,需要设计目标要求能支持平均每秒插入 1000 条数据以上。MySQL 提供了多种方法来实现大批量数据插入,包括使用...

    07-数据表中数据插入方式(4种)

    本文介绍了四种常见的数据插入方式,它们分别是:向表中所有字段插入数据、向表中某字段插入数据、同时插入多条记录以及将查询结果插入至数据表。以下是这四种数据插入方式的详细介绍: 1. 向表中所有字段插入数据 ...

    EXCEL数据插入到WORD中

    指定EXCEL每行的数据插入WORD模板标签中,需要请加QQ66561529

    labview 数据库的表格创建,数据更新,数据删除,数据查询,数据插入,数据显示。

    在LabVIEW中与数据库交互是常见的需求,本教程将详细介绍如何使用LabVIEW进行数据库的表格创建、数据更新、数据删除、数据查询以及数据插入,并展示如何显示这些数据。 首先,我们需要理解LabVIEW中的数据库接口。...

    mysql数据插入效率比较

    在MySQL数据库中,数据插入效率是数据库性能优化的关键因素,特别是在大数据量的场景下。本文主要探讨了四种不同的数据插入方式及其效率差异。 1. 单条插入:这是最基本的方式,通过for循环逐条执行INSERT语句。...

    数据插入数据库5种方式工具源码2012825

    数据插入数据库5种方式工具源码 功能描述: 基本Insert Into 单线程Bulk Insert 多线程Bulk Insert 单线程SqlBulkCopy 多线程SqlBulkCopy 试验的5种方法,比较各种方法的导入速度 要把导入的文件放在C盘如:c:\\20...

    Sqlserver大数据量插入速度慢或丢失数据的解决方法

    在处理大量数据插入SQL Server数据库的过程中,可能会遇到插入速度慢或者数据丢失的问题。这种情况通常出现在需要批量插入数千甚至上万条记录的场景中。本文将详细介绍如何解决SQL Server在大数据量插入时出现的速度...

    java批量插入Oracle数据方法

    在IT领域,特别是...通过合理设计代码结构,利用`PreparedStatement`的批处理功能,可以显著提升数据插入的速度和系统的整体性能。在实践中,还需注意细节如事务管理和异常处理,以确保数据完整性和系统的健壮性。

    c#插入多条数据datagridview

    以下是一个简单的示例代码片段,展示了如何将DataTable中的数据插入到数据库: ```csharp // 假设已有DataTable myDataTable,且已填充了用户输入的数据 using (SqlConnection connection = new SqlConnection...

    教学成绩管理数据库数据插入

    在这个系统中,数据插入操作是至关重要的,因为它确保了系统的初始化和数据的完整性。以下将详细解释涉及的知识点: 1. **数据库设计**:首先,我们需要了解数据库的结构。在这个例子中,存在多个表格,如“学院...

    实验二DML语言一(数据插入、修改和删除.doc

    实验二 DML 语言一(数据插入、修改和删除) 通过本实验,学生可以熟练掌握基本表的插入、删除与修改,并为后继学习作准备。本实验主要涉及到 SQL Server Management Studio 的使用、基本表的插入、删除与修改、T-...

    SQL的数据操纵功能之一---数据插入

    SQL 数据操纵功能是数据库操作的核心部分,而数据插入则是这些功能中的基础操作,用于向数据库表中添加新的记录。在 SQL 中,数据插入通常通过 `INSERT` 语句实现,可以分为插入单个元组和插入子查询结果两种方式。 ...

    用户角色菜单权限表结构创建以及数据插入

    用户菜单权限表建表语句以及数据插入语句,后台管理系统搭建必备,学习专用。 如果使用外键关联,在对表进行数据操作时就考虑另一张关联的表,相当于两张表就绑在一起了,操作这张表就必须考虑另一张关联表。我们...

    深入探索 MySQL 数据插入:技术指南与最佳实践

    合理使用这些技术,不仅可以提高数据插入的效率,还可以确保数据的完整性和安全性。 在 MySQL 中插入数据是一项基础操作,但涉及到许多细节和最佳实践。通过本文的介绍,你应该对如何在 MySQL 中插入数据有了深入的...

    mybaits 多线程 实现数据批量插入 (运用CountDownLatch实现闭锁)

    在IT行业中,数据库操作是应用开发中的重要环节,特别是在大数据量的情况下,如何高效地进行数据插入成为了一个关键问题。MyBatis,作为一个优秀的Java持久层框架,提供了多种优化手段,其中包括多线程和批处理技术...

    SqlBulkCopy批量数据插入

    本篇文章将详细介绍如何在C#中使用`SqlBulkCopy`进行批量数据插入,并通过一个手机号码归属地查询的案例来具体阐述其用法。 `SqlBulkCopy`类位于`System.Data.SqlClient`命名空间下,它是.NET Framework提供的一种...

    JAVA中向数据库中插入数据的源代码

    以下是实现数据插入的基本步骤: 1. **导入必要的库** 在Java程序的开头,需要导入JDBC相关的类: ```java import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; ...

    sqlite3性能优化源代码 数据插入 开启事务 执行准备 性能提升 每秒百万条数据写入

    在本文中,我们将深入探讨如何通过优化SQLite3的源代码来提高数据插入性能,尤其是如何利用事务和执行准备来实现每秒百万条数据的写入速度。 首先,了解SQLite3的事务机制是至关重要的。在SQLite3中,事务用于确保...

Global site tag (gtag.js) - Google Analytics