??xml version="1.0" encoding="utf-8" standalone="yes"?> 数据库连接池在编写应用服务是l常需要用到的模块Q太q频J的q接数据库对服务性能来讲是一个瓶颈,使用~冲池技术可以来消除q个瓉。我们可以在互联|上扑ֈ很多关于数据库连接池的源E序Q但是都发现q样一个共同的问题Q这些连接池的实现方法都不同E度地增加了与用者之间的耦合度。很多的q接池都要求用户通过其规定的Ҏ获取数据库的q接Q这一Ҏ们可以理解,毕竟目前所有的应用服务器取数据库连接的方式都是q种方式实现的。但是另外一个共同的问题是,它们同时不允怋用者显式的调用Connection.close()ҎQ而需要用其规定的一个方法来关闭q接。这U做法有两个~点Q?/p>
W一Q改变了用户使用习惯Q增加了用户的用难度?/p>
首先我们来看看一个正常的数据库操作过E: 使用者在用完数据库连接后通常是直接调用连接的Ҏclose来释放数据库资源Q如果用我们前面提到的连接池的实现方法,那语句conn.close()被某些特定的语句所替代?/p>
W二Qɘq接池无法对之中的所有连接进行独占控制。由于连接池不允许用L接调用连接的closeҎQ一旦用者在使用的过E中׃习惯问题直接关闭了数据库q接Q那么连接池无法正常维护所有连接的状态,考虑q接池和应用׃同开发h员实现时q种问题更容易出现?/p>
l合上面提到的两个问题,我们来讨Z下如何解册两个要命的问题?/p>
首先我们先设w处地的考虑一下用hx么h使用q个数据库连接池的。用户可以通过特定的方法来获取数据库的q接Q同时这个连接的cd应该是标准的java.sql.Connection。用户在获取到这个数据库q接后可以对q个q接q行L的操作,包括关闭q接{?/p>
通过对用户用的描述Q怎样可以接管Connection.closeҎ成了我们这文章的主题?/p>
Z接管数据库连接的closeҎQ我们应该有一U类g钩子的机制。例如在Windows~程中我们可以利用Hook API来实现对某个Windows API的接。在JAVA中同样也有这样一个机制。JAVA提供了一个Proxycd一个InvocationHandlerQ这两个c都在java.lang.reflect包中。我们先来看看SUN公司提供的文档是怎么描述q两个类的?/p>
SUN的API文档中关于Proxy的描q很多,q里׃|列出来。通过文档Ҏ口InvocationHandler的描q我们可以看到当调用一个Proxy实例的方法时会触发Invocationhanlder的invokeҎ。从JAVA的文档中我们也同时了解到q种动态代理机制只能接接口的ҎQ而对一般的cL效,考虑到java.sql.Connection本n也是一个接口由此就扑ֈ了解军_何接closeҎ的出路?/p>
首先Q我们先定义一个数据库q接池参数的c,定义了数据库的JDBC驱动E序cdQ连接的URL以及用户名口令等{一些信息,该类是用于初始化q接池的参数Q具体定义如下: 其次是连接池的工厂类ConnectionFactoryQ通过该类来将一个连接池对象与一个名U对应v来,使用者通过该名U就可以获取指定的连接池对象Q具体代码如下: ConnectionFactory主要提供了用户将连接池l定C个具体的名称上以及取消绑定的操作。用者只需要关心这两个cd可用数据库q接池的功能。下面我们给ZD如何用连接池的代码: 从用者的CZ代码可以看出,我们已经解决了常规连接池产生的两个问题。但是我们最最兛_的是如何解决接管closeҎ的办法。接工作主要在ConnectionFactory中的两句代码Q?/p>
DataSourceImpl是一个实C接口javax.sql.DataSource的类Q该cȝ护着一个连接池的对象。由于该cL一个受保护的类Q因此它暴露l用者的Ҏ只有接口DataSource中定义的ҎQ其他的所有方法对使用者来说都是不可视的。我们先来关心用户可讉K的一个方法getConnection DataSourceImplcM实现getConnectionҎ的跟正常的数据库q接池的逻辑是一致的Q首先判断是否有I闲的连接,如果没有的话判断q接数是否已l超q最大连接数{等的一些逻辑。但是有一点不同的是通过DriverManager得到的数据库q接q不是及时返回的Q而是通过一个叫_Connection的类中介一下,然后调用_Connection.getConnectionq回的。如果我们没有通过一个中介也是JAVA中的Proxy来接要q回的接口对象,那么我们没有办法截住Connection.closeҎ?/p>
l于C核心所在,我们先来看看_Connection是如何实现的Q然后再介绍是客L调用Connection.closeҎ时走的是怎样一个流E,Z么ƈ没有真正的关闭连接?/p>
一旦用者调用所得到q接的closeҎQ由于用Lq接对象是经q接后的对象,因此JAVA虚拟Z首先调用_Connection.invokeҎQ在该方法中首先判断是否为closeҎQ如果不是则代码{l真正的没有被接的q接对象conn。否则的话只是简单的该q接的状态设|ؓ可用。到此您可能明白了整个接管的过E,但是同时也有一个疑问:q样的话是不是这些已建立的连接就始终没有办法真正关闭Q答案是可以的。我们来看看ConnectionFactory.unbindҎQ该Ҏ首先扑ֈ名字对应的连接池对象Q然后关闭该q接池中的所有连接ƈ删除掉连接池。在DataSourceImplcM定义了一个closeҎ用来关闭所有的q接Q详l代码如下: 该方法一一调用q接池中每个对象的closeҎQ这个closeҎ对应的是_Connection中对close的实玎ͼ在_Connection定义中关闭数据库q接的时候是直接调用没有l过接管的对象的关闭ҎQ因此该closeҎ真正的释放了数据库资源?/p>
以上文字只是描述了接口方法的接管Q具体一个实用的q接池模块还需要对I闲q接的监控ƈ及时释放q接Q详l的代码请参照附件?/p>
当你需要多ơ执行相同的SQL语句Q一般情况下是updateQ但是用不同的参数值时 Q可以?br />
PrepareStatementҎQD例如下:
Connection conn=null;
PreparedStatement pst=null;
String[] nm=new String[3];
int[] nc=new int[3];
...
try {
nm[0]="Costescu",nm[1]="Alexandrescu",nm[2]="Popovici";
nc[0]=234423;nc[1]=123344;nc[2]=534562;
pst=conn.prepareStatement("UPDATE Table1 SET Nume=? WHERE Nr_cont=?");
for(int i=0;i<=2;i++)
{
pst.setString(1,nm[i]);
pst.setInt(2,nc[i]);
pst.executeUpdate();
}
}catch (SQLException e){System.out.println(e.getMessage());}
...
]]>
原文引自Q?a >http://www-128.ibm.com/developerworks/cn/java/l-connpoolproxy/
作者通过使用JAVA中的动态代理实现数据库q接池,使用者可以以普通的jdbcq接的用习惯来使用q接池?/blockquote>
int executeSQL(String sql) throws SQLException
{
Connection conn = getConnection(); //通过某种方式获取数据库连?
PreparedStatement ps = null;
int res = 0;
try{
ps = conn.prepareStatement(sql);
res = ps.executeUpdate();
}finally{
try{
ps.close();
}catch(Exception e){}
try{
conn.close();//
}catch(Exception e){}
}
return res;
}
public interface InvocationHandler
InvocationHandler is the interface implemented by the invocation handler of a proxy instance.
Each proxy instance has an associated invocation handler.
When a method is invoked on a proxy instance,
the method invocation is encoded and dispatched to the invoke method of its invocation handler.
public class ConnectionParam implements Serializable
{
private String driver; //数据库驱动程?
private String url; //数据q接的URL
private String user; //数据库用户名
private String password; //数据库密?
private int minConnection = 0; //初始化连接数
private int maxConnection = 50; //最大连接数
private long timeoutValue = 600000;//q接的最大空闲时?
private long waitTime = 30000; //取连接的时候如果没有可用连接最大的{待旉
/**
* q接池类厂,该类常用来保存多个数据源名称合数据库q接池对应的哈希
* @author liusoft
*/
public class ConnectionFactory
{
//该哈希表用来保存数据源名和连接池对象的关p表
static Hashtable connectionPools = null;
static{
connectionPools = new Hashtable(2,0.75F);
}
/**
* 从连接池工厂中获取指定名U对应的q接池对?
* @param dataSource q接池对象对应的名称
* @return DataSource q回名称对应的连接池对象
* @throws NameNotFoundException 无法扑ֈ指定的连接池
*/
public static DataSource lookup(String dataSource)
throws NameNotFoundException
{
Object ds = null;
ds = connectionPools.get(dataSource);
if(ds == null || !(ds instanceof DataSource))
throw new NameNotFoundException(dataSource);
return (DataSource)ds;
}
/**
* 指定的名字和数据库q接配置l定在一起ƈ初始化数据库q接?
* @param name 对应q接池的名称
* @param param q接池的配置参数Q具体请见类ConnectionParam
* @return DataSource 如果l定成功后返回连接池对象
* @throws NameAlreadyBoundException 一定名字name已经l定则抛异常
* @throws ClassNotFoundException 无法扑ֈq接池的配置中的驱动E序c?
* @throws IllegalAccessException q接池配|中的驱动程序类有误
* @throws InstantiationException 无法实例化驱动程序类
* @throws SQLException 无法正常q接指定的数据库
*/
public static DataSource bind(String name, ConnectionParam param)
throws NameAlreadyBoundException,ClassNotFoundException,
IllegalAccessException,InstantiationException,SQLException
{
DataSourceImpl source = null;
try{
lookup(name);
throw new NameAlreadyBoundException(name);
}catch(NameNotFoundException e){
source = new DataSourceImpl(param);
source.initConnection();
connectionPools.put(name, source);
}
return source;
}
/**
* 重新l定数据库连接池
* @param name 对应q接池的名称
* @param param q接池的配置参数Q具体请见类ConnectionParam
* @return DataSource 如果l定成功后返回连接池对象
* @throws NameAlreadyBoundException 一定名字name已经l定则抛异常
* @throws ClassNotFoundException 无法扑ֈq接池的配置中的驱动E序c?
* @throws IllegalAccessException q接池配|中的驱动程序类有误
* @throws InstantiationException 无法实例化驱动程序类
* @throws SQLException 无法正常q接指定的数据库
*/
public static DataSource rebind(String name, ConnectionParam param)
throws NameAlreadyBoundException,ClassNotFoundException,
IllegalAccessException,InstantiationException,SQLException
{
try{
unbind(name);
}catch(Exception e){}
return bind(name, param);
}
/**
* 删除一个数据库q接池对?
* @param name
* @throws NameNotFoundException
*/
public static void unbind(String name) throws NameNotFoundException
{
DataSource dataSource = lookup(name);
if(dataSource instanceof DataSourceImpl){
DataSourceImpl dsi = (DataSourceImpl)dataSource;
try{
dsi.stop();
dsi.close();
}catch(Exception e){
}finally{
dsi = null;
}
}
connectionPools.remove(name);
}
}
String name = "pool";
String driver = " sun.jdbc.odbc.JdbcOdbcDriver ";
String url = "jdbc:odbc:datasource";
ConnectionParam param = new ConnectionParam(driver,url,null,null);
param.setMinConnection(1);
param.setMaxConnection(5);
param.setTimeoutValue(20000);
ConnectionFactory.bind(name, param);
System.out.println("bind datasource ok.");
//以上代码是用来登C个连接池对象Q该操作可以在程序初始化只做一ơ即?
//以下开始就是用者真正需要写的代?
DataSource ds = ConnectionFactory.lookup(name);
try{
for(int i=0;i<10;i++){
Connection conn = ds.getConnection();
try{
testSQL(conn, sql);
}finally{
try{
conn.close();
}catch(Exception e){}
}
}
}catch(Exception e){
e.printStackTrace();
}finally{
ConnectionFactory.unbind(name);
System.out.println("unbind datasource ok.");
System.exit(0);
}
source = new DataSourceImpl(param);
source.initConnection();
/**
* @see javax.sql.DataSource#getConnection(String,String)
*/
public Connection getConnection(String user, String password) throws SQLException
{
//首先从连接池中找出空闲的对象
Connection conn = getFreeConnection(0);
if(conn == null){
//判断是否过最大连接数,如果过最大连接数
//则等待一定时间查看是否有I闲q接,否则抛出异常告诉用户无可用连?
if(getConnectionCount() >= connParam.getMaxConnection())
conn = getFreeConnection(connParam.getWaitTime());
else{//没有过q接敎ͼ重新获取一个数据库的连?
connParam.setUser(user);
connParam.setPassword(password);
Connection conn2 = DriverManager.getConnection(connParam.getUrl(),
user, password);
//代理要q回的连接对?
_Connection _conn = new _Connection(conn2,true);
synchronized(conns){
conns.add(_conn);
}
conn = _conn.getConnection();
}
}
return conn;
}
/**
* 从连接池中取一个空闲的q接
* @param nTimeout 如果该参数gؓ0则没有连接时只是q回一个null
* 否则的话{待nTimeout毫秒看是否还有空闲连接,如果没有抛出异常
* @return Connection
* @throws SQLException
*/
protected synchronized Connection getFreeConnection(long nTimeout)
throws SQLException
{
Connection conn = null;
Iterator iter = conns.iterator();
while(iter.hasNext()){
_Connection _conn = (_Connection)iter.next();
if(!_conn.isInUse()){
conn = _conn.getConnection();
_conn.setInUse(true);
break;
}
}
if(conn == null && nTimeout > 0){
//{待nTimeout毫秒以便看是否有I闲q接
try{
Thread.sleep(nTimeout);
}catch(Exception e){}
conn = getFreeConnection(0);
if(conn == null)
throw new SQLException("没有可用的数据库q接");
}
return conn;
}
/**
* 数据q接的自装Q屏蔽了closeҎ
* @author Liudong
*/
class _Connection implements InvocationHandler
{
private final static String CLOSE_METHOD_NAME = "close";
private Connection conn = null;
//数据库的忙状?
private boolean inUse = false;
//用户最后一ơ访问该q接Ҏ的时?
private long lastAccessTime = System.currentTimeMillis();
_Connection(Connection conn, boolean inUse){
this.conn = conn;
this.inUse = inUse;
}
/**
* Returns the conn.
* @return Connection
*/
public Connection getConnection() {
//q回数据库连接conn的接类Q以便截住closeҎ
Connection conn2 = (Connection)Proxy.newProxyInstance(
conn.getClass().getClassLoader(),
conn.getClass().getInterfaces(),this);
return conn2;
}
/**
* 该方法真正的关闭了数据库的连?
* @throws SQLException
*/
void close() throws SQLException{
//׃cd性conn是没有被接管的连接,因此一旦调用closeҎ后就直接关闭q接
conn.close();
}
/**
* Returns the inUse.
* @return boolean
*/
public boolean isInUse() {
return inUse;
}
/**
* @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object)
*/
public Object invoke(Object proxy, Method m, Object[] args)
throws Throwable
{
Object obj = null;
//判断是否调用了close的方法,如果调用closeҎ则把q接|ؓ无用状?
if(CLOSE_METHOD_NAME.equals(m.getName()))
setInUse(false);
else
obj = m.invoke(conn, args);
//讄最后一ơ访问时_以便及时清除时的连?
lastAccessTime = System.currentTimeMillis();
return obj;
}
/**
* Returns the lastAccessTime.
* @return long
*/
public long getLastAccessTime() {
return lastAccessTime;
}
/**
* Sets the inUse.
* @param inUse The inUse to set
*/
public void setInUse(boolean inUse) {
this.inUse = inUse;
}
}
/**
* 关闭该连接池中的所有数据库q接
* @return int q回被关闭连接的个数
* @throws SQLException
*/
public int close() throws SQLException
{
int cc = 0;
SQLException excp = null;
Iterator iter = conns.iterator();
while(iter.hasNext()){
try{
((_Connection)iter.next()).close();
cc ++;
}catch(Exception e){
if(e instanceof SQLException)
excp = (SQLException)e;
}
}
if(excp != null)
throw excp;
return cc;
}
你觉得自己是一个Java专家吗?是否肯定自己已经全面掌握了Java的异常处理机Ӟ在下面这D代码中Q你能够q速找出异常处理的六个问题吗?
1 OutputStreamWriter out = ... 2 java.sql.Connection conn = ... 3 try { // ? 4 Statement stat = conn.createStatement(); 5 ResultSet rs = stat.executeQuery( 6 "select uid, name from user"); 7 while (rs.next()) 8 { 9 out.println("IDQ? + rs.getString("uid") // ? 10 "Q姓名:" + rs.getString("name")); 11 } 12 conn.close(); // ? 13 out.close(); 14 } 15 catch(Exception ex) // ? 16 { 17 ex.printStackTrace(); //_? 18 } |
作ؓ一个JavaE序员,你至应该能够找Z个问题。但是,如果你不能找出全部六个问题,Ll阅L文?
本文讨论的不是Java异常处理的一般性原则,因ؓq些原则已经被大多数人熟知。我们要做的是分析各U可UCؓ“反例”Qanti-patternQ的q背优秀~码规范的常见坏习惯Q帮助读者熟悉这些典型的反面例子Q从而能够在实际工作中敏锐地察觉和避免这些问题?
反例之一Q丢弃异?
代码Q?5?18行?
q段代码捕获了异常却不作M处理Q可以算得上Java~程中的杀手。从问题出现的频J程度和害E度来看Q它也许可以和C/C++E序的一个恶名远播的问题相提q论??不检查缓冲区是否已满。如果你看到了这U丢弃(而不是抛出)异常的情况,可以癑ֈ之九十九地肯定代码存在问题(在极数情况下,q段代码有存在的理由Q但最好加上完整的注释Q以免引起别解)?
q段代码的错误在于,异常Q几乎)L意味着某些事情不对劲了Q或者说臛_发生了某些不d的事情,我们不应该对E序发出的求救信号保持沉默和无动于衷。调用一下printStackTrace不?#8220;处理异常”。不错,调用printStackTrace对调试程序有帮助Q但E序调试阶段l束之后QprintStackTrace׃应再在异常处理模块中担负主要责Q了?
丢弃异常的情形非常普遍。打开JDK的ThreadDeathcȝ文档Q可以看C面这D说明:“特别圎ͼ虽然出现 ThreadDeath是一U?#8216;正常的情?#8217;Q但ThreadDeathcLError而不是Exception的子c,因ؓ许多应用会捕h有的 Exception然后丢弃它不再理睬?#8221;q段话的意思是Q虽然ThreadDeath代表的是一U普通的问题Q但鉴于许多应用会试图捕h有异常然后不予以适当的处理,所以JDK把ThreadDeath定义成了Error的子c,因ؓErrorcM表的是一般的应用不应该去捕获的严重问题。可见,丢弃异常q一坏习惯是如此常见Q它甚至已经影响CJava本n的设计?
那么Q应该怎样Ҏ呢?主要有四个选择Q?
1、处理异常。针对该异常采取一些行动,例如修正问题、提醒某个h或进行其他一些处理,要根据具体的情Ş定应该采取的动作。再ơ说明,调用printStackTrace不上已l?#8220;处理好了异常”?
2、重新抛出异常。处理异常的代码在分析异怹后,认ؓ自己不能处理它,重新抛出异常也不׃ؓ一U选择?
3、把该异常{换成另一U异常。大多数情况下,q是指把一个低U的异常转换成应用的异常(其含义更Ҏ被用户了解的异常Q?
4、不要捕获异常?
l论一Q既然捕获了异常Q就要对它进行适当的处理。不要捕获异怹后又把它丢弃Q不予理睬?
反例之二Q不指定具体的异?
代码Q?5行?
许多时候h们会被这样一U?#8220;妙?#8221;x吸引Q用一个catch语句捕获所有的异常。最常见的情形就是用catch(Exception ex)语句。但实际上,在绝大多数情况下Q这U做法不值得提倡。ؓ什么呢Q?
要理解其原因Q我们必d一下catch语句的用途。catch语句表示我们预期会出现某U异常,而且希望能够处理该异常。异常类的作用就是告?Java~译器我们想要处理的是哪一U异常。由于绝大多数异帔R直接或间接从java.lang.ExceptionzQcatch (Exception ex)q当于说我们想要处理几乎所有的异常?
再来看看前面的代码例子。我们真正想要捕L异常是什么呢Q最明显的一个是SQLExceptionQ这是JDBC操作中常见的异常。另一个可能的异常是IOExceptionQ因为它要操?OutputStreamWriter。显Ӟ在同一个catch块中处理q两U截然不同的异常是不合适的。如果用两个catch块分别捕?SQLException和IOExceptionp好多了。这是_catch语句应当量指定具体的异常类型,而不应该指定늛范围太广?ExceptioncR?
另一斚wQ除了这两个特定的异常,q有其他许多异常也可能出现。例如,如果׃某种原因Q?executeQueryq回了nullQ该怎么办?{案是让它们l箋抛出Q即不必捕获也不必处理。实际上Q我们不能也不应该去捕获可能出现的所有异常,E序的其他地方还有捕获异常的Z??直至最后由JVM处理?
l论二:在catch语句中尽可能指定具体的异常类型,必要时用多个catch。不要试囑֤理所有可能出现的异常?
反例之三Q占用资源不释放
代码Q??14行?
异常改变了程序正常的执行程。这个道理虽然简单,却常常被Z忽视。如果程序用C文g、Socket、JDBCq接之类的资源,即遇到了异常,也要正确释放占用的资源。ؓ此,Java提供了一个简化这cL作的关键词finally?
finally是样好东西:不管是否出现了异常,Finally保证在try/catch/finally块结束之前,执行清理d的代码L有机会执行。遗憄是有些h却不习惯使用finally?
当然Q编写finally块应当多加小心,特别是要注意在finally块之内抛出的异常??q是执行清理d的最后机会,量不要再有难以处理的错误?
l论三:保证所有资源都被正释放。充分运用finally关键词?/font>
反例之四Q不说明异常的详l信?
代码Q??18行?
仔细观察q段代码Q如果@环内部出C异常Q会发生什么事情?我们可以得到_的信息判断@环内部出错的原因吗?不能。我们只能知道当前正在处理的cd生了某种错误Q但却不能获得Q何信息判断导致当前错误的原因?
printStackTrace的堆栈跟t功能显C出E序q行到当前类的执行流E,但只提供了一些最基本的信息,未能说明实际D错误的原因,同时也不易解诅R?
因此Q在出现异常Ӟ最好能够提供一些文字信息,例如当前正在执行的类、方法和其他状态信息,包括以一U更适合阅读的方式整理和l织printStackTrace提供的信息?
l论四:在异常处理模块中提供适量的错误原因信息,l织错误信息使其易于理解和阅诅R?
反例之五Q过于庞大的try?
代码Q??14行?
l常可以看到有h把大量的代码攑օ单个try块,实际上这不是好习惯。这U现象之所以常见,原因在于有些h囄事,不愿花时间分析一大块代码中哪几行代码会抛出异常、异常的具体cd是什么。把大量的语句装入单个巨大的try块就象是出门旅游时把所有日常用品塞入一个大子Q虽然东西是带上了,但要扑և来可不容易?
一些新手常常把大量的代码放入单个try块,然后再在catch语句中声明ExceptionQ而不是分d个可能出现异常的D落q分别捕获其异常。这U做法ؓ分析E序抛出异常的原因带来了困难Q因Z大段代码中有太多的地方可能抛出Exception?
l论五:量减小try块的体积?
反例之六Q输出数据不完整
代码Q??11行?
不完整的数据是JavaE序的隐形杀手。仔l观察这D代码,考虑一下如果@环的中间抛出了异常,会发生什么事情。@环的执行当然是要被打断的Q其ơ, catch块会执行??p些,再也没有其他动作了。已l输出的数据怎么办?使用q些数据的h或设备将收到一份不完整的(因而也是错误的Q数据,却得不到M有关q䆾数据是否完整的提C。对于有些系l来_数据不完整可能比pȝ停止q行带来更大的损失?
较ؓ理想的处|办法是向输备写一些信息,声明数据的不完整性;另一U可能有效的办法是,先缓冲要输出的数据,准备好全部数据之后再一ơ性输出?
l论六:全面考虑可能出现的异总及这些异常对执行程的媄响?
改写后的代码
Ҏ上面的讨论,下面l出改写后的代码。也许有Z说它E微有点?嗦,但是它有了比较完备的异常处理机制?
OutputStreamWriter out = ... java.sql.Connection conn = ... try { Statement stat = conn.createStatement(); ResultSet rs = stat.executeQuery( "select uid, name from user"); while (rs.next()) { out.println("IDQ? + rs.getString("uid") + "Q姓? " + rs.getString("name")); } } catch(SQLException sqlex) { out.println("警告Q数据不完整"); throw new ApplicationException("d数据时出现SQL错误", sqlex); } catch(IOException ioex) { throw new ApplicationException("写入数据时出现IO错误", ioex); } finally { if (conn != null) { try { conn.close(); } catch(SQLException sqlex2) { System.err(this.getClass().getName() + ".mymethod - 不能关闭数据库连? " + sqlex2.toString()); } } if (out != null) { try { out.close(); } catch(IOException ioex2) { System.err(this.getClass().getName() + ".mymethod - 不能关闭输出文g" + ioex2.toString()); } } } |
q个帖子主要ȝ提高查询速度的方法,涉及到减连接数据库ơ数、徏立烦引、优化语句等斚w?/p>
关于索引Q推荐{载的q篇文章
http://blog.csdn.net/dutguoyi/archive/2006/01/10/575617.aspx
改善SQL语句的效?br>http://community.csdn.net/Expert/topic/5087/5087396.xml?temp=.345669
数据量很大怎样加快索检速度
http://community.csdn.net/Expert/topic/5058/5058320.xml?temp=.1229517
索引建立Ҏ的区?br>http://community.csdn.net/Expert/topic/5068/5068154.xml?temp=.3010218
频繁插入删除数据需要更新烦?br>http://community.csdn.net/Expert/topic/4937/4937910.xml?temp=.8428614
试了一下sql server 2005 全文?br>http://community.csdn.net/Expert/topic/4878/4878430.xml?temp=.6049311
其他关于效率的高频问?/p>
判断一个表的数据不在另一个表中最优秀ҎQ?br>http://community.csdn.net/Expert/topic/5038/5038742.xml?temp=.4704553
删除千万U表中重复记录的办法
http://community.csdn.net/Expert/topic/5089/5089261.xml?temp=.7907068
数据库数据查询变得不正常cd问题
大数据量Q稳定运行一D|候以后无法得到查询结果?br>http://community.csdn.net/Expert/topic/4810/4810464.xml?temp=9.014529E-02
Class.forName("oracle.jdbc.driver.OracleDriver").newInstance(); String url="jdbc:oracle:thin:@localhost:1521:orcl"; //orcl为数据库的SID String user="test"; String password="test"; Connection conn= DriverManager.getConnection(url,user,password); |
Class.forName("com.ibm.db2.jdbc.app.DB2Driver ").newInstance(); String url="jdbc:db2://localhost:5000/sample"; //sampleZ的数据库? String user="admin"; String password=""; Connection conn= DriverManager.getConnection(url,user,password); |
Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver").newInstance(); String url="jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=mydb"; //mydb为数据库 String user="sa"; String password=""; Connection conn= DriverManager.getConnection(url,user,password); |
Class.forName("com.sybase.jdbc.SybDriver").newInstance(); String url =" jdbc:sybase:Tds:localhost:5007/myDB";//myDBZ的数据库? Properties sysProps = System.getProperties(); SysProps.put("user","userid"); SysProps.put("password","user_password"); Connection conn= DriverManager.getConnection(url, SysProps); |
Class.forName("com.informix.jdbc.IfxDriver").newInstance(); String url = "jdbc:informix-sqli://123.45.67.89:1533/myDB:INFORMIXSERVER=myserver; user=testuser;password=testpassword"; //myDB为数据库? Connection conn= DriverManager.getConnection(url); |
Class.forName("org.gjt.mm.mysql.Driver").newInstance(); String url ="jdbc:mysql://localhost/myDB?user=soft&password=soft1234&useUnicode=true&characterEncoding=8859_1" //myDB为数据库? Connection conn= DriverManager.getConnection(url); |
Class.forName("org.postgresql.Driver").newInstance(); String url ="jdbc:postgresql://localhost/myDB" //myDB为数据库? String user="myuser"; String password="mypassword"; Connection conn= DriverManager.getConnection(url,user,password); |
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver") ; String url="jdbc:odbc:Driver={MicroSoft Access Driver (*.mdb)};DBQ="+application.getRealPath("/Data/ReportDemo.mdb"); Connection conn = DriverManager.getConnection(url,"",""); Statement stmtNew=conn.createStatement() ; |
try{ Class.forName(com.mysql.jdbc.Driver); System.out.println(Success loading Mysql Driver!); }catch(Exception e) { System.out.println(Error loading Mysql Driver!); e.printStackTrace(); } |
jdbcQmysqlQ?/localhost/databasename[?pa=va][Qpa=va] |
PreparedStatement pstmt3D null; try { ((OraclePreparedStatement)pstmt).setExecuteBatch(30); ... pstmt.executeUpdate(); } |
JDBC驱动
下蝲版本Q?.1.8
http://dev.mysql.com/downloads/connector/j/3.1.html
Mysql界面插g:mysql-front
下蝲版本镜像QHongKongQ下回来安装是中文版了Q?br> http://www.mysqlfront.de/download.html
二. 软g安装
1.安装mysql
请参阅资料版区相x?/p>
http://info.mysql.cn/install/2006/0208/81.html
2.JDBC驱动Qmysql-connector-java-3.1.8
q只是一个压~包Qƈ不需要安装,只要其解压Q我么用的是文件夹mysql-connector-java-3.1.8里的文gQmysql-connector-java-3.1.8-bin.jarQ?/p>
3. Mysql界面插g:mysql-front
q是一个安装程序,按照提示安装可以了Q?/p>
三. 环境配置
首先Q我要说明的是我现在tomcat的安装\径是: D:\Program Files\Java\TomcatQJDK的安装\径是QD:\Program Files\Java\j2sdk?/p>
在这里,需要配|环境变量的是JDBC驱动Q在配置前先要把刚才说到的mysql-connector-java-3.1.8-bin.jar本地盘某处Q我攄地方QD:\Program Files\Java\mysqlforjdbcQ,然后Ҏ你放的地方,配置classpathQ我的配|是q样的:
D:\Program files\Java\j2sdk\lib\tools.jar;
D:\Program Files\Java\j2sdk\lib\mysql-connector-java-3.1.8-bin-g.jar;
D:\Program Files\Java\mysqlforjdbc\mysql-connector-java-3.1.8-bin.jar
配置q个的目的是让你的java应用E序扑ֈq接mysql的驱动.
配置完环境变量后q有很重要一步就是ؓJSPq接数据库配|驱动,q个其实很简单,是把mysql-connector-java-3.1.8- bin.jar拷到某些文g多wp了,我在|上看了很多资料问了很多人,各种说法都有Q我l合了一下,Z保险Q我都全做了Q呵呵,反正是拷一?400K的文件而已Q现列出要把mysql-connector-java-3.1.8-bin.jar拯ȝ文g夹,如下Q?br> D:\Program Files\Java\Tomcat\common\lib
D:\Program Files\Java\Tomcat\shared\lib
四. 数据库的使用
Mysql安装完毕以后Q还有一些要注意的地方(参考)Q?/p>
http://info.mysql.cn/install/2006/0208/82.html
p在文章提到的Qmysql安装好后最重要一样就是要看数据库有没有作为系l服务启动了Q所以在大家q行数据库操作前Q应要看看,在操作系l的开始-Q运行-Q输入services.mscQ确定你在安装时你设|的关于mysql的那个服务已l启动,q样你在操作数据库时不会报连接不上的错误Q?/p>
上面提到了一个较方便的mysql界面插gQ但是这个界面是我在已经开始用mysql后才扑ֈ的,刚开始我是在dos下用命o行进行操作的Q虽焉个界面也可以q行建库啊,讑֮权限{操作,但是Q我觉得懂得在用命令行也是一个很重要的技能,所以我先从命o行开始说Q怎样单用mysqlQ到后面会谈及mysqlQfront的用.
现在我想在mysql里徏一个数据库shujukuQ以及在数据库里Z个表biaoQ具体的命o如下Q假设mysql我是刚安装好的)
1. q入dos状态(C命o行的要运行在mysql的安装目录下的bin目录的)
2. q接mysql
输入Qmysql –h localhost –u root –p
输入在安装时已设好的密码Q就q入了mysql的命令编辑界面了?/p>
3. 使用mysql的基本命?在mysql命o行编辑每输入完命令后最后一定要有分P不然会报?
昄数据库:show databases;
使用数据库:use 数据库名Q?/p>
4Q徏?br> 命oQcreate database shujuku;
5.为数据库讄权限Q用户和密码Q?br> 命oQgrant all privileges on shujuku.* to test@localhost identified by “123456”;
当你执行完这个命令以后,只要你再以用户名Qtest,密码Q?23456d时你只可以对shujukuq个数据库操作,q样避开使用rootQ对数据库的安全有很大帮助.
6.
命oQcreate table biao(id int(8) primary key,name varchar(10));
剩下来的与标准sqsl命o基本上是一LQ具体操作略
值得一提的是,你在命o行上输入Q?Q,׃有mysql命o的简单帮助,如下Q?/p>
呵呵Q那P我们q可以知道退出,是QexitQ,呵呵Q?/p>
五. 关于mysql-front的?br> 我找了好几个mysql的界面工P觉得最z方便还是mysql-frontQ可惜的是要收费Q不q还好有试用期,呵呵Q可以先感受感受一下,最重要一Ҏmysql-front有简体中文版的,英文不好的我用v来就舒服多了Q下面简单说说用吧Q?/p>
首先Q安装就不用说了Q有向导Q而且很简单.安装好后W一ơ运行时会蟩出来一个要求添加对话的框,在这里你可以d例如上面已经讑֮好的shujukuQ过E如?
当你在注册的复选框里填上你在上面mysql讑֮好的用户名和密码后,在选择数据库框里就有shujuku 的数据库了,选上Q按定Q进入mysql-fron后,你就会看C面的界面Q这是你可以进行操作了Q?/p>
要说明的是,你还可以把root用户也加q去Q这要你在mysql-fron的界面上选设|-Q对话-Q新建,再按上面q行可以,Zroot你还可以加入更多的用PҎq是一LQ设|不同的用户Q是方便对不同数据库q行理Q呵呵,root是权限最高的Q可不要随便让别Z用你的root用户Q保正你数据库的安全Q?/p>
六. JSPq接mysql
现在是试用jspq接mysql?br> 我在eclipse里徏了个test_mysql.jsp面Q代码如下:
<%@ page contentType="text/html; charset=gb2312" %>
<%@ page language="java" %>
<%@ page import="com.mysql.jdbc.Driver" %>
<%@ page import="java.sql.*" %>
<%
//驱动E序?/p>
String driverName="com.mysql.jdbc.Driver";
//数据库用户名
String userName="cl41";
//密码
String userPasswd="123456";
//数据库名
String dbName="db";
//表名
String tableName="dbtest";
//联结字符?/p>
String url="jdbc:mysql://localhost/"+dbName+"?user="+userName+"&password="+userPasswd;
Class.forName("com.mysql.jdbc.Driver").newInstance();
Connection connection=DriverManager.getConnection(url);
Statement statement = connection.createStatement();
String sql="SELECT * FROM "+tableName;
ResultSet rs = statement.executeQuery(sql);
//获得数据l果集合
ResultSetMetaData rmeta = rs.getMetaData();
//定数据集的列数Q亦字段?/p>
int numColumns=rmeta.getColumnCount();
// 输出每一个数据?/p>
out.print("id");
out.print("|");
out.print("num");
out.print("<br>");
while(rs.next()) {
out.print(rs.getString(1)+" ");
out.print("|");
out.print(rs.getString(2));
out.print("<br>");
}
out.print("<br>");
out.print("数据库操作成功,恭喜?);
rs.close();
statement.close();
connection.close();
%>
然后把test??_mysql.jsp部v到tomcat处,如何部v可参?配置Eclpise+tomcatq实现JSP的编写与部v"Q在览器中可以看到结果了?/p>
双击该图?先保证你的电脑上安装了WinRAR或者WinZIP{解压羃工具Q压~工具也可以在上面的面中下载到)Q打开rar解压H口Q如?
你可以把文g解压都硬盘上Q然后再安装。也可以直接在窗口中Q双击Setup.exe文gQ开始mysql5.0的安装?br>先是{待Q它自己解压文gQ直到出C面的H口Q图3
q里是安装欢q程序,点击Next开始下一步安装。默认是TypicalQ徏议改成CustomQ因为Typical模式不允许改变安装\径,只能安装在C盘。下面会介绍Custom的安装方法,见图4?br>
到这一步需要选择lg及更Ҏ件夹位置Q组件就用默认的Q位|可以选择Change来改变,见图5
注意Q安装mysql的\径中Q不能含有中文!
一切就l,点击Install开始安装。见??br>
开始安装过E,会出现安装进度条Q见??br>
安装l束后,E序会提C是否要在mysql.com上注册,我们选择跌Q即Skip Sign-Up然后?#8220;Next”见图8
安装l束Q选择现在开始配|mysql服务器。点击Finishl箋。图9?br>
配置开始,点击Nextl箋Q见?0
选择Detailed ConfigurationQ见?1Q点Nextl箋
下面q个选项是选择mysql应用于何U类型,W一U是开发服务器Q将只用量的内存Q第二种是普通WEB服务器,用中{数量内存,最后一U是q台服务器上面只跑mysql数据库,占用全部的内存Q我q里只是CZQ就选择开发服务器Q占用尽量少的内存,用户可根据自q需求,选择其他选项Q见?2Q点Nextl箋
下面是选择数据库用途,W一U是多功能用途,把数据库优化成很好的innodb存储cd和高效率的myisam存储cdQ第二种是只用于事务处理cdQ最好的优化innodbQ但同时也支持myisamQ最后一U是非事务处理类型,适合于简单的应用Q只有不支持事务的myisamcd是被支持的。一般选择W一U多功能的。见?3
点Nextl箋Q下面是选择InnodDB的数据存放位|,一般默认好了,不需要改动,见图14
下面是选择mysql允许的最大连接数Q第一U是最?0个连接ƈ发数Q第二种是最?00个ƈ发连接数Q最后一U是自定义,你可以根据自q需要选择Q见?5
点Nextl箋Q下面是选择数据库监听的端口Q一般默认是3306Q如果改成其他端口,以后q接数据库的时候都要记住修改的端口Q否则不能连接mysql数据库,比较ȝQ这里不做修改,用mysq的默认端口:3306Q见?span id=attach_137 onmouseover="showMenu(this.id, 0, 1)" style="DISPLAY: none; POSITION: absolute">
点Nextl箋Q这一步设|mysql的默认编码,默认是latin1Q见?7
我们可以Ҏ需要,把它Ҏgb2312Q过gbkQ见?8
?8
注意Q如果要用原来数据库的数据,最好能定原来数据库用的是什么编码,如果q里讄的编码和原来数据库数据的~码不一_在用的时候可能会出现q?br>点Nextl箋Q这一步是是否要把mysql讄成windows的服务,一般选择设成服务Q这样以后就可以通过服务中启动和关闭mysql数据库了。推荐:下面的复选框也勾选上Q这P在cmd模式下,不必非到mysql的bin目录下执行命令。见?9
点Nextl箋Q这一步是讄mysql的超U用户密码,q个用户非常重要Q对mysql拥有全部的权限,误|好q牢记超U用L密码Q下面有个复选框是选择是否允许q程机器用root用户q接C的mysql服务器上面,如果有这个需求,也请N,见图20
?0
当两ơ输入的密码一致后Q记住该密码Q点Nextl箋Q见?1
?1
到现在位|,mysql已经得到了够的配置条gQ如果没有问题即可点击ExecuteQ让mysqlq行配置Q如果有不妥的地方,点击BackQ重C攚w|条Ӟ见图22
?2
q样mysql全部安装好了,见图23?br>
?3
可能出现的问题:
如果在第二十步,你出现的界面是像下面q样Q见?4Q?br>
?4
有三个输入密码的地方Q则有可能您是在原来基础上安装的。你在第一个文本框输入原来root的密码,后面两个文本框输入root的新密码Q点击Next基础Q出C图,见图25Q?br>
?5
l您推荐几种解决办法Q?br>1?nbsp; 点RetryQ重试;
2? 再运行一ơ设|,看到有关“U除原设|?#8221;的选项Q选择U除Q然后在重新讄?br>3?nbsp; 重装?br>重装注意事项Q最好删除原来的所有文Ӟ必要的话Q可以清一下注册表Q如果你机器上没有其它mysql相关的程序。而且一定记得不要保留原有的my.ini文g。还有就是删除原来安装\径下的文Ӟq删除数据目录下面的ibdata1文g.
l于发完了,不容易啊Q希望能对大家有所帮助Q如果有不对的地方,敬请指出Q我会尽快修
备䆾数据库两个主要方法是?mysqldump E序或直接拷贝数据库文gQ如?cp、cpio ?tar {)。每U方法都有其优缺点:
mysqldump ?MySQL 服务器协同操作。直接拷贝方法在服务器外部进行,q且你必采取措施保证没有客h在修改你拷贝的表。如果你想用文gpȝ备䆾来备份数据库Q也会发生同L问题Q如果数据库表在文gpȝ备䆾q程中被修改Q进入备份的表文件主语不一致的状态,而对以后的恢复表失L义。文件系l备份与直接拯文g的区别是对后者你完全控制了备份过E,q样你能采取措施保服务器让表不受干扰?
mysqldump 比直接拷贝要慢些?
mysqldump 生成能够UL到其它机器的文本文gQ甚至那些有不同gl构的机器上。直接拷贝文件不能移植到其它机器上,除非你正在拷贝的表?MyISAM 存储格式。ISAM 表只能在怼的硬件结构的机器上拷贝。在 MySQL 3.23 中引入的 MyISAM 表存储格式解决了该问题,因ؓ该格式是机器无关的,所以直接拷贝文件可以移植到h不同gl构的机器上。只要满两个条Ӟ另一台机器必Mq行 MySQL 3.23 或以后版本,而且文g必须?MyISAM 格式表示Q而不?ISAM 格式?
不管你用哪U备份方法,如果你需要恢复数据库Q有几个原则应该遵守Q以保最好的l果Q?
定期实施备䆾。徏立一个计划ƈ严格遵守?
让服务器执行更新日志。当你在崩溃后需要恢复数据时Q更新日志将帮助你。在你用备䆾文g恢复数据到备份时的状态后Q你可以通过q行更新日志中的查询再次q用备䆾后面的修改,q将数据库中的表恢复到崩溃发生时的状态?
以文件系l备份的术语Ԍ数据库备份文件代表完全們ր(full dumpQ,而更新日志代表渐q們ր(incremental dumpQ?
使用一U统一的和易理解的备䆾文g命名机制。象 backup1、buckup2 {不是特别有意义。当实施你的恢复Ӟ你将费旉扑և文g里是什么东ѝ你可能发觉用数据库名和日期构成备䆾文g名会很有用。例如:
%mysqldump samp_db >/usr/archives/mysql/samp_db.1999-10-02
%mysqldump menagerie >/usr/archives/mysql/menagerie.1999-10-02
你可能想在生成备份后压羃它们。备份一般都很大Q你也需要让你的备䆾文g有过期期限以避免它们填满你的盘Q就象你让你的日志文件过期那栗?
用文件系l备份备份你的备份文件。如果遇上了一个彻底崩溃,不仅清除了你的数据目录,也清除了包含你的数据库备份的盘驱动器,你将真正遇上了麻烦?
也要备䆾你的更新日志?
你的备份文件放在不同于用于你的数据库的文gpȝ上。这降低由于生成备份而填满包含数据目录的文gpȝ的可能性?
用于创徏备䆾的技术同样对拯数据库到另一台机器有用。最常见圎ͼ一个数据库被{Ud了运行在另一CZ的服务器Q但是你也可以将数据转移到同一CZ的另一个服务器?
1 使用 mysqldump 备䆾和拷贝数据库
当你使用 mysqldumo E序产生数据库备份文件时Q缺省地Q文件内容包含创建正在們ր的表的 CREATE 语句和包含表中行数据?INSERT 语句。换句话_mysqldump 产生的输出可在以后用?mysql 的输入来重徏数据库?
你可以将整个数据库們ր进一个单独的文本文g中,如下Q?
%mysqldump samp_db >/usr/archives/mysql/samp_db.1999-10-02
输出文g的开头看h象这P
# MySQL Dump 6.0# # Host: localhost Database: samp_db#-------------
--------------------------# Server version 3.23.2-alpha-log## Table st
ructure for table absence#CREATE TABLE absence( student_id int(10)
unsigned DEFAULT 0 NOT NULL, date date DEFAULT 0000-00-00 NOT NUL
L, PRIMARY KEY (student_id,date));## Dumping data for table absence
#INSERT INTO absence valueS (3,1999-09-03);INSERT INTO absence value
S (5,1999-09-03);INSERT INTO absence valueS (10,1999-09-08);......
文g剩下的部分有更多的INSERT和CREATE TABLE语句l成。如果你惛_~备份,使用cM如下的命令:
%mysqldump samp_db | gzip >/usr/archives/mysql/samp_db.1999-10-02.gz
如果你要一个庞大的数据库,输出文g也将很庞大,可能难于理。如果你愿意Q你可以?mysqldump 命o行的数据库名后列出单独的表名来們ֈ它们的内容,q将們ր文件分成较、更易于理的文件。下例显C如何将 samp_db 数据库的一些表們ֈq分开的文件中Q?
%mysqldump samp_db student score event absence >grapbook.sql
%mysqldump samp_db member president >hist-league.sql
如果你生成准备用于定期刷新另一个数据库内容的备份文Ӟ你可能想?--add- drop-table 选项。这告诉服务器将 DROP TABLE IF EXISTS 语句写入备䆾文gQ然后,当你取出备䆾文gq把它装载进W二个数据库Ӟ如果表已l存在,你不会得C个错误?
如果你倒出一个数据库以便能把数据库{Ud另一个服务器Q你甚至不必创徏备䆾文g。要保证数据库存在于另一C机,然后用管道們ր数据库Q这?mysql 能直接读?mysqldump 的输出。例如:你想从主?pit- viper.snake.net 拯数据?samp_db ?boa.snake.netQ可以这样很Ҏ做到Q?
%mysqladmin -h boa.snake.net create samp_db
%mysqldump samp_db | mysql -h boa.snake.net samp_db
以后Q如果你惛_ơ刷?boa.snake.net 上的数据库,跌 mysqladmin 命oQ但要对 mysqldump 加上--add-drop-table 以避免的得到表已存在的错误:
%mysqldump --add-drop-table samp_db | mysql -h boa.snake.net samp_db
mysqldump 其它有用的选项包括Q?
--flush-logs ?--lock-tables l合对你的数据库检查点有帮助?-lock-tables 锁定你正在們ր的所有表Q?--flush-logs 关闭q新打开更新日志文gQ新的更新日志将只包括从备䆾点v的修Ҏ据库的查询。这设|你的更新日志检查点位备份时间。(然而如果你有需要执行个更新的客P锁定所有表对备份期间的客户讉K不是件好事。)
如果你?--flush-logs 讄查点到备份时Q有可能最好是們ր整个数据库?
如果你們ր单独的文gQ较隑ְ更新日志查点与备份文件同步。在恢复期间Q你通常按数据库为基提取更新日志内容Q对单个表没有提取更新的选择Q所以你必须自己提取它们?
~省圎ͼmysqldump 在写入前一个表的整个内容读q内存。这通常实不必要,q且实际上如果你有一个大表,几乎是失败的。你可用 --quick 选项告诉 mysqldump 只要它检索出一行就写出每一行。ؓ了进一步优化們ր过E,使用 --opt 而不?--quick?-opt 选项打开其它选项Q加速数据的們ր和把它们读回?
?--opt 实施备䆾可能是最常用的方法,因ؓ备䆾速度上的优势。然而,要警告你Q?-opt 选项实有代P--opt 优化的是你的备䆾q程Q不是其他客户对数据库的讉K?-opt 选项通过一ơ锁定所有表LM人更C正在們ր的M表。你可在一般数据库讉K上很Ҏ看到其效果。当你的数据库一般非帔RJ地使用Q只是一天一ơ地调节备䆾?
一个具?--opt 的相反效果的选项?--dedayed。该选项使得 mysqldump 写出 INSERT DELAYED 语句而不?INSERT 语句。如果你数据文件装入另一个数据库q且你想是这个操作对可能出现在该数据库中的查询的影响最,--delayed Ҏ很有帮助?
--compress 选项在你拯数据库到另一台机器上时很有帮助,因ؓ它减网l传输字节的数量。下面有一个例子,注意?--compress 对与q端L上的服务器通信的程序才l出Q而不是对与本C接的E序Q?
%mysqldump --opt samp_db | mysql --compress -h boa.snake.net samp_db
2 使用直接拯数据库的备䆾和拷贝方?
另一U不涉及 mysqldump 备䆾数据库和表的方式是直接拷贝数据库表文件。典型地Q这用诸?cp、tar ?cpio 实用E序。本文的例子使用 cp?
当你使用一U直接备份方法时Q你必须保证表不在被使用。如果服务器在你则正在拷贝一个表时改变它Q拷贝就失去意义?
保证你的拯完整性的最好方法是关闭服务器,拯文gQ然后重启服务器。如果你不想关闭服务器,要在执行表检查的同时锁定服务器。如果服务器在运行,相同的制U也适用于拷贝文Ӟ而且你应该用相同的锁定协议让服务器“安静下来”?
假设服务器关闭或你已l锁定了你想拯的表Q下列显C如何将整个 samp_db 数据库备份到一个备份目录(DATADIR 表示服务器的数据目录Q:
%cd DATADIR%cp -r samp_db /usr/archive/mysql
单个表可以如下备份:
%cd DATADIR/samp_db%cp member.* /usr/archive/mysql/samp_db%cp score.*
/usr/archive/mysql/samp_db ....
当你完成了备份时Q你可以重启服务器(如果关闭了它Q或释放加在表上的锁定(如果你让服务器运行)?
要用直接拯文g把一个数据库从一台机器拷贝到另一台机器上Q只是将文g拯到另一台服务器L的适当数据目录下即可。要保文g?MyIASM 格式或两台机器有相同的硬件结构,否则你的数据库在另一CZ有奇怪的内容。你也应该保证在另一台机器上的服务器在你正在安装数据库表时不讉K它们?
3 复制数据库(Replicating DatabaseQ?
复制QReplicationQ类g拯数据库到另一台服务器上,但它的确切含义是实时C证两个数据库的完全同步。这个功能将?3.23 版中出现Q而且q不很成熟,因此本文不作详细介绍?
4 用备份恢复数?
数据库损坏的发生有很多原因,E度也不同。如果你走运Q你可能仅损坏一两个表(如掉电)Q如果你倒霉Q你可能必须替换整个数据目录Q如盘损坏Q。在某些情况下也需要恢复,比如用户错误地删除了数据库或表。不这些倒霉事g的原因,你将需要实施某U恢复?
如果表损坏但没丢失,试?myisamchk ?isamchk 修复它们Q如果这L损坏可有修复E序修复Q你可能Ҏ不需要用备份文件?/p>
恢复q程涉及两种信息源:你的备䆾文g和个更新日志。备份文件将表恢复到实施备䆾时的状态,然而一般表在备份与发生问题之间的时间内已经被修改,更新日志包含了用于进行这些修改的查询。你可以使用日志文g作ؓ mysql 的输入来重复查询。这已正是ؓ什么要启用更新日志的原因?
恢复q程视你必须恢复的信息多而不同。实际上Q恢复整个数据库比单个表跟容易,因ؓ对于数据库运用更新日志比单个表容易?
4.1 恢复整个数据?
首先Q如果你x复的数据库是包含授权表的 mysql 数据库,你需要用 --skip -grant-table 选项q行服务器。否则,它会抱怨不能找到授权表。在你已l恢复表后,执行 mysqladmin flush-privileges 告诉服务器装载授权标q用它们?
数据库目录内容拯到其它某个地方,如果你在以后需要它们?
用最新的备䆾文g重装数据库。如果你?mysqldump 产生的文Ӟ它作ؓ mysql 的输入。如果你用直接从数据库拷贝来的文Ӟ它们直接拷回数据库目录Q然而,此时你需要在拯文g之前关闭数据库,然后重启它?
使用更新日志重复做备份以后的修改数据库表的查询。对于Q何可适用的更新日志,它们作?mysql 的输入。指?--one-database 选项使得 mysql 只执行你有兴恢复的数据库的查询。如果你知道你需要运用所有更新日志文Ӟ你可以在包含日志的目录下使用q条命oQ?
% ls -t -r -1 update.[0-9]* | xargs cat | mysql --one-database db_name
ls 命o生成更新日志文g的一个单列列表,Ҏ服务器生它们的ơ序排序Q主意:如果你修改Q何一个文Ӟ你将改变排序ơ序Q这D更新日志一错误的次序被q用。)
很可能你会是q用某几个更新日志。例如,自从你备份以来生的更新日志被命名ؓ update.392、update.393 {等Q你可以q样重新q行Q?
%mysql --one-database db_name < update.392
%mysql --one-database db_name < update.393
.....
如果你正在实施恢复且使用更新日志恢复׃一个错误徏议的 DROP DATABASE、DROP TABLE ?DELETE 语句造成丢失的信息,在运用更新日志之前,要保证从其中删除q些语句?
4.2 恢复单个?
恢复单个表较为复杂。如果你用一个由 mysqldump 生成的备份文Ӟq且它不包含你感兴趣的表的数据,你需要从相关行中提取它们q将它们用作 mysql 的输入。这是容易的部分。难的部分是从只q用于该表的更新日志中拉出片断。你会发?mysql_find_rows 实用E序Ҏ很有帮助Q它从更新日志中提取多行查询?
另一个可能性是使用另一台服务器恢复整个数据库,然后拯你想要的表文件到原数据库中。这可能真的很容易!当你文件拷回数据库目录Ӟ要确保原数据库的服务器关闭?
1Q?strong>创徏数据库(createQ:create database database-name;
eg. create database test;
2Q?strong>删除数据库:drop database dbname;
eg.drop database test;
3Q?strong>创徏新表Q?/strong>create table tabname(col1 type1 [not null] [primary key],col2 type2 [not null],..);
eg.Ҏ已有的表创徏新表的例子:create table tab_new like tab_oldQcreate table tab_new as select col1,col2… from tab_old definition only;
4Q?strong>删除表:drop table tabname;
5Q?strong>增加列:alter table tabname add column col type;
6Q?strong>d主键Q?alter table tabname add primary key(col) ;
7Q?strong>删除主键Qalter table tabname drop primary key(col) ;
8Q?strong>创徏索引Qcreate [unique] index idxname on tabname(col….) ;
9Q?strong>删除索引Qdrop index idxname; 注:索引是不可更改的Q想更改必须删除重新建;
10Q?strong>创徏视图Qcreate view viewname as select statement;
2. 数据操纵语言QDMLQ?/strong>
1Q查询语句(selectQ?/strong>
eg1. select * from table1 where field1 like '%value1%';
eg2. select * from table1 order by field1,field2 [desc];
eg3. select count as totalcount from table1;
eg4. select sum(field1) as sumvalue from table1;
eg5. select avg(field1) as avgvalue from table1;
eg6. select max(field1) as maxvalue from table1;
eg7. select min(field1) as minvalue from table1;
eg8. select a.a, a.b, a.c, b.c, b.d, b.f from a LEFT OUT JOIN b ON a.a = b.c;Q注Q此为左外连接,l果集中包括q接表的匚w行,也包括左q接表的所有行Q?/p>
2Q插入语句(insertQ?/strong>
insert into table1(field1,field2) values(value1,value2);
3Q删除语句(deleteQ?/strong>
delete from table1 where 范围;
4Q更新语句(updateQ?/strong>
update table1 set field1=value1 where 范围;
3. 数据控制语言QDCLQ?/strong>
1Q授予权限语句(GRANTQ?/strong>
GRANT privileges (columns) ON what TO user IDENTIFIED BY "password" WITH GRANT OPTION;
其中Qprivileges可ؓ如下限定W:ALTER 修改表和索引、CREATE Q创建数据库和表Q、DELETEQ?删除表中已有的记录)、DROP Q删除数据库和表Q、INDEX Q创建或删除索引Q、INSERTQ?向表中插入新行)、REFERENCEQ?未用Q、SELECT Q检索表中的记录Q、UPDATE Q修改现存表记录Q、FILE Q读或写服务器上的文Ӟ、PROCESSQ?查看服务器中执行的线E信息或杀ȝE)、RELOAD Q重载授权表或清I日志、主机缓存或表缓存)、SHUTDOWNQ?关闭服务器)、ALL 所有;ALL PRIVILEGES同义词、USAGE Q特D的“无权?#8221;权限Q?/p>
columnsQ权限运用的列,它是可选的Qƈ且你只能讄列特定的权限。如果命令有多于一个列Q应该用逗号分开它们Q?/p>
whatQ权限运用的U别。权限可以是全局的(适用于所有数据库和所有表Q、特定数据库Q适用于一个数据库中的所有表Q或特定表的。可以通过指定一个columns字句是权限是列特定的?/p>
user Q权限授予的用户Q它׃个用户名和主机名l成。MySQL中的一个用户名?悄懔臃衿敝付ǖ挠没?该名字不必与你的Unixd名或Windows名联pv来。缺省地Q如果你不明指定一个名字,客户E序?br>你的d名作为MySQL用户名。这只是一个约定。你可以在授权表中将该名字改为nobodyQ然后以nobodyq接
执行需要超U用h限的操作?/p>
passwordQ赋予用L口oQ它是可选的。如果你Ҏ用户没有指定IDENTIFIED BY子句Q该用户不赋l口令(不安全)。对现有用户QQ何你指定的口令将代替老口令。如果你不指定口令,老口令保持不变,当你用IDENTIFIED BY
Ӟ口o字符串用改用口o的字面含义,GRANTؓ你编码口令,不要象你用SET PASSWORD 那样使用password()
函数?/p>
WITH GRANT OPTION子句是可选的。如果你包含它,用户可以授予权限通过GRANT语句授权l其它用戗你可以用该子句l与其它用户授权的能力?/p>
用户名、口令、数据库和表名在授权表记录中是大写敏感的,L名和列名不是?br> eg1. 创徏一个超U用户test1
grant all privilleges on *.* to test1@localhost identified by '123456' with grant option;
eg2. 创徏一个只能查询的用户 test2
mysql> grant select on *.* to test2@localhost identified by '9876543';
2) 撤权q删除用PrevokeQ?/strong>
要取消一个用L权限Q用REVOKE语句。REVOKE的语法非常类gGRANT语句Q除了TO用FROM取代q且没有INDETIFED BY和WITH GRANT OPTION子句Q?br>
revoke privileges (columns) ON what FROM user
user部分必须匚w原来GRANT语句的你x权的用户的user部分。privileges部分不需匚wQ你可以用GRANT
语句授权Q然后用REVOKE语句只撤销部分权限。REVOKE语句只删除权限,而不删除用户。即使你撤销了所?br>权限Q在user表中的用戯录依然保留,q意味着用户仍然可以q接服务器。要完全删除一个用P你必?br>用一条DELETE语句明确从user表中删除用户记录Q?br>
#mysql -u root mysql
DELETE FROM user WHERE User="user_name" and Host="host_name";
FLUSH PRIVILEGES;
DELETE语句删除用户记录Q而FLUSH语句告诉服务器重载授权表。(当你使用GRANT和REVOKE语句Ӟ表自动重载,而你直接修改授权表时不是。)
eg. 删除用户test1
revoke all on *.* from test2@localhost;
use mysql;
delete from user where user='test' and host='localhost';
flush privileges;
3Q提交语句(commitQ?/strong>
4Q回滚语句(rollbackQ?/strong>
摘要
q结 MySQL
->mysql -u username -p
username 是你的帐号名U?/p>
q程q结
->mysql -h hostname -u username -p
hostname ?MySQL L的名U?/p>
昄全部的数据库
SHOW DATABASES;
mysql ?MySQL 用来储存帐号和权限的数据库,不能删除?/p>
选择数据?br>USE database_name;
昄数据库里的资料表
SHOW TABLES;
昄资料表的信息
DESCRIBE table_name;
注销 MySQL 昄?br>\q
SQL 的执行指令可以从文本文g内输入?br>SOURCE file_name
如果没有d MySQL 的显C器Q用Q?br>->mysql -u username -p < file_name
Primary key - 用来识别字段?key?br>Foreign key - 代表q结的资料表。再另一个资料表里的 primary key?/p>
使用 MySQL
建立数据?br>CREATE DATABASE employee;
q会建立一个叫 employee 的数据库?/p>
建立资料?br>CREATE TABLE table_name (table definition) [type=table_type];
完整格式Q?/p>
E序代码:
CREATE [TEMPORARY] TABLE [IF NOT EXISTS] table_name [(create_definition, ...)]
[table_options] [select_statement];
or
CREATE [TEMPORARY] TABLE [IF NOT EXISTS] table_name LIKE old_table_name;
create_definition:
col_name TYPE [NOT NULL | NULL] [DEFAULT default_value] [AUTO_INCREMENT]
[PRIMARY KEY] [reference_definition]
or PRIMARY KEY (index_col_name,...)
or KEY [index_name] (index_col_name,...)
or INDEX [index_name] (index_col_name,...)
or UNIQUE [INDEX] [index_name] (index_col_name,...)
or FULLTEXT [INDEX] [index_name] (index_col_name,...)
or [CONSTRAINT symbol] FOREIGN KEY [index_name] (index_col_name,...)
[reference_definition]
or CHECK (expression)
TEMPORARY 关键词是用来建立暂时的资料表Q当你的q结阶段l束后会自动删除?br>CREATE TEMPORARY TABLE table_name;
IF NOT EXISTS 只有在资料表不存在时才会建立?br>CREATE TABLE IF NOT EXISTS table_name;
LIKE old_table_name 会依?old_table_name 的构造来建立新的资料表?br>字段定义 (column definition) 可用的选项Q?br>NOT NULL ?NULL 来定义字D不能包?NULL (NOT NULL) 或可以包?NULL (NULL)?br>默认值是可以包括 NULL?br>DEFAULT 可用来宣告字D늚默认倹{?br>AUTO_INCREMENT 会自动生连l的数字。生的数字会大于资料表内的最大数倹{?br>每个资料表只能有一?AUTO_INCREMENT 字段。他必须是烦引?br>M PRIMARY KEY 的字D会自动建立索引?br>PRIMARY KEY 可用来宣?PRIMARY KEY 的字Dc?br>REFERENCES 可用来宣告字D| FOREIGN KEYQ只能用?InnoDB 资料表?br>下面的关键词可用来宣告字D늚资料Q?br>PRIMARY KEY 来设定多字段?PRIMARY KEYQ跟着是字D늚名称?br>INDEX ?KEY 是一L关键词,用来讑֮索引?br>UNIQUE 表示字段是独特的Q一h索引?br>FULLTEXT 可用来徏?FULLTEXT 索引Q可用于 TEXT, CHAR, VARCHAR cd?br>FULLTEXT 只能用在 MyISAM 资料表?br>FOREIGN KEY 可用来宣?FOREIGN KEY?br>下面的选项可以不用Q通常是用在最佛_Q?br>AUTO_INCREMENT = #
讑֮开始的 AUTO_INCREMENT 数倹{?br>AVG_ROW_LENGTH = #
可用来估计你要的字段长度?br>CHECKSUM = 1
开启资料表的核对倹{可用来修复损坏的资料表。只能用?MyISAM?br>COMMENT = "字符?
用来输入资料表的Ҏ?br>MAX_ROWS = #
讑֮资料表允许的字段?(最??br>MIN_ROWS = #
讑֮资料表允许的字段?(最??br>PACK_KEYS = {0 | 1 | DEFAULT}
MySQL 的预设是会压~?CHAR, VARCHAR, ?TEXT 的字W串?br>如要关闭?0?br>DELAY_KEY_WRITE = {0 | 1}
延后 key 的更斎ͼ直到关闭数据库。只能用?MyISAM?br>ROW_FORMAT = {default | dynamic | fixed | compress}
用来讑֮字段的储存方式。只能用?MyISAM?br>RAID_TYPE = {1 | STRIPED | RAID0} RAID_CHUNKS = # RAID_CHUNKSIZE = #
RAID 的设定?br>UNION = (table_name, [table_name...])
用于 MERGE 资料表。允怽讑֮ MERGE 使用的资料表?br>INSERT_METHOD = {NO | FIRST | LAST}
用于 MERGE 资料表。设定要插入资料到哪个资料表?br>DATA_DIRECTORY = "l对路径"
储存资料的目录?br>INDEX_DIRECTORY = "l对路径"
储存索引的目录?/p>
字段和数据类?br>数字cd
INT ?FLOAT
范例Qsalary decimal(10, 2) - 宽度 10 ?2 个小数点?br>可以?UNSIGNED ?ZEROFILL 关键词?br>UNSIGNED 只能包括零或整数。ZEROFILL 会显C数字前的零数?br>整数和变?br>可以~写?INTQ大是 4 bytes?br>TINYINT ?1 byteQ跟 BIT ?BOOL 相同?br>SMALLINT ?2 bytes?br>MEDIUMINT ?3 bytes?br>BIGINT ?8 bytes?br>FLOAT 是单_֯度的点数?br>DOUBLE 是双_֯度的点敎ͼ?REAL ?DOUBLE PRECISION 相同?br>字符串和文字cd
CHAR 可用来储存固定长度的字符Ԍ如果不设定长度,预设?CHAR(1)?br>最大值是 255 个字W?br>固定长度有时候会?VARCHAR 来的快?br>如果跟着的是 BINARY 关键词,比较字符串的时候必L意大写?br>VARCHAR 可用来储存动态的字符Ԍ如果预先不知道字W串的长度,范围?0 ?255?br>TEXT 可储存较长的字符Ԍ最大到 65535 个字W或 bytes?br>BLOB 代表 binary large objectQ用来储?binary 资料Q最大到 65535 个字W或 bytes。比较字W串旉要注意大写?br>TINYTEXT ?TINYBLOB 可储存小?255 个字W或 bytes 的字W串?br>MEDIUMTEXT ?MEDIUMBLOB 可储存到 16777215 个字W或 bytes 的字W串?br>LONGTEXT ?LONGBLOB 可储存到 4294,967,295 个字W或 bytes 的字W串?br>ENUM 可用来储存自订的倹{?br>范例Qgender enum('m', 'f')
表示储存的直?m ?f。也可储?NULLQ所以可能的直是 m, f, NULL, ?error?br>SET ?ENUM cM不过可以储存其它?ENUM 倹{?br>日期和时间类?br>date 可用来储存日期,?YYYY-MM-DD 昄?br>time 可用来储存时_?HH:MM:SS 昄?br>datetime 包含了日期和旉Q以 YYYY-MM-DD HH:MM:SS 昄?br>timestamp 储存插入字段或改变的旉?br>版本 4.0 之前可以?timestamp(10) 来改变显C的宽度?br>year 可用来储存年份,可以?year(2) ?year(4) 来设定显C格式,预设?year(4)?br>year(2) 代表?1970 ?2069 的年份?/p>
建立索引
M宣告?PRIMARY KEY, KEY, UNIQUE, ?INDEX 的字D都会自动徏立烦引?br>要将索引建立到字D는Q?br>CREATE INDEX name ON employee(name);
q会建立一个叫 name 的烦引到 employee 资料表里?name 字段?/p>
删除数据库,资料表,和烦?br>删除整个数据库,包括里面的资料:
DROP DATABASE employee;
可以?employee 的前面加?IF EXISTS?br>删除一个资料表Q?br>DROP TABLE assignment;
完整格式Q?/p>
E序代码:
DROP [TEMPORARY] TABLE [IF EXISTS] table_name [, table_name...]
删除索引Q?br>DROP INDEX index_name ON employee;
改变资料表结?br>如果要改变资料表的结构,建立 name 的烦引在 employee 里面?name 字段Q?br>ALTER TABLE employee;
ADD INDEX name (name);
完整格式Q?/p>
E序代码:
ALTER [IGNORE] TABLE table_name alter_spec [, alter_spec ...]
alter_spec:
ADD [COLUMN] create_definition [FIRST | AFTER col_name]
or ADD [COLUMN] (create_definition, create_definition,...)
or ADD INDEX [index_name] (index_col_name,...)
or ADD PRIMARY KEY (index_col_name,...)
or ADD UNIQUE [index_name] (index_col_name,...)
or ADD FULLTEXT [index_name] (index_col_name,...)
or ADD [CONSTRAINT symbol] FOREIGN KYE [index_name] (index_col_name,...)
[reference_definition]
or ALTER [COLUMN] col_name {SET DEFAULT literal | DROP DEFAULT}
or CHANGE [COLUMN] old_col_name create_definition
[FIRST | AFTER column_name]
or MODIFY [COLUMN] create_definition [FIRST | AFTER col_name]
or DROP [COLUMN] col_name
or DROP PRIMARY KEY
or DROP INDEX index_name
or DISABLE KEYS
or ENABLE KEYS
or RENAME [TO] new_table_name
or ORDER BY col_name
or table_options
因ؓ ALTER 非常有弹性所以有很多的查询子句?br>CHANGE ?MODIFY 相同Q可以让你改变字D늚定义或位|?br>DROP COLUMN 会删除资料表里的字段?br>DROP PRIMARY KEY ?DROP INDEX 会删除相q的字段索引?br>DISABLE KEYS 会告?MySQL 停止更新索引Q只能用?MyISAM?br>ENABLE KEYS 会l更新烦引?br>RENAME 可以让你改变资料表的名称?br>ORDER BY 会重新排序字Dc?/p>
使用 INSERT
INSERT 可以让你输入字段到资料表里?br>完整格式Q?/p>
E序代码:
INSERT [LOW_PRIORITY | DELAYED] [IGNORE]
[INTO] table_name [(col_name,...)]
VALUES ((expression | DEFAULT),...),(...),...
[ON DUPLICATE KEY UPDATE col_name=expression, ...]
or
INSERT [LOW_PRIORITY | DELAYED] [IGNORE]
[INTO] table_name [(col_name,...)]
SELECT ...
or
INSERT [LOW_PRIORITY | DELAYED] [IGNORE]
[INTO] table_name
SET col_name=(expression | DEFAULT), ...
[ON DUPLICATE KEY UPDATE col_name=expression, ...]
范例Q?/p>
E序代码:
INSERT INTO department VALUES
(42, 'Finance'),
(128, 'Research and Development'),
(NULL, 'Human Resources');
INTO 可以不用?br>INSERT INTO department
SELECT ...
可以从其它的资料表里取得资料Q存?department q个资料表?br>INSERT INTO department
SET name = 'Asset Management';
q会输入一个字D늚资料Q只提供 name 的字Dc其它没有资料的字段会是 NULL?br>其它查询子句Q?br>LOW PRIORITY ?DELAYED 会等其它用户d完资料后再输入资料?br>LOW PRIORITY 会阻止要输入资料的用P所以在跑完查询后需要等待一D|间?br>DELAYED 不会L用户Q但是输入资料要{没Z用资料表后才会完成?br>范例QINSERT DELAYED INTO ...
IGNORE 会忽略输入跟字段?PRIMARY KEY ?UNIQUE 值的冲突所产生的错误讯息?br>DEFAULT 会用默认值徏立字Dc?br>范例QINSERT INTO department VALUES(DEFAULT)
ON DUPLICATE KEY UPDATE 会解册 PRIMARY KEY ?UNIQUE 的冲H?br>范例Q?br>INSERT INTO warning (employeeID)
VALUES(6651)
ON DUPLICATE KEY UPDATE count = count+1;
使用 REPLACE
使用Ҏ?INSERT 相同?br>REPLACE 可以解决有冲H的输入。如果有冲突字段会被更新?/p>
使用 DELETE
用来删除字段?br>范例QDELETE FROM department;
会删?department 里面所有的字段?br>如果要选择哪个字段Q用 WHERE?br>范例QDELETE FROM department WHERE name='Asset Management';
如果有开?--safe-updates ?--i-am-a-dummy 选项可以避免一ơ删除全部的字段?br>所以必选择要删除的字段?br>完整格式Q?/p>
E序代码:
DELETE [LOW_PRIORITY] [QUICK] FROM table_name
[WHERE where_definition]
[ORDER BY ...]
[LIMIT rows]
or
DELETE [LOW_PRIORITY] [QUICK] table_name[.*] [, table_name[.*] ...]
FROM table-references
[WHERE where_definition]
or
DELETE [LOW_PRIORITY] [QUICK]
FROM table_name[.*] [, table_name[.*] ...]
USING table-references
[WHERE where_definition]
后两个格式可以用来删除其它资料表里的字段?br>范例Q?/p>
E序代码:
DELETE employee, employeeSkills
FROM employee, employeeSkills, department
WHERE employee.employeeID = employeeSkills.employeeID
AND employee.departmentID = department.departmentID
AND department.name='Finance';
上面的会删除全部的有?Finance department 里面工作?employeesQ然后删除他们的 employeeSkills?br>FROM 里面的字D不会被删除Q他们只是用来搜寅R只有在 employee ?employeeSkills 里面的字D会被删除?br>AND 是包含的条g。employee.employeeID 表示 employee 资料表里?employeeID 字段?br>W三个格式跟W二个差不多Q但是删?FROM 里面的资料表Q用 USING 来表C搜寻的资料表?br>范例Q?/p>
E序代码:
DELETE FROM employee, employeeSkills
USING employee, employeeSkills, department
WHERE employee.employeeID = employeeSkills.employeeID
AND employee.departmentID = department.departmentID
AND department.name='Finance';
跟上面一P不同的表C方法?br>额外的查询子句:
LOW_PRIORITY ?INSERT 里的意思相同?br>QUICK 可用来加?DELETE 的速度?br>ORDER BY 是用来删除字D늚序?br>LIMIT 可用来限制被删除的字D|量?/p>
使用 TRUNCATE
可用来删除全部的字段?br>TRUNCATE TABLE employee;
速度?DELETE q快?/p>
使用 UPDATE
可以用来更新字段?/p>
E序代码:
UPDATE employee
SET job='DBA'
WHERE employeeID='6651';
完整格式Q?/p>
E序代码:
UDPATE [LOW_PRIORITY] [IGNORE] table_name
SET col_name1=expr1 [, col_name2=expr2 ...]
[WHERE where_definition]
[ORDER BY ...]
[LIMIT rows]
or
UPDATE [LOW_PRIORITY] [IGNORE] table_name [, table_name ...]
SET col_name=expr1 [, col_name2=expr2 ...]
[WHERE where_definition]
WHERE 可以用来选择要更新哪个字Dc?br>W二个格式可以用来更新多个资料表?br>LOW_PRIORITY ?IGNORE 跟在 INSERT 里的相同QORDER BY ?LIMIT 跟在 DELETE 的相同?/p>
?LOAD DATA INFILE 上传资料文g
可以让你用档案来输入资料C个资料表?br>数据文g范例Q?/p>
E序代码:
42 Finance
128 Research and Development
NULL Human Resources
NULL Marketing
加蝲资料文gQ?/p>
E序代码:
LOAD DATA LOCAL INFILE 'department_infile.txt'
INTO TABLE department;
LOAD DATA INFILE 需?FILE 的权限?/p>
完整格式Q?/p>
E序代码:
LOAD DATA [LOW_PRIORITY | CONCURRENT] [LOCAL] INFILE 'fileName.txt'
[REPLACE | IGNORE]
INTO TABLE table_name
[FIELDS
[TERMINATED BY '\t']
[[OPTIONALLY] ENCLOSED BY '']
[ESCAPED BY '\\']
]
[LINES TERMINATED BY '\n']
[IGNORE number LINES]
[(col_name, ...)]
额外的查询子句:
LOW_PRIORITY ?INSERT 里的cMQ会{用戯取完资料表后在l?br>CONCURRENT 允许其它用户读资料表里的资料?br>LOCAL 表示资料文g在用L计算机里Q如果不?MySQL 会在L内读取资料文件?br>REPLACE 会覆盖旧的字D,IGNORE 会留旧的字段Q如果有冲突?br>FIELDS ?LINES 可以用来规定资料表的格式Q预讄格式?br>每行一个字D,字段资料?tabs 来分开Q要或不要用单引P和用 \ 来蟩脱字W?br>IGNORE number LINES 会忽略档案内行数Qnumber 表示行数?br>最后一个子句可以用来设定只输入资料到某些字Dc?/p>
q里l出另一U解x?mysql-4.1.11).低版本的mysqlg没出现过中文问题(mysql-4.0.17). :)
1.d一个过滤器,字W集~码设ؓUTF-8.
修改web.xml:
<filter>
<filter-name>SetCharacterEncoding</filter-name>
<filter-class>hxz.filter.SetEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>SetCharacterEncoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
新徏一个过滤器:
package hxz.filter;
import java.io.IOException;
import javax.servlet.*;
public class SetEncodingFilter implements Filter {
// default character encoding
String defaultEncoding = "UTF-8";
public void init(FilterConfig config) throws ServletException {
String encoding = config.getInitParameter("encoding");
if (encoding != null) {
defaultEncoding = encoding;
}
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
request.setCharacterEncoding(defaultEncoding);
chain.doFilter(request, response);
}
public void destroy() {
defaultEncoding = null;
}
}
2.修改hibernate配置文g:
<property name="url">
<value>jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8</value>
</property>
注意后面?useUnicode=true&characterEncoding=UTF-8, 在xml?amp;要改?amp;
3.在新版本中mysql?你可以选择一U字W集,它设ؓutf-8.
jsp或servlet中把字符集改为UTF-8.
4.trying...
, '2', 4.0
. 本h最早的一网上文章,Nq前发于奥烦|。最q主要用MySQLQ再ơ整理帖出?br>------------------------------------------------------
mysql使用指南Q上Q?br>作者:大金?/p>
有很多朋友虽然安装好了mysql但却不知如何使用它。在q篇文章中我们就从连接MYSQL、修改密码、增加用L斚w来学习一些MYSQL的常用命令?/p>
一、连接MYSQL?/p>
格式Q?mysql -hL地址 -u用户?Qp用户密码
1、例1Q连接到本机上的MYSQL?br> 首先在打开DOSH口Q然后进入目?mysqlbinQ再键入命omysql -uroot -pQ回车后提示你输密码Q如果刚安装好MYSQLQ超U用户root是没有密码的Q故直接回R卛_q入到MYSQL中了QMYSQL的提C符是:mysql>
2、例2Q连接到q程L上的MYSQL。假设远E主机的IP为:110.110.110.110Q用户名为root,密码为abcd123。则键入以下命oQ?nbsp;
mysql -h110.110.110.110 -uroot -pabcd123
Q注:u与root可以不用加空|其它也一P
3、退出MYSQL命oQ?exit Q回车)
二、修改密码?/p>
格式Qmysqladmin -u用户?-p旧密?nbsp; password 新密?/p>
1、例1Q给root加个密码ab12。首先在DOS下进入目录mysqlbinQ然后键入以下命?br> mysqladmin -uroot -password ab12
注:因ؓ开始时root没有密码Q所?p旧密码一就可以省略了?/p>
2、例2Q再root的密码改为djg345?br> mysqladmin -uroot -pab12 password djg345
三、增加新用户。(注意Q和上面不同Q下面的因ؓ是MYSQL环境中的命oQ所以后面都带一个分号作为命令结束符Q?/p>
格式Qgrant select on 数据?* to 用户名@dL identified by "密码"
?、增加一个用户test1密码为abcQ让他可以在ML上登录,q对所有数据库有查询、插入、修攏V删除的权限。首先用以root用户q入MYSQLQ然后键入以下命令:
grant select,insert,update,delete on *.* to test1@"%" Identified by "abc";
但例1增加的用h十分危险的,你想如某个h知道test1的密码,那么他就可以在internet上的M一台电脑上d你的mysql数据库ƈ对你的数据可以ؓ所Ʋؓ了,解决办法见例2?/p>
?、增加一个用户test2密码为abc,让他只可以在localhost上登录,q可以对数据库mydbq行查询、插入、修攏V删除的操作Qlocalhost指本C机,即MYSQL数据库所在的那台LQ,q样用户即用知道test2的密码,他也无法从internet上直接访问数据库Q只能通过MYSQLL上的web|讉K了?br> grant select,insert,update,delete on mydb.* to test2@localhost identified by "abc";
如果你不想test2有密码,可以再打一个命令将密码消掉?br> grant select,insert,update,delete on mydb.* to test2@localhost identified by "";
好今天的评到q里了,明天有空我再奉上mysql的数据库操作?/p>
在上我们讲了登录、增加用戗密码更改等问题。下我们来看看MYSQL中有x据库斚w的操作。注意:你必首先登录到MYSQL中,以下操作都是在MYSQL的提C符下进行的Q而且每个命o以分L束?/p>
一、操作技?/p>
1、如果你打命令时Q回车后发现忘记加分P你无重打一遍命令,只要打个分号回R可以了。也是说你可以把一个完整的命o分成几行来打Q完后用分号作结束标志就OK?/p>
2、你可以使用光标上下键调Z前的命o。但以前我用q的一个MYSQL旧版本不支持。我现在用的是mysql-3.23.27-beta-win?/p>
二、显C命?/p>
1、显C数据库列表?br> show databases;
刚开始时才两个数据库Qmysql和test。mysql库很重要它里面有MYSQL的系l信息,我们改密码和新增用户Q实际上是用这个库q行操作?/p>
2、显C库中的数据表:
use mysqlQ?nbsp; Q/打开库,学过FOXBASE的一定不会陌生吧
show tables;
3、显C数据表的结构:
describe 表名;
4、徏库:
create database 库名;
5、徏表:
use 库名Q?br> create table 表名 (字段讑֮列表)Q?/p>
6、删库和删表:
drop database 库名;
drop table 表名Q?/p>
7、将表中记录清空Q?br> delete from 表名;
8、显C中的记录Q?br> select * from 表名;
三、一个徏库和以及插入数据的实?br>drop database if exists school; //如果存在SCHOOL则删?br>create database school; //建立库SCHOOL
use school; //打开库SCHOOL
create table teacher //建立表TEACHER
(
id int(3) auto_increment not null primary key,
name char(10) not null,
address varchar(50) default '深圳',
year date
); //l束
//以下为插入字D?nbsp;
insert into teacher values('','glchengang','深圳一?,'1976-10-10');
insert into teacher values('','jack','深圳一?,'1975-12-23');
注:在徏表中
Q?Q将ID设ؓ长度?的数字字D?int(3)q让它每个记录自动加一:auto_incrementq不能ؓI?not null而且让他成ؓdDprimary key
Q?Q将NAME设ؓ长度?0的字W字D?br>Q?Q将ADDRESS设ؓ长度50的字W字D,而且~省gؓ深圳。varchar和char有什么区别呢Q只有等以后的文章再说了?Q?Q将YEAR设ؓ日期字段?br> 如果你在mysql提示W键入上面的命o也可以,但不方便调试。你可以以上命令原样写入一个文本文件中假设为school.sqlQ然后复制到c:下,q在DOS状态进入目录mysqlbinQ然后键入以下命令:
mysql -uroot -p密码 < c:school.sql
如果成功Q空Z行无M昄Q如有错误,会有提示。(以上命o已经调试Q你只要?/的注释去掉即可用)?/p>
四、将文本数据转到数据库中
1、文本数据应W合的格式:字段数据之间用tab键隔开Qnull值用n来代?
例:
3 rose 深圳二中 1976-10-10
4 mike 深圳一?1975-12-23
2、数据传入命?load data local infile "文g? into table 表名;
注意Q你最好将文g复制到mysqlbin目录下,q且要先用use命o打表所在的库?nbsp;
五、备份数据库Q(命o在DOS的mysqlbin目录下执行)
mysqldump --opt school>school.bbb
注释:数据库school备䆾到school.bbb文gQschool.bbb是一个文本文Ӟ文g名Q取,打开看看你会有新发现?/p>
后记Q其实MYSQL的对数据库的操作与其它的SQLcL据库大同异Q您最好找本将SQL的书看看。我在这里只介绍一些基本的Q其实我也就只懂q些了,呵呵。最好的MYSQL教程q是“晏子“译的“MYSQL中文参考手?#8220;不仅免费每个相关|站都有下蝲Q而且它是最权威的。可惜不是象"PHP4中文手册 "那样是chm的格式,在查扑և数命令的时候不太方ѝ?nbsp;
可以下蝲q个压羃?限Windowsq_): http://beansoft.java-cn.org/download/tsqlref.zip 2.1MB CHM 格式, 有烦? 可搜?/p>
那么q个资料的好处是什么呢?
1) 全中?/p>
2) 语法特别详细(当然部分?MS Ҏ? 不太?.. q里可以带个例子l大家看:
Transact-SQL 参?
新行添加到表或视图?
INSERT [ INTO]
{ table_name WITH ( < table_hint_limited > [ ...n ] )
| view_name
| rowset_function_limited
}
[ ( column_list ) ]
{
{ VALUES(
{ DEFAULT | NULL | expression
} [ ,...n] )
| derived_table
| execute_statement
}
| DEFAULT VALUES
}
< table_hint_limited > ::=
{ FASTFIRSTROW
| HOLDLOCK
| PAGLOCK
| READCOMMITTED
| REPEATABLEREAD
| ROWLOCK
| SERIALIZABLE
| TABLOCK
| TABLOCKX
| UPDLOCK
}
[INTO]
一个可选的关键字,可以它用在 INSERT 和目标表之间?
table_name
要接收数据的表?table 变量的名U?
WITH (<table_hint_limited> [...n])
指定目标表所允许的一个或多个表提C。需要有 WITH 关键字和圆括受不允许?READPAST、NOLOCK ?READUNCOMMITTED。有兌提示的更多信息,请参?FROM?
view_name
视图的名U及可选的别名。通过 view_name 来引用的视图必须是可更新的。由 INSERT 语句所做的修改不能影响视图?FROM 子句中引用的多个。例如,在多表视图中?INSERT 必须使用 column_listQ?em>column_list 是只引用来自一个基表的列。有兛_更新视图的更多信息,请参?CREATE VIEW?
rowset_function_limited
?OPENQUERY ?OPENROWSET 函数。有x多信息,请参?OPENQUERY 以及 OPENROWSET?
(column_list)
要在其中插入数据的一列或多列的列表。必ȝ圆括号将 column_list 括v来,q且用逗号q行分隔?
如果某列不在 column_list 中,?Microsoft® SQL Server™ 必须能够Z该列的定义提供一个|否则不能装蝲行。如果列满下面的条Ӟ那么 SQL Server 自动ؓ列提供|
当向标识列中插入昑ּ的值时Q必M?column_list ?VALUES 列表Qƈ且对于表QSET IDENTITY_INSERT 选项必须?ON?
VALUES
引入要插入的数据值的列表。对?column_listQ如果已指定Q中或者表中的每个列,都必L一个数据倹{必ȝ圆括号将值列表括h?
如果 VALUES 列表中的g表中列的序不相同,或者未包含表中所有列的|那么必须使用 column_list 明确地指定存储每个传入值的列?
DEFAULT
强制 SQL Server 装蝲为列定义的默认倹{如果对于某列ƈ不存在默认|q且该列允许 NULLQ那么就插入 NULL。对于?timestamp 数据cd定义的列Q插入下一个时间戳倹{DEFAULT Ҏ识列无效?
expression
一个常量、变量或表达式。表辑ּ不能包含 SELECT ?EXECUTE 语句?
derived_table
M有效?SELECT 语句Q它q回装载到表中的数据行?
execute_statement
M有效?EXECUTE 语句Q它使用 SELECT ?READTEXT 语句q回数据?
如果?execute_statement ?INSERT 一起用,那么每个l果集都必须与表中或 column_list 中的列兼宏V?em>execute_statement 可以用来执行同一服务器或q程服务器上的存储过E。执行远E服务器中的q程Q然后将l果集返回到本地服务器,q装载到本地服务器的表中。如?execute_statement 使用 READTEXT 语句q回数据Q那么每个单独的 READTEXT 语句最多可以返?1 MB (1024 KB) 的数据,也可以将 execute_statement 与扩展过E一起用,q且插入扩展q程的主U程q回的数据。不会插入不是主U程的其它线E中的输出结果?
说明 对于 SQL Server 7.0Q?em>execute_statement 不包含返?text ?image 列的扩展存储q程。这个行为是?SQL Server 早期版本变化而来的?
DEFAULT VALUES
强制新行包含为每个列所定义的默认倹{?
INSERT 新行追加到表中。若要替换表中的数据Q必d使用 INSERT 装蝲新数据之前,使用 DELETE ?TRUNCATE TABLE 语句清除现有的数据。若要修改现有行中的列|请?UPDATE。若要创建新表,q且通过一个步骤给它装载数据,请?SELECT 语句?INTO 选项?
table 变量在其作用域内可以像常规表一栯问。因此,可以像在 INSERT 语句中将行添加到表一样?table 变量。有x多信息,请参?table?
?OPENDATASOURCE 函数建立的、作为服务器名部分的四段名称可以作ؓ表源Q该表源可以出现?INSERT 语句中显C名的所有位|?
使用 uniqueidentifier 数据cd创徏的列存储Ҏ格式?16 字节二进制倹{与标识列不同,SQL Server 不会为带?uniqueidentifier 数据cd的列自动地生成倹{在插入操作q程中,带有 uniqueidentifier 数据cd的变量以及某些字W串帔R可以用于 uniqueidentifier 列(q些字符串常量的形式为:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxQ有 36 个字W,其中包括q字W。x 是十六进制数Q范围ؓ 0-9 ?a-f。)。例如,对于 uniqueidentifier 变量或列Q?F9619FF-8B86-D011-B42D-00C04FC964FF 是一个有效倹{?NEWID() 函数可以获取全局唯一?ID (GUID)?
插入行时Q可以应用下列规则:
下表昄 SET ANSI_PADDING ?OFF 时的默认操作?
数据cd
默认操作
Char
带有空格的值填充到已定义的列宽?
Varchar
删除最后的非空格字W后面的NI格Q而对于只q格组成的字符Ԍ一直删除到只留下一个空格字W?
Varbinary
删除N的零?/p>
在本地和q程分区视图上,忽略 INSERT 语句?SET ROWCOUNT 选项的设|。而且Q当兼容U别讄?80 Ӟ?SQL Server 2000 中的q程表上也不支持 INSERT 语句?SET ROWCOUNT 选项?
当ؓ表或视图?INSERT 操作定义?INSTEAD-OF 触发器时Q该触发器就会执?INSERT 语句中的 instead of。以前的 SQL Server 版本只支持在 INSERT 中定义的 AFTER 触发器,以及其它数据修改语句?
如果在表辑ּ赋DE中 INSERT 语句遇到术错误Q溢出、被雉或域错误Q,那么 SQL Server 会处理这些错误,好?SET ARITHABORT ?ON 一栗批处理的其余部分将l止Qƈ且会q回一条错误信息?
默认情况下,INSERT 权限被授?sysadmin 固定服务器角色成员,db_owner ?db_datawriter 固定数据库角色成员,以及表的所有者?strong>sysadmin?strong>db_owner ?db_securityadmin 角色成员和表所有者可以将权限转让l其他用戗?
下面的示例创 T1Qƈ且插入一行?
IF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = 'T1')
DROP TABLE T1
GO
CREATE TABLE T1 ( column_1 int, column_2 varchar(30))
INSERT T1 VALUES (1, 'Row #1')
下面的示例?column_list ?VALUES 列表昑ּ地指定将被插入每个列的倹{?
IF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = 'T1')
DROP TABLE T1
GO
CREATE TABLE T1 ( column_1 int, column_2 varchar(30))
INSERT T1 (column_2, column_1) VALUES ('Row #1',1)
下面的示例创Z个带有四个列的表。INSERT 语句插入一些行Q这些行只有部分列包含倹{?
IF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = 'T1')
DROP TABLE T1
GO
CREATE TABLE T1
( column_1 int identity,
column_2 varchar(30)
CONSTRAINT default_name DEFAULT ('column default'),
column_3 int NULL,
column_4 varchar(40)
)
INSERT INTO T1 (column_4)
VALUES ('Explicit value')
INSERT INTO T1 (column_2,column_4)
VALUES ('Explicit value', 'Explicit value')
INSERT INTO T1 (column_2,column_3,column_4)
VALUES ('Explicit value',-44,'Explicit value')
SELECT *
FROM T1
前两?INSERT 语句允许为新行生成标识倹{第三个 INSERT 语句?SET IDENTITY_INSERT 语句替代列的 IDENTITY 属性,q且一个显式的值插入到标识列?
IF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = 'T1')
DROP TABLE T1
GO
CREATE TABLE T1 ( column_1 int IDENTITY, column_2 varchar(30))
INSERT T1 VALUES ('Row #1')
INSERT T1 (column_2) VALUES ('Row #2')
SET IDENTITY_INSERT T1 ON
INSERT INTO T1 (column_1,column_2)
VALUES (-99,'Explicit identity value')
SELECT *
FROM T1
在下面的CZ中,INSERT 语句指定一个视囑Q但是将新行插入该视囄基础表中。INSERT 语句?VALUES 列表的顺序必M视图的列序相匹配?
IF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = 'T1')
DROP TABLE T1
GO
IF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.VIEWS
WHERE TABLE_NAME = 'V1')
DROP VIEW V1
GO
CREATE TABLE T1 ( column_1 int, column_2 varchar(30))
GO
CREATE VIEW V1 AS SELECT column_2, column_1
FROM T1
GO
INSERT INTO V1
VALUES ('Row 1',1)
SELECT *
FROM T1
在下面的CZ中,CREATE TABLE 语句l每个列定义一个|当在 INSERT 语句中没有ؓ列指定显式的值时Q就可以使用q个倹{?INSERT 语句?DEFAULT VALUES 选项Q无L供显式的值就可以d行?
IF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = 'T1')
DROP TABLE T1
GO
CREATE DEFAULT bound_default AS 'Bound default value'
GO
CREATE TABLE T1
( column_1 int identity,
column_2 varchar(30)
CONSTRAINT default_name DEFAULT ('column default'),
column_3 timestamp,
column_4 varchar(30),
column_5 int NULL)
GO
USE master
EXEC sp_bindefault 'bound_default','T1.column_4'
INSERT INTO T1 DEFAULT VALUES
SELECT *
FROM T1
下面的示例演CZU不同的ҎQ用来从一个表获取数据Qƈ数据装载到另一个表。每U方法都Z一个多?SELECT 语句Q该语句在列列表中包含一个表辑ּ及一个文字倹{?
W一?INSERT 语句使用一?SELECT 语句直接从源?(authors) 索数据,q且结果集存储?author_sales 表。第二个 INSERT 执行一个包?SELECT 语句的过E,而第三个 INSERT ?SELECT 语句作ؓ一个文字字W串执行?
IF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'author_sales') DROP TABLE author_sales GO IF EXISTS(SELECT name FROM sysobjects WHERE name = 'get_author_sales' AND type = 'P') DROP PROCEDURE get_author_sales GO USE pubs CREATE TABLE author_sales ( data_source varchar(20), au_id varchar(11), au_lname varchar(40), sales_dollars smallmoney ) GO CREATE PROCEDURE get_author_sales AS SELECT 'PROCEDURE', authors.au_id, authors.au_lname, SUM(titles.price * sales.qty) FROM authors INNER JOIN titleauthor ON authors.au_id = titleauthor.au_id INNER JOIN titles ON titleauthor.title_id = titles.title_id INNER JOIN sales ON titles.title_id = sales.title_id WHERE authors.au_id like '8%'
GROUP BY authors.au_id, authors.au_lname
GO
--INSERT...SELECT example
USE pubs
INSERT author_sales
SELECT 'SELECT', authors.au_id, authors.au_lname,
SUM(titles.price * sales.qty)
FROM authors INNER JOIN titleauthor
ON authors.au_id = titleauthor.au_id INNER JOIN titles
ON titleauthor.title_id = titles.title_id INNER JOIN sales
ON titles.title_id = sales.title_id
WHERE authors.au_id LIKE '8%'
GROUP BY authors.au_id, authors.au_lname
--INSERT...EXECUTE procedure example
INSERT author_sales EXECUTE get_author_sales
--INSERT...EXECUTE('string') example
INSERT author_sales
EXECUTE
('
SELECT ''EXEC STRING'', authors.au_id, authors.au_lname,
SUM(titles.price * sales.qty)
FROM authors INNER JOIN titleauthor
ON authors.au_id = titleauthor.au_id INNER JOIN titles
ON titleauthor.title_id = titles.title_id INNER JOIN sales
ON titles.title_id = sales.title_id
WHERE authors.au_id like ''8%''
GROUP BY authors.au_id, authors.au_lname
')
--Show results.
SELECT * FROM author_sales
因ؓ可以?INSERT 语句中指?SELECT 语句Q所以也可以?TOP 子句用在 SELECT 语句中。下面的CZ?authors 表中最上面?10 个作者插入到名ؓ new_authors 的新表中?
IF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = 'new_authors')
DROP TABLE new_authors
GO
USE pubs
CREATE TABLE new_authors
(
au_id id,
au_lname varchar(40),
au_fname varchar(20),
phone char(12),
address varchar(40),
city varchar(20),
state char(2),
zip char(5),
contract bit
)
INSERT INTO new_authors
SELECT TOP 10 *
FROM authors
单说是如下所C?
<!-- Output sql of hibernate -->
<property name="hibernate.show_sql">true</property>
q时控制C昄如下的信?
Hibernate: select users_seq.nextval from dual
Hibernate: insert into users (username, password, age, sex, id) values (?, ?, ?, ?, ?)
可以看到 Hibernate 是用 PreparedStatement 工作? 跟我以前做的 BeanJDBC Persistence 研究目用的思\一?
一份完整的配置文g:
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- localhost mysql config -->
<property name="connection.username">root</property>
<property name="connection.url">
jdbc:mysql://localhost/test
</property>
<property name="dialect">
org.hibernate.dialect.MySQLDialect
</property>
<property name="myeclipse.connection.profile">
com.mysql.jdbc.Driver
</property>
<property name="connection.password"></property>
<property name="connection.driver_class">
com.mysql.jdbc.Driver
</property>
<!-- Output sql of hibernate -->
<property name="hibernate.show_sql">true</property>
<mapping resource="entity/User.hbm.xml"/>
</session-factory>
</hibernate-configuration>