不应该是家,窝更适合一点

发布新日志

  • java数据库链接程序

    2013-09-26 10:27:27

    import java.sql.*; 
    import java.io.*;
    import java.util.*;

    public class DatabaseLink {
     String sDB;//从属性文件获取的数据库驱动名
     String sUser,sPassword;//从属性文件获取的用户名和密码
     String sDataBaseDriver;  //jdbc-odbc桥:sun.jdbc.odbc.JdbcOdbcDriver
     String sJdbcOdbcConnHead="jdbc:odbc:";//jdbc-odbc驱动的头
     Connection conn=null; 
     Statement stmt=null;

     /*
      建立数据库的连接
     */
       
      public DatabaseLink()throws IOException{//连接数据库
         try{
          Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
         }catch(ClassNotFoundException ex){
          System.out.println(ex.getMessage());
         }     
          try {
                conn = DriverManager.getConnection("jdbc:odbc:comm","Administrator", "");
                stmt = conn.createStatement();//创建一个 Statement 对象来将 SQL 语句发送到数据库。
             } catch (SQLException ex1) {
                System.out.println(ex1.getMessage());
             } 
        }//end of the method DatabaseLink
     
     /*//////////////数据库的关闭/////////////////////////////////*/
     public void databaseclose(){
      try{   
       if(stmt!=null){
        stmt.close();
        stmt=null;
       }//end of if...
       
       if(conn!=null){
        conn.close();
        conn=null;       
       }//end of if...
      }catch(SQLException e){
      }//end of try...catch...
     }//end of the method databaseclose
     

     ///////////////////////数据库的查询///////////////////////////
     public ResultSet query(String sql) {
      ResultSet rs=null;
      
      try{
       if(conn==null){
        DatabaseLink();
       }//end of if...    
       rs=stmt.executeQuery(sql);   
      }catch (SQLException e){   
      }finally{
      //databaseclose();
       return rs;//返回sql语句的执行结果
      }//end of try...catch...finally...
     }//end of the method query(String)
     
     
     
     //////////要查找的列名,表名,和条件组成查询语句/////////////////
     public ResultSet query(String sColumn,String sTableName,String sCondition) {
      ResultSet rs=null;
      try{
       if(conn==null){
        DatabaseLink(); 
      }//end of if....  
       rs=stmt.executeQuery(" select "+sColumn+" from "+sTableName+" where "+sCondition);   
      }catch (SQLException e){   
      }finally{
      //databaseclose();
       return rs;//返回sql语句的执行结果
      }//end of try...catch...finally...
     }//end of the method query(String,String,String)
     
     
     
     ////////////////根据表名 查找表名中的全部内容/////////////////////////////
     public ResultSet queryAll(String sTableName){
      ResultSet rs=null;
      try{
       if(conn==null){
         DatabaseLink();
       }//end of if...
       
       rs=stmt.executeQuery(" select * from "+sTableName);   
      }catch(SQLException e){    
      }finally{
       return rs;//返回sql语句的执行结果
      }//end of try...catch...finally...
     
     }//end of the method queryAll(String)
     
     
     /*
      根据表名和条件名 来查找表中的全部信息
     */
     public ResultSet queryAll(String sTableName,String sCondition){
      ResultSet rs;
      
      try{
       if(conn==null){
         DatabaseLink();
       }//end of if...   
       rs=stmt.executeQuery(" select * from "+sTableName+" where "+sCondition);
       return rs;
      }catch(SQLException e){
       //System.err.println("192zxf查询:"+e.getMessage());
       return null;
      }//end of try...catch....
     }//end of the method queryAll(String,String)
     
     
     
     
     /*
      ///////////////数据库的插入///////////////////////////
     */

     public boolean insert(String sql){
      try{
       if(stmt!=null){
        stmt.close();
        stmt=null;
       }//end of if...
       if(conn==null){
        DatabaseLink();
       }//end of if...
       
       stmt=conn.createStatement();
       int result=stmt.executeUpdate(sql);
       if(result==0){
        conn.rollback();
        return false;
       }//end of if...
       conn.commit();   
      }catch(SQLException e){   
       return false;
      }//end of try...catch....  
      return true;
     }//end of the method insert(String)
     
     
     /*////////////////////
       根据表名,列名和列名值组成插入语句。插入一条记录
     */
     public boolean insert(String sTable,String strRowName[],String[] strRowValue){
      int iLength=strRowName.length;//要插入列的个数
      
      String sql=" insert into "+sTable+" ( ";
      for(int i=0;i<iLength-1;i++){
       sql=sql+" "+strRowName[i]+",";
      }//end of for...
      
      sql=sql+strRowName[iLength-1]+") values (";
      for(int i=0;i<iLength-1;i++){
       sql=sql+" '"+strRowValue[i]+"',";
      }//end of for...
      
      sql=sql+"'"+strRowValue[iLength-1]+"')";
      try{
       if(stmt!=null){
        stmt.close();
        stmt=null;
       }//end of if...
       if(conn==null){
        DatabaseLink();
       }//end of if...
       stmt=conn.createStatement();
       
       int result=stmt.executeUpdate(sql);
       if(result==0){
        conn.rollback();
        return false;
       }//end of if...
       conn.commit();   
      }catch(SQLException e){   
       return false;
      }//end of try...catch....  
      return true;
     }//end of the method insert(String)
     
     /*
      根据表名,列名和列名值组成插入语句。插入一批记 录
     */
     public boolean insertMany(String sTable,String strRowName[],String[][] strRowValue){
      int iNameLength=strRowName.length;//总共的表字段的个数
      int iValueLength=strRowValue.length;//所插入的行数
      
      String sql=" insert into "+sTable+" ( ";
      for(int i=0;i<iNameLength-1;i++){
       sql=sql+" "+strRowName[i]+",";
      }//end of for...
      
      sql=sql+strRowName[iNameLength-1]+") values (";
      
      for(int j=0;j<iValueLength-1;j++){
       for(int i=0;i<iNameLength-1;i++){
        sql=sql+" '"+strRowValue[j][i]+"',";
       }//end of for...
       sql=sql+" '"+strRowValue[j][iNameLength-1] +"'), (";
      }//end of outer for....
      
      for(int i=0;i<iNameLength-1;i++){
       sql=sql+" '"+strRowValue[iValueLength-1][i]+"',";
      }//end of for...
      
      sql=sql+" '"+strRowValue[iValueLength-1][iNameLength-1] +"')";
      
      try{
       if(stmt!=null){
        stmt.close();
        stmt=null;
       }//end of if...
       if(conn==null)
        DatabaseLink();
       stmt=conn.createStatement();
       
       int result=stmt.executeUpdate(sql);
       if(result==0){
        conn.rollback();
        return false;
       }//end of if...
       conn.commit();   
      }catch(SQLException e){   
       return false;
      }//end of try...catch....  
      return true;
     }//end of the method insertMany(String)
     
     
     
     /*
        ////////////////////数据库记录的删除///////////////////////////
     */
     
     //删除一项记录
     public boolean delete(String sql){
      try{
       if(stmt!=null){
        stmt.close();
        stmt=null;
       }//end of if...
       if(conn==null){
        DatabaseLink();
       }//end of if...
       
       stmt=conn.createStatement();
       int result=stmt.executeUpdate(sql);
       if(result==0){
        conn.rollback();
        return false;
       }//end of if...
       conn.commit();   
      }catch(SQLException e){   
       return false;
      }//end of try...catch....  
      return true;  
     }//end of the method delete(String)
     
     
     ////////////根据表名和条件删除记录/////////////////////
     public boolean delete(String sTable,String sCondition){
      try{
       if(stmt!=null){
        stmt.close();
        stmt=null;
       }//end of if...
       if(conn==null)
        DatabaseLink();
       stmt=conn.createStatement();
       
       String sDelete="delete from"+sTable+" where "+sCondition;
       
       int result=stmt.executeUpdate(sDelete);
       if(result==0){
        conn.rollback();
        return false;
       }//end of if...
       conn.commit();   
      }catch(SQLException e){   
       return false;
      }//end of try...catch....  
      return true;
     }//end of the method delete(String,String,String)
     
     
     ///////////根据表名删除所有记录////////////////
     public boolean deleteAll(String sTable){
      try{
       if(stmt!=null){
        stmt.close();
        stmt=null;
       }//end of if...
       if(conn==null){
        DatabaseLink();
       }//end of if...
       stmt=conn.createStatement();
       String sDelete=" delete from "+sTable;
       int result=stmt.executeUpdate(sDelete);
       if(result==0){
        conn.rollback();
        return false;
       }//end of if....
       conn.commit();
      }catch(SQLException e){   
       return false;
      }//end of try...catch..
      return true;
     }//end of the method deleteAll(String)
     
     
     
     /*
     //////////////更新数据库的记录///////////////////////
     */
     public boolean update(String sql){
      try{
       if(stmt!=null){
        stmt.close();
        stmt=null;
       }//end of if...
       if(conn==null){
        DatabaseLink();
       }//end of if....
       stmt=conn.createStatement();
       
       int result=stmt.executeUpdate(sql);
       
       if(result==0){
        conn.rollback();
        return false;
       }//end of if....
       conn.commit();
      }catch(SQLException e){   
       return false;
      }//end of try...catch....
      return true;
     }//end of the mehtod update(String)
     
     /*
      根据表名,条件,(查找列,旧的值,新的值)
     */
     public boolean update(String sTable,String sColumn,String sOldColumn,String sNewColumn){
      try{
       if(stmt!=null){
        stmt.close();
        stmt=null;
       }//end of if....
       if(conn==null){
        DatabaseLink();
       }//end of if....
       String sQuery=" select * from "+sTable+" where "+sColumn+"="+sOldColumn;
       ResultSet rs=query(sQuery);
       if(rs.next()){
        rs.close();
        String sUpdate="update "+sTable+" set "+sColumn+" ="+sOldColumn+" where "+sColumn+" ="+sNewColumn;
        int result=stmt.executeUpdate(sUpdate);
        if(result==0){
         conn.rollback();
         return false;     
        }else{
         conn.commit();     
        }//end of if....
       }else{
        return false;
       }//end of if....
      }catch(SQLException e){  
       return false;
      }//end of try...catch....
      return true;
     }//end of the method update(String,String,String)
    }


  • ORACLE数据库导出导入

    2013-01-21 18:17:05

     数据导出:

      1、将数据库test完全导出,用户名system 密码manager 导出到d:/daochu.dmp中

      exp system/manager@test file=d:/daochu.dmp full=y

      2、将数据库中system用户与sys用户的表导出

      exp system/manager@test file=d:/daochu.dmp wner=(system,sys)

      3、将数据库中的表inner_notify、notify_staff_relat导出

      exp aichannel/aichannel@testdb2 file= d:/data/newsmgnt.dmp tables=(inner_notify,notify_staff_relat)

      4、将数据库中的表table1中的字段filed1以"00"打头的数据导出

      exp system/manager@test file=d:/daochu.dmp tables=(table1) query=/" where filed1 like 00%/"

      上面是常用的导出,对于压缩,既用winzip把dmp文件可以很好的压缩。也可以在上面命令后面 加上 compress=y 来实现。

      数据导入:

      1、将d:/daochu.dmp 中的数据导入 test数据库中。

      imp system/manager@test  file=d:/daochu.dmp   imp aichannel/aichannel@hust full=y  file=file= d:/data/newsmgnt.dmp ignore=y

      上面可能有点问题,因为有的表已经存在,然后它就报错,对该表就不进行导入。在后面加上 ignore=y 就可以了。

      2、将d:/daochu.dmp中的表table1 导入

      imp system/manager@test  file=d:/daochu.dmp  tables=(table1)

      基本上上面的导入导出够用了。不少情况要先是将表彻底删除,然后导入。

      注意: 操作者要有足够的权限,权限不够它会提示。数据库时可以连上的。可以用tnsping test 来获得数据库test能否连上。

      以上记载,只是oracle数据导入导出的最基本方法,在实际应用中会有各种因素影响导入导出的结果,所以要灵活运用这些最基本的命令,但也要统筹整个oracle运行的环境来考虑问题。

  • 数据库查询优化原则

    2011-02-21 08:58:13

    1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。

      2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如:

    select id from t where num is null

      可以在num上设置默认值0,确保表中num列没有null值,然后这样查询:

    select id from t where num=0

      3.应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。

      4.应尽量避免在 where 子句中使用 or 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描,如:

    select id from t where num=10 or num=20

      可以这样查询:

    select id from t where num=10   
    union all   
    select id from t where num=20

      5.in 和 not in 也要慎用,否则会导致全表扫描,如:

    select id from t where num in(1,2,3)

      对于连续的数值,能用 between 就不要用 in 了:

      select id from t where num between 1 and 3

      6.下面的查询也将导致全表扫描:

    select id from t where name like '%abc%'

      若要提高效率,可以考虑全文检索。

      7.如果在 where 子句中使用参数,也会导致全表扫描。因为SQL只有在运行时才会解析局部变量,但优化程序不能将访问计划的选择推迟到运行时;它必须在编译时进行选择。然而,如果在编译时建立访问计划,变量的值还是未知的,因而无法作为索引选择的输入项。如下面语句将进行全表扫描:

    select id from t wherenum=@num

      可以改为强制查询使用索引:

    select id from t with(index(索引名)) wherenum=@num

      8.应尽量避免在 where 子句中对字段进行表达式操作,这将导致引擎放弃使用索引而进行全表扫描。如:

    select id from t where num/2=100

      应改为:

    select id from t where num=100*2

      9.应尽量避免在where子句中对字段进行函数操作,这将导致引擎放弃使用索引而进行全表扫描。如:

    select id from t where substring(name,1,3)='abc'--name以abc开头的id   
    select id from t where datediff(day,createdate,'2005-11-30')=0--‘2005-11-30’生成的id

      应改为:

    select id from t where name like 'abc%'   
    select id from t where createdate>='2005-11-30' and createdate<'2005-12-1'

    10.不要在 where 子句中的“=”左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引。

    11.在使用索引字段作为条件时,如果该索引是复合索引,那么必须使用到该索引中的第一个字段作为条件时才能保证系统使用该索引,否则该索引将不会被使用,并且应尽可能的让字段顺序与索引顺序相一致。

    12.不要写一些没有意义的查询,如需要生成一个空表结构:

    select col1,col2 into #t from t where 1=0

      这类代码不会返回任何结果集,但是会消耗系统资源的,应改成这样:

    create table #t(...)

    13.很多时候用 exists 代替 in 是一个好的选择:

    select num from a where num in(select num from b)

      用下面的语句替换:

    select num from a where exists(select 1 from b where num=a.num)

    14.并不是所有索引对查询都有效,SQL是根据表中数据来进行查询优化的,当索引列有大量数据重复时,SQL查询可能不会去利用索引,如一表中有字段sex,male、female几乎各一半,那么即使在sex上建了索引也对查询效率起不了作用。

    15.索引并不是越多越好,索引固然可以提高相应的 select 的效率,但同时也降低了 insert 及 update 的效率,因为 insert 或 update 时有可能会重建索引,所以怎样建索引需要慎重考虑,视具体情况而定。一个表的索引数最好不要超过6个,若太多则应考虑一些不常使用到的列上建的索引是否有必要。

    16.应尽可能的避免更新 clustered 索引数据列,因为 clustered 索引数据列的顺序就是表记录的物理存储顺序,一旦该列值改变将导致整个表记录的顺序的调整,会耗费相当大的资源。若应用系统需要频繁更新 clustered 索引数据列,那么需要考虑是否应将该索引建为 clustered 索引。

    17.尽量使用数字型字段,若只含数值信息的字段尽量不要设计为字符型,这会降低查询和连接的性能,并会增加存储开销。这是因为引擎在处理查询和连接时会逐个比较字符串中每一个字符,而对于数字型而言只需要比较一次就够了。

    18.尽可能的使用 varchar/nvarchar 代替 char/nchar ,因为首先变长字段存储空间小,可以节省存储空间,其次对于查询来说,在一个相对较小的字段内搜索效率显然要高些。

    19.任何地方都不要使用 select * from t ,用具体的字段列表代替“*”,不要返回用不到的任何字段。

    20.尽量使用表变量来代替临时表。如果表变量包含大量数据,请注意索引非常有限(只有主键索引)。

    21.避免频繁创建和删除临时表,以减少系统表资源的消耗。

    22.临时表并不是不可使用,适当地使用它们可以使某些例程更有效,例如,当需要重复引用大型表或常用表中的某个数据集时。但是,对于一次性事件,最好使用导出表。

    23.在新建临时表时,如果一次性插入数据量很大,那么可以使用 select into 代替 create table,避免造成大量 log ,以提高速度;如果数据量不大,为了缓和系统表的资源,应先create table,然后insert。

    24.如果使用到了临时表,在存储过程的最后务必将所有的临时表显式删除,先 truncate table ,然后 drop table ,这样可以避免系统表的较长时间锁定。

    25.尽量避免使用游标,因为游标的效率较差,如果游标操作的数据超过1万行,那么就应该考虑改写。

    26.使用基于游标的方法或临时表方法之前,应先寻找基于集的解决方案来解决问题,基于集的方法通常更有效。

    27.与临时表一样,游标并不是不可使用。对小型数据集使用 FAST_FORWARD 游标通常要优于其他逐行处理方法,尤其是在必须引用几个表才能获得所需的数据时。在结果集中包括“合计”的例程通常要比使用游标执行的速度快。如果开发时间允许,基于游标的方法和基于集的方法都可以尝试一下,看哪一种方法的效果更好。

    28.在所有的存储过程和触发器的开始处设置 SET NOCOUNT ON ,在结束时设置 SET NOCOUNT OFF 。无需在执行存储过程和触发器的每个语句后向客户端发送 DONE_IN_PROC 消息。

    29.尽量避免大事务操作,提高系统并发能力。

    30.尽量避免向客户端返回大数据量,若数据量过大,应该考虑相应需求是否合理。

  • 写出高性能SQL语句的十三条法则【zt】

    2011-02-21 08:55:52


      1、首先要搞明白什么叫执行计划?

      执行计划是数据库根据SQL语句和相关表的统计信息作出的一个查询方案,这个方案是由查询优化器自动分析产生的,比如一条SQL语句如果用来从一个10万条记录的表中查1条记录,那查询优化器会选择“索引查找”方式,如果该表进行了归档,当前只剩下5000条记录了,那查询优化器就会改变方案,采用“全表扫描”方式。

      可见,执行计划并不是固定的,它是“个性化的”。产生一个正确的“执行计划”有两点很重要:

      (1)SQL语句是否清晰地告诉查询优化器它想干什么?

      (2)查询优化器得到的数据库统计信息是否是最新的、正确的?

      2、统一SQL语句的写法

      对于以下两句SQL语句,程序员认为是相同的,数据库查询优化器认为是不同的。

    select * from dual 

    select * From dual

      其实就是大小写不同,查询分析器就认为是两句不同的SQL语句,必须进行两次解析。生成2个执行计划。所以作为程序员,应该保证相同的查询语句在任何地方都一致,多一个空格都不行!

      3、不要把SQL语句写得太复杂

      我经常看到,从数据库中捕捉到的一条SQL语句打印出来有2张A4纸这么长。一般来说这么复杂的语句通常都是有问题的。我拿着这2页长的SQL语句去请教原作者,结果他说时间太长,他一时也看不懂了。可想而知,连原作者都有可能看糊涂的SQL语句,数据库也一样会看糊涂。

      一般,将一个Select语句的结果作为子集,然后从该子集中再进行查询,这种一层嵌套语句还是比较常见的,但是根据经验,超过3层嵌套,查询优化器就很容易给出错误的执行计划。因为它被绕晕了。像这种类似人工智能的东西,终究比人的分辨力要差些,如果人都看晕了,我可以保证数据库也会晕的。

      另外,执行计划是可以被重用的,越简单的SQL语句被重用的可能性越高。而复杂的SQL语句只要有一个字符发生变化就必须重新解析,然后再把这一大堆垃圾塞在内存里。可想而知,数据库的效率会何等低下。

      4、使用“临时表”暂存中间结果

      简化SQL语句的重要方法就是采用临时表暂存中间结果,但是,临时表的好处远远不止这些,将临时结果暂存在临时表,后面的查询就在tempdb中了,这可以避免程序中多次扫描主表,也大大减少了程序执行中“共享锁”阻塞“更新锁”,减少了阻塞,提高了并发性能。

      5、OLTP系统SQL语句必须采用绑定变量

    select * from orderheader where changetime > ‘2010-10-20 00:00:01’ 
    select * from orderheader where changetime > ‘2010-09-22 00:00:01’

      以上两句语句,查询优化器认为是不同的SQL语句,需要解析两次。如果采用绑定变量

    select * from orderheader where changetime > @chgtime

      @chgtime变量可以传入任何值,这样大量的类似查询可以重用该执行计划了,这可以大大降低数据库解析SQL语句的负担。一次解析,多次重用,是提高数据库效率的原则。

      6、绑定变量窥测

      事物都存在两面性,绑定变量对大多数OLTP处理是适用的,但是也有例外。比如在where条件中的字段是“倾斜字段”的时候。

    倾斜字段”指该列中的绝大多数的值都是相同的,比如一张人口调查表,其中“民族”这列,90%以上都是汉族。那么如果一个SQL语句要查询30岁的汉族人口有多少,那“民族”这列必然要被放在where条件中。这个时候如果采用绑定变量@nation会存在很大问题。

    试想如果@nation传入的第一个值是“汉族”,那整个执行计划必然会选择表扫描。然后,第二个值传入的是“布依族”,按理说“布依族”占的比例可能只有万分之一,应该采用索引查找。但是,由于重用了第一次解析的“汉族”的那个执行计划,那么第二次也将采用表扫描方式。这个问题就是著名的“绑定变量窥测”,建议对于“倾斜字段”不要采用绑定变量。

      7、只在必要的情况下才使用begin tran

      SQL Server中一句SQL语句默认就是一个事务,在该语句执行完成后也是默认commit的。其实,这就是begin tran的一个最小化的形式,好比在每句语句开头隐含了一个begin tran,结束时隐含了一个commit。

      有些情况下,我们需要显式声明begin tran,比如做“插、删、改”操作需要同时修改几个表,要求要么几个表都修改成功,要么都不成功。begin tran 可以起到这样的作用,它可以把若干SQL语句套在一起执行,最后再一起commit。好处是保证了数据的一致性,但任何事情都不是完美无缺的。Begin tran付出的代价是在提交之前,所有SQL语句锁住的资源都不能释放,直到commit掉。

      可见,如果Begin tran套住的SQL语句太多,那数据库的性能就糟糕了。在该大事务提交之前,必然会阻塞别的语句,造成block很多。

      Begin tran使用的原则是,在保证数据一致性的前提下,begin tran 套住的SQL语句越少越好!有些情况下可以采用触发器同步数据,不一定要用begin tran。

      8、一些SQL查询语句应加上nolock

      在SQL语句中加nolock是提高SQL Server并发性能的重要手段,在oracle中并不需要这样做,因为oracle的结构更为合理,有undo表空间保存“数据前影”,该数据如果在修改中还未commit,那么你读到的是它修改之前的副本,该副本放在undo表空间中。这样,oracle的读、写可以做到互不影响,这也是oracle广受称赞的地方。SQL Server 的读、写是会相互阻塞的,为了提高并发性能,对于一些查询,可以加上nolock,这样读的时候可以允许写,但缺点是可能读到未提交的脏数据。使用nolock有3条原则。

      (1)查询的结果用于“插、删、改”的不能加nolock !

      (2)查询的表属于频繁发生页分裂的,慎用nolock !

      (3)使用临时表一样可以保存“数据前影”,起到类似oracle的undo表空间的功能,

      能采用临时表提高并发性能的,不要用nolock 。

      9、聚集索引没有建在表的顺序字段上,该表容易发生页分裂

      比如订单表,有订单编号orderid,也有客户编号contactid,那么聚集索引应该加在哪个字段上呢?对于该表,订单编号是顺序添加的,如果在orderid上加聚集索引,新增的行都是添加在末尾,这样不容易经常产生页分裂。然而,由于大多数查询都是根据客户编号来查的,因此,将聚集索引加在contactid上才有意义。而contactid对于订单表而言,并非顺序字段。

      比如“张三”的“contactid”是001,那么“张三”的订单信息必须都放在这张表的第一个数据页上,如果今天“张三”新下了一个订单,那该订单信息不能放在表的最后一页,而是第一页!如果第一页放满了呢?很抱歉,该表所有数据都要往后移动为这条记录腾地方。

      SQL Server的索引和Oracle的索引是不同的,SQL Server的聚集索引实际上是对表按照聚集索引字段的顺序进行了排序,相当于oracle的索引组织表。SQL Server的聚集索引就是表本身的一种组织形式,所以它的效率是非常高的。也正因为此,插入一条记录,它的位置不是随便放的,而是要按照顺序放在该放的数据页,如果那个数据页没有空间了,就引起了页分裂。所以很显然,聚集索引没有建在表的顺序字段上,该表容易发生页分裂。

      曾经碰到过一个情况,一位哥们的某张表重建索引后,插入的效率大幅下降了。估计情况大概是这样的。该表的聚集索引可能没有建在表的顺序字段上,该表经常被归档,所以该表的数据是以一种稀疏状态存在的。比如张三下过20张订单,而最近3个月的订单只有5张,归档策略是保留3个月数据,那么张三过去的15张订单已经被归档,留下15个空位,可以在insert发生时重新被利用。在这种情况下由于有空位可以利用,就不会发生页分裂。但是查询性能会比较低,因为查询时必须扫描那些没有数据的空位。

    重建聚集索引后情况改变了,因为重建聚集索引就是把表中的数据重新排列一遍,原来的空位没有了,而页的填充率又很高,插入数据经常要发生页分裂,所以性能大幅下降。

      对于聚集索引没有建在顺序字段上的表,是否要给与比较低的页填充率?是否要避免重建聚集索引?是一个值得考虑的问题!

      10、加nolock后查询经常发生页分裂的表,容易产生跳读或重复读

      加nolock后可以在“插、删、改”的同时进行查询,但是由于同时发生“插、删、改”,在某些情况下,一旦该数据页满了,那么页分裂不可避免,而此时nolock的查询正在发生,比如在第100页已经读过的记录,可能会因为页分裂而分到第101页,这有可能使得nolock查询在读101页时重复读到该条数据,产生“重复读”。同理,如果在100页上的数据还没被读到就分到99页去了,那nolock查询有可能会漏过该记录,产生“跳读”。

      上面提到的哥们,在加了nolock后一些操作出现报错,估计有可能因为nolock查询产生了重复读,2条相同的记录去插入别的表,当然会发生主键冲突。

      11、使用like进行模糊查询时应注意

      有的时候会需要进行一些模糊查询比如

    select * from contact where username like ‘%yue%’

      关键词%yue%,由于yue前面用到了“%”,因此该查询必然走全表扫描,除非必要,否则不要在关键词前加%,

      12、数据类型的隐式转换对查询效率的影响

      sql server2000的数据库,我们的程序在提交sql语句的时候,没有使用强类型提交这个字段的值,由sql server 2000自动转换数据类型,会导致传入的参数与主键字段类型不一致,这个时候sql server 2000可能就会使用全表扫描。Sql2005上没有发现这种问题,但是还是应该注意一下。

      13、SQL Server 表连接的三种方式

      (1)Merge Join

      (2)Nested Loop Join

      (3)Hash Join

      SQL Server 2000只有一种join方式——Nested Loop Join,如果A结果集较小,那就默认作为外表,A中每条记录都要去B中扫描一遍,实际扫过的行数相当于A结果集行数x B结果集行数。所以如果两个结果集都很大,那Join的结果很糟糕。

      SQL Server 2005新增了Merge Join,如果A表和B表的连接字段正好是聚集索引所在字段,那么表的顺序已经排好,只要两边拼上去就行了,这种join的开销相当于A表的结果集行数加上B表的结果集行数,一个是加,一个是乘,可见merge join 的效果要比Nested Loop Join好多了。

      如果连接的字段上没有索引,那SQL2000的效率是相当低的,而SQL2005提供了Hash join,相当于临时给A,B表的结果集加上索引,因此SQL2005的效率比SQL2000有很大提高,我认为,这是一个重要的原因。

      总结一下,在表连接时要注意以下几点:

      (1)连接字段尽量选择聚集索引所在的字段

      (2)仔细考虑where条件,尽量减小A、B表的结果集

      (3)如果很多join的连接字段都缺少索引,而你还在用SQL Server 2000,赶紧升级吧。

  • 测试中用到的几个复制表的sql语句

    2010-08-21 16:39:30

        1、只复制表结构的sql

      create table b as select * from a where 1<>1

      2、即复制表结构又复制表中数据的sql

      create table b as select * from a

      3、复制表的指定字段的sql

      create table b as select row_id,name,age from a where 1<>1//前提是row_id,name,age都是a表的列

      4、复制表的指定字段及这些指定字段的数据的sql

      create table b as select row_id,name,age from a

      以上语句虽然能够很容易的根据a表结构复制创建b表,但是a表的索引等却复制不了,需要在b中手动建立。

      5、insert into 会将查询结果保存到已经存在的表中

      insert into t2(column1, column2, ....) select column1, column2, .... from t1

  • ORACLE 物化视图 之验证

    2010-07-01 16:59:19


        针对开发同事引入的物化视图的概念做了一个简单的了解和实验:

    引文出自:http://icbbs.supcon.com/viewthread.php?tid=1181

    物化视图中上面的引文中已做了简介,下面说一下它的优缺点和验证的结果:

    优点:

     1,物化视图的最大的优势是可以提高性能:Oracle的物化视图提供了强大的功能,可以用于预先计算并保存表连接或聚集等耗时较多的操作的结果,这样,在执行查询时,就可以避免进行这些耗时的操作,而从快速的得到结果。

     2, 物化视图有很多方面和索引很相似

     3通过预先计算好答案存储起来,可以大大地减少机器的负载

       A,更少的物理读--扫描更少的数据

       B,更少的写--不用经常排序和聚集

       C。减少CPU的消耗--不用对数据进行聚集计算和函数调用

       D,显著地加快响应时间--在使用物化视图查询数据时(与主表相反),将会很快的返回查询结果

    缺点:

      1物化视图用于只读或者“精读”环境下工作最好 ,不用于联机事务处理系统(OLTP)环境, 在事实表等更新时会导致物化视图行锁,从而影响系统并发性。

       2物化视图有出现无法快速刷新,导致查询数据不准确的现象 

      3,Rowid物化视图(创建的物化视图通常情况下主键,rowid,和子查询视图只有一个单一的主表,不能包括下面任何一项:

        A,Distinct 或者聚合函数.

        B,Group by,子查询,连接和SET操作

      4,物化视图会增加对磁盘资源的需求,即需要永久分配的硬盘空间给物化视图来存储数据

      5,物化视图的工作原理受一些可能的约束,比如主键,外键等等

    实验:(一)

    1,创建物化视图:

      /* Formatted on 2010-7-1 10:46:08 (QP5 v5.115.810.9015) */

    CREATE MATERIALIZED VIEW Contract REFRESH FORCE ON DEMAND AS SELECT "Contract_ID","Contract_ProjectID","Contract_TableID","Contract_NO" FROM "Comm_Contract" WHERE "Contract_TableID"

    IN(SELECT "AppTab_ID" FROM "Base_AppTableInfo" WHERE "AppTab_TableCode"='SaleContractP_Base' )

    2,查询

     从基表中查询:

    SELECT    "Contract_ID"

                        FROM   "Comm_Contract"

                       WHERE   "Contract_NO" LIKE '%2009011%'

      A,单用户查询响应时间:206ms  

      B,50并发查询响应时间:1670ms               

       从物化视图查询:                

     select "Contract_ID" 

                        from "Contract"  

                       where "Contract_NO" like '%2009011%'  

      A,单用户查询响应时间:23ms  

      B,50并发查询响应时间:48ms  

    实验:(二)

    生产任务单参照生产订单按合同编号查询系统响应时间---是否用物化视图的区别

    操作步骤:

    1,修改资源文件:
    [Unit]

          Name = Sale.Contract1

          [Master]

             [Table]

                Name = Contract

                [Field]

                   ID = Contract_ID,Integer

                   ProjectID = Contract_ProjectID,Integer

                   TableID = Contract_TableID,Integer

                   NO = Contract_NO,Text               

                [/Field]

             [/Table]

          [/Master]

       [/Unit]

    2,修改.ets  .xsl 文件

    .xsl:QuickCondition += ' AND _field_(Order_ContractID) in _subquery_(Sale.Contract1【Sale.Contract】,ID,_FIELD_(NO) LIKE  _Value_($^QuickContract_NO,@NO))';

    .ets:<et:class Var="ContractList" Class="Sale.Contract1Sale.Contract" Condition="_FIELD_(ID)=_VALUE_($.Order_ContractID,@ID)" OutputPageInfo="no" OutputField="ID,NO,Customer_ShortName"/>

    3,分别用步骤2的两种情况查询

      生产任务单参照生产订单:按销售合同条件查询:查询输入“2009011” ,结果页面响应时间: 

     A,不用物化视图<!--Execute the main script casted 2ms-->

     B,用物化视图<!--Execute the main script casted 1ms-->

  • 处理并发---索引的优点(实验贴)

    2010-06-30 14:52:59


    1,测试验证用到的简单的sql语句:
    /* Formatted on 2010-6-29 11:56:58 (QP5 v5.115.810.9015) */
    SELECT   *
      FROM   (SELECT   row_.*, ROWNUM rownum_
                FROM   (SELECT   "order_date"
                          FROM   "test"
                         WHERE   "order_no" =
                                    TRUNC (DBMS_RANDOM.VALUE (24, 50024))) row_
               WHERE   ROWNUM <= 20)
    WHERE   rownum_ > 0

    2,数据准备说明
    a,本次对一个有5个字段的表test进行基本测试,验证两种情况:一,字段order_no有索引;二,字段order_no无所有,有无索引时做相同的测试验证
       b,相应时间单位:ms
       c,测试验证分同时并发和分钟并发两种情况验证
       d,表中有50000条数据
    3,测试得到的数据

    同时并发
    10并发 50并发 80并发 100并发
    无索引 756 2109 3053 3723
    有索引 357 385 413 430


    分钟并发
    200并发 500并发 1000并发 1500并发
    无索引 255 260 10702 33163
    有索引 4 3 1 4


    4,结论总结
    1,500以下的并发,有无索引,用户不会有太明显的感觉,因为他们的执行时间都不会大于0.3s
    2,以“较高(500~3000)”并发频率对50000数据的表进行简单的查询,此时有无索引就会有明显的差别,可以达到5s以上
    3,以“极高(>3000)”并发频率对50000数据的表进行简单的查询,此时相应时间就会很慢,很慢

        结合实际应用考虑,一些简单的表(字段不太多,结果不复杂),在单个用户反复执行sql语句时,有无索引对用户来说可能体验不到响应时间上的差异,而对于多用户并发对这个表做操作时,有无索引的差异就会很明显:在“较低”频率并发情况下,由于表比较简单,响应时间很小,看不出大的差异,当并发频率“较高”,如大于500时,这种差异就会很明显,如上面1500的并发,响应时间相差3s,依此类推,如果表字段很多,嵌套结构复杂,有无索引并发执行的差异将会很大。


  • oracle索引插入数据性能 + 数据量大小查询效率

    2010-06-24 09:29:26

    1,建表

    CREATE TABLE "test"

    (

      "id"             INTEGER                   NOT NULL,

      "order_no"       NUMBER(10),

      "order_date"     DATE,

      "ordership"      VARCHAR2(500 BYTE),

      "order_comment"  VARCHAR2(100 BYTE)

    )

    2,插入数据脚本

    declare

     BEGIN

       for i in 1 .. X

        loop

        --syexecute immediate

    insert into "test" values(i,24+i,sysdate(),'ship' || i,'coment' || i);

       end loop;

       commit;

    END; 

    3,有无索引对比

    50000

    500000

    100000

    无索引

    2s

    20s

    40s

    主键索引

    2s

    25s

    50s

    全部索引

    5s

    96s

    215s

    4,查询数据:

    001sql

    002sql

    003sql

    004sql

    005sql

    006sql

    007sql

    10000

    16ms

    16ms

    16ms

    16ms

    16ms

    16ms

    待补充

    1000000

    18ms

    204ms

    266ms

    31ms

    141ms

    109ms

    待补充

    说明:

    1),10000 ---表中10000条数据 ;1000000----表中1000000条数据;

    2),001sql--select "order_date" from "test"

    3),002sql--select "order_date" from "test" group by "order_date";

    4),003sql--select "order_date" from "test"  order by DESC;

    5),004sql--select max("id") from "test";

    6),004sql--select sum("order_no") from "test";

    7),004sql--select "order_date" from "test" where {加区间}group by "order_date" 

    5,结论:

    1),表中索引越多,插入数据效率越差

    2),表查询默认是顺序排序的,查询倒序排序比顺序效率差

    3),...

  • Oracle数据库索引优化技术关联查询性能调优【ZT】

    2010-06-23 08:26:53

    Oracle数据库索引优化技术关联查询性能调优

      数据库性能优化是无止境的,无论哪种优化技术只是一种手段,但最重要的不是技术,而是思想,掌握了索引优化技术仅仅刚入门,只有融会贯通,举一反三才能成为高手。

      本文引用一套实验室信息管理系统(LIS)使用的数据库,假设我们要查询2008年11月做检验的患者记录,条件是大于80岁,姓周的患者,最终结果按检查日期进行倒序排列。要使用的表有三个:

      ◆lis_report:报告主表,我们要用到的字段包括i_checkno(检查号),d_checkdate(检查日期),i_patientid(患者ID);

      ◆comm_patient:患者信息表,我们要用到的字段包括i_patientid(患者ID),s_name(患者姓名),s_code(患者住院号),i_age(患者年龄),i_dept(患者所在病区);

      ◆lis_code_dept:病区信息表,我们要用到的字段包括i_id(病区ID,主键,与comm_patient中的i_dept关联),s_name(病区名)。

      最终我们构造的SQL如下:

    select a.i_checkno, a.d_checkdate,b.s_name, b.s_code, b.i_age,c.s_name 
    from lis_report a inner join comm_patient b on a. i_patientid =b.i_patientid  inner join lis_code_dept c on b.i_dept = c.i_id  
    where a.d_checkdate > '2008-11-01' and a.d_checkdate < '2008-11-30' and b.i_age>=80 and b.s_name like '周%'
    order by a.d_checkdate desc

      我们的SQL使用的这三张表除了创建主键时自动创建的索引外,均未创建其它索引,下图是无索引时的执行计划。

      表comm_patient和lis_report都使用了全表扫描,comm_patient全表扫描的成本是18,lis_report全表扫描的成本是191,只有表lis_code_dept因关联时使用的是其主键,因此这里使用了主键索引,从而避免了全表扫描,它的成本是0。我们知道提高查询性能的目标之一就是消灭掉全表扫描,因此我们应该给表comm_patient和lis_report加上适当的索引,在SQL代码的where子句中,对comm_patient表,我们引用了i_age和s_name字段,对lis_report表,我们引用了d_checkdate字段,通常给这些条件中引用的字段加上索引会提高查询速度,我们先给comm_patient的i_gae字段加上索引,下面是对应的执行计划。

      表comm_patient的全表扫描消失了,取而代之的是索引唯一性扫描,成本从18一下子降低到1了,注意这里并未使用我们给i_age增加的索引,但却靠它触发了使用表主键对应的索引。但表lis_report仍然是全表扫描,由于where子句中引用了该表的d_checkdate字段,因此我们给该字段加上索引看看效果。

      表lis_report的全表扫描消失了,取而代之的是索引范围降序扫描(INDEX RANGE SCAN DESCENDING),成本也从191下降到189。注意这里的索引范围降序扫描的来历,因为我的where子句中引用d_checkdate是介于2008-11-01至2008-11-30的一个范围,这时引用的这种字段上建立的索引通常都是执行范围扫描,因为这种条件返回的值往往不止一行。使用降序扫描的原因是order by子句使用了降序排序,如果我们将SQL代码中的"order by a.d_checkdate desc"改为"order by a.d_checkdate",则变为索引范围扫描(INDEX RANGE SCAN)。

      至此我们全部消除了全表扫描,我们看到加上索引后,查询执行的成本开销也有所降低,因为数据库表中的记录数不大,因此效果不太明显,如果有上百万条记录则会更直观。

      虽然索引能提高查询性能,但索引也不能滥用,一是因为索引会降低写入性能,二是索引过多给索引管理带来麻烦,有些索引根本就没有使用,这样的索引只会带来负面影响,基于这些弊端的考虑,在设计数据库结构时应综合考虑表的使用频率(使用次数越多越应重点考虑是否建立索引),表中字段的使用频率(字段使用次数越多越应建立索引),字段类型(数值型字段越应建立索引),值的唯一性(最应建立索引的字段),值的重复性(值重复度越高,建立索引的必要性越低),值是否可为空(允许为空的字段一般不建立索引),表中记录数(记录数很少时一般不宜建立索引),表是读操作多一些还是写操作多一些(读操作越多的表越应建立索引,写操作越多的表越应避免建立索引)等,创建索引的一般原则是:在大表的常用且值重复几率小的字段上创建索引。

  • 常用的sql语句

    2009-08-11 13:34:12

                    常用的sql语句

    asc 按升序排列
    desc 按降序排列

    下列语句部分是Mssql语句,不可以在access中使用。

    SQL分类: 
    DDL—数据定义语言(CREATE,ALTER,DROP,DECLARE) 
    DML—数据操纵语言(SELECT,DELETE,UPDATE,INSERT) 
    DCL—数据控制语言(GRANT,REVOKE,COMMIT,ROLLBACK)

    首先,简要介绍基础语句:
    1、说明:创建数据库
    CREATE DATABASE database-name 
    2、说明:删除数据库
    drop database dbname
    3、说明:备份sql server
    --- 创建 备份数据的 device
    USE master
    EXEC sp_addumpdevice 'disk', 'testBack', 'c:\mssql7backup\MyNwind_1.dat'
    --- 开始 备份
    BACKUP DATABASE pubs TO testBack 
    4、说明:创建新表
    create table tabname(col1 type1 [not null] [primary key],col2 type2 [not null],..)
    根据已有的表创建新表: 
    A:create table tab_new like tab_old (使用旧表创建新表)
    B:create table tab_new as select col1,col2… from tab_old definition only
    5、说明:删除新表drop table tabname 
    6、说明:增加一个列
    Alter table tabname add column col type
    注:列增加后将不能删除。DB2中列加上后数据类型也不能改变,唯一能改变的是增加varchar类型的长度。
    7、说明:添加主键: Alter table tabname add primary key(col) 
    说明:删除主键: Alter table tabname drop primary key(col) 
    8、说明:创建索引:create [unique] index idxname on tabname(col….) 
    删除索引:drop index idxname
    注:索引是不可更改的,想更改必须删除重新建。
    9、说明:创建视图:create view viewname as select statement 
    删除视图:drop view viewname
    10、说明:几个简单的基本的sql语句
    选择:select * from table1 where 范围
    插入:insert into table1(field1,field2) values(value1,value2)
    删除:delete from table1 where 范围
    更新:update table1 set field1=value1 where 范围
    查找:select * from table1 where field1 like ’%value1%’ ---like的语法很精妙,查资料!
    排序:select * from table1 order by field1,field2 [desc]
    总数:select count as totalcount from table1
    求和:select sum(field1) as sumvalue from table1
    平均:select avg(field1) as avgvalue from table1
    最大:select max(field1) as maxvalue from table1
    最小:select min(field1) as minvalue from table1
    11、说明:几个高级查询运算词
    A: UNION 运算符 
    UNION 运算符通过组合其他两个结果表(例如 TABLE1 和 TABLE2)并消去表中任何重复行而派生出一个结果表。当 ALL 随 UNION 一起使用时(即 UNION ALL),不消除重复行。两种情况下,派生表的每一行不是来自 TABLE1 就是来自 TABLE2。 
    B: EXCEPT 运算符 
    EXCEPT 运算符通过包括所有在 TABLE1 中但不在 TABLE2 中的行并消除所有重复行而派生出一个结果表。当 ALL 随 EXCEPT 一起使用时 (EXCEPT ALL),不消除重复行。 
    C: INTERSECT 运算符
    INTERSECT 运算符通过只包括 TABLE1 和 TABLE2 中都有的行并消除所有重复行而派生出一个结果表。当 ALL 随 INTERSECT 一起使用时 (INTERSECT ALL),不消除重复行。 
    注:使用运算词的几个查询结果行必须是一致的。 
    12、说明:使用外连接 
    A、left outer join: 
    左外连接(左连接):结果集几包括连接表的匹配行,也包括左连接表的所有行。 
    sql: select a.a, a.b, a.c, b.c, b.d, b.f from a LEFT OUT JOIN b ON a.a = b.c
    B:right outer join: 
    右外连接(右连接):结果集既包括连接表的匹配连接行,也包括右连接表的所有行。 
    C:full outer join: 
    全外连接:不仅包括符号连接表的匹配行,还包括两个连接表中的所有记录。

    其次,大家来看一些不错的sql语句
    1、说明:复制表(只复制结构,源表名:a 新表名:b) (Access可用)

     法一:select * into b from a where 1<>1
    法二:select top 0 * into b from a
    2、说明:拷贝表(拷贝数据,源表名:a 目标表名:b) (Access可用)
    insert into b(a, b, c) select d,e,f from b;

    3、说明:跨数据库之间表的拷贝(具体数据使用绝对路径) (Access可用)
    insert into b(a, b, c) select d,e,f from b in ‘具体数据库’ where 条件
    例子:..from b in '"&Server.MapPath(".")&"\data.mdb" &"' where..

    4、说明:子查询(表名1:a 表名2:b)
    select a,b,c from a where a IN (select d from b ) 或者: select a,b,c from a where a IN (1,2,3)

    5、说明:显示文章、提交人和最后回复时间
    select a.title,a.username,b.adddate from table a,(select max(adddate) adddate from table where table.title=a.title) b

    6、说明:外连接查询(表名1:a 表名2:b)
    select a.a, a.b, a.c, b.c, b.d, b.f from a LEFT OUT JOIN b ON a.a = b.c

    7、说明:在线视图查询(表名1:a )
    select * from (SELECT a,b,c FROM a) T where t.a > 1;

    8、说明:between的用法,between限制查询数据范围时包括了边界值,not between不包括
    select * from table1 where time between time1 and time2
    select a,b,c, from table1 where a not between 数值1 and 数值2

    9、说明:in 的使用方法
    select * from table1 where a [not] in (‘值1’,’值2’,’值4’,’值6’)

    10、说明:两张关联表,删除主表中已经在副表中没有的信息 
    delete from table1 where not exists ( select * from table2 where table1.field1=table2.field1 )

    11、说明:四表联查问题:
    select * from a left inner join b on a.a=b.b right inner join c on a.a=c.c inner join d on a.a=d.d where .....

    12、说明:日程安排提前五分钟提醒 
    sql: select * from 日程安排 where datediff('minute',f开始时间,getdate())>5

    13、说明:一条sql 语句搞定数据库分页
    select top 10 b.* from (select top 20 主键字段,排序字段 from 表名 order by 排序字段 desc) a,表名 b where b.主键字段 = a.主键字段 order by a.排序字段

    14、说明:前10条记录
    select top 10 * form. table1 where 范围

    15、说明:选择在每一组b值相同的数据中对应的a最大的记录的所有信息(类似这样的用法可以用于论坛每月排行榜,每月热销产品分析,按科目成绩排名,等等.)
    select a,b,c from tablename ta where a=(select max(a) from tablename tb where tb.b=ta.b)

    16、说明:包括所有在 TableA 中但不在 TableB和TableC 中的行并消除所有重复行而派生出一个结果表
    (select a from tableA ) except (select a from tableB) except (select a from tableC)

    17、说明:随机取出10条数据
    select top 10 * from tablename order by newid()

    18、说明:随机选择记录
    select newid()

    19、说明:删除重复记录
    Delete from tablename where id not in (select max(id) from tablename group by col1,col2,...)

    20、说明:列出数据库里所有的表名
    select name from sysobjects where type='U'

    21、说明:列出表里的所有的
    select name from syscolumns where id=object_id('TableName')

    22、说明:列示type、vender、pcs字段,以type字段排列,case可以方便地实现多重选择,类似select 中的case。
    select type,sum(case vender when 'A' then pcs else 0 end),sum(case vender when 'C' then pcs else 0 end),sum(case vender when 'B' then pcs else 0 end) FROM tablename group by type
    显示结果:
    type vender pcs
    电脑 A 1
    电脑 A 1
    光盘 B 2
    光盘 A 2
    手机 B 3
    手机 C 3

    23、说明:初始化表table1

    TRUNCATE TABLE table1

    24、说明:选择从10到15的记录
    select top 5 * from (select top 15 * from table order by id asc) table_别名 order by id desc
      
    随机选择数据库记录的方法(使用Randomize函数,通过SQL语句实现)
      对存储在数据库中的数据来说,随机数特性能给出上面的效果,但它们可能太慢了些。你不能要求ASP“找个随机数”然后打印出来。实际上常见的解决方案是建立如下所示的循环: 
    Randomize 
    RNumber = Int(Rnd*499) +1 
     
    While Not objRec.EOF 
    If objRec("ID") = RNumber THEN 
    ... 这里是执行脚本 ... 
    end if 
    objRec.MoveNext 
    Wend 
     
      这很容易理解。首先,你取出1到500范围之内的一个随机数(假设500就是数据库内记录的总数)。然后,你遍历每一记录来测试ID 的值、检查其是否匹配RNumber。满足条件的话就执行由THEN 关键字开始的那一块代码。假如你的RNumber 等于495,那么要循环一遍数据库花的时间可就长了。虽然500这个数字看起来大了些,但相比更为稳固的企业解决方案这还是个小型数据库了,后者通常在一个数据库内就包含了成千上万条记录。这时候不就死定了? 
      采用SQL,你就可以很快地找出准确的记录并且打开一个只包含该记录的recordset,如下所示: 
    Randomize 
    RNumber = Int(Rnd*499) + 1 
     
    sql = "SELECT * FROM Customers WHERE ID = " & RNumber 
     
    set bjRec = ObjConn.Execute(SQL) 
    Response.WriteRNumber & " = " & objRec("ID") & " " & objRec("c_email") 
     
      不必写出RNumber 和ID,你只需要检查匹配情况即可。只要你对以上代码的工作满意,你自可按需操作“随机”记录。Recordset没有包含其他内容,因此你很快就能找到你需要的记录这样就大大降低了处理时间。 
    再谈随机数 
      现在你下定决心要榨干Random 函数的最后一滴油,那么你可能会一次取出多条随机记录或者想采用一定随机范围内的记录。把上面的标准Random 示例扩展一下就可以用SQL应对上面两种情况了。 
      为了取出几条随机选择的记录并存放在同一recordset内,你可以存储三个随机数,然后查询数据库获得匹配这些数字的记录: 
    sql = "SELECT * FROM Customers WHERE ID = " & RNumber & " OR ID = " & RNumber2 & " OR ID = " & RNumber3 
     
      假如你想选出10条记录(也许是每次页面装载时的10条链接的列表),你可以用BETWEEN 或者数学等式选出第一条记录和适当数量的递增记录。这一操作可以通过好几种方式来完成,但是 SELECT 语句只显示一种可能(这里的ID 是自动生成的号码): 
    sql = "SELECT * FROM Customers WHERE ID BETWEEN " & RNumber & " AND " & RNumber & "+ 9"

      注意:以上代码的执行目的不是检查数据库内是否有9条并发记录。

     
    随机读取若干条记录,测试过
    Access语法:SELECT top 10 * From 表名 ORDER BY Rnd(id)
    sql server:select top n * from 表名 order by newid()
    mysqlelect * From 表名 Order By rand() Limit n
    Access左连接语法(最近开发要用左连接,Access帮助什么都没有,网上没有Access的SQL说明,只有自己测试, 现在记下以备后查)
    语法elect table1.fd1,table1,fd2,table2.fd2 From table1 left join table2 on table1.fd1,table2.fd1 where ...
    使用SQL语句 用...代替过长的字符串显示
    语法:
    SQL数据库:select case when len(field)>10 then left(field,10)+'...' else field end as news_name,news_id from tablename
    Access数据库:SELECT iif(len(field)>2,left(field,2)+'...',field) FROM tablename; 
     
    Conn.Execute说明
    Execute方法
      该方法用于执行SQL语句。根据SQL语句执行后是否返回记录集,该方法的使用格式分为以下两种:

    1.执行SQL查询语句时,将返回查询得到的记录集。用法为:
        Set 对象变量名=连接对象.Execute("SQL 查询语言")
       Execute方法调用后,会自动创建记录集对象,并将查询结果存储在该记录对象中,通过Set方法,将记录集赋给指定的对象保存,以后对象变量就代表了该记录集对象。

    2.执行SQL的操作性语言时,没有记录集的返回。此时用法为:
        连接对象.Execute "SQL 操作性语句" [, RecordAffected][, Option]
          ·RecordAffected 为可选项,此出可放置一个变量,SQL语句执行后,所生效的记录数会自动保存到该变量中。通过访问该变量,就可知道SQL语句队多少条记录进行了操作。
          ·Option 可选项,该参数的取值通常为adCMDText,它用于告诉ADO,应该将Execute方法之后的第一个字符解释为命令文本。通过指定该参数,可使执行更高效。

    ·BeginTrans、RollbackTrans、CommitTrans方法
      这三个方法是连接对象提供的用于事务处理的方法。BeginTrans用于开始一个事物;RollbackTrans用于回滚事务;CommitTrans用于提交所有的事务处理结果,即确认事务的处理。
      事务处理可以将一组操作视为一个整体,只有全部语句都成功执行后,事务处理才算成功;若其中有一个语句执行失败,则整个处理就算失败,并恢复到处里前的状态。
      BeginTrans和CommitTrans用于标记事务的开始和结束,在这两个之间的语句,就是作为事务处理的语句。判断事务处理是否成功,可通过连接对象的Error集合来实现,若Error集合的成员个数不为0,则说明有错误发生,事务处理失败。Error集合中的每一个Error对象,代表一个错误信息。

Open Toolbar