<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
  <channel>
    <title>jiakechong</title>
    <description></description>
    <link>http://jiakechong.javaeye.com</link>
    <language>UTF-8</language>
    <copyright>Copyright 2003-2008, JavaEye.com</copyright>
    <docs>http://blogs.law.harvard.edu/tech/rss</docs>
    <generator>JavaEye - 做最棒的软件开发交流社区</generator>
      <item>
        <title>设计模式(转)</title>
        <author>jiakechong</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://jiakechong.javaeye.com">jiakechong</a>&nbsp;
          链接：<a href="http://jiakechong.javaeye.com/blog/223647" style="color:red;">http://jiakechong.javaeye.com/blog/223647</a>&nbsp;
          发表时间: 2008年08月03日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          关键字: 设计模式 <br />创建模式 <br />1.工厂方法模式（Factory Method） <br />多态性工厂模式，创建一个产品的工厂接口，把实际的工作转移到具体的子类。 <br />public class TestFactoryMethod { <br />public static void main(String[] args) { <br />AnimalFactory af=new DogFactory(); <br />Animal1 a=af.getAnimal(); <br />} <br />} <br />abstract class Animal1{} <br />class Dog1 extends Animal1{} <br />class Cat1 extends Animal1{} <br /><br />abstract class AnimalFactory{ <br />public abstract Animal1 getAnimal(); <br />} <br />class DogFactory extends AnimalFactory{ <br />public Animal1 getAnimal(){ <br />System.out.println("Dog"); <br />return new Dog1(); <br />} <br />} <br />class CatFactory extends AnimalFactory{ <br />public Animal1 getAnimal(){ <br />System.out.println("Cat"); <br />return new Cat1(); <br />} <br />} <br /><br />2.抽象工厂模式（Abstract Factory） <br />针对多个产品等级的情况，而工厂方法模式针对单一产品等级的情况。 <br />import java.awt.*; <br />import javax.swing.*; <br />import java.awt.event.*; <br />public class TestAbstractFactory { <br />public static void main(String[] args) { <br />GUIFactory fact=new SwingFactory(); <br />Frame f=fact.getFrame(); <br />Component c1=fact.getButton(); <br />Component c2=fact.getTextField(); <br /><br />f.setSize(500,300); <br />f.setLayout(new FlowLayout()); <br />f.add(c1); <br />f.add(c2); <br />f.setVisible(true); <br /><br />f.addWindowListener(new WindowAdapter(){ <br />public void windowClosing(WindowEvent e){ <br />System.exit(0); <br />} <br />}); <br />} <br />} <br />abstract class GUIFactory{ <br />public abstract Component getButton(); <br />public abstract Component getTextField(); <br />public abstract Frame getFrame(); <br />} <br />class AWTFactory extends GUIFactory{ <br />public Component getButton() { <br />return new Button("AWT Button"); <br />} <br />public Frame getFrame() { <br />return new Frame("AWT Frame"); <br />} <br />public Component getTextField() { <br />return new TextField(20); <br />} <br /><br />} <br />class SwingFactory extends GUIFactory{ <br />public Component getButton() { <br />return new JButton("Swing Button"); <br />} <br />public Frame getFrame() { <br />return new JFrame("Swing Frame"); <br />} <br />public Component getTextField() { <br />return new JTextField(20); <br />} <br />} <br />3.单例模式（Singleton） <br />系统中只有一个实例，因此构造方法应该为私有 <br /> 饿汉式：类加载时直接创建静态实例 <br /> 懒汉式：第一次需要时才创建一个实例，那么newInstance方法要加同步 <br /> 饿汉式比懒汉式要好，尽管资源利用率要差。但是不用同步。 <br />public class TestSingleton { <br />public static void main(String[] args) { <br /><br />} <br />} <br />class ClassA{ //饿汉式 <br />private static ClassA i=new ClassA(); <br />public static ClassA newInstance(){ <br />return i; <br />} <br />private ClassA(){} <br />} <br />class ClassB{ //懒汉式 <br />private static ClassB i=null; <br />public static synchronized ClassB newInstance(){ <br />if (i==null) i=new ClassB(); <br />return i; <br />} <br />private ClassB(){} <br />} <br />4.建造模式（Builder） <br />将一个对象的内部表象和建造过程分割，一个建造过程可以造出不同表象的对象。可简化为模版方法模式. <br />public class TestBuilder { <br />public static void main(String[] args) { <br />Builder b=new BuilderImpl1(); <br />Director d=new Director(b); <br /><br />Product p=d.createProduct(); <br />} <br /><br />} <br />interface Builder{ <br />void buildPart1(); <br />void buildPart2(); <br />void buildPart3(); <br />Product getProduct(); <br />} <br />class BuilderImpl1 implements Builder{ <br /><br />public void buildPart1() { <br />System.out.println("create part1"); <br />} <br /><br />public void buildPart2() { <br />System.out.println("create part2"); <br />} <br /><br />public void buildPart3() { <br />System.out.println("create part3"); <br />} <br /><br />public Product getProduct() { <br />return new Product(); <br />} <br /><br />} <br /><br />class Director{ <br />Builder b; <br />public Director(Builder b){ <br />this.b=b; <br />} <br />public Product createProduct(){ <br />b.buildPart1(); <br />b.buildPart2(); <br />b.buildPart3(); <br />return b.getProduct(); <br />} <br />} <br />class Product{} <br />5.原型模式（ProtoType） <br />通过一个原型对象来创建一个新对象（克隆）。Java中要给出Clonable接口的实现，具体类要实现这个接口，并给出clone()方法的实现细节，这就是简单原型模式的应用。 <br /> 浅拷贝：只拷贝简单属性的值和对象属性的地址 <br /> 深拷贝：拷贝本对象引用的对象，有可能会出现循环引用的情况。可以用串行化解决深拷贝。写到流里再读出来，这时会是一个对象的深拷贝结果。 <br />import java.io.*; <br />public class TestClonealbe { <br />public static void main(String[] args) throws Exception { <br />Father f=new Father(); <br /><br />User u1=new User("123456",f); <br />User u2=(User)u1.clone(); <br />System.out.println(u1==u2); <br />System.out.println(u1.f==u2.f); <br />} <br />} <br />class User implements Cloneable,Serializable{ <br />String password; <br />Father f; <br />public User(String password,Father f){ <br />this.password=password; <br />this.f=f; <br />} <br />public Object clone() throws CloneNotSupportedException { <br />//return super.clone(); <br />ObjectOutputStream out=null; <br />ObjectInputStream in=null; <br />try { <br />ByteArrayOutputStream bo=new ByteArrayOutputStream(); <br />out = new ObjectOutputStream(bo); <br />out.writeObject(this); <br />out.flush(); <br />byte[] bs=bo.toByteArray(); <br /><br />ByteArrayInputStream bi=new ByteArrayInputStream(bs); <br />in = new ObjectInputStream(bi); <br />Object o=in.readObject(); <br /><br />return o; <br />} catch (IOException e) { <br />e.printStackTrace(); <br />return null; <br />} catch (ClassNotFoundException e) { <br />e.printStackTrace(); <br />return null; <br />} <br />finally{ <br />try { <br />out.close(); <br />in.close(); <br />} catch (IOException e) { <br />e.printStackTrace(); <br />} <br />} <br />} <br />} <br />class Father implements Serializable{} <br /><br />结构模式 <br />如何把简单的类根据某种结构组装为大的系统 <br />6.适配器模式（Adapter） <br />用一个适配器类把一个接口转成另一个接口。 <br />public class TestAdapter { <br />public static void main(String[] args) { <br />USB mouse=new Mouse(); <br />PC pc=new PC(); <br />//pc.useMouse(mouse); <br />PS2 adapter=new USB2PS2Adapter(mouse); <br />pc.useMouse(adapter); <br />} <br />} <br />interface PS2{ <br />void usePs2(); <br />} <br />interface USB{ <br />void useUsb(); <br />} <br />class Mouse implements USB{ <br />public void useUsb(){ <br />System.out.println("通过USB接口工作"); <br />} <br />} <br />class PC{ <br />public void useMouse(PS2 ps2Mouse){ <br />ps2Mouse.usePs2(); <br />} <br />} <br />class USB2PS2Adapter implements PS2{ <br />private USB usb; <br />public USB2PS2Adapter(USB usb) { <br />this.usb = usb; <br />} <br />public void usePs2(){ <br />System.out.println("把对usePS2的方法调用转换成对useUSB的方法调用"); <br />usb.useUsb(); <br />} <br />} <br />7.组合模式（Composite） <br />把整体和局部的关系用树状结构描述出来，使得客户端把整体对象和局部对象同等看待。 <br />import java.util.*; <br />public class TestComposite { <br />public static void main(String[] args) { <br />Node n1=new LeafNode(3); <br />Node n2=new LeafNode(4); <br />Node n3=new LeafNode(6); <br />Node n4=new LeafNode(5); <br />Node n5=new LeafNode(2); <br />Node n6=new LeafNode(9); <br />Node n7=new LeafNode(12); <br />Node n8=new LeafNode(7); <br />Node n9=new LeafNode(8); <br />Node c1=new CompositeNode(n1,n2,n3); <br />Node c4=new CompositeNode(n8,n9); <br />Node c3=new CompositeNode(n5,c4); <br />Node c2=new CompositeNode(n4,c3); <br />Node c5=new CompositeNode(n6,n7); <br />Node root=new CompositeNode(c1,c2,c5); <br /><br />System.out.println(root.getValue()); <br />} <br />} <br />abstract class Node{ <br />public abstract int getValue(); <br />} <br />class LeafNode extends Node{ <br />int value; <br />public LeafNode(int value){ <br />this.value=value; <br />} <br />public int getValue(){ <br />return value; <br />} <br />} <br />class CompositeNode extends Node{ <br />private List&lt;Node> children=new ArrayList&lt;Node>(); <br />public CompositeNode(Node... nodes){ <br />for(Node n:nodes){ <br />children.add(n); <br />} <br />} <br />public int getValue(){ <br />int result=0; <br />for(Node n:children){ <br />result+=n.getValue(); <br />} <br />return result; <br />} <br /><br />} <br />8.装饰模式（Decorator） <br />以对客户透明的方式来扩展对象的功能。 <br />用户根据功能需求随意选取组成对象的成分，通过方法的链式调用来实现。 <br />可以给对象动态的增加功能，比继承灵活性更大。 <br />public class TestDecorator { <br />public static void main(String[] args) { <br />Teacher t1=new SimpleTeacher(); <br />Teacher t2=new CppTeacher(t1); <br />Teacher t3=new JavaTeacher(t2); <br />t3.teach(); <br />//t.teach(); <br />} <br />} <br /><br />abstract class Teacher{ <br />public abstract void teach(); <br />} <br />class SimpleTeacher extends Teacher{ <br />public void teach(){ <br />System.out.println("Good Good Study, Day Day Up"); <br />} <br />} <br />class JavaTeacher extends Teacher{ <br />Teacher teacher; <br />public JavaTeacher(Teacher t){ <br />this.teacher=t; <br />} <br />public void teach(){ <br />teacher.teach(); <br />System.out.println("Teach Java"); <br />} <br />} <br />class CppTeacher extends Teacher{ <br />Teacher teacher; <br />public CppTeacher(Teacher t){ <br />this.teacher=t; <br />} <br />public void teach(){ <br />teacher.teach(); <br />System.out.println("Teach C++"); <br />} <br />} <br />9.代理模式（Proxy） <br />用一个代理对象来作为另一个对象的代理，对客户来说是透明的。 <br />存在一个抽象主题类，具体主题类和代理主题类都继承（实现）抽象主题，代理主题类中的方法会调用具体主题类中相对应的方法。 <br /><br />10.享元模式（Flyweight Pattern） <br />对象的状态分为内蕴状态和外蕴状态。内蕴状态不随环境变化而变化，因此可以作成系统共享. <br />11.门面模式（Facade） <br />访问子系统的时候，通过一个Façade对象访问。Facade类是单例的。 <br />客户代码只需要和门面对象通信，不需要和具体子系统内部的对象通信，使得他们之间的耦合关系减弱。 <br />12.桥梁模式（Bridge） <br />将抽象和实现脱耦，使得二者可以单独变化。使得一个继承关系不承担两个变化因素.使用合成来代替继承的一种体现. <br />public YuanUser(BankAccount account) { <br />super(account); <br /><br />} <br />public void getMoney() { <br />System.out.print("人民币"); <br />account.withdraw(); <br />} <br />public void saveMoney() { <br />System.out.print("人民币"); <br />account.deposit(); <br />} <br /><br />} <br />class DollarUser extends BankUser{ <br /><br />public DollarUser(BankAccount account) { <br />super(account); <br /><br />} <br />public void getMoney() { <br />System.out.print("美元"); <br />account.withdraw(); <br />} <br />public void saveMoney() { <br />System.out.print("美元"); <br />account.deposit(); <br />} <br />} <br />行为模式 <br />描述如何在对象之间划分责任 <br />13.策略模式（Strategy） <br />如同LayoutManager和具体的布局管理器的关系，在抽象策略类中定义方法，在具体策略子类中实现。客户代码根据不同的需要选择相应的具体类，例如电子商务中多种价格算法。 <br />一种策略一旦选中，整个系统运行期是不变化的 <br />public class TestStrategy { <br />public static void main(String[] args) { <br />Strategy s1=new May1Strategy(); <br />Strategy s2=new June1Strategy(); <br />Book b=new Book(100); <br />b.setS(s2); <br /><br />System.out.println(b.getPrice()); <br /><br />} <br />} <br /><br />class Book{ <br />Strategy s; <br />public Book(double price){ <br />this.price=price; <br />} <br />private double price; <br /><br />public void setS(Strategy s) { <br />this.s = s; <br />} <br /><br />public double getPrice(){ <br />return price*s.getZheKou(); <br />} <br /><br />} <br /><br />interface Strategy{ <br />double getZheKou(); <br />} <br />class May1Strategy implements Strategy{ <br />public double getZheKou(){ <br />return 0.8; <br />} <br />} <br />class June1Strategy implements Strategy{ <br />public double getZheKou(){ <br />return 0.7; <br />} <br />} <br />14.模板方法（Template Method） <br />准备一个抽象类，把部分确定的逻辑定义在某些方法中，用其他抽象方法实现剩余的逻辑。不同子类对这些逻辑有不同的实现。 <br />用法：定义多个抽象操作，定义并实现一个模板方法，将步骤放在这个具体方法里，推迟到子类实现。子类可以改变父类的可变部分，但不能改变模板方法所代表的顶级逻辑。 <br />public class TestTemplateMethod { <br />public static void main(String[] args) { <br />XiaoPin xp=new DaPuKe(); <br />xp.act(); <br />} <br />} <br />abstract class XiaoPin{ <br />public abstract void jiaoLiu(); <br />public abstract void xuShi(); <br />public abstract void gaoXiao(); <br />public abstract void shanQing(); <br />public final void act(){ <br />jiaoLiu(); <br />xuShi(); <br />gaoXiao(); <br />shanQing(); <br />} <br />} <br />class DaPuKe extends XiaoPin{ <br />public void jiaoLiu(){ <br />System.out.println("顺口溜"); <br />} <br />public void xuShi(){ <br />System.out.println("火车除夕，老同学见面"); <br />} <br />public void gaoXiao(){ <br />System.out.println("名片当作扑克"); <br />} <br />public void shanQing(){ <br />System.out.println("马家军"); <br />} <br />} <br />15.观察者模式（Observer） <br />多个观察者同时监听某一主题对象，这个主题对象状态发生变化时，会通知所有观察者对象，使他们自动更新自己。在低耦合的对象间完成协调。 <br />Java中的事件模型就是一个应用。 <br /><br />16.迭代器模式（Iterator） <br />类似于集合中的Iterator，使用迭代器来统一不同集合对象的遍历方式，隐藏内部细节，用一个抽象迭代器，每个具体的集合类来实现特有的迭代器。 <br />public class TestIterator { <br />public static void main(String[] args) { <br />Stack s=new Stack(); <br />s.push("Liucy"); <br />s.push("Huxz"); <br />s.push("George"); <br /><br />LinkedList l=new LinkedList(); <br />l.addFirst("Liucy"); <br />l.addFirst("Huxz"); <br />l.addFirst("George"); <br /><br />print(l.iterator()); <br />} <br /><br />public static void print(Itr it){ <br />while(it.hasNext()){ <br />System.out.println(it.next()); <br />} <br />} <br />} <br />interface Itr{ <br />boolean hasNext(); <br />Object next(); <br />} <br />class Stack{ <br />Object[] os=new Object[10]; <br />int index=0; <br />private void expand(){ <br />Object[] os2=new Object[os.length*2]; <br />System.arraycopy(os,0,os2,0,os.length); <br />os=os2; <br />} <br />public void push(Object o){ <br />if (index==os.length) expand(); <br />os[index]=o; <br />index++; <br />} <br />public Object pop(){ <br />index--; <br />Object o=os[index]; <br />os[index]=null; <br />return o; <br />} <br />private class StackItr implements Itr{ <br />int cursor=0; <br />public boolean hasNext(){ <br />return cursor&lt;index; <br />} <br />public Object next(){ <br />return os[cursor++]; <br />} <br />} <br />public Itr iterator(){ <br />return new StackItr(); <br />} <br />} <br /><br />class LinkedList{ <br />private class Node{ <br />Object o; <br />Node next; <br />public Node(Object o){ <br />this.o=o; <br />} <br />public void setNext(Node next){ <br />this.next=next; <br />} <br />public Node getNext(){ <br />return this.next; <br />} <br />} <br /><br />Node head; <br />public void addFirst(Object o){ <br />Node n=new Node(o); <br />n.setNext(head); <br />head=n; <br />} <br />public Object removeFirst(){ <br />Node n=head; <br />head=head.getNext(); <br />return n.o; <br />} <br /><br />class LinkedListItr implements Itr{ <br />Node currentNode=head; <br />public boolean hasNext(){ <br />return this.currentNode!=null; <br />} <br />public Object next(){ <br />Node n=currentNode; <br />currentNode=currentNode.getNext(); <br />return n.o; <br />} <br />} <br />public Itr iterator(){ <br />return new LinkedListItr(); <br />} <br />} <br />17.责任链（Chain of Responsibility） <br />多个处理器对象连成一串，请求在这条链上传递，由该处理这个请求的处理器来处理。发出请求的客户端并不知道哪个对象处理请求。 <br />public class TestChain { <br />public static void main(String[] args) { <br />String pass1="123456"; <br />String pass2="123456"; <br />String personId="123456789012345678"; <br />String email="huxz@tarena.com.cn"; <br /><br />register(pass1,pass2,personId,email); <br /><br />} <br />public static void register(String pass1,String pass2,String personId,String email){ <br />Filter f1=new PasswordFilter1(); <br />Filter f2=new PasswordFilter2(); <br />Filter f3=new PersonIdFilter(); <br />Filter f4=new EmailFilter(); <br /><br />f1.setNext(f2); <br />f2.setNext(f3); <br />f3.setNext(f4); <br /><br />System.out.println(f1.doFilter(pass1,pass2,personId,email)); <br />} <br />} <br />abstract class Filter{ <br />Filter next=null; <br />public Filter getNext() { <br />return next; <br />} <br />public void setNext(Filter next) { <br />this.next = next; <br />} <br />public String doFilter(String pass1,String pass2,String personId,String email){ <br />if (next==null) return "成功"; <br />else return next.doFilter(pass1,pass2,personId,email); <br />} <br />} <br />class PasswordFilter1 extends Filter{ <br />public String doFilter(String pass1,String pass2,String personId,String email){ <br />if (!(pass1.equals(pass2))) <br />return "两次密码输入不一致"; <br />else return super.doFilter(pass1,pass2,personId,email); <br />} <br />} <br />class PasswordFilter2 extends Filter{ <br />public String doFilter(String pass1,String pass2,String personId,String email){ <br />if (pass1.length()!=6) <br />return "密码长度必须为6"; <br />else return super.doFilter(pass1,pass2,personId,email); <br />} <br />} <br />class PersonIdFilter extends Filter{ <br />public String doFilter(String pass1,String pass2,String personId,String email){ <br />if (personId.length()!=15 && personId.length()!=18) <br />return "身份证号码非法"; <br />else return super.doFilter(pass1,pass2,personId,email); <br />} <br />} <br />class EmailFilter extends Filter{ <br />public String doFilter(String pass1,String pass2,String personId,String email){ <br />int i1=email.indexOf("@"); <br />int i2=email.indexOf("."); <br />if (i1==-1 || i2==-1 || i2-i1&lt;=1 || i1==0 || i2==email.length()-1) <br />return "email非法"; <br />else return super.doFilter(pass1,pass2,personId,email); <br />} <br />} <br />18.状态模式（State） <br />在对象内部状态改变时改变其行为。把所研究的对象的行为封装在不同的状态对象中。 <br />import static java.lang.System.*; <br />public class TestState { <br />public static void main(String[] args) { <br />BBSUser u=new BBSUser(); <br />u.setState(new GuestState()); <br />u.publish(); <br /><br />u.setState(new NormalState()); <br />u.publish(); <br /><br />u.setState(new BlockedState()); <br />u.publish(); <br /><br />u.setState(new NewComerState()); <br />u.publish(); <br />} <br />} <br />class BBSUser{ <br />private State state; <br />public void setState(State state){ <br />this.state=state; <br />} <br />public void publish(){ <br />state.action(); <br />} <br />} <br />abstract class State{ <br />public abstract void action(); <br />} <br />class GuestState extends State{ <br />public void action(){ <br />out.println("您处在游客状态，请先登录"); <br />} <br />} <br />class NormalState extends State{ <br />public void action(){ <br />out.println("您处在正常状态，文章发表成功"); <br />} <br />} <br />class BlockedState extends State{ <br />public void action(){ <br />out.println("您处在被封状态，文章发表失败"); <br />} <br />} <br />class NewComerState extends State{ <br />public void action(){ <br />out.println("您是新手，请先学习一下，3天后再来"); <br />} <br />} <br /><br />class StateFactory{ <br />public static State createState(int i){ <br />if (i==1) return new GuestState(); <br />else return new NormalState(); <br />} <br />} <br />19.备忘录模式（Memento） <br />备忘录对象用来存储另一个对象的快照对象，保存其内部状态，使得可以随时恢复。 <br />备忘录角色：保存发起人对象的内部状态，保护内容不被除发起人对象之外的对象获取。窄接口：负责人对象和其他对象看到的接口，只允许把备忘录对象传给其他对象。宽接口：发起人能看到的接口，允许读取内部状态。 <br />发起人角色：创建并使用备忘录对象来保存其状态 <br />负责人角色：负责保存备忘录对象。 <br /> 白箱实现：备忘录类对其他类也可见，这样发起人的状态可能会存在安全问题。 <br /> 黑箱实现：把备忘录类作成发起人的内部类，对外提供一个标识接口。 <br />public class TestMemento{ <br />public static void main(String[] args){ <br />Originator ori=new Originator(); <br />Caretaker c=new Caretaker(); <br />ori.setState("State 1"); <br />IFMemento m=ori.createMemento(); <br />c.save(m); <br />ori.setState("State 2"); <br />m=c.retrieve(); <br />ori.restore(m); <br />System.out.println("Now State:"+ori.getState()); <br /><br />} <br />} <br />class Originator{ <br />String state; <br />public void setState(String s){ <br />state=s; <br />System.out.println("State change to: "+s); <br />} <br />public String getState(){ <br />return this.state; <br />} <br />public IFMemento createMemento(){ <br />return new Memento(state); <br />} <br />public void restore(IFMemento m){ <br />Memento mt=(Memento)m; <br />this.state=mt.getState(); <br />} <br />private class Memento implements IFMemento{ <br />private String state; <br />public Memento(String s){ <br />this.state=s; <br />} <br />public String getState(){ <br />return this.state; <br />} <br />} <br />} <br /><br />class Caretaker{ <br />private IFMemento m; <br />public IFMemento retrieve(){ <br />return this.m; <br />} <br />public void save(IFMemento m){ <br />this.m=m; <br />} <br />} <br /><br />interface IFMemento{ <br /><br />}
          <br/>
          <span style="color:red;">
            <a href="http://jiakechong.javaeye.com/blog/223647#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sun, 03 Aug 2008 17:30:52 +0800</pubDate>
        <link>http://jiakechong.javaeye.com/blog/223647</link>
        <guid>http://jiakechong.javaeye.com/blog/223647</guid>
      </item>
      <item>
        <title>学习Java多线程和并发的最好资料(转)</title>
        <author>jiakechong</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://jiakechong.javaeye.com">jiakechong</a>&nbsp;
          链接：<a href="http://jiakechong.javaeye.com/blog/223393" style="color:red;">http://jiakechong.javaeye.com/blog/223393</a>&nbsp;
          发表时间: 2008年08月02日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          [分享]学习Java多线程和并发的最好资料<br />一直以来经常上IBM的developWorkers。<br /><br /> <br /><br />上面有非常丰富的资料。下面是java多线程和并发编程的专题http://www.ibm.com/developerworks/cn/java/j-concurrent/。<br /><br /> <br /><br />推荐给大家学习。
          <br/>
          <span style="color:red;">
            <a href="http://jiakechong.javaeye.com/blog/223393#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sat, 02 Aug 2008 18:06:51 +0800</pubDate>
        <link>http://jiakechong.javaeye.com/blog/223393</link>
        <guid>http://jiakechong.javaeye.com/blog/223393</guid>
      </item>
      <item>
        <title>华为公司 java 面试题(转)</title>
        <author>jiakechong</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://jiakechong.javaeye.com">jiakechong</a>&nbsp;
          链接：<a href="http://jiakechong.javaeye.com/blog/222056" style="color:red;">http://jiakechong.javaeye.com/blog/222056</a>&nbsp;
          发表时间: 2008年07月31日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          第一部分：选择题<br />QUESTION NO: 1<br />1、<br /><br /><br />public   class  Test {<br />     public   static   void  changeStr(String str){<br />        str = " welcome " ;<br />    }<br />     public   static   void  main(String[] args) {<br />        String str = " 1234 " ;<br />        changeStr(str);<br />        System.out.println(str);<br />    }<br />}<br /><br />Please write the output result ：<br /><br />QUESTION NO:2<br /><br />1. public class Test {<br />2. static boolean foo(char c) {<br />3. System.out.print(c);<br />4. return true;<br />5. }<br />6. public static void main( String[] argv ) {<br />7. int i =0;<br />8. for ( foo('A'); foo('B')&&(i&lt;2); foo('C')){<br />9. i++ ;<br />10. foo('D');<br />12. }<br />13. }<br />14. }<br /><br /><br />What is the result?<br />A. ABDCBDCB<br />B. ABCDABCD<br />C. Compilation fails.<br />D. An exception is thrown at runtime.<br /><br /><br />QUESTION NO: 3<br />1. class A {<br />2. protected int method1(int a, int b) { return 0; }<br />3. }<br /><br />Which two are valid in a class that extends class A? (Choose two)<br />A. public int method1(int a, int b) { return 0; }<br />B. private int method1(int a, int b) { return 0; }<br />C. private int method1(int a, long b) { return 0; }<br />D. public short method1(int a, int b) { return 0; }<br />E. static protected int method1(int a, int b) { return 0; }<br /><br />QUESTION NO: 4<br />1. public class Outer{<br />2. public void someOuterMethod() {<br />3. // Line 3<br />4. }<br />5. public class Inner{}<br />6. public static void main( String[]argv ) {<br />7. Outer o = new Outer();<br />8. // Line 8<br />9. }<br />10. }<br /><br />Which instantiates an instance of Inner?<br />A. new Inner(); // At line 3<br />B. new Inner(); // At line 8<br />C. new o.Inner(); // At line 8<br />D. new Outer.Inner(); // At line 8//new Outer().new Inner()<br /><br />QUESTION NO: 5<br />Which method is used by a servlet to place its session ID in a URL that is written to the servlet’s response output stream?<br />A. The encodeURL method of the HttpServletRequest interface.<br />B. The encodeURL method of the HttpServletResponse interface.<br />C. The rewriteURL method of the HttpServletRequest interface.<br />D. The rewriteURL method of the HttpServletResponse interface.<br /><br /><br />QUESTION NO: 6<br />Which two are equivalent? (Choose two)<br />A. &lt;%= YoshiBean.size%><br />B. &lt;%= YoshiBean.getSize()%><br />C. &lt;%= YoshiBean.getProperty("size")%><br />D. &lt;jsp:getProperty id="YoshiBean" param="size"/><br />E. &lt;jsp:getProperty name="YoshiBean" param="size"/><br />F. &lt;jsp:getProperty id="YoshiBean" property="size"/><br />G. &lt;jsp:getProperty name="YoshiBean" property="size"/><br /><br /><br />QUESTION NO: 7<br />Which of the following statements regarding the lifecycle of a session bean are correct?<br />1.  java.lang.IllegalStateException is thrown if SessionContext.getEJBObject() is invoked when a stateful session bean instance is passivated.<br />2.  SessionContext.getRollbackOnly() does not throw an exception when a session bean with bean-managed transaction demarcation is activated.<br />3.  An exception is not thrown when SessionContext.getUserTransaction() is called in the afterBegin method of a bean with container-managed transactions.<br />4.  JNDI access to java:comp/env is permitted in all the SessionSynchronization methods of a stateful session bean with container-managed transaction demarcation.<br />5.  Accessing resource managers in the SessionSynchronization.afterBegin method of a stateful session bean with bean-managed transaction does not throw an exception.<br /><br /><br />第二部分：概念题<br />1．    描述Struts体系结构？对应各个部分的开发工作主要包括哪些？<br /><br /> <br /><br />2．    XML包括哪些解释技术，区别是什么？<br /><br /> <br /><br /><br />3．    JSP有哪些内置对象和动作？它们的作用分别是什么？<br /><br /> <br /><br /><br />4、SQL问答题<br />SELECT * FROM TABLE<br />和<br />SELECT * FROM TABLE<br />WHERE NAME LIKE '%%' AND ADDR LIKE '%%'<br />AND (1_ADDR LIKE '%%' OR 2_ADDR LIKE '%%'<br />OR 3_ADDR LIKE '%%' OR 4_ADDR LIKE '%%' )<br />的检索结果为何不同？<br /><br /> <br /><br />5、SQL问答题<br />表结构：<br />1、    表名：g_cardapply<br />字段(字段名/类型/长度)：<br />g_applyno        varchar   8；//申请单号（关键字）<br />g_applydate     bigint     8；//申请日期<br />g_state        varchar     2；//申请状态<br /><br />2、    表名：g_cardapplydetail<br />字段(字段名/类型/长度)：<br />g_applyno        varchar     8；//申请单号（关键字）<br />g_name        varchar     30；//申请人姓名<br />g_idcard        varchar     18；//申请人身份证号<br />g_state        varchar     2；//申请状态<br /><br />其中，两个表的关联字段为申请单号。<br /><br />题目：<br />1、    查询身份证号码为440401430103082的申请日期<br /><br />2、    查询同一个身份证号码有两条以上记录的身份证号码及记录个数<br /><br />3、    将身份证号码为440401430103082的记录在两个表中的申请状态均改为07<br /><br />4、    删除g_cardapplydetail表中所有姓李的记录
          <br/>
          <span style="color:red;">
            <a href="http://jiakechong.javaeye.com/blog/222056#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 31 Jul 2008 09:43:10 +0800</pubDate>
        <link>http://jiakechong.javaeye.com/blog/222056</link>
        <guid>http://jiakechong.javaeye.com/blog/222056</guid>
      </item>
      <item>
        <title>JVM，反射与动态代理</title>
        <author>jiakechong</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://jiakechong.javaeye.com">jiakechong</a>&nbsp;
          链接：<a href="http://jiakechong.javaeye.com/blog/221140" style="color:red;">http://jiakechong.javaeye.com/blog/221140</a>&nbsp;
          发表时间: 2008年07月29日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          （从csdn的blog转来） <br /><br />Java 程序的工作机制： Java 对象都以单独的 class 文件存在， java 虚拟机将其载入并执行其虚拟机指令。<br /><br /> <br /><br />Java 虚拟机查找这些 java 对象：<br /><br />java 虚拟机根据 class path 来查找 java 对象，而虚拟机的 class path 又分为三层：<br /><br />bootstrap ： sun.boot.class.path<br /><br />extension: java.ext.dirs<br /><br />application: java.class.path<br /><br />三个 class path 各有对应的 classloader 。由上而下形成父子关系<br /><br />当程序中调用 new 指令，或者 ClassLoader.load 方法时。其顺序如下：<br /><br />1.       首先查看 application 的 classloader 中是否已有对应的 class 缓存，如果有则返回，并根据 class 分配内存。如果没有，接下一步。<br /><br />2.       首先查看 extension 的 classloader 中是否已有对应的 class 缓存，如果有则返回，并根据 class 分配内存。如果没有，接下一步。<br /><br />3.       首先查看 bootstrap 的 classloader 中是否已有对应的 class 缓存，如果有则返回，并根据 class 分配内存。如果没有，接下一步。<br /><br />4.       由 bootstrap 的 classloader 在其 class path 中试图加载该 class ，如果有，则将该 class 放入 cache 中，并返回。如果没有，接下一步。<br /><br />5.       由 extension 的 classloader 在其 class path 中试图加载该 class ，如果有，则将该 class 放入 cache 中，并返回。如果没有，接下一步。<br /><br />6.       由 application 的 classloader 在其 class path 中试图加载该 class ，如果有，则将该 class 放入 cache 中，并返回。如果没有，则抛出 ClassNotFound 的 exception 。<br /><br /> <br /><br />Java 虚拟机加载这些 java 对象：<br /><br />每个 java 虚拟机都在其启动时产生一个唯一的 class heap ，并把所有的 class instance 都分配在其中。其中每个类实例的信息又分两部分， fields 域和 methods 域。每个类实例各自拥有 fields ，但同一个类的不同实例共享 methods<br /><br /> <br /><br />反射<br /><br />JVM 对反射的处理<br /><br />简单例子代码：<br /><br />import java.lang.reflect.InvocationHandler;<br /><br />import java.lang.reflect.Method;<br /><br />import java.lang.reflect.InvocationTargetException;<br /><br />import java.io.IOException;<br /><br /> <br /><br />public class Main {<br /><br />    public static void main(String[] args){<br /><br />        TempImpl t1 = new TempImpl("temp1");<br /><br />        try {<br /><br />            Method t1Talk = t1.getClass().getMethod("Talk", new Class[0]) ;<br /><br />            t1Talk.invoke(t1, null);<br /><br />        } catch (NoSuchMethodException e) {<br /><br />            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.<br /><br />        } catch (IllegalAccessException e) {<br /><br />            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.<br /><br />        } catch (InvocationTargetException e) {<br /><br />            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.<br /><br />        }<br /><br />        try {<br /><br />            System.in.read();<br /><br />        } catch (IOException e) {<br /><br />            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.<br /><br />        }<br /><br />    }<br /><br />}<br /><br />复杂例子代码：<br /><br />import java.lang.reflect.InvocationHandler;<br /><br />import java.lang.reflect.Method;<br /><br />import java.lang.reflect.InvocationTargetException;<br /><br />import java.io.IOException;<br /><br /> <br /><br />public class Main {<br /><br />    public static void main(String[] args){<br /><br />        TempImpl t1 = new TempImpl("temp1");<br /><br />        TempImpl t2 = new TempImpl("temp2");<br /><br />        Temp2 temp2 = new Temp2();<br /><br />        try {<br /><br />            Method t1Talk = t1.getClass().getMethod("Talk", new Class[0]) ;<br /><br />            Method t2Talk = t2.getClass().getMethod("Talk", new Class[0]) ;<br /><br />            t1Talk.invoke(t2, null);<br /><br />            t2Talk.invoke(t1, null);<br /><br />            if(t1Talk.equals(t2Talk)){<br /><br />                System.out.println("equals");<br /><br />            }<br /><br />           else{<br /><br />                System.out.println("not equals");<br /><br />            }<br /><br />            if(t1Talk==t2Talk){<br /><br />                System.out.println("ref equals");<br /><br />            }<br /><br />           else{<br /><br />                System.out.println("ref not equals");<br /><br />            }<br /><br />            t2Talk.invoke(temp2, null);<br /><br />        } catch (NoSuchMethodException e) {<br /><br />            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.<br /><br />        } catch (IllegalAccessException e) {<br /><br />            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.<br /><br />        } catch (InvocationTargetException e) {<br /><br />            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.<br /><br />        }<br /><br />        try {<br /><br />            System.in.read();<br /><br />        } catch (IOException e) {<br /><br />            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.<br /><br />        }<br /><br />    }<br /><br />}<br /><br /> <br /><br />分析： java 虚拟机把每个 methods 当作一个执行单元。该执行单元带有两种签名：类签名和属性签名（ public ， static 等）。 反射的第一步，验证签名的合法性。验证通过后，顺序执行该 method 中的指令，当需要访问类实例的 fields 和传入参数时，由虚拟机注入。<br /><br /> <br /><br />动态代理<br /><br />Sun 对动态代理的说明：<br /><br />一个简单例子代码：<br /><br />动态代理的内部实现——代码生成：<br /><br />研究 JDK 源代码，发现在 Proxy 的 sun 实现中调用了 sun.misc.ProxyGenerator 类的 generateProxyClass( proxyName, interfaces) 方法，其返回值为 byte[] 和 class 文件的内存类型一致。于是做如下试验：<br /><br />public class  ProxyClassFile{<br /><br />       public static void main(String[] args){<br /><br />              String proxyName = "TempProxy";<br /><br />        TempImpl t = new TempImpl("proxy");<br /><br />              Class[] interfaces =t.getClass().getInterfaces();<br /><br />             <br /><br />              byte[] proxyClassFile = ProxyGenerator.generateProxyClass(<br /><br />                  proxyName, interfaces);<br /><br />        File f = new File("classes/TempProxy.class");<br /><br />        try {<br /><br />            FileOutputStream fos = new FileOutputStream(f);<br /><br />            fos.write(proxyClassFile);<br /><br />            fos.flush();<br /><br />            fos.close();<br /><br />        } catch (FileNotFoundException e) {<br /><br />            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.<br /><br />        } catch (IOException e) {<br /><br />            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.<br /><br />        }<br /><br />       }<br /><br />}<br /><br />运行该类，到 class 文件夹下，利用反编译技术，发现原来其采用了代码生产技术：<br /><br /> <br /><br />public interface Temp{<br /><br />       public void Talk();<br /><br />       public void Run();<br /><br />}<br /><br />import java.lang.reflect.*;<br /><br /> <br /><br />public final class TempProxy extends Proxy<br /><br />    implements Temp{<br /><br /> <br /><br />    private static Method m4;<br /><br />    private static Method m2;<br /><br />    private static Method m0;<br /><br />    private static Method m3;<br /><br />    private static Method m1;<br /><br /> <br /><br />    public TempProxy(InvocationHandler invocationhandler)   {<br /><br />        super(invocationhandler);<br /><br />    }<br /><br /> <br /><br />    public final void Run()    {<br /><br />        try {<br /><br />            h.invoke(this, m4, null);<br /><br />            return;<br /><br />        }<br /><br />        catch(Error _ex) { }<br /><br />        catch(Throwable throwable)  {<br /><br />            throw new UndeclaredThrowableException(throwable);<br /><br />        }<br /><br />    }<br /><br /> <br /><br />    public final String toString(){<br /><br />        try{<br /><br />            return (String)h.invoke(this, m2, null);<br /><br />        }<br /><br />        catch(Error _ex) { }<br /><br />        catch(Throwable throwable)  {<br /><br />            throw new UndeclaredThrowableException(throwable);<br /><br />        }<br /><br />        return "";<br /><br />    }<br /><br /> <br /><br />    public final int hashCode() {<br /><br />        try {<br /><br />            return ((Integer)h.invoke(this, m0, null)).intValue();<br /><br />        }<br /><br />        catch(Error _ex) { }<br /><br />        catch(Throwable throwable){<br /><br />            throw new UndeclaredThrowableException(throwable);<br /><br />        }<br /><br />        return 123;<br /><br />    }<br /><br /> <br /><br />    public final void Talk(){<br /><br />        try{<br /><br />            h.invoke(this, m3, null);<br /><br />            return;<br /><br />        }<br /><br />        catch(Error _ex) { }<br /><br />        catch(Throwable throwable) {<br /><br />            throw new UndeclaredThrowableException(throwable);<br /><br />        }<br /><br />    }<br /><br /> <br /><br />    public final boolean equals(Object obj) {<br /><br />        try  {<br /><br />            return ((Boolean)h.invoke(this, m1, new Object[] {<br /><br />                obj<br /><br />            })).booleanValue();<br /><br />        }<br /><br />        catch(Error _ex) { }<br /><br />        catch(Throwable throwable) {<br /><br />            throw new UndeclaredThrowableException(throwable);<br /><br />        }<br /><br />        return false;<br /><br />    }<br /><br /> <br /><br />    static{<br /><br />        try{<br /><br />     m4 = Class.forName("Temp").getMethod("Run", new Class[0]);<br /><br />     m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);<br /><br />     m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);<br /><br />     m3 = Class.forName("Temp").getMethod("Talk", new Class[0]);<br /><br />     m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] {<br /><br />                Class.forName("java.lang.Object")<br /><br />            });<br /><br />        }<br /><br />        catch(NoSuchMethodException nosuchmethodexception) {<br /><br />            throw new NoSuchMethodError(nosuchmethodexception.getMessage());<br /><br />        }<br /><br />        catch(ClassNotFoundException classnotfoundexception) {<br /><br />            throw new NoClassDefFoundError(classnotfoundexception.getMessage());<br /><br />        }<br /><br />    }<br /><br />}
          <br/>
          <span style="color:red;">
            <a href="http://jiakechong.javaeye.com/blog/221140#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 29 Jul 2008 16:15:31 +0800</pubDate>
        <link>http://jiakechong.javaeye.com/blog/221140</link>
        <guid>http://jiakechong.javaeye.com/blog/221140</guid>
      </item>
      <item>
        <title>别人的blog不能收藏，mysql</title>
        <author>jiakechong</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://jiakechong.javaeye.com">jiakechong</a>&nbsp;
          链接：<a href="http://jiakechong.javaeye.com/blog/211644" style="color:red;">http://jiakechong.javaeye.com/blog/211644</a>&nbsp;
          发表时间: 2008年07月04日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          关键字: mysql<br />启动：net start mySql;<br />　　进入：mysql -u root -p/mysql -h localhost -u root -p databaseName;<br />　　列出数据库：show databases;<br />　　选择数据库：use databaseName;<br />　　列出表格：show tables；<br />　　显示表格列的属性：show columns from tableName；<br />　　建立数据库：source fileName.txt;<br />　　匹配字符：可以用通配符_代表任何一个字符，％代表任何字符串;<br />　　增加一个字段：alter table tabelName add column fieldName dateType;<br />　　增加多个字段：alter table tabelName add column fieldName1 dateType,add columns fieldName2 dateType;<br />　　多行命令输入:注意不能将单词断开;当插入或更改数据时，不能将字段的字符串展开到多行里，否则硬回车将被储存到数据中;<br />　　增加一个管理员帐户：grant all on *.* to user@localhost identified by "password";<br />　　每条语句输入完毕后要在末尾填加分号';'，或者填加'\g'也可以；<br />　　查询时间：select now();<br />　　查询当前用户：select user();<br />　　查询数据库版本：select version();<br />　　查询当前使用的数据库：select database();<br />　　<br />　　1、删除student_course数据库中的students数据表：<br />　　rm -f student_course/students.*<br />　　<br />　　2、备份数据库：(将数据库test备份)<br />　　mysqldump -u root -p test>c:\test.txt<br />　　备份表格：(备份test数据库下的mytable表格)<br />　　mysqldump -u root -p test mytable>c:\test.txt<br />　　将备份数据导入到数据库：(导回test数据库)<br />　　mysql -u root -p test<br />　　<br />　　3、创建临时表：(建立临时表zengchao)<br />　　create temporary table zengchao(name varchar(10));<br />　　<br />　　4、创建表是先判断表是否存在<br />　　create table if not exists students(……);<br />　　<br />　　5、从已经有的表中复制表的结构<br />　　create table table2 select * from table1 where 1&lt;>1;<br />　　<br />　　6、复制表<br />　　create table table2 select * from table1;<br />　　<br />　　7、对表重新命名<br />　　alter table table1 rename as table2;<br />　　<br />　　8、修改列的类型<br />　　alter table table1 modify id int unsigned;//修改列id的类型为int unsigned<br />　　alter table table1 change id sid int unsigned;//修改列id的名字为sid，而且把属性修改为int unsigned<br />　　<br />　　9、创建索引<br />　　alter table table1 add index ind_id (id);<br />　　create index ind_id on table1 (id);<br />　　create unique index ind_id on table1 (id);//建立唯一性索引<br />　　<br />　　10、删除索引<br />　　drop index idx_id on table1;<br />　　alter table table1 drop index ind_id;<br />　　<br />　　11、联合字符或者多个列(将列id与":"和列name和"="连接)<br />　　select concat(id,':',name,'=') from students;<br />　　<br />　　12、limit(选出10到20条)&lt;第一个记录集的编号是0><br />　　select * from students order by id limit 9,10;<br />　　<br />　　13、MySQL不支持的功能<br />　　事务，视图，外键和引用完整性，存储过程和触发器<br />　　<br />　　<br />　　14、MySQL会使用索引的操作符号<br />　　&lt;,&lt;=,>=,>,=,between,in,不带%或者_开头的like<br />　　<br />　　15、使用索引的缺点<br />　　1)减慢增删改数据的速度；<br />　　2）占用磁盘空间；<br />　　3）增加查询优化器的负担；<br />　　当查询优化器生成执行计划时，会考虑索引，太多的索引会给查询优化器增加工作量，导致无法选择最优的查询方案；<br />　　<br />　　16、分析索引效率<br />　　方法：在一般的SQL语句前加上explain；<br />　　分析结果的含义：<br />　　1）table：表名；<br />　　2）type：连接的类型，(ALL/Range/Ref)。其中ref是最理想的；<br />　　3）possible_keys：查询可以利用的索引名；<br />　　4）key：实际使用的索引；<br />　　5）key_len：索引中被使用部分的长度（字节）；<br />　　6）ref：显示列名字或者"const"（不明白什么意思）；<br />　　7）rows：显示MySQL认为在找到正确结果之前必须扫描的行数；<br />　　8）extra：MySQL的建议；<br />　　<br />　　17、使用较短的定长列<br />　　1）尽可能使用较短的数据类型；<br />　　2）尽可能使用定长数据类型；<br />　　a）用char代替varchar，固定长度的数据处理比变长的快些；<br />　　b）对于频繁修改的表，磁盘容易形成碎片，从而影响数据库的整体性能；<br />　　c）万一出现数据表崩溃，使用固定长度数据行的表更容易重新构造。使用固定长度的数据行，每个记录的开始位置都是固定记录长度的倍数，可以很容易被检测到，但是使用可变长度的数据行就不一定了；<br />　　d）对于MyISAM类型的数据表，虽然转换成固定长度的数据列可以提高性能，但是占据的空间也大；<br />　　<br />　　18、使用not null和enum<br />　　尽量将列定义为not null，这样可使数据的出来更快，所需的空间更少，而且在查询时，MySQL不需要检查是否存在特例，即null值，从而优化查询；<br />　　如果一列只含有有限数目的特定值，如性别，是否有效或者入学年份等，在这种情况下应该考虑将其转换为enum列的值，MySQL处理的更快，因为所有的enum值在系统内都是以标识数值来表示的；<br />　　<br />　　19、使用optimize table<br />　　对于经常修改的表，容易产生碎片，使在查询数据库时必须读取更多的磁盘块，降低查询性能。具有可变长的表都存在磁盘碎片问题，这个问题对 blob数据类型更为突出，因为其尺寸变化非常大。可以通过使用optimize table来整理碎片，保证数据库性能不下降，优化那些受碎片影响的数据表。 optimize table可以用于MyISAM和BDB类型的数据表。实际上任何碎片整理方法都是用mysqldump来转存数据表，然后使用转存后的文件并重新建数据表；<br />　　<br />　　20、使用procedure analyse()<br />　　可以使用procedure analyse()显示最佳类型的建议，使用很简单，在select语句后面加上procedure analyse()就可以了；例如：<br />　　select * from students procedure analyse();<br />　　select * from students procedure analyse(16,256);<br />　　第二条语句要求procedure analyse()不要建议含有多于16个值，或者含有多于256字节的enum类型，如果没有限制，输出可能会很长；<br />　　<br />　　21、使用查询缓存<br />　　1）查询缓存的工作方式：<br />　　第一次执行某条select语句时，服务器记住该查询的文本内容和查询结果，存储在缓存中，下次碰到这个语句时，直接从缓存中返回结果；当更新数据表后，该数据表的任何缓存查询都变成无效的，并且会被丢弃。<br />　　2）配置缓存参数：<br />　　变量：query_cache _type，查询缓存的操作模式。有3中模式，0：不缓存；1：缓存查询，除非与 select sql_no_cache开头；2：根据需要只缓存那些以select sql_cache开头的查询； query_cache_size：设置查询缓存的最大结果集的大小，比这个值大的不会被缓存。<br />　　<br />　　22、调整硬件<br />　　1）在机器上装更多的内存；<br />　　2）增加更快的硬盘以减少I/O等待时间；<br />　　寻道时间是决定性能的主要因素，逐字地移动磁头是最慢的，一旦磁头定位，从磁道读则很快；<br />　　3）在不同的物理硬盘设备上重新分配磁盘活动；<br />　　如果可能，应将最繁忙的数据库存放在不同的物理设备上，这跟使用同一物理设备的不同分区是不同的，因为它们将争用相同的物理资源（磁头）。<br /><br />    * 18:03<br />    * 浏览 (1840)<br />    * 评论 (5)<br />    * 分类: 技术<br />    * 发布在 盘古党 圈子<br />    * 收藏<br />    * 相关推荐<br /><br />评论<br />xuejianshan 2007-12-11<br />你公司用的是mysql数据库吗?<br />kyo100900 2007-10-23<br />mysql有类似于SQL Server那样的backup disk的备份能力吗?<br />抛出异常的爱 2007-10-22<br />MySQL 备份和恢复<br />&lt;script language="javascript" type="text" src="misc/cr.js" />&lt;/script><br /><br />作/译者：叶金荣（Email: ），来源：http://imysql.cn，转载请注明作/译者和出处，并且不能用于商业用途，违者必究。<br /><br />日期：2006/10/01<br /><br />本文讨论 MySQL 的备份和恢复机制，以及如何维护数据表，包括最主要的两种表类型：MyISAM 和 Innodb，文中设计的 MySQL 版本为 5.0.22。<br /><br />目前 MySQL 支持的免费备份工具有：mysqldump、mysqlhotcopy，还可以用 SQL 语法进行备份：BACKUP TABLE 或者 SELECT INTO OUTFILE，又或者备份二进制日志（binlog），还可以是直接拷贝数据文件和相关的配置文件。MyISAM 表是保存成文件的形式，因此相对比较容易备份，上面提到的几种方法都可以使用。Innodb 所有的表都保存在同一个数据文件 ibdata1 中（也可能是多个文件，或者是独立的表空间文件），相对来说比较不好备份，免费的方案可以是拷贝数据文件、备份 binlog，或者用 mysqldump。<br />1、mysqldump<br />1.1 备份<br /><br />mysqldump 是采用SQL级别的备份机制，它将数据表导成 SQL 脚本文件，在不同的 MySQL 版本之间升级时相对比较合适，这也是最常用的备份方法。<br />现在来讲一下 mysqldump 的一些主要参数：<br /><br />* --compatible=name<br /><br />它告诉 mysqldump，导出的数据将和哪种数据库或哪个旧版本的 MySQL 服务器相兼容。值可以为 ansi、mysql323、mysql40、postgresql、oracle、mssql、db2、maxdb、no_key_options、 no_tables_options、no_field_options 等，要使用几个值，用逗号将它们隔开。当然了，它并不保证能完全兼容，而是尽量兼容。<br />* --complete-insert，-c<br /><br />导出的数据采用包含字段名的完整 INSERT 方式，也就是把所有的值都写在一行。这么做能提高插入效率，但是可能会受到 max_allowed_packet 参数的影响而导致插入失败。因此，需要谨慎使用该参数，至少我不推荐。<br />* --default-character-set=charset<br /><br />指定导出数据时采用何种字符集，如果数据表不是采用默认的 latin1 字符集的话，那么导出时必须指定该选项，否则再次导入数据后将产生乱码问题。<br />* --disable-keys<br /><br />告诉 mysqldump 在 INSERT 语句的开头和结尾增加 /*!40000 ALTER TABLE table DISABLE KEYS */; 和 /*!40000 ALTER TABLE table ENABLE KEYS */; 语句，这能大大提高插入语句的速度，因为它是在插入完所有数据后才重建索引的。该选项只适合 MyISAM 表。<br />* --extended-insert = true|false<br /><br />默认情况下，mysqldump 开启 --complete-insert 模式，因此不想用它的的话，就使用本选项，设定它的值为 false 即可。<br />* --hex-blob<br /><br />使用十六进制格式导出二进制字符串字段。如果有二进制数据就必须使用本选项。影响到的字段类型有 BINARY、VARBINARY、BLOB。<br />* --lock-all-tables，-x<br /><br />在开始导出之前，提交请求锁定所有数据库中的所有表，以保证数据的一致性。这是一个全局读锁，并且自动关闭 --single-transaction 和 --lock-tables 选项。<br />* --lock-tables<br /><br />它和 --lock-all-tables 类似，不过是锁定当前导出的数据表，而不是一下子锁定全部库下的表。本选项只适用于 MyISAM 表，如果是 Innodb 表可以用 --single-transaction 选项。<br />* --no-create-info，-t<br /><br />只导出数据，而不添加 CREATE TABLE 语句。<br />* --no-data，-d<br /><br />不导出任何数据，只导出数据库表结构。<br />* --opt<br /><br />这只是一个快捷选项，等同于同时添加 --add-drop-tables --add-locking --create-option --disable-keys --extended-insert --lock-tables --quick --set-charset 选项。本选项能让 mysqldump 很快的导出数据，并且导出的数据能很快导回。该选项默认开启，但可以用 --skip-opt 禁用。注意，如果运行 mysqldump 没有指定 --quick 或 --opt 选项，则会将整个结果集放在内存中。如果导出大数据库的话可能会出现问题。<br />* --quick，-q<br /><br />该选项在导出大表时很有用，它强制 mysqldump 从服务器查询取得记录直接输出而不是取得所有记录后将它们缓存到内存中。<br />* --routines，-R<br /><br />导出存储过程以及自定义函数。<br />* --single-transaction<br /><br />该选项在导出数据之前提交一个 BEGIN SQL语句，BEGIN 不会阻塞任何应用程序且能保证导出时数据库的一致性状态。它只适用于事务表，例如 InnoDB 和 BDB。<br />本选项和 --lock-tables 选项是互斥的，因为 LOCK TABLES 会使任何挂起的事务隐含提交。<br />要想导出大表的话，应结合使用 --quick 选项。<br />* --triggers<br /><br />同时导出触发器。该选项默认启用，用 --skip-triggers 禁用它。<br /><br />其他参数详情请参考手册，我通常使用以下 SQL 来备份 MyISAM 表：<br /><br />/usr/local/mysql/bin/mysqldump -uyejr -pyejr \<br />--default-character-set=utf8 --opt --extended-insert=false \<br />--triggers -R --hex-blob -x db_name > db_name.sql<br /><br />使用以下 SQL 来备份 Innodb 表：<br /><br />/usr/local/mysql/bin/mysqldump -uyejr -pyejr \<br />--default-character-set=utf8 --opt --extended-insert=false \<br />--triggers -R --hex-blob --single-transaction db_name > db_name.sql<br /><br />另外，如果想要实现在线备份，还可以使用 --master-data 参数来实现，如下：<br /><br />/usr/local/mysql/bin/mysqldump -uyejr -pyejr \<br />--default-character-set=utf8 --opt --master-data=1 \<br />--single-transaction --flush-logs db_name > db_name.sql<br /><br />它只是在一开始的瞬间请求锁表，然后就刷新binlog了，而后在导出的文件中加入CHANGE MASTER 语句来指定当前备份的binlog位置，如果要把这个文件恢复到slave里去，就可以采用这种方法来做。<br />1.2 还原<br /><br />用 mysqldump 备份出来的文件是一个可以直接倒入的 SQL 脚本，有两种方法可以将数据导入。<br /><br />* 直接用 mysql 客户端<br /><br />例如：<br /><br />/usr/local/mysql/bin/mysql -uyejr -pyejr db_name &lt; db_name.sql<br /><br /><br />* 用 SOURCE 语法<br /><br />其实这不是标准的 SQL 语法，而是 mysql 客户端提供的功能，例如：<br /><br />SOURCE /tmp/db_name.sql;<br /><br />这里需要指定文件的绝对路径，并且必须是 mysqld 运行用户(例如 nobody)有权限读取的文件。<br /><br />2、 mysqlhotcopy<br />2.1 备份<br /><br />mysqlhotcopy 是一个 PERL 程序，最初由Tim Bunce编写。它使用 LOCK TABLES、FLUSH TABLES 和 cp 或 scp 来快速备份数据库。它是备份数据库或单个表的最快的途径，但它只能运行在数据库文件（包括数据表定义文件、数据文件、索引文件）所在的机器上。 mysqlhotcopy 只能用于备份 MyISAM，并且只能运行在 类Unix 和 NetWare 系统上。<br /><br />mysqlhotcopy 支持一次性拷贝多个数据库，同时还支持正则表达。以下是几个例子：<br /><br />root#/usr/local/mysql/bin/mysqlhotcopy -h=localhost -u=yejr -p=yejr \<br />db_name /tmp (把数据库目录 db_name 拷贝到 /tmp 下)<br />root#/usr/local/mysql/bin/mysqlhotcopy -h=localhost -u=yejr -p=yejr \<br />db_name_1 ... db_name_n /tmp<br />root#/usr/local/mysql/bin/mysqlhotcopy -h=localhost -u=yejr -p=yejr \<br />db_name./regex/ /tmp<br /><br />更详细的使用方法请查看手册，或者调用下面的命令来查看 mysqlhotcopy 的帮助：<br /><br />perldoc /usr/local/mysql/bin/mysqlhotcopy<br /><br />注意，想要使用 mysqlhotcopy，必须要有 SELECT、RELOAD(要执行 FLUSH TABLES) 权限，并且还必须要能够有读取 datadir/db_name 目录的权限。<br />2.2 还原<br /><br />mysqlhotcopy 备份出来的是整个数据库目录，使用时可以直接拷贝到 mysqld 指定的 datadir (在这里是 /usr/local/mysql/data/)目录下即可，同时要注意权限的问题，如下例：<br /><br />root#cp -rf db_name /usr/local/mysql/data/<br />root#chown -R nobody:nobody /usr/local/mysql/data/ (将 db_name 目录的属主改成 mysqld 运行用户)<br /><br /><br />3、 SQL 语法备份<br />3.1 备份<br /><br />BACKUP TABLE 语法其实和 mysqlhotcopy 的工作原理差不多，都是锁表，然后拷贝数据文件。它能实现在线备份，但是效果不理想，因此不推荐使用。它只拷贝表结构文件和数据文件，不同时拷贝索引文件，因此恢复时比较慢。<br />例子：<br /><br />BACK TABLE tbl_name TO '/tmp/db_name/';<br /><br />注意，必须要有 FILE 权限才能执行本SQL，并且目录 /tmp/db_name/ 必须能被 mysqld 用户可写，导出的文件不能覆盖已经存在的文件，以避免安全问题。<br /><br />SELECT INTO OUTFILE 则是把数据导出来成为普通的文本文件，可以自定义字段间隔的方式，方便处理这些数据。<br />例子：<br /><br />SELECT * INTO OUTFILE '/tmp/db_name/tbl_name.txt' FROM tbl_name;<br /><br />注意，必须要有 FILE 权限才能执行本SQL，并且文件 /tmp/db_name/tbl_name.txt 必须能被 mysqld 用户可写，导出的文件不能覆盖已经存在的文件，以避免安全问题。<br />3.2 恢复<br /><br />用 BACKUP TABLE 方法备份出来的文件，可以运行 RESTORE TABLE 语句来恢复数据表。<br />例子：<br /><br />RESTORE TABLE FROM '/tmp/db_name/';<br /><br />权限要求类似上面所述。<br /><br />用 SELECT INTO OUTFILE 方法备份出来的文件，可以运行 LOAD DATA INFILE 语句来恢复数据表。<br />例子：<br /><br />LOAD DATA INFILE '/tmp/db_name/tbl_name.txt' INTO TABLE tbl_name;<br /><br />权限要求类似上面所述。倒入数据之前，数据表要已经存在才行。如果担心数据会发生重复，可以增加 REPLACE 关键字来替换已有记录或者用 IGNORE 关键字来忽略他们。<br />4、 启用二进制日志(binlog)<br /><br />采用 binlog 的方法相对来说更灵活，省心省力，而且还可以支持增量备份。<br /><br />启用 binlog 时必须要重启 mysqld。首先，关闭 mysqld，打开 my.cnf，加入以下几行：<br /><br />server-id = 1<br />log-bin = binlog<br />log-bin-index = binlog.index<br /><br />然后启动 mysqld 就可以了。运行过程中会产生 binlog.000001 以及 binlog.index，前面的文件是 mysqld 记录所有对数据的更新操作，后面的文件则是所有 binlog 的索引，都不能轻易删除。关于 binlog 的信息请查看手册。<br /><br />需要备份时，可以先执行一下 SQL 语句，让 mysqld 终止对当前 binlog 的写入，就可以把文件直接备份，这样的话就能达到增量备份的目的了：<br /><br />FLUSH LOGS;<br /><br />如果是备份复制系统中的从服务器，还应该备份 master.info 和 relay-log.info 文件。<br /><br />备份出来的 binlog 文件可以用 MySQL 提供的工具 mysqlbinlog 来查看，如：<br /><br />/usr/local/mysql/bin/mysqlbinlog /tmp/binlog.000001<br /><br />该工具允许你显示指定的数据库下的所有 SQL 语句，并且还可以限定时间范围，相当的方便，详细的请查看手册。<br /><br />恢复时，可以采用类似以下语句来做到：<br /><br />/usr/local/mysql/bin/mysqlbinlog /tmp/binlog.000001 | mysql -uyejr -pyejr db_name<br /><br />把 mysqlbinlog 输出的 SQL 语句直接作为输入来执行它。<br /><br />如果你有空闲的机器，不妨采用这种方式来备份。由于作为 slave 的机器性能要求相对不是那么高，因此成本低，用低成本就能实现增量备份而且还能分担一部分数据查询压力，何乐而不为呢？<br />5、 直接备份数据文件<br /><br />相较前几种方法，备份数据文件最为直接、快速、方便，缺点是基本上不能实现增量备份。为了保证数据的一致性，需要在靠背文件前，执行以下 SQL 语句：<br /><br />FLUSH TABLES WITH READ LOCK;<br /><br />也就是把内存中的数据都刷新到磁盘中，同时锁定数据表，以保证拷贝过程中不会有新的数据写入。这种方法备份出来的数据恢复也很简单，直接拷贝回原来的数据库目录下即可。<br /><br />注意，对于 Innodb 类型表来说，还需要备份其日志文件，即 ib_logfile* 文件。因为当 Innodb 表损坏时，就可以依靠这些日志文件来恢复。<br />6、 备份策略<br /><br />对于中等级别业务量的系统来说，备份策略可以这么定：第一次全量备份，每天一次增量备份，每周再做一次全量备份，如此一直重复。而对于重要的且繁忙的系统来说，则可能需要每天一次全量备份，每小时一次增量备份，甚至更频繁。为了不影响线上业务，实现在线备份，并且能增量备份，最好的办法就是采用主从复制机制 (replication)，在 slave 机器上做备份。<br />7、 数据维护和灾难恢复<br /><br />作为一名DBA(我目前还不是，呵呵)，最重要的工作内容之一是保证数据表能安全、稳定、高速使用。因此，需要定期维护你的数据表。以下 SQL 语句就很有用：<br /><br />CHECK TABLE 或 REPAIR TABLE，检查或维护 MyISAM 表<br />OPTIMIZE TABLE，优化 MyISAM 表<br />ANALYZE TABLE，分析 MyISAM 表<br /><br />当然了，上面这些命令起始都可以通过工具 myisamchk 来完成，在这里不作详述。<br /><br />Innodb 表则可以通过执行以下语句来整理碎片，提高索引速度：<br /><br />ALTER TABLE tbl_name ENGINE = Innodb;<br /><br />这其实是一个 NULL 操作，表面上看什么也不做，实际上重新整理碎片了。<br /><br />通常使用的 MyISAM 表可以用上面提到的恢复方法来完成。如果是索引坏了，可以用 myisamchk 工具来重建索引。而对于 Innodb 表来说，就没这么直接了，因为它把所有的表都保存在一个表空间了。不过 Innodb 有一个检查机制叫模糊检查点，只要保存了日志文件，就能根据日志文件来修复错误。可以在 my.cnf 文件中，增加以下参数，让 mysqld 在启动时自动检查日志文件：<br /><br />innodb_force_recovery = 4<br /><br />关于该参数的信息请查看手册。<br />8、 总结<br /><br />做好数据备份，定只好合适的备份策略，这是一个DBA所做事情的一小部分，万事开头难，就从现在开始吧！<br />抛出异常的爱 2007-10-22<br />1016错误：文件无法打开，使用后台修复或者使用phpmyadmin进行修复。<br />1044错误：数据库用户权限不足，请联系空间商解决<br />1045错误：数据库服务器/数据库用户名/数据库名/数据库密码错误，请联系空间商检查帐户。<br />1054错误：程序文件跟数据库有冲突，请使用正确的程序文件上传上去覆盖。<br />1146错误：数据表缺失,请恢复备份数据.<br />1005：创建表失败<br />1006：创建数据库失败<br />1007：数据库已存在，创建数据库失败<br />1008：数据库不存在，删除数据库失败<br />1009：不能删除数据库文件导致删除数据库失败<br />1010：不能删除数据目录导致删除数据库失败<br />1011：删除数据库文件失败<br />1012：不能读取系统表中的记录<br />1020：记录已被其他用户修改<br />1021：硬盘剩余空间不足，请加大硬盘可用空间<br />1022：关键字重复，更改记录失败<br />1023：关闭时发生错误<br />1024：读文件错误<br />1025：更改名字时发生错误<br />1026：写文件错误<br />1032：记录不存在<br />1036：数据表是只读的，不能对它进行修改<br />1037：系统内存不足，请重启数据库或重启服务器<br />1038：用于排序的内存不足，请增大排序缓冲区<br />1040：已到达数据库的最大连接数，请加大数据库可用连接数<br />1041：系统内存不足<br />1042：无效的主机名<br />1043：无效连接<br />1044：当前用户没有访问数据库的权限<br />1045：不能连接数据库，用户名或密码错误<br />1048：字段不能为空<br />1049：数据库不存在<br />1050：数据表已存在<br />1051：数据表不存在<br />1054：字段不存在<br />1065：无效的SQL语句，SQL语句为空<br />1081：不能建立Socket连接<br />1114：数据表已满，不能容纳任何记录<br />1116：打开的数据表太多<br />1129：数据库出现异常，请重启数据库<br />1130：连接数据库失败，没有连接数据库的权限<br />1133：数据库用户不存在<br />1141：当前用户无权访问数据库<br />1142：当前用户无权访问数据表<br />1143：当前用户无权访问数据表中的字段<br />1146：数据表不存在<br />1147：未定义用户对数据表的访问权限<br />1149：SQL语句语法错误<br />1158：网络错误，出现读错误，请检查网络连接状况<br />1159：网络错误，读超时，请检查网络连接状况<br />1160：网络错误，出现写错误，请检查网络连接状况<br />1161：网络错误，写超时，请检查网络连接状况<br />1062：字段值重复，入库失败<br />1169：字段值重复，更新记录失败<br />1177：打开数据表失败<br />1180：提交事务失败<br />1181：回滚事务失败<br />1203：当前用户和数据库建立的连接已到达数据库的最大连接数，请增大可用的数据库连接数或重启数据库<br />1205：加锁超时<br />1211：当前用户没有创建用户的权限<br />1216：外键约束检查失败，更新子表记录失败<br />1217：外键约束检查失败，删除或修改主表记录失败<br />1226：当前用户使用的资源已超过所允许的资源，请重启数据库或重启服务器<br />1227：权限不足，您无权进行此操作<br />1235：MySQL版本过低，不具有本功能<br />2002：Can't connect to ...通常意味着没有一个MySQL服务器运行在系统上或当试图连接mysqld服务器时，你正在使用一个错误的套接字文件或TCP/IP端口。<br /><br /><br /><br /><br />说明：以上只是常见错误号，并且解决办法也不一定肯定管用！具体请参考MYSQL手册（各大下载站均有下载）<br /><br /><br />更多详细错误代码<br />错误名称 / 错误代码 SQL状态<br />ER_HASHCHK 1000 HY000<br />ER_NISAMCHK 1001 HY000<br />ER_NO 1002 HY000<br />ER_YES 1003 HY000<br />ER_CANT_CREATE_FILE 1004 HY000<br />ER_CANT_CREATE_TABLE 1005 HY000<br />ER_CANT_CREATE_DB 1006 HY000<br />ER_DB_CREATE_EXISTS 1007 HY000<br />ER_DB_DROP_EXISTS 1008 HY000<br />ER_DB_DROP_DELETE 1009 HY000<br />ER_DB_DROP_RMDIR 1010 HY000<br />ER_CANT_DELETE_FILE 1011 HY000<br />ER_CANT_FIND_SYSTEM_REC 1012 HY000<br />ER_CANT_GET_STAT 1013 HY000<br />ER_CANT_GET_WD 1014 HY000<br />ER_CANT_LOCK 1015 HY000<br />ER_CANT_OPEN_FILE 1016 HY000<br />ER_FILE_NOT_FOUND 1017 HY000<br />ER_CANT_READ_DIR 1018 HY000<br />ER_CANT_SET_WD 1019 HY000<br />ER_CHECKREAD 1020 HY000<br />ER_DISK_FULL 1021 HY000<br />ER_DUP_KEY 1022 23000<br />ER_ERROR_ON_CLOSE 1023 HY000<br />ER_ERROR_ON_READ 1024 HY000<br />ER_ERROR_ON_RENAME 1025 HY000<br />ER_ERROR_ON_WRITE 1026 HY000<br />ER_FILE_USED 1027 HY000<br />ER_FILSORT_ABORT 1028 HY000<br />ER_FORM_NOT_FOUND 1029 HY000<br />ER_GET_ERRNO 1030 HY000<br />ER_ILLEGAL_HA 1031 HY000<br />ER_KEY_NOT_FOUND 1032 HY000<br />ER_NOT_FORM_FILE 1033 HY000<br />ER_NOT_KEYFILE 1034 HY000<br />ER_OLD_KEYFILE 1035 HY000<br />ER_OPEN_AS_READONLY 1036 HY000<br />ER_OUTOFMEMORY 1037 HY001<br />ER_OUT_OF_SORTMEMORY 1038 HY001<br />ER_UNEXPECTED_EOF 1039 HY000<br />ER_CON_COUNT_ERROR 1040 08004<br />ER_OUT_OF_RESOURCES 1041 08004<br />ER_BAD_HOST_ERROR 1042 08S01<br />ER_HANDSHAKE_ERROR 1043 08S01<br />ER_DBACCESS_DENIED_ERROR 1044 42000<br />ER_ACCESS_DENIED_ERROR 1045 42000<br />ER_NO_DB_ERROR 1046 42000<br />ER_UNKNOWN_COM_ERROR 1047 08S01<br />ER_BAD_NULL_ERROR 1048 23000<br />ER_BAD_DB_ERROR 1049 42000<br />ER_TABLE_EXISTS_ERROR 1050 42S01<br />ER_BAD_TABLE_ERROR 1051 42S02<br />ER_NON_UNIQ_ERROR 1052 23000<br />ER_SERVER_SHUTDOWN 1053 08S01<br />ER_BAD_FIELD_ERROR 1054 42S22<br />ER_WRONG_FIELD_WITH_GROUP 1055 42000<br />ER_WRONG_GROUP_FIELD 1056 42000<br />ER_WRONG_SUM_SELECT 1057 42000<br />ER_WRONG_VALUE_COUNT 1058 21S01<br />ER_TOO_LONG_IDENT 1059 42000<br />ER_DUP_FIELDNAME 1060 42S21<br />ER_DUP_KEYNAME 1061 42000<br />ER_DUP_ENTRY 1062 23000<br />ER_WRONG_FIELD_SPEC 1063 42000<br />ER_PARSE_ERROR 1064 42000<br />ER_EMPTY_QUERY 1065 42000<br />ER_NONUNIQ_TABLE 1066 42000<br />ER_INVALID_DEFAULT 1067 42000<br />ER_MULTIPLE_PRI_KEY 1068 42000<br />ER_TOO_MANY_KEYS 1069 42000<br />ER_TOO_MANY_KEY_PARTS 1070 42000<br />ER_TOO_LONG_KEY 1071 42000<br />ER_KEY_COLUMN_DOES_NOT_EXITS 1072 42000<br />ER_BLOB_USED_AS_KEY 1073 42000<br />ER_TOO_BIG_FIELDLENGTH 1074 42000<br />ER_WRONG_AUTO_KEY 1075 42000<br />ER_READY 1076 00000<br />ER_NORMAL_SHUTDOWN 1077 00000<br />ER_GOT_SIGNAL 1078 00000<br />ER_SHUTDOWN_COMPLETE 1079 00000<br />ER_FORCING_CLOSE 1080 08S01<br />ER_IPSOCK_ERROR 1081 08S01<br />ER_NO_SUCH_INDEX 1082 42S12<br />ER_WRONG_FIELD_TERMINATORS 1083 42000<br />ER_BLOBS_AND_NO_TERMINATED 1084 42000<br />ER_TEXTFILE_NOT_READABLE 1085 HY000<br />ER_FILE_EXISTS_ERROR 1086 HY000<br />ER_LOAD_INFO 1087 HY000<br />ER_ALTER_INFO 1088 HY000<br />ER_WRONG_SUB_KEY 1089 HY000<br />ER_CANT_REMOVE_ALL_FIELDS 1090 42000<br />ER_CANT_DROP_FIELD_OR_KEY 1091 42000<br />ER_INSERT_INFO 1092 HY000<br />ER_UPDATE_TABLE_USED 1093 HY000<br />ER_NO_SUCH_THREAD 1094 HY000<br />ER_KILL_DENIED_ERROR 1095 HY000<br />ER_NO_TABLES_USED 1096 HY000<br />ER_TOO_BIG_SET 1097 HY000<br />ER_NO_UNIQUE_LOGFILE 1098 HY000<br />ER_TABLE_NOT_LOCKED_FOR_WRITE 1099 HY000<br />ER_TABLE_NOT_LOCKED 1100 HY000<br />ER_BLOB_CANT_HAVE_DEFAULT 1101 42000<br />ER_WRONG_DB_NAME 1102 42000<br />ER_WRONG_TABLE_NAME 1103 42000<br />ER_TOO_BIG_SELECT 1104 42000<br />ER_UNKNOWN_ERROR 1105 HY000<br />ER_UNKNOWN_PROCEDURE 1106 42000<br />ER_WRONG_PARAMCOUNT_TO_PROCEDURE 1107 42000<br />ER_WRONG_PARAMETERS_TO_PROCEDURE 1108 HY000<br />ER_UNKNOWN_TABLE 1109 42S02<br />ER_FIELD_SPECIFIED_TWICE 1110 42000<br />ER_INVALID_GROUP_FUNC_USE 1111 42000<br />ER_UNSUPPORTED_EXTENSION 1112 42000<br />ER_TABLE_MUST_HAVE_COLUMNS 1113 42000<br />ER_RECORD_FILE_FULL 1114 HY000<br />ER_UNKNOWN_CHARACTER_SET 1115 42000<br />ER_TOO_MANY_TABLES 1116 HY000<br />ER_TOO_MANY_FIELDS 1117 HY000<br />ER_TOO_BIG_ROWSIZE 1118 42000<br />ER_STACK_OVERRUN 1119 HY000<br />ER_WRONG_OUTER_JOIN 1120 42000<br />ER_NULL_COLUMN_IN_INDEX 1121 42000<br />ER_CANT_FIND_UDF 1122 HY000<br />ER_CANT_INITIALIZE_UDF 1123 HY000<br />ER_UDF_NO_PATHS 1124 HY000<br />ER_UDF_EXISTS 1125 HY000<br />ER_CANT_OPEN_LIBRARY 1126 HY000<br />ER_CANT_FIND_DL_ENTRY 1127 HY000<br />ER_FUNCTION_NOT_DEFINED 1128 HY000<br />ER_HOST_IS_BLOCKED 1129 HY000<br />ER_HOST_NOT_PRIVILEGED 1130 HY000<br />ER_PASSWORD_ANONYMOUS_USER 1131 42000<br />ER_PASSWORD_NOT_ALLOWED 1132 42000<br />ER_PASSWORD_NO_MATCH 1133 42000<br />ER_UPDATE_INFO 1134 HY000<br />ER_CANT_CREATE_THREAD 1135 HY000<br />ER_WRONG_VALUE_COUNT_ON_ROW 1136 21S01<br />ER_CANT_REOPEN_TABLE 1137 HY000<br />ER_INVALID_USE_OF_NULL 1138 42000<br />ER_REGEXP_ERROR 1139 42000<br />ER_MIX_OF_GROUP_FUNC_AND_FIELDS 1140 42000<br />ER_NONEXISTING_GRANT 1141 42000<br />ER_TABLEACCESS_DENIED_ERROR 1142 42000<br />ER_COLUMNACCESS_DENIED_ERROR 1143 42000<br />ER_ILLEGAL_GRANT_FOR_TABLE 1144 42000<br />ER_GRANT_WRONG_HOST_OR_USER 1145 42000<br />ER_NO_SUCH_TABLE 1146 42S02<br />ER_NONEXISTING_TABLE_GRANT 1147 42000<br />ER_NOT_ALLOWED_COMMAND 1148 42000<br />ER_SYNTAX_ERROR 1149 42000<br />ER_DELAYED_CANT_CHANGE_LOCK 1150 HY000<br />ER_TOO_MANY_DELAYED_THREADS 1151 HY000<br />ER_ABORTING_CONNECTION 1152 08S01<br />ER_NET_PACKET_TOO_LARGE 1153 08S01<br />ER_NET_READ_ERROR_FROM_PIPE 1154 08S01<br />ER_NET_FCNTL_ERROR 1155 08S01<br />ER_NET_PACKETS_OUT_OF_ORDER 1156 08S01<br />ER_NET_UNCOMPRESS_ERROR 1157 08S01<br />ER_NET_READ_ERROR 1158 08S01<br />ER_NET_READ_INTERRUPTED 1159 08S01<br />ER_NET_ERROR_ON_WRITE 1160 08S01<br />ER_NET_WRITE_INTERRUPTED 1161 08S01<br />ER_TOO_LONG_STRING 1162 42000<br />ER_TABLE_CANT_HANDLE_BLOB 1163 42000<br />ER_TABLE_CANT_HANDLE_AUTO_INCREMENT 1164 42000<br />ER_DELAYED_INSERT_TABLE_LOCKED 1165 HY000<br />ER_WRONG_COLUMN_NAME 1166 42000<br />ER_WRONG_KEY_COLUMN 1167 42000<br />ER_WRONG_MRG_TABLE 1168 HY000<br />ER_DUP_UNIQUE 1169 23000<br />ER_BLOB_KEY_WITHOUT_LENGTH 1170 42000<br />ER_PRIMARY_CANT_HAVE_NULL 1171 42000<br />ER_TOO_MANY_ROWS 1172 42000<br />ER_REQUIRES_PRIMARY_KEY 1173 42000<br />ER_NO_RAID_COMPILED 1174 HY000<br />ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE 1175 HY000<br />ER_KEY_DOES_NOT_EXITS 1176 HY000<br />ER_CHECK_NO_SUCH_TABLE 1177 42000<br />ER_CHECK_NOT_IMPLEMENTED 1178 42000<br />ER_CANT_DO_THIS_DURING_AN_TRANSACTION 1179 25000<br />ER_ERROR_DURING_COMMIT 1180 HY000<br />ER_ERROR_DURING_ROLLBACK 1181 HY000<br />ER_ERROR_DURING_FLUSH_LOGS 1182 HY000<br />ER_ERROR_DURING_CHECKPOINT 1183 HY000<br />ER_NEW_ABORTING_CONNECTION 1184 08S01<br />ER_DUMP_NOT_IMPLEMENTED 1185 HY000<br />ER_FLUSH_MASTER_BINLOG_CLOSED 1186 HY000<br />ER_INDEX_REBUILD 1187 HY000<br />ER_MASTER 1188 HY000<br />ER_MASTER_NET_READ 1189 08S01<br />ER_MASTER_NET_WRITE 1190 08S01<br />ER_FT_MATCHING_KEY_NOT_FOUND 1191 HY000<br />ER_LOCK_OR_ACTIVE_TRANSACTION 1192 HY000<br />ER_UNKNOWN_SYSTEM_VARIABLE 1193 HY000<br />ER_CRASHED_ON_USAGE 1194 HY000<br />ER_CRASHED_ON_REPAIR 1195 HY000<br />ER_WARNING_NOT_COMPLETE_ROLLBACK 1196 HY000<br />ER_TRANS_CACHE_FULL 1197 HY000<br />ER_SLAVE_MUST_STOP 1198 HY000<br />ER_SLAVE_NOT_RUNNING 1199 HY000<br />ER_BAD_SLAVE 1200 HY000<br />ER_MASTER_INFO 1201 HY000<br />ER_SLAVE_THREAD 1202 HY000<br />ER_TOO_MANY_USER_CONNECTIONS 1203 42000<br />ER_SET_CONSTANTS_ONLY 1204 HY000<br />ER_LOCK_WAIT_TIMEOUT 1205 HY000<br />ER_LOCK_TABLE_FULL 1206 HY000<br />ER_READ_ONLY_TRANSACTION 1207 25000<br />ER_DROP_DB_WITH_READ_LOCK 1208 HY000<br />ER_CREATE_DB_WITH_READ_LOCK 1209 HY000<br />ER_WRONG_ARGUMENTS 1210 HY000<br />ER_NO_PERMISSION_TO_CREATE_USER 1211 42000<br />ER_UNION_TABLES_IN_DIFFERENT_DIR 1212 HY000<br />ER_LOCK_DEADLOCK 1213 40001<br />ER_TABLE_CANT_HANDLE_FULLTEXT 1214 HY000<br />ER_CANNOT_ADD_FOREIGN 1215 HY000<br />ER_NO_REFERENCED_ROW 1216 23000<br />ER_ROW_IS_REFERENCED 1217 23000<br />ER_CONNECT_TO_MASTER 1218 08S01<br />ER_QUERY_ON_MASTER 1219 HY000<br />ER_ERROR_WHEN_EXECUTING_COMMAND 1220 HY000<br />ER_WRONG_USAGE 1221 HY000<br />ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT 1222 21000<br />ER_CANT_UPDATE_WITH_READLOCK 1223 HY000<br />ER_MIXING_NOT_ALLOWED 1224 HY000<br />ER_DUP_ARGUMENT 1225 HY000<br />ER_USER_LIMIT_REACHED 1226 42000<br />ER_SPECIFIC_ACCESS_DENIED_ERROR 1227 HY000<br />ER_LOCAL_VARIABLE 1228 HY000<br />ER_GLOBAL_VARIABLE 1229 HY000<br />ER_NO_DEFAULT 1230 42000<br />ER_WRONG_VALUE_FOR_VAR 1231 42000<br />ER_WRONG_TYPE_FOR_VAR 1232 42000<br />ER_VAR_CANT_BE_READ 1233 HY000<br />ER_CANT_USE_OPTION_HERE 1234 42000<br />ER_NOT_SUPPORTED_YET 1235 42000<br />ER_MASTER_FATAL_ERROR_READING_BINLOG 1236 HY000<br />ER_WRONG_FK_DEF 1237 42000<br />ER_KEY_REF_DO_NOT_MATCH_TABLE_REF 1238 HY000<br />ER_CARDINALITY_COL 1239 21000<br />ER_SUBSELECT_NO_1_ROW 1240 21000<br />ER_UNKNOWN_STMT_HANDLER 1241 HY000<br />ER_CORRUPT_HELP_DB 1242 HY000<br />ER_CYCLIC_REFERENCE 1243 HY000<br />ER_AUTO_CONVERT 1244 HY000<br />ER_ILLEGAL_REFERENCE 1245 42S22<br />ER_DERIVED_MUST_HAVE_ALIAS 1246 42000<br />ER_SELECT_REDUCED 1247 01000<br />ER_TABLENAME_NOT_ALLOWED_HERE 1248 42000<br />ER_NOT_SUPPORTED_AUTH_MODE 1249 08004<br />ER_SPATIAL_CANT_HAVE_NULL 1250 42000<br />ER_COLLATION_CHARSET_MISMATCH 1251 42000<br />ER_SLAVE_WAS_RUNNING 1252 HY000<br />ER_SLAVE_WAS_NOT_RUNNING 1253 HY000<br />ER_TOO_BIG_FOR_UNCOMPRESS 1254 HY000<br />ER_ZLIB_Z_MEM_ERROR 1255 HY000<br />ER_ZLIB_Z_BUF_ERROR 1256 HY000<br />ER_ZLIB_Z_DATA_ERROR 1257 HY000<br />ER_CUT_VALUE_GROUP_CONCAT 1258 HY000<br />ER_WARN_TOO_FEW_RECORDS 1259 01000<br />ER_WARN_TOO_MANY_RECORDS 1260 01000<br />ER_WARN_NULL_TO_NOTNULL 1261 01000<br />ER_WARN_DATA_OUT_OF_RANGE 1262 01000<br />ER_WARN_DATA_TRUNCATED 1263 01000<br />ER_WARN_USING_OTHER_HANDLER 1264 01000<br />ER_CANT_AGGREGATE_COLLATIONS 1265 42000<br />ER_DROP_USER 1266 42000<br />ER_REVOKE_GRANTS 1267 42000<br />抛出异常的爱 2007-10-22<br />1. Mysql 培训<br />1.1. 培训目的<br />本文档是针对MySQL 数据库方面的基础培训，为了使项目组成员能够达到使用MySQL 数据库的目的。<br />1.2. 培训对象<br />开发人员<br />1.3. 常用词及符号说明<br />常用词：<br />Mysql：一种免费的跨平台的数据库系统<br />E:\mysql：表示是在dos 命令窗口下面<br />mysql> 表示是在mysql 的命令行下<br />1.4. 参考信息<br />http://dev.mysql.com/doc/refman/5.0/en/index.html<br /><br /><br />2. MYSQL<br />2.1. 连接MYSQL<br />格式： mysql -h主机地址 -u用户名 -p用户密码<br />连接远程机器：<br />E:\mysql>mysql -h10.4.3.188 -uptsdb -p<br />等价写法<br />E:\mysql>mysql --host=10.4.3.188 --user=ptsdb --password<br />连接本地机器：<br />E:\mysql>mysql -uroot -p<br />等价写法<br />E:\mysql>mysql --user=root -password<br />（注:u与root可以不用加空格，其它也一样）<br />注意事项：环境变量path 里面要设定mysql的bin的路径：<br />C:\Program Files\MySQL\MySQL Server 5.0\bin<br />2.2. 修改密码<br />方法一：使用mysqladmin<br />格式：mysqladmin -u用户名 -p旧密码 password 新密码<br />例1：E:\mysql>mysqladmin -uroot password root<br />注：因为开始时root没有密码，所以-p旧密码一项就可以省略了。<br />例2：再将root的密码改为root123。<br />E:\mysql>mysqladmin -uroot -proot password root123<br />方法二：直接更新 user 表<br />mysql>UPDATE user SET password=PASSWORD("test123") WHERE user='test';<br />mysql> FLUSH PRIVILEGES;<br />mysql> SET PASSWORD FOR test=PASSWORD('test123');<br />mysql> FLUSH PRIVILEGES;<br />方法三：使用 grant<br />格式：grant 权限 on 数据库.表格| 其他 to 用户@主机 IDENTIFIED BY 口令<br />例1：给test用户在本地localhost 所有权限(除了GRANT OPTION)，口令为 test<br />(相当于修改了test 用户的口令)<br />mysql>grant all on *.* to test@localhost identified by "test";<br />等同于<br />mysql>grant all on *.* to test @localhost identified by PASSWORD " *94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29 ";<br /><br />例2、增加一个用户test密码为abc，让他可以在任何主机上登录，并对test数据库有查询、插入、修改、删除的权限。首先用以root用户连入MYSQL，然后键入以下命令：<br />mysql>grant select,insert,update,delete on test.* to test@"%" Identified by "abc";<br /><br />在mysql.user 表中，有两个test 用户<br />一个test 用户，在本地有所有的权限<br />另外的test 用户，在所有主机上有增删改查权限<br /><br />同样可以取消部分权限（全部）<br />mysql>revoke insert,update,delete on test.* from test@"%"<br />mysql>REVOKE ALL PRIVILEGES, GRANT OPTION FROM test@"%"<br />然后 mysql> FLUSH PRIVILEGES;<br /><br />Test 用户不再使用用了，也可以删除<br />mysql>Delete from user where user='test' and host='%'<br />mysql> FLUSH PRIVILEGES;<br /><br />注意：例2增加的用户是比较危险的，你想如某个人知道test的密码，那么他就可以在internet上的任何一台电脑上登录你的mysql数据库并对你的数据库test为所欲为了(可以通过限定主机)<br />mysql>grant select,insert,update,delete on test.* to test@"IP地址" Identified by "abc";<br />2.3. 显示命令<br />显示数据库列表:<br />mysql>show databases;<br />mysql>show schemas; --mysql 5.0.2<br />显示表格<br />mysql>show tables from mydb;<br />显示表格状态<br />Mysql>SHOW TABLE STATUS;<br />显示字符集:<br />mysql> SHOW CHARACTER SET;<br />显示创建表:<br />mysql> show create table quote;<br />显示用户权限:<br />mysql> SHOW GRANTS FOR 'test'@'localhost';<br />mysql>SHOW GRANTS;<br />mysql>SHOW GRANTS FOR CURRENT_USER;<br />mysql>SHOW GRANTS FOR CURRENT_USER();<br />显示index:<br />mysql>SHOW INDEX FROM mydb.mytable;<br />显示表结构:<br />mysql>desc mydb.tablename;<br />mysql>show columns from mydb.tablename;<br />显示MySQL数据库的版本：<br />mysql>select version();<br />显示函数<br />mysql>Select * from mysql.func;<br />显示存储过程<br />mysql>Select * from mysql.proc;<br />显示存储引擎<br />mysql> SHOW ENGINES;<br />显示变量:<br />mysql>SHOW VARIABLES;<br />显示状态:<br />Mysql> SHOW STATUS;<br />显示进程<br />Mysql>SHOW PROCESSLIST<br />显示 INNODB 状态<br />Mysql>SHOW INNODB STATUS<br />显示连接状态<br />Mysql>SHOW STATUS LIKE '%CONNECT%';<br />显示线程状态<br />Mysql>SHOW STATUS LIKE '%THREAD%';<br /><br />等等..<br /><br />2.4. 创建.修改.删除<br />2.4.1. 创建数据库<br />CREATE {DATABASE | SCHEMA} [IF NOT EXISTS] db_name<br />[create_specification [, create_specification] ...]<br /><br />create_specification:<br />[DEFAULT] CHARACTER SET charset_name<br />| [DEFAULT] COLLATE collation_name<br />例如:<br />CREATE DATABASE IF NOT EXISTS ddd --如果不存在,则创建.<br />CHARACTER SET 'ujis' --设定字符集<br />COLLATE 'ujis_japanese_ci';<br />2.4.2. 创建表<br />CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name<br />[(create_definition,...)]<br />[table_options] [select_statement]<br />例子:<br />CREATE TABLE if not exists `Admin_User` (<br />`id` int(11) NOT NULL auto_increment, --PRIMARY KEY，<br />`livedoorId` varchar(255) NOT NULL default '',<br />`password` varchar(255) NOT NULL default '',<br />`auth` int(11) default '0',<br />PRIMARY KEY (`id`) --设定主健<br />) ENGINE=MyISAM DEFAULT CHARSET=ujis ?设定字符集<br />ENGINE=MyISAM 默认存储引擎<br />The binary portable storage engine that is the default storage engine used by MySQL<br />对于每个MyISAM 存储引擎的表,在硬盘上存在3个文件<br />File Purpose<br />tbl_name.frm Table format (definition) file<br />tbl_name.MYD Data file<br />tbl_name.MYI Index file<br /><br />ENGINE= InnoDB<br />Transaction-safe tables with row locking and foreign keys.<br />ENGINE = BDB<br />Transaction-safe tables with page locking.<br />还有其他的内存引擎 MEMORY 归档 ARCHIVE 等等<br />ISAM 不再使用了<br /><br />2.4.3. 创建索引<br />CREATE [UNIQUE|FULLTEXT|SPATIAL] INDEX index_name<br />[USING index_type]<br />ON tbl_name (index_col_name,...)<br />index_col_name:<br />col_name [(length)] [ASC | DESC]<br /><br />将customer 表的name 字段前十个字符做为索引<br />CREATE INDEX part_of_name ON customer (name(10));<br />MYSQL 5.0 特性<br />存储引擎为 MyISAM, InnoDB, or BDB 的表格上,可以在有null值的字段上创建索引<br />存储引擎为 MyISAM, InnoDB, or BDB 的表格上,可以在BLOB TEXT 上创建索引<br />只有在MyISAM 类型表格上,可以在CHAR, VARCHAR, and TEXT 字段类型上创建FULLTEXT 索引<br />Storage Engine Allowable Index Types<br />MyISAM BTREE<br />InnoDB BTREE<br />MEMORY/HEAP HASH, BTREE<br />可以指定索引类型<br /><br /><br /><br />Example:<br />CREATE TABLE testtable (id INT) ENGINE = MEMORY;<br />CREATE INDEX id_index USING BTREE ON testtable (id);<br />2.4.4. 修改表<br />ALTER [IGNORE] TABLE tbl_name<br />alter_specification [, alter_specification] ...<br />IGNORE 忽略主健重复的错误,如果重复,采用第一条,其余删除<br />例子:同时多个操作<br />mysql> ALTER TABLE t2 DROP COLUMN c, DROP COLUMN d;<br />例子, 重命名 INTEGER 字段,从 a 到 b:<br />mysql> ALTER TABLE t1 CHANGE a b INTEGER;<br />例子 修改字段类型,仍然需要新旧字段名称,即使字段名称相同:<br />mysql> ALTER TABLE t1 CHANGE b b BIGINT NOT NULL;<br />也可以使用modify<br />mysql> ALTER TABLE t1 MODIFY b BIGINT NOT NULL;<br /><br />在mysql 5.0 可以使用FIRST or AFTER 字段来添加add 字段,默认是在最后<br />modify change 也可以使用<br />在mysql 5.0 InnoDB 存储引擎支持 ALTER TABLE 删除外健:<br />mysql>ALTER TABLE yourtablename DROP FOREIGN KEY fk_symbol;<br /><br />例子:<br />创建表<br />mysql> CREATE TABLE t1 (a INTEGER,b CHAR(10));<br />重命名表<br />mysql> ALTER TABLE t1 RENAME t2;<br />MODIFY a 字段为 TINYINT NOT NULL , 并且 change 字段 b,从 CHAR(10) 到 CHAR(20) 并改名为c:<br /><br />mysql> ALTER TABLE t2 MODIFY a TINYINT NOT NULL, CHANGE b c CHAR(20);<br />添加新字段 d:<br />mysql> ALTER TABLE t2 ADD d TIMESTAMP;<br />在a d 上增加索引:<br />mysql> ALTER TABLE t2 ADD INDEX (d), ADD INDEX (a);<br />删除字段c:<br />mysql> ALTER TABLE t2 DROP COLUMN c;<br />添加一个自动增长的字段c ,并且添加c 为主健:<br />mysql> ALTER TABLE t2 ADD c INT UNSIGNED NOT NULL AUTO_INCREMENT,<br />-> ADD PRIMARY KEY (c);<br />2.4.4.1. 修改外键<br />语法:<br />ALTER TABLE tbl_name<br />ADD [CONSTRAINT symbol] FOREIGN KEY [id] (index_col_name, ...)<br />REFERENCES tbl_name (index_col_name, ...)<br />[ON DELETE {RESTRICT | CASCADE | SET NULL | NO ACTION}]<br />[ON UPDATE {RESTRICT | CASCADE | SET NULL | NO ACTION}]<br />例子:<br />create table aa (id1 int not null,name varchar(20),primary key(id1))type=InnoDB;<br />create table b(id2 int not null,lessonname varchar(20),primary key(id2))type=InnoDB;<br />alter table b add FOREIGN KEY id (id2) references aa(id1);<br /><br />2.4.5. 删除<br />删除数据库<br />DROP {DATABASE | SCHEMA} [IF EXISTS] db_name<br />例子: mysql>drop DATABASE IF EXISTS testdb;<br />删除表<br />DROP [TEMPORARY] TABLE [IF EXISTS]<br />tbl_name [, tbl_name] ...<br />[RESTRICT | CASCADE]<br />例子: mysql>drop TABLE IF EXISTS testTable;<br />删除索引<br />DROP INDEX index_name ON tbl_name<br />例子: mysql>drop index testIndex on testTable;<br />重命名<br />RENAME TABLE tbl_name TO new_tbl_name<br />[, tbl_name2 TO new_tbl_name2] ...<br />例子:RENAME TABLE current_db.tbl_name TO other_db.tbl_name;<br />2.5. 数据库备份恢复<br />数据库备份<br />数据库备份命令：<br />mysqldump --opt --user=用户名 --password=密码 --default_character-set=字符集 -B数据库> 输出的sql文件<br />例子:<br />E:\mysql>Mysqldump --user=ptsdb --password=ptsdb --default_character-set=ujis --opt pts>dump.sql<br />参见批处理文件<br /><br />数据库导入命令：<br />mysql --user=用户名 --password=密码 --default_character-set=字符集 [数据库]&lt;导入的sql 语句<br /><br />E:\mysql>mysql -uptsdb -pptsdb --default-character-set=ujis<br /><br />例子： 对于InnoDB（没有设定字符集）<br />Following mysqldump import example for InnoDB tables is at least 100x faster than previous examples.<br />1. mysqldump --opt --user=username --password database > dumbfile.sql<br />2. Edit the dump file and put these lines at the beginning:<br />SET AUTOCOMMIT = 0;<br />SET FOREIGN_KEY_CHECKS=0;<br />3. Put these lines at the end:<br />SET FOREIGN_KEY_CHECKS = 1;<br />COMMIT;<br />SET AUTOCOMMIT = 1;<br />4. mysql --user=username --password database &lt; dumpfile.sql<br /><br />参数说明：<br />--add-drop-database<br />Add a DROP DATABASE statement before each CREATE DATABASE statement.<br /><br />--add-drop-table<br />Add a DROP TABLE statement before each CREATE TABLE statement.<br /><br />--all-databases, -A<br />Dump all tables in all databases. This is the same as using the --databases option and naming all the databases on the command line.<br />--databases, -B<br />Dump several databases. Normally, mysqldump treats the first name argument on the command line as a database name<br />and following names as table names. With this option, it treats all name arguments as database names.<br />CREATE DATABASE IF NOT EXISTS db_name and USE db_name statements are included in the output before each new database.<br /><br />--host=host_name, -h host_name<br />Dump data from the MySQL server on the given host. The default host is localhost.<br />--opt<br />This option is shorthand; it is the same as specifying --add-drop-table --add-locks --create-options<br />--disable-keys --extended-insert --lock-tables --quick --set-charset.<br />It should give you a fast dump operation and produce a dump file that can be reloaded into a MySQL server quickly.<br />In MySQL 5.0, --opt is on by default, but can be disabled with --skip-opt.<br />To disable only certain of the options enabled by --opt, use their --skip forms;<br />for example, --skip-add-drop-table or --skip-quick.<br />还有一些其他参数，有兴趣可以学习<br />2.6. 表数据备份<br />mysql>use test;<br />mysql> CREATE TABLE imptest(id INT, n VARCHAR(30));<br />Query OK, 0 rows affected (0.03 sec)<br />方法一：<br />导出使用：Mysqldump<br />E:\mysql>mysqldump -uptsdb -pptsdb -where "id>='100'"<br />test imptest<br />E:\mysql>mysqldump -uptsdb -pptsdb test imptest>e:\mysql\imp\imptest2.txt<br />导入使用 mysql<br />mysql -uptsdb -pptsdb&lt; imptest2.txt<br />方法二：<br />导出使用 select into OUTFILE<br />mysql> select * from imptest where id=101 into OUTFILE 'e:\\mysql\\imp\\test3.txt' FIELDS TERMINATED BY ',';<br /><br />导入使用 LOAD DATA INFILE<br />LOAD DATA [LOW_PRIORITY | CONCURRENT] [LOCAL] INFILE 'file_name.txt'<br />[REPLACE | IGNORE]<br />INTO TABLE tbl_name<br />[FIELDS<br />[TERMINATED BY 'string']<br />[[OPTIONALLY] ENCLOSED BY 'char']<br />[ESCAPED BY 'char' ]<br />]<br />[LINES<br />[STARTING BY 'string']<br />[TERMINATED BY 'string']<br />]<br />[IGNORE number LINES]<br />[(col_name_or_user_var,...)]<br />[SET col_name = expr,...]]<br />例子：<br />mysql> LOAD DATA INFILE 'e:\\mysql\\imp\\test3.txt' INTO TABLE imptest FIELDS TERMINATED BY ',';<br /><br />导入使用mysqlimport：<br />E:\mysql>mysqlimport -uptsdb -pptsdb --local test E:\mysql\imp\imp.txt<br />mysqlimport: Error: Table 'test.imp' doesn't exist, when using table: imp<br /><br />E:\mysql>mysqlimport -uptsdb -pptsdb --local test E:\mysql\imp\imptest.txt<br />test.imptest: Records: 2 Deleted: 0 Skipped: 0 Warnings: 0<br />注意：文件名必须跟表名相同<br />参数<br />-d or --delete 新数据导入数据表中之前删除数据数据表中的所有信息<br />-f or --force 不管是否遇到错误，mysqlimport将强制继续插入数据<br />-i or --ignore mysqlimport跳过或者忽略那些有相同唯一<br />-r or -replace 这个选项与－i选项的作用相反；此选项将替代 表中有相同唯一关键字的记录<br />2.7. 数据管道导入导出<br />E:\mysql>mysql -h10.5.1.66 -uroot -proot --default-character-set=name frontdb_20060415(databasename)<br />>e:/mysql/test.txt (输出的sql 语句)<br /><br /><br /><br />1:>;create databases newname(在新的server上建立空的数据库)<br />2:#/usr/local/mysql/bin/mysqldump databasename >*.sql(在旧的服务器上导出数据库)<br />3:#/usr/local/mysql/bin/mysql databasename &lt; *.sql(在新的服务器上导入*.sql)<br />注意数据库名要一一对应.<br />2.8. 各种字段的取值范围<br />TINYINT 1 byte<br />-128 - 127<br />TINYINT UNSIGNED 1 byte<br />0 ? 255 即0-（28-1）<br />SMALLINT 2 bytes<br />-32768 - 32767 即-215至(215-1)<br />SMALLINT UNSIGNED 2 bytes<br />0 - 65535 即0至(216-1)<br />MEDIUMINT 3 bytes<br />-8388608 - 8388607 即?223至(223-1)<br />MEDIUMINT UNSIGNED 3 bytes<br />0 - 16777215 即0至(224-1)<br />INT 或 INTEGER 4 bytes<br />-2147483648 - 2147483647 即?231至(231-1)<br />INT UNSIGNED 或 INTEGER UNSIGNED 4 bytes<br />0 - 4294967295 即0至(232-1)<br />BIGINT 8 bytes<br />-9223372036854775808 - 9223372036854775807 即?263至(263-1)<br />BIGINT UNSIGNED 8 bytes<br />0 - 18446744073709551615 即0至(264-1)<br />FLOAT 4 bytes<br />-3.402823466E+38 - -1.175494351E-38<br />0<br />1.175494351E-38 - 3.402823466E+38<br />DOUBLE 或 DOUBLE PRECISION 或 REAL 8 bytes<br />-1.7976931348623157E+308 - -2.2250738585072014E-308<br />0<br />2.2250738585072014E-308 - 1.7976931348623157E+308<br />DECIMAL[(M,[D])] 或 NUMERIC(M,D) 不定<br />由M(整个数字的长度,包括小数点,小数点左边的位数,小数点右边的位数,但不包括负号)和<br />D(小数点右边的位数)来决定,M缺省为10,D缺省为0<br />DATE 3 bytes<br />1000-01-01 - 9999-12-31<br />DATETIME 8 bytes<br />1000-01-01 00:00:00 - 9999-12-31 23:59:59<br />TIMESTAMP 4 bytes<br />1970-01-01 00:00:00 - 2037-12-31 23:59:59<br />TIME 3 bytes<br />-838:59:59' to 838:59:59<br />YEAR[(2|4)] 1 byte<br />缺省为4位格式,4位格式取值范围为1901 - 2155,0000,2位格式取值范围为70-69(1970-2069)<br />CHAR(M) [BINARY] 或 NCHAR(M) [BINARY] M bytes<br />M的范围为1 - 255,如果没有BINARY项,则不分大小写,NCHAR表示使用缺省的字符集.在数据库 中以空格补足,但在取出来时末尾的空格将被去掉.<br />[NATIONAL] VARCHAR(M) [BINARY]<br />Before 5.0.3 M的范围为0?255 L+1 bytes L&lt;=M<br />5.0.3 以及以后 M 范围为 0-65535<br />L+1 bytes L&lt;=M 0&lt;=M&lt;=256<br />L+2 bytes L&lt;=M 256&lt;=65535<br />在数据库中末尾的空格将自动去掉.<br />TINYBLOB 或 TINYTEXT L+1 bytes<br />255(2^8-1)个字符<br />BLOB 或 TEXT L+2 bytes<br />65535(2^16-1)个字符<br />MEDIUMBLOB 或 MEDIUMTEXT L+3 bytes<br />16777215 (2^24-1)个字符<br />LONGBLOB 或 LONGTEXT L+4 bytes<br />4294967295 (2^32-1)个字符<br />ENUM('value1','value2',...) 1 or 2 bytes<br />可以总共有65535个不同的值<br />SET('value1','value2',...) 1/2/3/4/8 bytes<br />最多有64个成员<br />2.9. 查询<br />2.9.1. limit<br />LIMIT子句可以用来限制由SELECT语句返回过来的数据数量，它有一个或两个参数，如果给出两个参数，<br />第一个参数指定返回的第一行在所有数据中的位置，从0开始（注意不是1），第二个参数指定最多返回行<br />数。例如：<br />select * from table LIMIT 5,10; #返回第6-15行数据<br />select * from table LIMIT 5; #返回前5行<br />select * from table LIMIT 0,5; #返回前5行<br />2.9.2. join 详解<br />还是先 Create table 吧<br /><br />create table emp(<br />id int not null primary key,<br />name varchar(10)<br />);<br /><br />create table emp_dept(<br />dept_id varchar(4) not null,<br />emp_id int not null,<br />emp_name varchar(10),<br />primary key (dept_id,emp_id));<br /><br />insert into emp() values<br />(1,"Dennis-1"),<br />(2,"Dennis-2"),<br />(3,"Dennis-3"),<br />(4,"Dennis-4"),<br />(5,"Dennis-5"),<br />(6,"Dennis-6"),<br />(7,"Dennis-7"),<br />(8,"Dennis-8"),<br />(9,"Dennis-9"),<br />(10,"Dennis-10");<br /><br />insert into emp_dept() values<br />("R&D",1,"Dennis-1"),<br />("DEv",2,"Dennis-2"),<br />("R&D",3,"Dennis-3"),<br />("Test",4,"Dennis-4"),<br />("Test",5,"Dennis-5");<br />("dddd",20,"eeee");<br />>> left join<br />-------------<br />select a.id,a.name,b.dept_id<br />from emp a left join emp_dept b on (a.id=b.emp_id);<br /><br /># 挑出左边的 table emp 中的所有资料,即使 emp_dept 中没有的资料也挑出来,没有的就用 NULL 来显示,<br /># 也即显示资料是以左边的 table emp 中的资料为基础<br /><br />mysql> select a.id,a.name,b.dept_id<br />-> from emp a left join emp_dept b on (a.id=b.emp_id);<br />+----+-----------+---------+<br />| id | name | dept_id |<br />+----+-----------+---------+<br />| 1 | Dennis-1 | R&D |<br />| 2 | Dennis-2 | DEv |<br />| 3 | Dennis-3 | R&D |<br />| 4 | Dennis-4 | Test |<br />| 5 | Dennis-5 | Test |<br />| 6 | Dennis-6 | NULL |<br />| 7 | Dennis-7 | NULL |<br />| 8 | Dennis-8 | NULL |<br />| 9 | Dennis-9 | NULL |<br />| 10 | Dennis-10 | NULL |<br />+----+-----------+---------+<br /># 挑出 table emp 中有而 table emp_dept 中没有的人员资料<br />select a.id,a.name,b.dept_id<br />from emp a left join emp_dept b on (a.id=b.emp_id)<br />where b.dept_id IS NULL;<br /><br />mysql> select a.id,a.name,b.dept_id<br />-> from emp a left join emp_dept b on (a.id=b.emp_id)<br />-> where b.dept_id IS NULL;<br />+----+-----------+---------+<br />| id | name | dept_id |<br />+----+-----------+---------+<br />| 6 | Dennis-6 | NULL |<br />| 7 | Dennis-7 | NULL |<br />| 8 | Dennis-8 | NULL |<br />| 9 | Dennis-9 | NULL |<br />| 10 | Dennis-10 | NULL |<br />+----+-----------+---------+<br /><br /># 把 table emp_dept 放在左边的情形(当然以 emp_dept 中的数据为基础来显示资料,emp 中比emp_dept 中多的资料也就不会显示出来了):<br />select a.id,a.name,b.dept_id<br />from emp_dept b left join emp a on (a.id=b.emp_id);<br />mysql> select a.id,a.name,b.dept_id<br />-> from emp_dept b left join emp a on (a.id=b.emp_id);<br />+------+----------+---------+<br />| id | name | dept_id |<br />+------+----------+---------+<br />| NULL | NULL | dddd |<br />| 2 | Dennis-2 | DEv |<br />| 1 | Dennis-1 | R&D |<br />| 3 | Dennis-3 | R&D |<br />| 4 | Dennis-4 | Test |<br />| 5 | Dennis-5 | Test |<br />+------+----------+---------+<br />>> right join<br />---------------<br />select a.id,a.name,b.dept_id<br />from emp a right join emp_dept b on (a.id=b.emp_id);<br /># 挑资料时以右边 table emp_dept 中的资料为基础来显示资料<br />mysql> select a.id,a.name,b.dept_id<br />-> from emp a right join emp_dept b on (a.id=b.emp_id);<br />+------+----------+---------+<br />| id | name | dept_id |<br />+------+----------+---------+<br />| NULL | NULL | dddd |<br />| 2 | Dennis-2 | DEv |<br />| 1 | Dennis-1 | R&D |<br />| 3 | Dennis-3 | R&D |<br />| 4 | Dennis-4 | Test |<br />| 5 | Dennis-5 | Test |<br />+------+----------+---------+<br />6 rows in set (0.00 sec)<br /># 我们再把 table 的位置交换一下,再用 right join 试试<br /><br />select a.id,a.name,b.dept_id<br />from emp_dept b right join emp a on (a.id=b.emp_id);<br /><br />mysql> select a.id,a.name,b.dept_id<br />-> from emp_dept b right join emp a on (a.id=b.emp_id);<br />+----+-----------+---------+<br />| id | name | dept_id |<br />+----+-----------+---------+<br />| 1 | Dennis-1 | R&D |<br />| 2 | Dennis-2 | DEv |<br />| 3 | Dennis-3 | R&D |<br />| 4 | Dennis-4 | Test |<br />| 5 | Dennis-5 | Test |<br />| 6 | Dennis-6 | NULL |<br />| 7 | Dennis-7 | NULL |<br />| 8 | Dennis-8 | NULL |<br />| 9 | Dennis-9 | NULL |<br />| 10 | Dennis-10 | NULL |<br />+----+-----------+---------+<br /># 是不是和 left join 一样了?<br />>> inner join STRAIGHT_JOIN<br />select a.id,a.name,b.dept_id<br />from emp a ,emp_dept b<br />where a.id=b.emp_id;<br /><br />mysql> select a.id,a.name,b.dept_id<br />-> from emp a ,emp_dept b<br />-> where a.id=b.emp_id;<br />+----+----------+---------+<br />| id | name | dept_id |<br />+----+----------+---------+<br />| 2 | Dennis-2 | DEv |<br />| 1 | Dennis-1 | R&D |<br />| 3 | Dennis-3 | R&D |<br />| 4 | Dennis-4 | Test |<br />| 5 | Dennis-5 | Test |<br />+----+----------+---------+<br />2.9.3. 别名 alias<br />你可以在GROUP BY、ORDER BY或在HAVING部分中使用别名引用列。别名也可以用来为列取一个更好点的名字：<br />SELECT SQRT(a*b) as rt FROM table_name GROUP BY rt HAVING rt > 0;<br />SELECT id,COUNT(*) AS cnt FROM table_name GROUP BY id HAVING cnt > 0;<br />SELECT id AS "Customer identity" FROM table_name;<br />注意，你的 ANSI SQL 不允许你在一个WHERE子句中引用一个别名。这是因为在WHERE代码被执行时，列值还可能没有终结。例如下列查询是不合法：<br />SELECT id,COUNT(*) AS cnt FROM table_name WHERE cnt > 0 GROUP BY id;<br />WHERE语句被执行以确定哪些行应该包括GROUP BY部分中，而HAVING用来决定应该只用结果集合中的哪些行。<br />2.9.4. 正则<br />正则表达式（regex）是定义复杂查询的一个强有力的工具。<br />这里是一个简单的资料，它忽略了一些详细的信息。<br />正则表达式定义了一个字符串的规则。最简单的正则表达式不包含任何保留字。例如，<br /><br />正则表达式hello只和字符串“hello”匹配。<br />一般的正则表达式使用了某些特殊的结构，所以它能匹配更多的字符串。例如，正则<br />表达式hello|word既能匹配字符串“hello”也能匹配字符串“word”。<br />举一个更复杂一点的例子，正则表达式B[an]*s可以匹配字符串“Bananas”、“Baaaaa<br />s”<br />、“Bs”以及其他任何以B开头以s结尾的字符串，中间可以包括任意个a和任意个n的组<br />合。<br />一个正则表达式中的可以使用以下保留字<br />^<br />所匹配的字符串以后面的字符串开头<br />mysql> select "fonfo" REGEXP "^fo$"; -> 0（表示不匹配）<br />mysql> select "fofo" REGEXP "^fo"; -> 1（表示匹配）<br />$<br />所匹配的字符串以前面的字符串结尾<br />mysql> select "fono" REGEXP "^fono$"; -> 1（表示匹配）<br />mysql> select "fono" REGEXP "^fo$"; -> 0（表示不匹配）<br />..<br />匹配任何字符（包括新行）<br />mysql> select "fofo" REGEXP "^f.*"; -> 1（表示匹配）<br />mysql> select "fonfo" REGEXP "^f.*"; -> 1（表示匹配）<br />a*<br />匹配任意0-n多个a（包括空串）<br />mysql> select "Ban" REGEXP "^Ba*n"; -> 1（表示匹配）<br />mysql> select "Baaan" REGEXP "^Ba*n"; -> 1（表示匹配）<br />mysql> select "Bn" REGEXP "^Ba*n"; -> 1（表示匹配）<br />a+<br />匹配任意1-n多个a（不包括空串）<br />mysql> select "Ban" REGEXP "^Ba+n"; -> 1（表示匹配）<br />mysql> select "Bn" REGEXP "^Ba+n"; -> 0（表示不匹配）<br />a?<br />匹配0-1个a<br />mysql> select "Bn" REGEXP "^Ba?n"; -> 1（表示匹配）<br />mysql> select "Ban" REGEXP "^Ba?n"; -> 1（表示匹配）<br />mysql> select "Baan" REGEXP "^Ba?n"; -> 0（表示不匹配）<br />de|abc<br />匹配de或abc<br />mysql> select "pi" REGEXP "pi|apa"; -> 1（表示匹配）<br />mysql> select "axe" REGEXP "pi|apa"; -> 0（表示不匹配）<br />mysql> select "apa" REGEXP "pi|apa"; -> 1（表示匹配）<br />mysql> select "apa" REGEXP "^(pi|apa)$"; -> 1（表示匹配）<br />mysql> select "pi" REGEXP "^(pi|apa)$"; -> 1（表示匹配）<br />mysql> select "pix" REGEXP "^(pi|apa)$"; -> 0（表示不匹配）<br />(abc)*<br />匹配任意多个（0-n个）abc（包括空串)<br />mysql> select "pi" REGEXP "^(pi)*$"; -> 1（表示匹配）<br />mysql> select "pip" REGEXP "^(pi)*$"; -> 0（表示不匹配）<br />mysql> select "pipi" REGEXP "^(pi)*$"; -> 1（表示匹配）<br />{1}<br />{2,3}<br />这是一个更全面的方法，它可以实现前面好几种保留字的功能<br />a*<br />可以写成a{0,}<br />a+<br />可以写成a{1,}<br />a?<br />可以写成a{0,1}<br />在{}内只有一个整型参数i，表示字符只能出现i次；在{}内有一个整型参数i，<br />后面跟一个“，”，表示字符可以出现i次或i次以上；在{}内只有一个整型参数i，<br />后面跟一个“，”，再跟一个整型参数j,表示字符只能出现i次以上，j次以下<br />（包括i次和j次）。其中的整型参数必须大于等于0，小于等于 RE_DUP_MAX（默认是25<br />5）。<br />如果有两个参数，第二个必须大于等于第一个<br />[a-dX]<br />匹配“a”、“b”、“c”、“d”或“X”<br />[^a-dX]<br />匹配除“a”、“b”、“c”、“d”、“X”以外的任何字符。<br />“[”、“]”必须成对使用<br />mysql> select "aXbc" REGEXP "[a-dXYZ]"; -> 1（表示匹配）<br />mysql> select "aXbc" REGEXP "^[a-dXYZ]$"; -> 0（表示不匹配）<br />mysql> select "aXbc" REGEXP "^[a-dXYZ]+$"; -> 1（表示匹配）<br />mysql> select "aXbc" REGEXP "^[^a-dXYZ]+$"; -> 0（表示不匹配）<br />mysql> select "gheis" REGEXP "^[^a-dXYZ]+$"; -> 1（表示匹配）<br />mysql> select "gheisa" REGEXP "^[^a-dXYZ]+$"; -> 0（表示不匹配）<br />------------------------------------------------------------<br />[[.characters.]]<br />表示比较元素的顺序。在括号内的字符顺序是唯一的。但是括号中可以包含通配符,<br />所以他能匹配更多的字符。举例来说：正则表达式[[.ch.]]*c匹配chchcc的前五个字符<br />。<br />[=character_class=]<br />表示相等的类，可以代替类中其他相等的元素，包括它自己。例如，如果o和(+)是<br />一个相等的类的成员，那么[[=o=]]、[[=(+)=]]和[o(+)]是完全等价的。<br />[:character_class:]<br />在括号里面，在[:和:]中间是字符类的名字，可以代表属于这个类的所有字符。<br />字符类的名字有: alnum、digit、punct、alpha、graph、space、blank、lower、uppe<br />r、cntrl、print和xdigit<br />mysql> select "justalnums" REGEXP "[[:alnum:]]+"; -> 1（表示匹配）<br />mysql> select "!!" REGEXP "[[:alnum:]]+"; -> 0（表示不匹配）<br />[[:&lt;:><br />[[:>:]]<br />分别匹配一个单词开头和结尾的空的字符串，这个单词开头和结尾都不是包含在alnum中<br />的字符也不能是下划线。<br />mysql> select "a word a" REGEXP "[[:&lt;:>:]]"; -> 1（表示匹配）<br />mysql> select "a xword a" REGEXP "[[:&lt;:>:]]"; -> 0（表示不匹配）<br />mysql> select "weeknights" REGEXP "^(wee|week)(knights|nights)$"; -> 1（表示<br />匹配）<br />2.9.5. Select 中使用 IF Statement<br />mysql> select * from test;<br />+------+------+------+-------+<br />| dept | id | sex | name |<br />+------+------+------+-------+<br />| 1 | 1 | 0 | wang |<br />| 2 | 2 | 1 | zhang |<br />| 3 | 3 | 0 | li |<br />+------+------+------+-------+<br />3 rows in set (0.00 sec)<br />mysql> select dept,id,if(sex=0,'女','男') sex,name from test;<br />+------+------+-----+-------+<br />| dept | id | sex | name |<br />+------+------+-----+-------+<br />| 1 | 1 | 女 | wang |<br />| 2 | 2 | 男 | zhang |<br />| 3 | 3 | 女 | li |<br />+------+------+-----+-------+<br />3 rows in set (0.00 sec)<br />2.9.6. Select中使用CASE Statement<br />mysql> select dept,id,(case sex when '0' then '女' else '男' end) as sex,name from test;<br />+------+------+------+-------+<br />| dept | id | sex | name |<br />+------+------+------+-------+<br />| 1 | 1 | 女 | wang |<br />| 2 | 2 | 男 | zhang |<br />| 3 | 3 | 女 | li |<br />+------+------+------+-------+<br />mysql> select (case dept when '1' then 'no1' when '2' then 'no2' else 'other' end) as dept from test;<br />+-------+<br />| dept |<br />+-------+<br />| no1 |<br />| no2 |<br />| other |<br />+-------+<br />3 rows in set (0.00 sec)<br />注意: 相当于Oracle 中的decode 和case when<br />在统计报表中很有用处<br /><br />2.10. 存储过程和函数<br />CREATE PROCEDURE sp_name ([proc_parameter[,...]])<br />[characteristic ...] routine_body<br /><br />CREATE FUNCTION sp_name ([func_parameter[,...]])<br />RETURNS type<br />[characteristic ...] routine_body<br /><br />proc_parameter:<br />[ IN | OUT | INOUT ] param_name type<br /><br />func_parameter:<br />param_name type<br /><br />type:<br />Any valid MySQL data type<br /><br />characteristic:<br />LANGUAGE SQL<br />| [NOT] DETERMINISTIC<br />| { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }<br />| SQL SECURITY { DEFINER | INVOKER }<br />| COMMENT 'string'<br /><br />routine_body:<br />Valid SQL procedure statement or statements<br /><br />例子：创建一个过程hello，显示问候语<br />mysql> delimiter ;<br />mysql> drop PROCEDURE if exists hello;<br />Query OK, 0 rows affected (0.00 sec)<br /><br />mysql> delimiter //<br />mysql><br />mysql> CREATE PROCEDURE hello (IN s varchar(20))<br />-> BEGIN<br />-> SELECT CONCAT('Hello,',s,'!') as hello;<br />-> END;<br />-> //<br />Query OK, 0 rows affected (0.00 sec)<br /><br />mysql> delimiter ;<br />mysql> call hello('wangyl');<br />+---------------+<br />| hello |<br />+---------------+<br />| Hello,wangyl! |<br />+---------------+<br />1 row in set (0.00 sec)<br /><br />Query OK, 0 rows affected (0.00 sec)<br />例子2: 查询t表的记录总数<br />mysql> delimiter //<br /><br />mysql> CREATE PROCEDURE simpleproc (OUT param1 INT)<br />-> BEGIN<br />-> SELECT COUNT(*) INTO param1 FROM t;<br />-> END<br />-> //<br />Query OK, 0 rows affected (0.00 sec)<br /><br />mysql> delimiter ;<br /><br />mysql> CALL simpleproc(@a);<br />Query OK, 0 rows affected (0.00 sec)<br /><br />mysql> SELECT @a;<br />+------+<br />| @a |<br />+------+<br />| 3 |<br />+------+<br />1 row in set (0.00 sec)<br /><br />例子：创建一个函数<br />mysql> delimiter ;<br />mysql> drop FUNCTION if exists dateFunction;<br />Query OK, 0 rows affected (0.00 sec)<br /><br />mysql> delimiter //<br />mysql> CREATE FUNCTION dateFunction (iCase int)<br />-> RETURNS varchar(50)<br />-> begin<br />-> DECLARE iType int;<br />-> DECLARE sReturn varchar(50);<br />-> set iType =icase +1;<br />-> case iType<br />-> when 1 then select DATE_FORMAT(NOW(),'%Y-%m-%d') into sReturn;<br />-> when 2 then select DATE_FORMAT(NOW(),'%W %M %Y') into sReturn;<br />-> else<br />-> select NOW() into sReturn;<br />-> end case;<br />-> return sReturn;<br />-> end;<br />-> //<br />Query OK, 0 rows affected (0.00 sec)<br /><br />mysql> delimiter ;<br />mysql> select dateFunction(0);<br />+-----------------+<br />| dateFunction(0) |<br />+-----------------+<br />| 2005-11-14 |<br />+-----------------+<br />1 row in set (0.00 sec)<br /><br />mysql> select dateFunction(1);<br />+----------------------+<br />| dateFunction(1) |<br />+----------------------+<br />| Monday November 2005 |<br />+----------------------+<br />1 row in set (0.00 sec)<br /><br />mysql> select dateFunction(2);<br />+---------------------+<br />| dateFunction(2) |<br />+---------------------+<br />| 2005-11-14 15:05:43 |<br />+---------------------+<br />1 row in set (0.00 sec)<br /><br />2.11. 补充：trigger<br />CREATE TRIGGER trigger_name trigger_time trigger_event<br />ON tbl_name FOR EACH ROW trigger_stmt<br />CREATE TABLE test1(a1 INT);<br />CREATE TABLE test2(a2 INT);<br />CREATE TABLE test3(a3 INT NOT NULL AUTO_INCREMENT PRIMARY KEY);<br />CREATE TABLE test4(<br />a4 INT NOT NULL AUTO_INCREMENT PRIMARY KEY,<br />b4 INT DEFAULT 0<br />);<br /><br />DELIMITER |<br /><br />CREATE TRIGGER testref BEFORE INSERT ON test1<br />FOR EACH ROW BEGIN<br />INSERT INTO test2 SET a2 = NEW.a1;<br />DELETE FROM test3 WHERE a3 = NEW.a1;<br />UPDATE test4 SET b4 = b4 + 1 WHERE a4 = NEW.a1;<br />END|<br /><br />DELIMITER ;<br /><br />INSERT INTO test3 (a3) VALUES<br />(NULL), (NULL), (NULL), (NULL), (NULL),<br />(NULL), (NULL), (NULL), (NULL), (NULL);<br /><br />INSERT INTO test4 (a4) VALUES<br />(0), (0), (0), (0), (0), (0), (0), (0), (0), (0);<br /><br />If you insert the following values into table test1 as shown here:<br /><br />mysql> INSERT INTO test1 VALUES<br />-> (1), (3), (1), (7), (1), (8), (4), (4);<br />Query OK, 8 rows affected (0.01 sec)<br />Reco
          <br/>
          <span style="color:red;">
            <a href="http://jiakechong.javaeye.com/blog/211644#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 04 Jul 2008 16:37:02 +0800</pubDate>
        <link>http://jiakechong.javaeye.com/blog/211644</link>
        <guid>http://jiakechong.javaeye.com/blog/211644</guid>
      </item>
  </channel>
</rss>