ORACLE日期时间函数大全

admin 发表了文章 • 0 个评论 • 66 次浏览 • 2018-04-26 20:27 • 来自相关话题

   TO_DATE格式(以时间:2007-11-02   13:45:25为例)
   
        Year:      
        yy two digits 两位年                显示值:07
        yyy three digits 三位年                显示值:007
        yyyy four digits 四位年                显示值:2007
            
        Month:      
        mm    number     两位月              显示值:11
        mon    abbreviated 字符集表示          显示值:11月,若是英文版,显示nov     
        month spelled out 字符集表示          显示值:11月,若是英文版,显示november 
          
        Day:      
        dd    number         当月第几天        显示值:02
        ddd    number         当年第几天        显示值:02
        dy    abbreviated 当周第几天简写    显示值:星期五,若是英文版,显示fri
        day    spelled out   当周第几天全写    显示值:星期五,若是英文版,显示friday        
        ddspth spelled out, ordinal twelfth 
             
              Hour:
              hh    two digits 12小时进制            显示值:01
              hh24 two digits 24小时进制            显示值:13
              
              Minute:
              mi    two digits 60进制                显示值:45
              
              Second:
              ss    two digits 60进制                显示值:25
              
              其它
              Q     digit         季度                  显示值:4
              WW    digit         当年第几周            显示值:44
              W    digit          当月第几周            显示值:1
              
        24小时格式下时间范围为: 0:00:00 - 23:59:59....      
        12小时格式下时间范围为: 1:00:00 - 12:59:59 .... 
            
1. 日期和字符转换函数用法(to_date,to_char)
         
select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') as nowTime from dual;   //日期转化为字符串   
select to_char(sysdate,'yyyy') as nowYear   from dual;   //获取时间的年   
select to_char(sysdate,'mm')    as nowMonth from dual;   //获取时间的月   
select to_char(sysdate,'dd')    as nowDay    from dual;   //获取时间的日   
select to_char(sysdate,'hh24') as nowHour   from dual;   //获取时间的时   
select to_char(sysdate,'mi')    as nowMinute from dual;   //获取时间的分   
select to_char(sysdate,'ss')    as nowSecond from dual;   //获取时间的秒

    
select to_date('2004-05-07 13:23:44','yyyy-mm-dd hh24:mi:ss')    from dual//

2.      
    select to_char( to_date(222,'J'),'Jsp') from dual      
    
    显示Two Hundred Twenty-Two    

3.求某天是星期几      
   select to_char(to_date('2002-08-26','yyyy-mm-dd'),'day') from dual;      
   星期一      
   select to_char(to_date('2002-08-26','yyyy-mm-dd'),'day','NLS_DATE_LANGUAGE = American') from dual;      
   monday      
   设置日期语言      
   ALTER SESSION SET NLS_DATE_LANGUAGE='AMERICAN';      
   也可以这样      
   TO_DATE ('2002-08-26', 'YYYY-mm-dd', 'NLS_DATE_LANGUAGE = American')    

4. 两个日期间的天数      
    select floor(sysdate - to_date('20020405','yyyymmdd')) from dual;    

5. 时间为null的用法      
   select id, active_date from table1      
   UNION      
   select 1, TO_DATE(null) from dual;      
   
   注意要用TO_DATE(null)    

6.月份差   
   a_date between to_date('20011201','yyyymmdd') and to_date('20011231','yyyymmdd')      
   那么12月31号中午12点之后和12月1号的12点之前是不包含在这个范围之内的。      
   所以,当时间需要精确的时候,觉得to_char还是必要的 
      
7. 日期格式冲突问题      
    输入的格式要看你安装的ORACLE字符集的类型, 比如: US7ASCII, date格式的类型就是: '01-Jan-01'      
    alter system set NLS_DATE_LANGUAGE = American      
    alter session set NLS_DATE_LANGUAGE = American      
    或者在to_date中写      
    select to_char(to_date('2002-08-26','yyyy-mm-dd'),'day','NLS_DATE_LANGUAGE = American') from dual;      
    注意我这只是举了NLS_DATE_LANGUAGE,当然还有很多,      
    可查看      
    select * from nls_session_parameters      
    select * from V$NLS_PARAMETERS    

8.      
   select count(*)      
   from ( select rownum-1 rnum      
       from all_objects      
       where rownum <= to_date('2002-02-28','yyyy-mm-dd') - to_date('2002-      
       02-01','yyyy-mm-dd')+1      
      )      
   where to_char( to_date('2002-02-01','yyyy-mm-dd')+rnum-1, 'D' )      
        not in ( '1', '7' )      
   
   查找2002-02-28至2002-02-01间除星期一和七的天数      
   在前后分别调用DBMS_UTILITY.GET_TIME, 让后将结果相减(得到的是1/100秒, 而不是毫秒).    

9. 查找月份     
    select months_between(to_date('01-31-1999','MM-DD-YYYY'),to_date('12-31-1998','MM-DD-YYYY')) "MONTHS" FROM DUAL;      
    1      
   select months_between(to_date('02-01-1999','MM-DD-YYYY'),to_date('12-31-1998','MM-DD-YYYY')) "MONTHS" FROM DUAL;      
    1.03225806451613 
       
10. Next_day的用法      
    Next_day(date, day)      
    
    Monday-Sunday, for format code DAY      
    Mon-Sun, for format code DY      
    1-7, for format code D    

11      
   select to_char(sysdate,'hh:mi:ss') TIME from all_objects      
   注意:第一条记录的TIME 与最后一行是一样的      
   可以建立一个函数来处理这个问题      
   create or replace function sys_date return date is      
   begin      
   return sysdate;      
   end;      
   
   select to_char(sys_date,'hh:mi:ss') from all_objects;   
     
12.获得小时数      
     extract()找出日期或间隔值的字段值
    SELECT EXTRACT(HOUR FROM TIMESTAMP '2001-02-16 2:38:40') from offer      
    SQL> select sysdate ,to_char(sysdate,'hh') from dual;      
    
    SYSDATE TO_CHAR(SYSDATE,'HH')      
    -------------------- ---------------------      
    2003-10-13 19:35:21 07      
    
    SQL> select sysdate ,to_char(sysdate,'hh24') from dual;      
    
    SYSDATE TO_CHAR(SYSDATE,'HH24')      
    -------------------- -----------------------      
    2003-10-13 19:35:21 19    

       
13.年月日的处理      
   select older_date,      
       newer_date,      
       years,      
       months,      
       abs(      
        trunc(      
         newer_date-      
         add_months( older_date,years*12+months )      
        )      
       ) days 
       
   from ( select      
        trunc(months_between( newer_date, older_date )/12) YEARS,      
        mod(trunc(months_between( newer_date, older_date )),12 ) MONTHS,      
        newer_date,      
        older_date      
        from ( 
              select hiredate older_date, add_months(hiredate,rownum)+rownum newer_date      
              from emp 
             )      
      )    

14.处理月份天数不定的办法      
   select to_char(add_months(last_day(sysdate) +1, -2), 'yyyymmdd'),last_day(sysdate) from dual    

16.找出今年的天数      
   select add_months(trunc(sysdate,'year'), 12) - trunc(sysdate,'year') from dual    

   闰年的处理方法      
   to_char( last_day( to_date('02'    | | :year,'mmyyyy') ), 'dd' )      
   如果是28就不是闰年    

17.yyyy与rrrr的区别      
   'YYYY99 TO_C      
   ------- ----      
   yyyy 99 0099      
   rrrr 99 1999      
   yyyy 01 0001      
   rrrr 01 2001    

18.不同时区的处理      
   select to_char( NEW_TIME( sysdate, 'GMT','EST'), 'dd/mm/yyyy hh:mi:ss') ,sysdate      
   from dual;    

19.5秒钟一个间隔      
   Select TO_DATE(FLOOR(TO_CHAR(sysdate,'SSSSS')/300) * 300,'SSSSS') ,TO_CHAR(sysdate,'SSSSS')      
   from dual    

   2002-11-1 9:55:00 35786      
   SSSSS表示5位秒数    

20.一年的第几天      
   select TO_CHAR(SYSDATE,'DDD'),sysdate from dual
        
   310 2002-11-6 10:03:51    

21.计算小时,分,秒,毫秒      
    select      
     Days,      
     A,      
     TRUNC(A*24) Hours,      
     TRUNC(A*24*60 - 60*TRUNC(A*24)) Minutes,      
     TRUNC(A*24*60*60 - 60*TRUNC(A*24*60)) Seconds,      
     TRUNC(A*24*60*60*100 - 100*TRUNC(A*24*60*60)) mSeconds      
    from      
    (      
     select      
     trunc(sysdate) Days,      
     sysdate - trunc(sysdate) A      
     from dual      
   )    


   select * from tabname      
   order by decode(mode,'FIFO',1,-1)*to_char(rq,'yyyymmddhh24miss');      
   
   //      
   floor((date2-date1) /365) 作为年      
   floor((date2-date1, 365) /30) 作为月      
   d(mod(date2-date1, 365), 30)作为日.

23.next_day函数      返回下个星期的日期,day为1-7或星期日-星期六,1表示星期日
   next_day(sysdate,6)是从当前开始下一个星期五。后面的数字是从星期日开始算起。      
   1 2 3 4 5 6 7      
   日 一 二 三 四 五 六    
   
   --------------------------------------------------------------- 
   
   select    (sysdate-to_date('2003-12-03 12:55:45','yyyy-mm-dd hh24:mi:ss'))*24*60*60 from ddual
   日期 返回的是天 然后 转换为ss
     
24,round[舍入到最接近的日期](day:舍入到最接近的星期日)
   select sysdate S1,
   round(sysdate) S2 ,
   round(sysdate,'year') YEAR,
   round(sysdate,'month') MONTH ,
   round(sysdate,'day') DAY from dual

25,trunc[截断到最接近的日期,单位为天] ,返回的是日期类型
   select sysdate S1,                     
     trunc(sysdate) S2,                 //返回当前日期,无时分秒
     trunc(sysdate,'year') YEAR,        //返回当前年的1月1日,无时分秒
     trunc(sysdate,'month') MONTH ,     //返回当前月的1日,无时分秒
     trunc(sysdate,'day') DAY           //返回当前星期的星期天,无时分秒
   from dual

26,返回日期列表中最晚日期
   select greatest('01-1月-04','04-1月-04','10-2月-04') from dual

27.计算时间差
     注:oracle时间差是以天数为单位,所以换算成年月,日
     
      select floor(to_number(sysdate-to_date('2007-11-02 15:55:03','yyyy-mm-dd hh24:mi:ss'))/365) as spanYears from dual        //时间差-年
      select ceil(moths_between(sysdate-to_date('2007-11-02 15:55:03','yyyy-mm-dd hh24:mi:ss'))) as spanMonths from dual        //时间差-月
      select floor(to_number(sysdate-to_date('2007-11-02 15:55:03','yyyy-mm-dd hh24:mi:ss'))) as spanDays from dual             //时间差-天
      select floor(to_number(sysdate-to_date('2007-11-02 15:55:03','yyyy-mm-dd hh24:mi:ss'))*24) as spanHours from dual         //时间差-时
      select floor(to_number(sysdate-to_date('2007-11-02 15:55:03','yyyy-mm-dd hh24:mi:ss'))*24*60) as spanMinutes from dual    //时间差-分
      select floor(to_number(sysdate-to_date('2007-11-02 15:55:03','yyyy-mm-dd hh24:mi:ss'))*24*60*60) as spanSeconds from dual //时间差-秒

28.更新时间
     注:oracle时间加减是以天数为单位,设改变量为n,所以换算成年月,日
     select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),to_char(sysdate+n*365,'yyyy-mm-dd hh24:mi:ss') as newTime from dual        //改变时间-年
     select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),add_months(sysdate,n) as newTime from dual                                 //改变时间-月
     select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),to_char(sysdate+n,'yyyy-mm-dd hh24:mi:ss') as newTime from dual            //改变时间-日
     select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),to_char(sysdate+n/24,'yyyy-mm-dd hh24:mi:ss') as newTime from dual         //改变时间-时
     select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),to_char(sysdate+n/24/60,'yyyy-mm-dd hh24:mi:ss') as newTime from dual      //改变时间-分
     select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),to_char(sysdate+n/24/60/60,'yyyy-mm-dd hh24:mi:ss') as newTime from dual   //改变时间-秒

29.查找月的第一天,最后一天
     SELECT Trunc(Trunc(SYSDATE, 'MONTH') - 1, 'MONTH') First_Day_Last_Month,
       Trunc(SYSDATE, 'MONTH') - 1 / 86400 Last_Day_Last_Month,
       Trunc(SYSDATE, 'MONTH') First_Day_Cur_Month,
       LAST_DAY(Trunc(SYSDATE, 'MONTH')) + 1 - 1 / 86400 Last_Day_Cur_Month
   FROM dual;


三. 字符函数(可用于字面字符或数据库列)

1,字符串截取
   select substr('abcdef',1,3) from dual

2,查找子串位置
   select instr('abcfdgfdhd','fd') from dual

3,字符串连接
   select 'HELLO'||'hello world' from dual;

4, 1)去掉字符串中的空格
    select ltrim(' abc') s1,
    rtrim('zhang ') s2,
    trim(' zhang ') s3 from dual
   2)去掉前导和后缀
    select trim(leading 9 from 9998767999) s1,
    trim(trailing 9 from 9998767999) s2,
    trim(9 from 9998767999) s3 from dual;
   
5,返回字符串首字母的Ascii值
   select ascii('a') from dual

6,返回ascii值对应的字母
   select chr(97) from dual

7,计算字符串长度 
   select length('abcdef') from dual

8,initcap(首字母变大写) ,lower(变小写),upper(变大写)
   select lower('ABC') s1, 
       upper('def') s2, 
       initcap('efg') s3
   from dual;

9,Replace
   select replace('abc','b','xy') from dual;

10,translate
   select translate('abc','b','xx') from dual; -- x是1位

11,lpad [左添充] rpad [右填充](用于控制输出格式)
   select lpad('func',15,'=') s1, rpad('func',15,'-') s2 from dual;
   select lpad(dname,14,'=') from dept;

12, decode[实现if ..then 逻辑]   注:第一个是表达式,最后一个是不满足任何一个条件的值
   select deptno,decode(deptno,10,'1',20,'2',30,'3','其他') from dept;
   例:
   select seed,account_name,decode(seed,111,1000,200,2000,0) from t_userInfo//如果seed为111,则取1000;为200,取2000;其它取0
   select seed,account_name,decode(sign(seed-111),1,'big seed',-1,'little seed','equal seed') from t_userInfo//如果seed>111,则显示大;为200,则显示小;其它则显

示相等

13 case[实现switch ..case 逻辑]
    SELECT CASE X-FIELD 
         WHEN X-FIELD < 40 THEN 'X-FIELD 小于 40'
         WHEN X-FIELD < 50 THEN 'X-FIELD 小于 50'
         WHEN X-FIELD < 60 THEN 'X-FIELD 小于 60'
         ELSE 'UNBEKNOWN'
        END
   FROM DUAL 
   
   注:CASE语句在处理类似问题就显得非常灵活。当只是需要匹配少量数值时,用Decode更为简洁。

四.数字函数
1,取整函数(ceil 向上取整,floor 向下取整)
   select ceil(66.6) N1,floor(66.6) N2 from dual;

2, 取幂(power) 和 求平方根(sqrt)
   select power(3,2) N1,sqrt(9) N2 from dual;

3,求余
   select mod(9,5) from dual;

4,返回固定小数位数 (round:四舍五入,trunc:直接截断)
   select round(66.667,2) N1,trunc(66.667,2) N2 from dual;

5,返回值的符号(正数返回为1,负数为-1)
   select sign(-32),sign(293) from dual;

五.转换函数
1,to_char()[将日期和数字类型转换成字符类型]
   1) select to_char(sysdate) s1,
        to_char(sysdate,'yyyy-mm-dd') s2,
        to_char(sysdate,'yyyy') s3,
        to_char(sysdate,'yyyy-mm-dd hh12:mi:ss') s4,
        to_char(sysdate, 'hh24:mi:ss') s5,
        to_char(sysdate,'DAY') s6 
    from dual;
   2) select sal,to_char(sal,'$99999') n1,to_char(sal,'$99,999') n2 from emp

2, to_date()[将字符类型转换为日期类型] 
    insert into emp(empno,hiredate) values(8000,to_date('2004-10-10','yyyy-mm-dd'));
   
3, to_number() 转换为数字类型 
    select to_number(to_char(sysdate,'hh12')) from dual; //以数字显示的小时数
   
六.其他函数
   1.user: 
    返回登录的用户名称 
    select user from dual;
    
   2.vsize: 
    返回表达式所需的字节数
    select vsize('HELLO') from dual;
   
   3.nvl(ex1,ex2):
    ex1值为空则返回ex2,否则返回该值本身ex1(常用) 
    例:如果雇员没有佣金,将显示0,否则显示佣金 
    select comm,nvl(comm,0) from emp;
   
   4.nullif(ex1,ex2): 
    值相等返空,否则返回第一个值
    例:如果工资和佣金相等,则显示空,否则显示工资
    select nullif(sal,comm),sal,comm from emp;
   
   5.coalesce:
    返回列表中第一个非空表达式
    select comm,sal,coalesce(comm,sal,sal*10) from emp;
   
   6.nvl2(ex1,ex2,ex3) :
    如果ex1不为空,显示ex2,否则显示ex3
    如:查看有佣金的雇员姓名以及他们的佣金 
      select nvl2(comm,ename,') as HaveCommName,comm from emp;
   
   
七.分组函数
max min avg count sum
1,整个结果集是一个组
   1) 求部门30 的最高工资,最低工资,平均工资,总人数,有工作的人数,工种数量及工资总和
     select max(ename),max(sal), 
     min(ename),min(sal),
     avg(sal),
     count(*) ,count(job),count(distinct(job)) ,
     sum(sal) from emp where deptno=30;
2, 带group by 和 having 的分组
   1)按部门分组求最高工资,最低工资,总人数,有工作的人数,工种数量及工资总和
    select deptno, max(ename),max(sal),
    min(ename),min(sal),
    avg(sal),
    count(*) ,count(job),count(distinct(job)) ,
    sum(sal) from emp group by deptno;
   
   2)部门30的最高工资,最低工资,总人数,有工作的人数,工种数量及工资总和 
    select deptno, max(ename),max(sal),
    min(ename),min(sal),
    avg(sal),
    count(*) ,count(job),count(distinct(job)) ,
    sum(sal) from emp group by deptno having deptno=30;
   
3, stddev 返回一组值的标准偏差
    select deptno,stddev(sal) from emp group by deptno;
    variance 返回一组值的方差差
    select deptno,variance(sal) from emp group by deptno;

4, 带有rollup和cube操作符的Group By
    rollup 按分组的第一个列进行统计和最后的小计
    cube 按分组的所有列的进行统计和最后的小计
    select deptno,job ,sum(sal) from emp group by deptno,job;
    select deptno,job ,sum(sal) from emp group by rollup(deptno,job); 
    cube 产生组内所有列的统计和最后的小计
    select deptno,job ,sum(sal) from emp group by cube(deptno,job);

八、临时表
   只在会话期间或在事务处理期间存在的表.
   临时表在插入数据时,动态分配空间 
   create global temporary table temp_dept
   (dno number,
   dname varchar2(10))
   on commit delete rows;
   insert into temp_dept values(10,'ABC');
   commit;
   select * from temp_dept; --无数据显示,数据自动清除
   on commit preserve rows:在会话期间表一直可以存在(保留数据)
   on commit delete rows:事务结束清除数据(在事务结束时自动删除表的数据) 查看全部


   TO_DATE格式(以时间:2007-11-02   13:45:25为例)
   
        Year:      
        yy two digits 两位年                显示值:07
        yyy three digits 三位年                显示值:007
        yyyy four digits 四位年                显示值:2007
            
        Month:      
        mm    number     两位月              显示值:11
        mon    abbreviated 字符集表示          显示值:11月,若是英文版,显示nov     
        month spelled out 字符集表示          显示值:11月,若是英文版,显示november 
          
        Day:      
        dd    number         当月第几天        显示值:02
        ddd    number         当年第几天        显示值:02
        dy    abbreviated 当周第几天简写    显示值:星期五,若是英文版,显示fri
        day    spelled out   当周第几天全写    显示值:星期五,若是英文版,显示friday        
        ddspth spelled out, ordinal twelfth 
             
              Hour:
              hh    two digits 12小时进制            显示值:01
              hh24 two digits 24小时进制            显示值:13
              
              Minute:
              mi    two digits 60进制                显示值:45
              
              Second:
              ss    two digits 60进制                显示值:25
              
              其它
              Q     digit         季度                  显示值:4
              WW    digit         当年第几周            显示值:44
              W    digit          当月第几周            显示值:1
              
        24小时格式下时间范围为: 0:00:00 - 23:59:59....      
        12小时格式下时间范围为: 1:00:00 - 12:59:59 .... 
            
1. 日期和字符转换函数用法(to_date,to_char)
         
select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') as nowTime from dual;   //日期转化为字符串   
select to_char(sysdate,'yyyy') as nowYear   from dual;   //获取时间的年   
select to_char(sysdate,'mm')    as nowMonth from dual;   //获取时间的月   
select to_char(sysdate,'dd')    as nowDay    from dual;   //获取时间的日   
select to_char(sysdate,'hh24') as nowHour   from dual;   //获取时间的时   
select to_char(sysdate,'mi')    as nowMinute from dual;   //获取时间的分   
select to_char(sysdate,'ss')    as nowSecond from dual;   //获取时间的秒

    
select to_date('2004-05-07 13:23:44','yyyy-mm-dd hh24:mi:ss')    from dual//

2.      
    select to_char( to_date(222,'J'),'Jsp') from dual      
    
    显示Two Hundred Twenty-Two    

3.求某天是星期几      
   select to_char(to_date('2002-08-26','yyyy-mm-dd'),'day') from dual;      
   星期一      
   select to_char(to_date('2002-08-26','yyyy-mm-dd'),'day','NLS_DATE_LANGUAGE = American') from dual;      
   monday      
   设置日期语言      
   ALTER SESSION SET NLS_DATE_LANGUAGE='AMERICAN';      
   也可以这样      
   TO_DATE ('2002-08-26', 'YYYY-mm-dd', 'NLS_DATE_LANGUAGE = American')    

4. 两个日期间的天数      
    select floor(sysdate - to_date('20020405','yyyymmdd')) from dual;    

5. 时间为null的用法      
   select id, active_date from table1      
   UNION      
   select 1, TO_DATE(null) from dual;      
   
   注意要用TO_DATE(null)    

6.月份差   
   a_date between to_date('20011201','yyyymmdd') and to_date('20011231','yyyymmdd')      
   那么12月31号中午12点之后和12月1号的12点之前是不包含在这个范围之内的。      
   所以,当时间需要精确的时候,觉得to_char还是必要的 
      
7. 日期格式冲突问题      
    输入的格式要看你安装的ORACLE字符集的类型, 比如: US7ASCII, date格式的类型就是: '01-Jan-01'      
    alter system set NLS_DATE_LANGUAGE = American      
    alter session set NLS_DATE_LANGUAGE = American      
    或者在to_date中写      
    select to_char(to_date('2002-08-26','yyyy-mm-dd'),'day','NLS_DATE_LANGUAGE = American') from dual;      
    注意我这只是举了NLS_DATE_LANGUAGE,当然还有很多,      
    可查看      
    select * from nls_session_parameters      
    select * from V$NLS_PARAMETERS    

8.      
   select count(*)      
   from ( select rownum-1 rnum      
       from all_objects      
       where rownum <= to_date('2002-02-28','yyyy-mm-dd') - to_date('2002-      
       02-01','yyyy-mm-dd')+1      
      )      
   where to_char( to_date('2002-02-01','yyyy-mm-dd')+rnum-1, 'D' )      
        not in ( '1', '7' )      
   
   查找2002-02-28至2002-02-01间除星期一和七的天数      
   在前后分别调用DBMS_UTILITY.GET_TIME, 让后将结果相减(得到的是1/100秒, 而不是毫秒).    

9. 查找月份     
    select months_between(to_date('01-31-1999','MM-DD-YYYY'),to_date('12-31-1998','MM-DD-YYYY')) "MONTHS" FROM DUAL;      
    1      
   select months_between(to_date('02-01-1999','MM-DD-YYYY'),to_date('12-31-1998','MM-DD-YYYY')) "MONTHS" FROM DUAL;      
    1.03225806451613 
       
10. Next_day的用法      
    Next_day(date, day)      
    
    Monday-Sunday, for format code DAY      
    Mon-Sun, for format code DY      
    1-7, for format code D    

11      
   select to_char(sysdate,'hh:mi:ss') TIME from all_objects      
   注意:第一条记录的TIME 与最后一行是一样的      
   可以建立一个函数来处理这个问题      
   create or replace function sys_date return date is      
   begin      
   return sysdate;      
   end;      
   
   select to_char(sys_date,'hh:mi:ss') from all_objects;   
     
12.获得小时数      
     extract()找出日期或间隔值的字段值
    SELECT EXTRACT(HOUR FROM TIMESTAMP '2001-02-16 2:38:40') from offer      
    SQL> select sysdate ,to_char(sysdate,'hh') from dual;      
    
    SYSDATE TO_CHAR(SYSDATE,'HH')      
    -------------------- ---------------------      
    2003-10-13 19:35:21 07      
    
    SQL> select sysdate ,to_char(sysdate,'hh24') from dual;      
    
    SYSDATE TO_CHAR(SYSDATE,'HH24')      
    -------------------- -----------------------      
    2003-10-13 19:35:21 19    

       
13.年月日的处理      
   select older_date,      
       newer_date,      
       years,      
       months,      
       abs(      
        trunc(      
         newer_date-      
         add_months( older_date,years*12+months )      
        )      
       ) days 
       
   from ( select      
        trunc(months_between( newer_date, older_date )/12) YEARS,      
        mod(trunc(months_between( newer_date, older_date )),12 ) MONTHS,      
        newer_date,      
        older_date      
        from ( 
              select hiredate older_date, add_months(hiredate,rownum)+rownum newer_date      
              from emp 
             )      
      )    

14.处理月份天数不定的办法      
   select to_char(add_months(last_day(sysdate) +1, -2), 'yyyymmdd'),last_day(sysdate) from dual    

16.找出今年的天数      
   select add_months(trunc(sysdate,'year'), 12) - trunc(sysdate,'year') from dual    

   闰年的处理方法      
   to_char( last_day( to_date('02'    | | :year,'mmyyyy') ), 'dd' )      
   如果是28就不是闰年    

17.yyyy与rrrr的区别      
   'YYYY99 TO_C      
   ------- ----      
   yyyy 99 0099      
   rrrr 99 1999      
   yyyy 01 0001      
   rrrr 01 2001    

18.不同时区的处理      
   select to_char( NEW_TIME( sysdate, 'GMT','EST'), 'dd/mm/yyyy hh:mi:ss') ,sysdate      
   from dual;    

19.5秒钟一个间隔      
   Select TO_DATE(FLOOR(TO_CHAR(sysdate,'SSSSS')/300) * 300,'SSSSS') ,TO_CHAR(sysdate,'SSSSS')      
   from dual    

   2002-11-1 9:55:00 35786      
   SSSSS表示5位秒数    

20.一年的第几天      
   select TO_CHAR(SYSDATE,'DDD'),sysdate from dual
        
   310 2002-11-6 10:03:51    

21.计算小时,分,秒,毫秒      
    select      
     Days,      
     A,      
     TRUNC(A*24) Hours,      
     TRUNC(A*24*60 - 60*TRUNC(A*24)) Minutes,      
     TRUNC(A*24*60*60 - 60*TRUNC(A*24*60)) Seconds,      
     TRUNC(A*24*60*60*100 - 100*TRUNC(A*24*60*60)) mSeconds      
    from      
    (      
     select      
     trunc(sysdate) Days,      
     sysdate - trunc(sysdate) A      
     from dual      
   )    


   select * from tabname      
   order by decode(mode,'FIFO',1,-1)*to_char(rq,'yyyymmddhh24miss');      
   
   //      
   floor((date2-date1) /365) 作为年      
   floor((date2-date1, 365) /30) 作为月      
   d(mod(date2-date1, 365), 30)作为日.

23.next_day函数      返回下个星期的日期,day为1-7或星期日-星期六,1表示星期日
   next_day(sysdate,6)是从当前开始下一个星期五。后面的数字是从星期日开始算起。      
   1 2 3 4 5 6 7      
   日 一 二 三 四 五 六    
   
   --------------------------------------------------------------- 
   
   select    (sysdate-to_date('2003-12-03 12:55:45','yyyy-mm-dd hh24:mi:ss'))*24*60*60 from ddual
   日期 返回的是天 然后 转换为ss
     
24,round[舍入到最接近的日期](day:舍入到最接近的星期日)
   select sysdate S1,
   round(sysdate) S2 ,
   round(sysdate,'year') YEAR,
   round(sysdate,'month') MONTH ,
   round(sysdate,'day') DAY from dual

25,trunc[截断到最接近的日期,单位为天] ,返回的是日期类型
   select sysdate S1,                     
     trunc(sysdate) S2,                 //返回当前日期,无时分秒
     trunc(sysdate,'year') YEAR,        //返回当前年的1月1日,无时分秒
     trunc(sysdate,'month') MONTH ,     //返回当前月的1日,无时分秒
     trunc(sysdate,'day') DAY           //返回当前星期的星期天,无时分秒
   from dual

26,返回日期列表中最晚日期
   select greatest('01-1月-04','04-1月-04','10-2月-04') from dual

27.计算时间差
     注:oracle时间差是以天数为单位,所以换算成年月,日
     
      select floor(to_number(sysdate-to_date('2007-11-02 15:55:03','yyyy-mm-dd hh24:mi:ss'))/365) as spanYears from dual        //时间差-年
      select ceil(moths_between(sysdate-to_date('2007-11-02 15:55:03','yyyy-mm-dd hh24:mi:ss'))) as spanMonths from dual        //时间差-月
      select floor(to_number(sysdate-to_date('2007-11-02 15:55:03','yyyy-mm-dd hh24:mi:ss'))) as spanDays from dual             //时间差-天
      select floor(to_number(sysdate-to_date('2007-11-02 15:55:03','yyyy-mm-dd hh24:mi:ss'))*24) as spanHours from dual         //时间差-时
      select floor(to_number(sysdate-to_date('2007-11-02 15:55:03','yyyy-mm-dd hh24:mi:ss'))*24*60) as spanMinutes from dual    //时间差-分
      select floor(to_number(sysdate-to_date('2007-11-02 15:55:03','yyyy-mm-dd hh24:mi:ss'))*24*60*60) as spanSeconds from dual //时间差-秒

28.更新时间
     注:oracle时间加减是以天数为单位,设改变量为n,所以换算成年月,日
     select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),to_char(sysdate+n*365,'yyyy-mm-dd hh24:mi:ss') as newTime from dual        //改变时间-年
     select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),add_months(sysdate,n) as newTime from dual                                 //改变时间-月
     select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),to_char(sysdate+n,'yyyy-mm-dd hh24:mi:ss') as newTime from dual            //改变时间-日
     select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),to_char(sysdate+n/24,'yyyy-mm-dd hh24:mi:ss') as newTime from dual         //改变时间-时
     select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),to_char(sysdate+n/24/60,'yyyy-mm-dd hh24:mi:ss') as newTime from dual      //改变时间-分
     select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),to_char(sysdate+n/24/60/60,'yyyy-mm-dd hh24:mi:ss') as newTime from dual   //改变时间-秒

29.查找月的第一天,最后一天
     SELECT Trunc(Trunc(SYSDATE, 'MONTH') - 1, 'MONTH') First_Day_Last_Month,
       Trunc(SYSDATE, 'MONTH') - 1 / 86400 Last_Day_Last_Month,
       Trunc(SYSDATE, 'MONTH') First_Day_Cur_Month,
       LAST_DAY(Trunc(SYSDATE, 'MONTH')) + 1 - 1 / 86400 Last_Day_Cur_Month
   FROM dual;


三. 字符函数(可用于字面字符或数据库列)

1,字符串截取
   select substr('abcdef',1,3) from dual

2,查找子串位置
   select instr('abcfdgfdhd','fd') from dual

3,字符串连接
   select 'HELLO'||'hello world' from dual;

4, 1)去掉字符串中的空格
    select ltrim(' abc') s1,
    rtrim('zhang ') s2,
    trim(' zhang ') s3 from dual
   2)去掉前导和后缀
    select trim(leading 9 from 9998767999) s1,
    trim(trailing 9 from 9998767999) s2,
    trim(9 from 9998767999) s3 from dual;
   
5,返回字符串首字母的Ascii值
   select ascii('a') from dual

6,返回ascii值对应的字母
   select chr(97) from dual

7,计算字符串长度 
   select length('abcdef') from dual

8,initcap(首字母变大写) ,lower(变小写),upper(变大写)
   select lower('ABC') s1, 
       upper('def') s2, 
       initcap('efg') s3
   from dual;

9,Replace
   select replace('abc','b','xy') from dual;

10,translate
   select translate('abc','b','xx') from dual; -- x是1位

11,lpad [左添充] rpad [右填充](用于控制输出格式)
   select lpad('func',15,'=') s1, rpad('func',15,'-') s2 from dual;
   select lpad(dname,14,'=') from dept;

12, decode[实现if ..then 逻辑]   注:第一个是表达式,最后一个是不满足任何一个条件的值
   select deptno,decode(deptno,10,'1',20,'2',30,'3','其他') from dept;
   例:
   select seed,account_name,decode(seed,111,1000,200,2000,0) from t_userInfo//如果seed为111,则取1000;为200,取2000;其它取0
   select seed,account_name,decode(sign(seed-111),1,'big seed',-1,'little seed','equal seed') from t_userInfo//如果seed>111,则显示大;为200,则显示小;其它则显

示相等

13 case[实现switch ..case 逻辑]
    SELECT CASE X-FIELD 
         WHEN X-FIELD < 40 THEN 'X-FIELD 小于 40'
         WHEN X-FIELD < 50 THEN 'X-FIELD 小于 50'
         WHEN X-FIELD < 60 THEN 'X-FIELD 小于 60'
         ELSE 'UNBEKNOWN'
        END
   FROM DUAL 
   
   注:CASE语句在处理类似问题就显得非常灵活。当只是需要匹配少量数值时,用Decode更为简洁。

四.数字函数
1,取整函数(ceil 向上取整,floor 向下取整)
   select ceil(66.6) N1,floor(66.6) N2 from dual;

2, 取幂(power) 和 求平方根(sqrt)
   select power(3,2) N1,sqrt(9) N2 from dual;

3,求余
   select mod(9,5) from dual;

4,返回固定小数位数 (round:四舍五入,trunc:直接截断)
   select round(66.667,2) N1,trunc(66.667,2) N2 from dual;

5,返回值的符号(正数返回为1,负数为-1)
   select sign(-32),sign(293) from dual;

五.转换函数
1,to_char()[将日期和数字类型转换成字符类型]
   1) select to_char(sysdate) s1,
        to_char(sysdate,'yyyy-mm-dd') s2,
        to_char(sysdate,'yyyy') s3,
        to_char(sysdate,'yyyy-mm-dd hh12:mi:ss') s4,
        to_char(sysdate, 'hh24:mi:ss') s5,
        to_char(sysdate,'DAY') s6 
    from dual;
   2) select sal,to_char(sal,'$99999') n1,to_char(sal,'$99,999') n2 from emp

2, to_date()[将字符类型转换为日期类型] 
    insert into emp(empno,hiredate) values(8000,to_date('2004-10-10','yyyy-mm-dd'));
   
3, to_number() 转换为数字类型 
    select to_number(to_char(sysdate,'hh12')) from dual; //以数字显示的小时数
   
六.其他函数
   1.user: 
    返回登录的用户名称 
    select user from dual;
    
   2.vsize: 
    返回表达式所需的字节数
    select vsize('HELLO') from dual;
   
   3.nvl(ex1,ex2):
    ex1值为空则返回ex2,否则返回该值本身ex1(常用) 
    例:如果雇员没有佣金,将显示0,否则显示佣金 
    select comm,nvl(comm,0) from emp;
   
   4.nullif(ex1,ex2): 
    值相等返空,否则返回第一个值
    例:如果工资和佣金相等,则显示空,否则显示工资
    select nullif(sal,comm),sal,comm from emp;
   
   5.coalesce:
    返回列表中第一个非空表达式
    select comm,sal,coalesce(comm,sal,sal*10) from emp;
   
   6.nvl2(ex1,ex2,ex3) :
    如果ex1不为空,显示ex2,否则显示ex3
    如:查看有佣金的雇员姓名以及他们的佣金 
      select nvl2(comm,ename,') as HaveCommName,comm from emp;
   
   
七.分组函数
max min avg count sum
1,整个结果集是一个组
   1) 求部门30 的最高工资,最低工资,平均工资,总人数,有工作的人数,工种数量及工资总和
     select max(ename),max(sal), 
     min(ename),min(sal),
     avg(sal),
     count(*) ,count(job),count(distinct(job)) ,
     sum(sal) from emp where deptno=30;
2, 带group by 和 having 的分组
   1)按部门分组求最高工资,最低工资,总人数,有工作的人数,工种数量及工资总和
    select deptno, max(ename),max(sal),
    min(ename),min(sal),
    avg(sal),
    count(*) ,count(job),count(distinct(job)) ,
    sum(sal) from emp group by deptno;
   
   2)部门30的最高工资,最低工资,总人数,有工作的人数,工种数量及工资总和 
    select deptno, max(ename),max(sal),
    min(ename),min(sal),
    avg(sal),
    count(*) ,count(job),count(distinct(job)) ,
    sum(sal) from emp group by deptno having deptno=30;
   
3, stddev 返回一组值的标准偏差
    select deptno,stddev(sal) from emp group by deptno;
    variance 返回一组值的方差差
    select deptno,variance(sal) from emp group by deptno;

4, 带有rollup和cube操作符的Group By
    rollup 按分组的第一个列进行统计和最后的小计
    cube 按分组的所有列的进行统计和最后的小计
    select deptno,job ,sum(sal) from emp group by deptno,job;
    select deptno,job ,sum(sal) from emp group by rollup(deptno,job); 
    cube 产生组内所有列的统计和最后的小计
    select deptno,job ,sum(sal) from emp group by cube(deptno,job);

八、临时表
   只在会话期间或在事务处理期间存在的表.
   临时表在插入数据时,动态分配空间 
   create global temporary table temp_dept
   (dno number,
   dname varchar2(10))
   on commit delete rows;
   insert into temp_dept values(10,'ABC');
   commit;
   select * from temp_dept; --无数据显示,数据自动清除
   on commit preserve rows:在会话期间表一直可以存在(保留数据)
   on commit delete rows:事务结束清除数据(在事务结束时自动删除表的数据)

ORA-12154: TNS: 无法解析指定的连接标识符

admin 发表了文章 • 0 个评论 • 69 次浏览 • 2018-04-26 17:26 • 来自相关话题

      相信使用过Oracle数据库的人一定碰到过“ORA-12154: TNS: 无法解析指定的连接标识符”错误,我在此做一个小小的总结。

      在程序中连接Oracle数据库的方式与其他常用数据库,如:MySql,Sql Server不同,这些数据库可以通过直接指定IP的方式连接,但是Oracle则需要通过Oracle客户端配置网络服务名的方式来连接。否则就会出现“ORA-12154: TNS: 无法解析指定的连接标识符”。配置Oracle客户端详细步骤如下:
      安装好Oracle客户端之后,在开始菜单中依次找到“Oracle - OraClient10g_home1—>配置和移植工具—>Net Manager”并打开(Win7,Win8用户如果没有取得Administrator账号登陆需要以管理员方式运行),依次展开“Oracle Net配置—>本地—>服务命名”点击左侧“加号”配置新的网络服务

[image]

[image]

[image]

[image]

      最后,点击“下一步”完成即可,如果不知道或者忘记Oracle服务名可以通过查看服务获得,比如我这里配置的主机名是我本机,在我的电脑服务中找到oracle相关的服务

[image]

通过上面的服务名称,可以看出我安装的服务名就是“ORCL”,或者在服务端通过SQL Plus使用sys账号登陆,输入命令
show parameter service_name查看。
OracleDBConsoleORCL是Oracle网页端管理工具的服务,访问地址一般为“http://127.0.0.1:1158/em/console/logon/logon”,如果不习惯用这个来管理数据库可以不用启动。
OracleJobSchedulerORCL是管理Oracle中计划任务的,一般不用启动。
OracleOraDb10g_home1iSQL*Plus是SQL Plus的服务,如果不习惯在命令行下面操作数据库,可以不用启动。
OracleServiceORCL,OracleOraDb10g_home1TNSListener都需要开启,前者是主服务,后者是监听服务。

     当在Oracle客户端中配置好Net Manager中配置好服务后就可以通过我们配置的网络服务名访问Oracle数据库了,此配置实质想D:\Oracle\product\10.2.0\client_1\NETWORK\ADMIN\tnsnames.ora中增加了一行配置(由于我的Oracle是安装在D盘Oracle目录中,具体路径根据安装时选择的路径而定)。[复制代码]
# tnsnames.ora Network Configuration File: d:\Oracle\product\10.2.0\client_1\NETWORK\ADMIN\tnsnames.ora # Generated by Oracle configuration tools. ORCL = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = 127.0.0.1)(PORT = 1521)) ) (CONNECT_DATA = (SERVICE_NAME = ORCL) ) )
[复制代码]    如果在同一台电脑上面同时安装了Oracle客户端和服务端,那么在服务端的安装目录中也会存在同样的配置文件D:\Oracle\product\10.2.0\db_1\NETWORK\ADMIN\tnsnames.ora,在这种情况下如果我们配置好了客户端Net Manager然后连接Oracle数据库,可能会出现“ORA-12154: TNS: 无法解析指定的连接标识符”这时,你就应该怀疑,我到底访问的是哪个路径下的配置文件呢?此时可以使用tnsping命令

[image]

      如果你是在客户端Net Manager中配置的网络服务,但是此时解析出来的使用参数文件却是D:\Oracle\product\10.2.0\db_1\NETWORK\ADMIN\sqlnet.ora,那么我想你应该明白了。这种情况有两种解决办法:
      第一:在服务端的Net Manager也配置相同的网络服务,或者直接拷贝D:\Oracle\product\10.2.0\client_1\NETWORK\ADMIN\tnsnames.ora中的配置到D:\Oracle\product\10.2.0\db_1\NETWORK\ADMIN\tnsnames.ora,每次配置了新的网络服务你都需要这么做,如果不想这么麻烦那就使用第二种解决办法。     
      第二:修改系统环境变量Path值,将D:\Oracle\product\10.2.0\client_1\bin;路径移至D:\Oracle\product\10.2.0\db_1\bin;前面即可一劳永逸。
      注意:造成以上这种情况出现的原因是:在一台电脑上同时安装了oracle客户端和数据库服务,并且是先安装客户端,再安装数据库服务造成的,如果先安装数据库服务,再安装客户端就不会出现这种情况了。
      根据以上方式配置完oracle后,相信在程序中就可以正常连接oracle数据库了。

      当我安装好PLSQL Developer软件后登陆时任然出现了“ORA-12154: TNS: 无法解析指定的连接标识符”,如果是Win7,Win8用户甚至可以会出现弹出一个白框的情况,这时需要以管理员身份运行PLSQL Developer,并且确保你的PLSQL Developer是读取的oracle客户端配置,直接取消登陆,在PLSQL Developer工具栏中找到“Tools—>Preferences”,在Oracle的Connection节点中找到Oracle Home选择OraClient10g_home1,保存后关闭PLSQL Developer就可以正常登陆了。

[image]

     需要注意的是,在安装PLSQL Developer时不能安装在带有括号的目录中,如64bit系统的Program Files (x86)目录,就会出现无论你怎么设置,它依然不停的弹出“ORA-12154: TNS: 无法解析指定的连接标识符”。同样的问题也会出现在其他Oracle数据库管理软件中,比如Toad for Oracle

     “ORA-12154: TNS: 无法解析指定的连接标识符”是使用Oracle数据库的新手遇到的比较常见的问题之一,只要我们了解了它的工作方式,冷静排查,相信很容易就能够找到问题的解决办法的。 查看全部

      相信使用过Oracle数据库的人一定碰到过“ORA-12154: TNS: 无法解析指定的连接标识符”错误,我在此做一个小小的总结。

      在程序中连接Oracle数据库的方式与其他常用数据库,如:MySql,Sql Server不同,这些数据库可以通过直接指定IP的方式连接,但是Oracle则需要通过Oracle客户端配置网络服务名的方式来连接。否则就会出现“ORA-12154: TNS: 无法解析指定的连接标识符”。配置Oracle客户端详细步骤如下:
      安装好Oracle客户端之后,在开始菜单中依次找到“Oracle - OraClient10g_home1—>配置和移植工具—>Net Manager”并打开(Win7,Win8用户如果没有取得Administrator账号登陆需要以管理员方式运行),依次展开“Oracle Net配置—>本地—>服务命名”点击左侧“加号”配置新的网络服务

[image]

[image]

[image]

[image]

      最后,点击“下一步”完成即可,如果不知道或者忘记Oracle服务名可以通过查看服务获得,比如我这里配置的主机名是我本机,在我的电脑服务中找到oracle相关的服务

[image]

通过上面的服务名称,可以看出我安装的服务名就是“ORCL”,或者在服务端通过SQL Plus使用sys账号登陆,输入命令
show parameter service_name查看。
OracleDBConsoleORCL是Oracle网页端管理工具的服务,访问地址一般为“http://127.0.0.1:1158/em/console/logon/logon”,如果不习惯用这个来管理数据库可以不用启动。
OracleJobSchedulerORCL是管理Oracle中计划任务的,一般不用启动。
OracleOraDb10g_home1iSQL*Plus是SQL Plus的服务,如果不习惯在命令行下面操作数据库,可以不用启动。
OracleServiceORCL,OracleOraDb10g_home1TNSListener都需要开启,前者是主服务,后者是监听服务。

     当在Oracle客户端中配置好Net Manager中配置好服务后就可以通过我们配置的网络服务名访问Oracle数据库了,此配置实质想D:\Oracle\product\10.2.0\client_1\NETWORK\ADMIN\tnsnames.ora中增加了一行配置(由于我的Oracle是安装在D盘Oracle目录中,具体路径根据安装时选择的路径而定)。[复制代码]
# tnsnames.ora Network Configuration File: d:\Oracle\product\10.2.0\client_1\NETWORK\ADMIN\tnsnames.ora # Generated by Oracle configuration tools. ORCL = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = 127.0.0.1)(PORT = 1521)) ) (CONNECT_DATA = (SERVICE_NAME = ORCL) ) )
[复制代码]    如果在同一台电脑上面同时安装了Oracle客户端和服务端,那么在服务端的安装目录中也会存在同样的配置文件D:\Oracle\product\10.2.0\db_1\NETWORK\ADMIN\tnsnames.ora,在这种情况下如果我们配置好了客户端Net Manager然后连接Oracle数据库,可能会出现“ORA-12154: TNS: 无法解析指定的连接标识符”这时,你就应该怀疑,我到底访问的是哪个路径下的配置文件呢?此时可以使用tnsping命令

[image]

      如果你是在客户端Net Manager中配置的网络服务,但是此时解析出来的使用参数文件却是D:\Oracle\product\10.2.0\db_1\NETWORK\ADMIN\sqlnet.ora,那么我想你应该明白了。这种情况有两种解决办法:
      第一:在服务端的Net Manager也配置相同的网络服务,或者直接拷贝D:\Oracle\product\10.2.0\client_1\NETWORK\ADMIN\tnsnames.ora中的配置到D:\Oracle\product\10.2.0\db_1\NETWORK\ADMIN\tnsnames.ora,每次配置了新的网络服务你都需要这么做,如果不想这么麻烦那就使用第二种解决办法。     
      第二:修改系统环境变量Path值,将D:\Oracle\product\10.2.0\client_1\bin;路径移至D:\Oracle\product\10.2.0\db_1\bin;前面即可一劳永逸。
      注意:造成以上这种情况出现的原因是:在一台电脑上同时安装了oracle客户端和数据库服务,并且是先安装客户端,再安装数据库服务造成的,如果先安装数据库服务,再安装客户端就不会出现这种情况了。
      根据以上方式配置完oracle后,相信在程序中就可以正常连接oracle数据库了。

      当我安装好PLSQL Developer软件后登陆时任然出现了“ORA-12154: TNS: 无法解析指定的连接标识符”,如果是Win7,Win8用户甚至可以会出现弹出一个白框的情况,这时需要以管理员身份运行PLSQL Developer,并且确保你的PLSQL Developer是读取的oracle客户端配置,直接取消登陆,在PLSQL Developer工具栏中找到“Tools—>Preferences”,在Oracle的Connection节点中找到Oracle Home选择OraClient10g_home1,保存后关闭PLSQL Developer就可以正常登陆了。

[image]

     需要注意的是,在安装PLSQL Developer时不能安装在带有括号的目录中,如64bit系统的Program Files (x86)目录,就会出现无论你怎么设置,它依然不停的弹出“ORA-12154: TNS: 无法解析指定的连接标识符”。同样的问题也会出现在其他Oracle数据库管理软件中,比如Toad for Oracle

     “ORA-12154: TNS: 无法解析指定的连接标识符”是使用Oracle数据库的新手遇到的比较常见的问题之一,只要我们了解了它的工作方式,冷静排查,相信很容易就能够找到问题的解决办法的。

cmd重启ORACLE数据

admin 发表了文章 • 0 个评论 • 75 次浏览 • 2018-04-26 11:52 • 来自相关话题

建立一个 startup.sql的文件,内容:

1
2
3
conn /as sysdba;
shutdow immediate;
startup

然后再创建一个restartup.bat

1
sqlplus /nolog @startup.sql

然后用restartup.bat就可以了。 查看全部
建立一个 startup.sql的文件,内容:

1
2
3
conn /as sysdba;
shutdow immediate;
startup

然后再创建一个restartup.bat

1
sqlplus /nolog @startup.sql

然后用restartup.bat就可以了。

记32位Oracle客户端登录报12560协议适配器错误的解决办法

admin 发表了文章 • 0 个评论 • 61 次浏览 • 2018-04-26 11:26 • 来自相关话题

64位windows操作系统,必须装64位Oracle数据库服务器端,pl/sql必须连接32位Oracle数据库客户端,那么就必须要下一个Oracle的32位客户端程序。我下了,然后安装了,这里注意一点:第二步选择管理员。然后问题出现了,先别说pl/sql能不能连上Oracle,就连sqlplus都连不上,输入用户名密码后,提示一个tns12560:协议适配器错误的报错信息。笔者也是Oracle新手啊,找问题原因期间遇到了无数次失败,又无数次地问度娘。这里说说度娘给的几点很有用的意见:1、OracleOraDb11g_home1TNSListener这个服务必须启动运行(注意11g_home1跟你安装数据库的版本以及路径有关系);2、OracleServiceORCL这个服务也必须启动运行(orcl与你Oracle数据库名称有关系);3、环境变量中最好设置变量名为oracle_sid,变量值为orcl的变量(orcl与你Oracle数据库名称有关系);4、启用和禁用用户名的命令是alter user scott account lock/unlock;(scott是一个用户名);5、用户启用后首次登录会提示更改预设密码,改为原密码也可以;6、还有人没有安装Oracle数据库32位客户端程序,而是安装了一个instant_client_basic(名字好像是这个,可能不准确)程序,然后仅将Oracle服务器端里的network/admin/文件夹下的配置文件复制到那个程序的文件夹中,且将pl/sql的OCI库设置到那个程序文件夹即可(这里表述不是很清晰,请有用这个方法的人自行百度,很多很全)。可是我的问题没解决呢!经过多番尝试,明确一点,那就是Oracle数据库服务器配置没有问题,用服务器端里的sqlplus能够正确连接并登录数据库。然后打开客户端的网络配置(NET Manager),发现里面没有服务,猜想是不是这里的问题呢?于是就将服务器端的网络配置打开,那里面已经配好了两个服务,其中一个就是我默认的orcl。然后参照里面的参数在客户端的网络配置中配置了一个一模一样的服务,这里有个小插曲,当时已经启用的scott这个用户,但是还没有登录过数据库,在配置最后一步进行测试时,默认用scott用户测试,结果报错,错误信息当时没看懂。于是用sqlplus登录scott用户(当然这是还用的服务器端的sqlplus),结果并没有立刻进去,而是提示请立即更改预设密码,这是回看刚才的报错,一样的信息嘛!更改以后,再到配置最后一步进行测试,提示连接成功。这次该到客户端的sqlplus中登录用户了,可惜还是登录不上去,到底为什么呢?这时回忆刚才度娘里那些前人给的说法,依稀记得有人用“用户名/密码@服务名”方式登录数据库,这种方式在之前导入导出数据库时也用过,于是就用这种格式尝试,sqlplus终于不提示协议适配器错误了,而是显示连接到数据库服务器中了,泪流满面啊!还差最后一步了,启动pl/sql developer程序,先不登录用户,点击取消按钮,直接进入软件,在工具-首选项-连接中(其实就是进入首选项后的第一个界面,用英文的朋友差不多能找到吧),Oracle主目录名选择下拉列表框中给出的选项即可,OCI库也是一样(这里注意一定要是客户端安装目录,比如路径中还有client_1这样的字眼,跟你安装客户端是的路径有关系,当然一般下拉列表框中给出的选项就是客户端的)。然后退出pl/sql程序,重新启动并进入,这时登录用户名为scott、密码为tiger、数据库为orcl,这几个值都跟个人的设置有关系,我这里给出的是默认值。然后pl/sql启动画面显示已连接,过几秒就进入软件主窗体界面,至此问题全都解决,可以在64位系统下使用Oracle数据库喽!

以上就是今天解决问题的全过程。真心想用64位操作系统,但是之前的内存太小,而且64位存在兼容问题,于是迟迟没有用。今天借着预装正版64位系统的东风,熟悉一下,并且解决了一个小问题。以后会坚定的走在64位平台上,服务器从win2008开始就没有32位了,而手机也快迈入64位了,我们开发人员不要固守32位系统了,当然如果你有需要,可以用虚拟机嘛,我的下一篇文章可能就是解决使用虚拟机碰到的问题。希望这篇文章能够帮到遇到同样问题的朋友! 查看全部
64位windows操作系统,必须装64位Oracle数据库服务器端,pl/sql必须连接32位Oracle数据库客户端,那么就必须要下一个Oracle的32位客户端程序。我下了,然后安装了,这里注意一点:第二步选择管理员。然后问题出现了,先别说pl/sql能不能连上Oracle,就连sqlplus都连不上,输入用户名密码后,提示一个tns12560:协议适配器错误的报错信息。笔者也是Oracle新手啊,找问题原因期间遇到了无数次失败,又无数次地问度娘。这里说说度娘给的几点很有用的意见:1、OracleOraDb11g_home1TNSListener这个服务必须启动运行(注意11g_home1跟你安装数据库的版本以及路径有关系);2、OracleServiceORCL这个服务也必须启动运行(orcl与你Oracle数据库名称有关系);3、环境变量中最好设置变量名为oracle_sid,变量值为orcl的变量(orcl与你Oracle数据库名称有关系);4、启用和禁用用户名的命令是alter user scott account lock/unlock;(scott是一个用户名);5、用户启用后首次登录会提示更改预设密码,改为原密码也可以;6、还有人没有安装Oracle数据库32位客户端程序,而是安装了一个instant_client_basic(名字好像是这个,可能不准确)程序,然后仅将Oracle服务器端里的network/admin/文件夹下的配置文件复制到那个程序的文件夹中,且将pl/sql的OCI库设置到那个程序文件夹即可(这里表述不是很清晰,请有用这个方法的人自行百度,很多很全)。可是我的问题没解决呢!经过多番尝试,明确一点,那就是Oracle数据库服务器配置没有问题,用服务器端里的sqlplus能够正确连接并登录数据库。然后打开客户端的网络配置(NET Manager),发现里面没有服务,猜想是不是这里的问题呢?于是就将服务器端的网络配置打开,那里面已经配好了两个服务,其中一个就是我默认的orcl。然后参照里面的参数在客户端的网络配置中配置了一个一模一样的服务,这里有个小插曲,当时已经启用的scott这个用户,但是还没有登录过数据库,在配置最后一步进行测试时,默认用scott用户测试,结果报错,错误信息当时没看懂。于是用sqlplus登录scott用户(当然这是还用的服务器端的sqlplus),结果并没有立刻进去,而是提示请立即更改预设密码,这是回看刚才的报错,一样的信息嘛!更改以后,再到配置最后一步进行测试,提示连接成功。这次该到客户端的sqlplus中登录用户了,可惜还是登录不上去,到底为什么呢?这时回忆刚才度娘里那些前人给的说法,依稀记得有人用“用户名/密码@服务名”方式登录数据库,这种方式在之前导入导出数据库时也用过,于是就用这种格式尝试,sqlplus终于不提示协议适配器错误了,而是显示连接到数据库服务器中了,泪流满面啊!还差最后一步了,启动pl/sql developer程序,先不登录用户,点击取消按钮,直接进入软件,在工具-首选项-连接中(其实就是进入首选项后的第一个界面,用英文的朋友差不多能找到吧),Oracle主目录名选择下拉列表框中给出的选项即可,OCI库也是一样(这里注意一定要是客户端安装目录,比如路径中还有client_1这样的字眼,跟你安装客户端是的路径有关系,当然一般下拉列表框中给出的选项就是客户端的)。然后退出pl/sql程序,重新启动并进入,这时登录用户名为scott、密码为tiger、数据库为orcl,这几个值都跟个人的设置有关系,我这里给出的是默认值。然后pl/sql启动画面显示已连接,过几秒就进入软件主窗体界面,至此问题全都解决,可以在64位系统下使用Oracle数据库喽!

以上就是今天解决问题的全过程。真心想用64位操作系统,但是之前的内存太小,而且64位存在兼容问题,于是迟迟没有用。今天借着预装正版64位系统的东风,熟悉一下,并且解决了一个小问题。以后会坚定的走在64位平台上,服务器从win2008开始就没有32位了,而手机也快迈入64位了,我们开发人员不要固守32位系统了,当然如果你有需要,可以用虚拟机嘛,我的下一篇文章可能就是解决使用虚拟机碰到的问题。希望这篇文章能够帮到遇到同样问题的朋友!

Oracle常用命令大全(很有用,做笔记)

admin 发表了文章 • 0 个评论 • 53 次浏览 • 2018-04-26 10:05 • 来自相关话题

Oracle常用命令大全(很有用,做笔记)

一、ORACLE的启动和关闭 
1、在单机环境下 
要想启动或关闭ORACLE系统必须首先切换到ORACLE用户,如下 
su - oracle 

a、启动ORACLE系统 
oracle>svrmgrl 
SVRMGR>connect internal 
SVRMGR>startup 
SVRMGR>quit 

b、关闭ORACLE系统 
oracle>svrmgrl 
SVRMGR>connect internal 
SVRMGR>shutdown 
SVRMGR>quit 

启动oracle9i数据库命令: 
$ sqlplus /nolog 

SQL*Plus: Release 9.2.0.1.0 - Production on Fri Oct 31 13:53:53 2003 

Copyright (c) 1982, 2002, Oracle Corporation.  All rights reserved. 

SQL> connect / as sysdba  
Connected to an idle instance. 
SQL> startup^C 

SQL> startup 
ORACLE instance started. 


2、在双机环境下 
要想启动或关闭ORACLE系统必须首先切换到root用户,如下 
su - root 

a、启动ORACLE系统 
hareg -y oracle 

b、关闭ORACLE系统 
hareg -n oracle 

Oracle数据库有哪几种启动方式 


说明: 

有以下几种启动方式: 
1、startup nomount 
非安装启动,这种方式启动下可执行:重建控制文件、重建数据库 

读取init.ora文件,启动instance,即启动SGA和后台进程,这种启动只需要init.ora文件。 


2、startup mount dbname 
安装启动,这种方式启动下可执行: 
数据库日志归档、 
数据库介质恢复、 
使数据文件联机或脱机, 
重新定位数据文件、重做日志文件。 

执行“nomount”,然后打开控制文件,确认数据文件和联机日志文件的位置, 
但此时不对数据文件和日志文件进行校验检查。 


3、startup open dbname 
先执行“nomount”,然后执行“mount”,再打开包括Redo log文件在内的所有数据库文件, 
这种方式下可访问数据库中的数据。 


4、startup,等于以下三个命令 
startup nomount 
alter database mount 
alter database open 


5、startup restrict 
约束方式启动 
这种方式能够启动数据库,但只允许具有一定特权的用户访问 
非特权用户访问时,会出现以下提示: 
ERROR: 
ORA-01035: ORACLE 只允许具有 RESTRICTED SESSION 权限的用户使用 


6、startup force 
强制启动方式 
当不能关闭数据库时,可以用startup force来完成数据库的关闭 
先关闭数据库,再执行正常启动数据库命令 


7、startup pfile=参数文件名 
带初始化参数文件的启动方式 
先读取参数文件,再按参数文件中的设置启动数据库 
例:startup pfile=E:Oracleadminoradbpfileinit.ora 


8、startup EXCLUSIVE 
二、用户如何有效地利用数据字典 
   ORACLE的数据字典是数据库的重要组成部分之一,它随着数据库的产生而产生, 随着数据库的变化而变化, 
体现为sys用户下的一些表和视图。数据字典名称是大写的英文字符。 

    数据字典里存有用户信息、用户的权限信息、所有数据对象信息、表的约束条件、统计分析数据库的视图等。 
我们不能手工修改数据字典里的信息。 

很多时候,一般的ORACLE用户不知道如何有效地利用它。 

dictionary   全部数据字典表的名称和解释,它有一个同义词dict 
    dict_column   全部数据字典表里字段名称和解释 

    如果我们想查询跟索引有关的数据字典时,可以用下面这条SQL语句: 

    SQL>select * from dictionary where instr(comments,'index')>0; 

    如果我们想知道user_indexes表各字段名称的详细含义,可以用下面这条SQL语句: 

    SQL>select column_name,comments from dict_columns where table_name='USER_INDEXES'; 

    依此类推,就可以轻松知道数据字典的详细名称和解释,不用查看ORACLE的其它文档资料了。 

    下面按类别列出一些ORACLE用户常用数据字典的查询使用方法。 

    1、用户 

            查看当前用户的缺省表空间 
            SQL>select username,default_tablespace from user_users; 

        查看当前用户的角色 
        SQL>select * from user_role_privs; 

        查看当前用户的系统权限和表级权限 
        SQL>select * from user_sys_privs; 
        SQL>select * from user_tab_privs; 

    2、表 

            查看用户下所有的表 
            SQL>select * from user_tables; 

            查看名称包含log字符的表 
            SQL>select object_name,object_id from user_objects 
                where instr(object_name,'LOG')>0; 

            查看某表的创建时间 
            SQL>select object_name,created from user_objects where object_name=upper('&table_name'); 

            查看某表的大小 
            SQL>select sum(bytes)/(1024*1024) as "size(M)" from user_segments 
                where segment_name=upper('&table_name'); 

            查看放在ORACLE的内存区里的表 
            SQL>select table_name,cache from user_tables where instr(cache,'Y')>0; 

    3、索引 

            查看索引个数和类别 
            SQL>select index_name,index_type,table_name from user_indexes order by table_name; 

            查看索引被索引的字段 
            SQL>select * from user_ind_columns where index_name=upper('&index_name'); 

            查看索引的大小 
            SQL>select sum(bytes)/(1024*1024) as "size(M)" from user_segments 
                where segment_name=upper('&index_name'); 

    4、序列号 

            查看序列号,last_number是当前值 
            SQL>select * from user_sequences; 

    5、视图 

            查看视图的名称 
            SQL>select view_name from user_views; 

            查看创建视图的select语句 
            SQL>set view_name,text_length from user_views; 
            SQL>set long 2000;                说明:可以根据视图的text_length值设定set long 的大小 
            SQL>select text from user_views where view_name=upper('&view_name'); 

    6、同义词 

            查看同义词的名称 
            SQL>select * from user_synonyms; 

    7、约束条件 

            查看某表的约束条件 
            SQL>select constraint_name, constraint_type,search_condition, r_constraint_name 
                from user_constraints where table_name = upper('&table_name'); 

        SQL>select c.constraint_name,c.constraint_type,cc.column_name 
            from user_constraints c,user_cons_columns cc 
            where c.owner = upper('&table_owner') and c.table_name = upper('&table_name') 
            and c.owner = cc.owner and c.constraint_name = cc.constraint_name 
            order by cc.position; 

    8、存储函数和过程 

            查看函数和过程的状态 
            SQL>select object_name,status from user_objects where object_type='FUNCTION'; 
            SQL>select object_name,status from user_objects where object_type='PROCEDURE'; 

            查看函数和过程的源代码 
            SQL>select text from all_source where owner=user and name=upper('&plsql_name'); 


三、查看数据库的SQL 
1、查看表空间的名称及大小 

    select t.tablespace_name, round(sum(bytes/(1024*1024)),0) ts_size 
    from dba_tablespaces t, dba_data_files d 
    where t.tablespace_name = d.tablespace_name 
    group by t.tablespace_name; 

2、查看表空间物理文件的名称及大小 

    select tablespace_name, file_id, file_name, 
    round(bytes/(1024*1024),0) total_space 
    from dba_data_files 
    order by tablespace_name; 

3、查看回滚段名称及大小 

    select segment_name, tablespace_name, r.status, 
    (initial_extent/1024) InitialExtent,(next_extent/1024) NextExtent, 
    max_extents, v.curext CurExtent 
    From dba_rollback_segs r, v$rollstat v 
    Where r.segment_id = v.usn(+) 
    order by segment_name ; 

4、查看控制文件 

    select name from v$controlfile; 

5、查看日志文件 

    select member from v$logfile; 

6、查看表空间的使用情况 

    select sum(bytes)/(1024*1024) as free_space,tablespace_name 
    from dba_free_space 
    group by tablespace_name; 

    SELECT A.TABLESPACE_NAME,A.BYTES TOTAL,B.BYTES USED, C.BYTES FREE, 
    (B.BYTES*100)/A.BYTES "% USED",(C.BYTES*100)/A.BYTES "% FREE" 
    FROM SYS.SM$TS_AVAIL A,SYS.SM$TS_USED B,SYS.SM$TS_FREE C 
    WHERE A.TABLESPACE_NAME=B.TABLESPACE_NAME AND A.TABLESPACE_NAME=C.TABLESPACE_NAME; 

7、查看数据库库对象 

    select owner, object_type, status, count(*) count# from all_objects group by owner, object_type, status; 

8、查看数据库的版本 

    Select version FROM Product_component_version 
    Where SUBSTR(PRODUCT,1,6)='Oracle'; 

9、查看数据库的创建日期和归档方式 

    Select Created, Log_Mode, Log_Mode From V$Database; 
四、ORACLE用户连接的管理 

用系统管理员,查看当前数据库有几个用户连接: 

SQL> select username,sid,serial# from v$session; 

如果要停某个连接用 

SQL> alter system kill session 'sid,serial#'; 

如果这命令不行,找它UNIX的进程数 

SQL> select pro.spid from v$session ses,v$process pro where ses.sid=21 and ses.paddr=pro.addr; 

说明:21是某个连接的sid数 

然后用 kill 命令杀此进程号。 


五、SQL*PLUS使用 
a、近入SQL*Plus 
$sqlplus 用户名/密码 

   退出SQL*Plus 
SQL>exit 

b、在sqlplus下得到帮助信息 
列出全部SQL命令和SQL*Plus命令 
SQL>help 
列出某个特定的命令的信息 
SQL>help 命令名 

c、显示表结构命令DESCRIBE 
SQL>DESC 表名 

d、SQL*Plus中的编辑命令 
显示SQL缓冲区命令 
SQL>L 

修改SQL命令 
首先要将待改正行变为当前行 
SQL>n 
用CHANGE命令修改内容 
SQL>c/旧/新 
重新确认是否已正确 
SQL>L 

使用INPUT命令可以在SQL缓冲区中增加一行或多行 
SQL>i 
SQL>输入内容 

e、调用外部系统编辑器 
SQL>edit 文件名 
可以使用DEFINE命令设置系统变量EDITOR来改变文本编辑器的类型,在login.sql文件中定义如下一行 
DEFINE_EDITOR=vi 

f、运行命令文件 
SQL>START test 
SQL>@test 

常用SQL*Plus语句 
a、表的创建、修改、删除 
创建表的命令格式如下: 
create table 表名 (列说明列表); 

为基表增加新列命令如下: 
ALTER TABLE 表名 ADD (列说明列表) 
例:为test表增加一列Age,用来存放年龄 
    sql>alter table test 
        add (Age number(3)); 

修改基表列定义命令如下: 
ALTER TABLE 表名 
MODIFY (列名 数据类型) 
例:将test表中的Count列宽度加长为10个字符 
    sql>alter atble test 
        modify (County char(10)); 

b、将一张表删除语句的格式如下: 
DORP TABLE 表名; 
例:表删除将同时删除表的数据和表的定义 
sql>drop table test 

c、表空间的创建、删除 


六、ORACLE逻辑备份的SH文件 

完全备份的SH文件:exp_comp.sh 

rq=` date +"%m%d" ` 

su - oracle -c "exp system/manager full=y inctype=complete file=/oracle/export/db_comp$rq.dmp" 

累计备份的SH文件:exp_cumu.sh 

rq=` date +"%m%d" ` 

su - oracle -c "exp system/manager full=y inctype=cumulative file=/oracle/export/db_cumu$rq.dmp" 

增量备份的SH文件: exp_incr.sh 

rq=` date +"%m%d" ` 

su - oracle -c "exp system/manager full=y inctype=incremental file=/oracle/export/db_incr$rq.dmp" 

root用户crontab文件 
/var/spool/cron/crontabs/root增加以下内容 

0 2 1 * * /oracle/exp_comp.sh 

30 2 * * 0-5 /oracle/exp_incr.sh 

45 2 * * 6 /oracle/exp_cumu.sh 

当然这个时间表可以根据不同的需求来改变的,这只是一个例子。 


七、ORACLE 常用的SQL语法和数据对象 

一.数据控制语句 (DML) 部分 

1.INSERT  (往数据表里插入记录的语句) 

INSERT INTO 表名(字段名1, 字段名2, ……) VALUES ( 值1, 值2, ……); 
INSERT INTO 表名(字段名1, 字段名2, ……)  SELECT (字段名1, 字段名2, ……) FROM 另外的表名; 

字符串类型的字段值必须用单引号括起来, 例如: ’GOOD DAY’ 
如果字段值里包含单引号’ 需要进行字符串转换, 我们把它替换成两个单引号''. 
字符串类型的字段值超过定义的长度会出错, 最好在插入前进行长度校验. 

日期字段的字段值可以用当前数据库的系统时间SYSDATE, 精确到秒 
或者用字符串转换成日期型函数TO_DATE(‘2001-08-01’,’YYYY-MM-DD’) 
TO_DATE()还有很多种日期格式, 可以参看ORACLE DOC. 
年-月-日 小时:分钟:秒 的格式YYYY-MM-DD HH24:MI:SS 

INSERT时最大可操作的字符串长度小于等于4000个单字节, 如果要插入更长的字符串, 请考虑字段用CLOB类型, 
方法借用ORACLE里自带的DBMS_LOB程序包. 

INSERT时如果要用到从1开始自动增长的序列号, 应该先建立一个序列号 
CREATE SEQUENCE 序列号的名称 (最好是表名+序列号标记) INCREMENT BY 1  START  WITH  1 
MAXVALUE  99999  CYCLE  NOCACHE; 
其中最大的值按字段的长度来定, 如果定义的自动增长的序列号 NUMBER(6) , 最大值为999999 
INSERT 语句插入这个字段值为: 序列号的名称.NEXTVAL 

2.DELETE  (删除数据表里记录的语句) 

DELETE FROM表名 WHERE 条件; 

注意:删除记录并不能释放ORACLE里被占用的数据块表空间. 它只把那些被删除的数据块标成unused. 

如果确实要删除一个大表里的全部记录, 可以用 TRUNCATE 命令, 它可以释放占用的数据块表空间 
TRUNCATE TABLE 表名; 
此操作不可回退. 

3.UPDATE  (修改数据表里记录的语句) 

UPDATE表名 SET 字段名1=值1, 字段名2=值2, …… WHERE 条件; 

如果修改的值N没有赋值或定义时, 将把原来的记录内容清为NULL, 最好在修改前进行非空校验; 
值N超过定义的长度会出错, 最好在插入前进行长度校验.. 

注意事项: 
A.        以上SQL语句对表都加上了行级锁, 
        确认完成后, 必须加上事物处理结束的命令 COMMIT 才能正式生效, 
        否则改变不一定写入数据库里. 
        如果想撤回这些操作, 可以用命令 ROLLBACK 复原. 

B.        在运行INSERT, DELETE 和 UPDATE 语句前最好估算一下可能操作的记录范围, 
        应该把它限定在较小 (一万条记录) 范围内,. 否则ORACLE处理这个事物用到很大的回退段. 
        程序响应慢甚至失去响应. 如果记录数上十万以上这些操作, 可以把这些SQL语句分段分次完成, 
        其间加上COMMIT 确认事物处理. 
二.数据定义 (DDL) 部分 

1.CREATE (创建表, 索引, 视图, 同义词, 过程, 函数, 数据库链接等) 

ORACLE常用的字段类型有 
CHAR                        固定长度的字符串 
VARCHAR2                可变长度的字符串 
NUMBER(M,N)                数字型M是位数总长度, N是小数的长度 
DATE                        日期类型 

创建表时要把较小的不为空的字段放在前面, 可能为空的字段放在后面 

创建表时可以用中文的字段名, 但最好还是用英文的字段名 

创建表时可以给字段加上默认值, 例如 DEFAULT SYSDATE 
这样每次插入和修改时, 不用程序操作这个字段都能得到动作的时间 

创建表时可以给字段加上约束条件 
例如 不允许重复 UNIQUE, 关键字 PRIMARY KEY 

2.ALTER        (改变表, 索引, 视图等) 

改变表的名称 
ALTER TABLE 表名1  TO 表名2; 

在表的后面增加一个字段 
ALTER TABLE表名 ADD 字段名 字段名描述; 

修改表里字段的定义描述 
ALTER TABLE表名 MODIFY字段名 字段名描述; 

给表里的字段加上约束条件 
ALTER TABLE 表名 ADD CONSTRAINT 约束名 PRIMARY KEY (字段名); 
ALTER TABLE 表名 ADD CONSTRAINT 约束名 UNIQUE (字段名); 

把表放在或取出数据库的内存区 
ALTER TABLE 表名 CACHE; 
ALTER TABLE 表名 NOCACHE; 

3.DROP        (删除表, 索引, 视图, 同义词, 过程, 函数, 数据库链接等) 

删除表和它所有的约束条件 
DROP TABLE 表名 CASCADE CONSTRAINTS; 

4.TRUNCATE (清空表里的所有记录, 保留表的结构) 

TRUNCATE 表名; 

三.查询语句 (SELECT) 部分 

SELECT字段名1, 字段名2, …… FROM 表名1, [表名2, ……] WHERE 条件; 

字段名可以带入函数 
  例如:  COUNT(*), MIN(字段名),  MAX(字段名),  AVG(字段名), DISTINCT(字段名), 
           TO_CHAR(DATE字段名,'YYYY-MM-DD HH24:MI:SS') 

NVL(EXPR1, EXPR2)函数 
解释: 
IF EXPR1=NULL 
                RETURN EXPR2 
ELSE 
                       RETURN EXPR1 

DECODE(AA﹐V1﹐R1﹐V2﹐R2....)函数 
解释: 
IF AA=V1 THEN RETURN R1 
IF AA=V2 THEN RETURN R2 
..… 
ELSE 
RETURN NULL 

LPAD(char1,n,char2)函数 
解释: 
字符char1按制定的位数n显示,不足的位数用char2字符串替换左边的空位 

字段名之间可以进行算术运算 
例如:  (字段名1*字段名1)/3 

查询语句可以嵌套 
例如: SELECT …… FROM 
(SELECT …… FROM表名1, [表名2, ……] WHERE 条件) WHERE 条件2; 

两个查询语句的结果可以做集合操作 
例如: 并集UNION(去掉重复记录), 并集UNION ALL(不去掉重复记录), 差集MINUS,  交集INTERSECT 

分组查询 
SELECT字段名1, 字段名2, …… FROM 表名1, [表名2, ……] GROUP BY字段名1 
[HAVING 条件] ; 

两个以上表之间的连接查询 

SELECT字段名1, 字段名2, …… FROM 表名1, [表名2, ……] WHERE 
                表名1.字段名 = 表名2. 字段名 [ AND ……] ; 

SELECT字段名1, 字段名2, …… FROM 表名1, [表名2, ……] WHERE 
                表名1.字段名 = 表名2. 字段名(+) [ AND ……] ; 

有(+)号的字段位置自动补空值 

查询结果集的排序操作, 默认的排序是升序ASC, 降序是DESC 

SELECT字段名1, 字段名2, …… FROM 表名1, [表名2, ……] 
ORDER BY字段名1, 字段名2 DESC; 

字符串模糊比较的方法 

INSTR(字段名, ‘字符串’)>0 
字段名 LIKE  ‘字符串%’  [‘%字符串%’] 

每个表都有一个隐含的字段ROWID, 它标记着记录的唯一性. 

四.ORACLE里常用的数据对象 (SCHEMA) 

1.索引 (INDEX) 

CREATE INDEX 索引名ON 表名 ( 字段1, [字段2, ……] ); 
ALTER INDEX 索引名 REBUILD; 

一个表的索引最好不要超过三个 (特殊的大表除外), 最好用单字段索引, 结合SQL语句的分析执行情况, 
也可以建立多字段的组合索引和基于函数的索引 

ORACLE8.1.7字符串可以索引的最大长度为1578 单字节 
ORACLE8.0.6字符串可以索引的最大长度为758 单字节 

2.视图 (VIEW) 

CREATE VIEW 视图名AS SELECT …. FROM …..; 
ALTER VIEW视图名 COMPILE; 

视图仅是一个SQL查询语句, 它可以把表之间复杂的关系简洁化. 

3.同义词 (SYNONMY) 
CREATE SYNONYM同义词名FOR 表名; 
CREATE SYNONYM同义词名FOR 表名@数据库链接名; 

4.数据库链接 (DATABASE LINK) 
CREATE DATABASE LINK数据库链接名CONNECT TO 用户名 IDENTIFIED BY 密码 USING ‘数据库连接字符串’; 

数据库连接字符串可以用NET8 EASY CONFIG或者直接修改TNSNAMES.ORA里定义. 

数据库参数global_name=true时要求数据库链接名称跟远端数据库名称一样 

数据库全局名称可以用以下命令查出 
SELECT * FROM GLOBAL_NAME; 

查询远端数据库里的表 
SELECT …… FROM 表名@数据库链接名; 

五.权限管理 (DCL) 语句 

1.GRANT        赋于权限 
常用的系统权限集合有以下三个: 
CONNECT(基本的连接), RESOURCE(程序开发), DBA(数据库管理) 
常用的数据对象权限有以下五个: 
ALL         ON 数据对象名,         SELECT ON 数据对象名,         UPDATE ON 数据对象名, 
DELETE         ON 数据对象名,  INSERT ON 数据对象名,   ALTER  ON 数据对象名 

GRANT CONNECT, RESOURCE TO 用户名; 
GRANT SELECT ON 表名 TO 用户名; 
GRANT SELECT, INSERT, DELETE ON表名 TO 用户名1, 用户名2; 

2.REVOKE 回收权限 

REVOKE CONNECT, RESOURCE FROM 用户名; 
REVOKE SELECT ON 表名 FROM 用户名; 
REVOKE SELECT, INSERT, DELETE ON表名 FROM 用户名1, 用户名2; 


查询数据库中第63号错误: 
select orgaddr,destaddr from sm_histable0116 where error_code='63'; 

查询数据库中开户用户最大提交和最大下发数: select MSISDN,TCOS,OCOS from ms_usertable; 


查询数据库中各种错误代码的总和: 
select error_code,count(*) from sm_histable0513 group by error_code order 
by error_code; 

查询报表数据库中话单统计种类查询。 
select sum(Successcount) from tbl_MiddleMt0411 where ServiceType2=111 
select sum(successcount),servicetype from tbl_middlemt0411 group by servicetype  查看全部
Oracle常用命令大全(很有用,做笔记)

一、ORACLE的启动和关闭 
1、在单机环境下 
要想启动或关闭ORACLE系统必须首先切换到ORACLE用户,如下 
su - oracle 

a、启动ORACLE系统 
oracle>svrmgrl 
SVRMGR>connect internal 
SVRMGR>startup 
SVRMGR>quit 

b、关闭ORACLE系统 
oracle>svrmgrl 
SVRMGR>connect internal 
SVRMGR>shutdown 
SVRMGR>quit 

启动oracle9i数据库命令: 
$ sqlplus /nolog 

SQL*Plus: Release 9.2.0.1.0 - Production on Fri Oct 31 13:53:53 2003 

Copyright (c) 1982, 2002, Oracle Corporation.  All rights reserved. 

SQL> connect / as sysdba  
Connected to an idle instance. 
SQL> startup^C 

SQL> startup 
ORACLE instance started. 


2、在双机环境下 
要想启动或关闭ORACLE系统必须首先切换到root用户,如下 
su - root 

a、启动ORACLE系统 
hareg -y oracle 

b、关闭ORACLE系统 
hareg -n oracle 

Oracle数据库有哪几种启动方式 


说明: 

有以下几种启动方式: 
1、startup nomount 
非安装启动,这种方式启动下可执行:重建控制文件、重建数据库 

读取init.ora文件,启动instance,即启动SGA和后台进程,这种启动只需要init.ora文件。 


2、startup mount dbname 
安装启动,这种方式启动下可执行: 
数据库日志归档、 
数据库介质恢复、 
使数据文件联机或脱机, 
重新定位数据文件、重做日志文件。 

执行“nomount”,然后打开控制文件,确认数据文件和联机日志文件的位置, 
但此时不对数据文件和日志文件进行校验检查。 


3、startup open dbname 
先执行“nomount”,然后执行“mount”,再打开包括Redo log文件在内的所有数据库文件, 
这种方式下可访问数据库中的数据。 


4、startup,等于以下三个命令 
startup nomount 
alter database mount 
alter database open 


5、startup restrict 
约束方式启动 
这种方式能够启动数据库,但只允许具有一定特权的用户访问 
非特权用户访问时,会出现以下提示: 
ERROR: 
ORA-01035: ORACLE 只允许具有 RESTRICTED SESSION 权限的用户使用 


6、startup force 
强制启动方式 
当不能关闭数据库时,可以用startup force来完成数据库的关闭 
先关闭数据库,再执行正常启动数据库命令 


7、startup pfile=参数文件名 
带初始化参数文件的启动方式 
先读取参数文件,再按参数文件中的设置启动数据库 
例:startup pfile=E:Oracleadminoradbpfileinit.ora 


8、startup EXCLUSIVE 
二、用户如何有效地利用数据字典 
   ORACLE的数据字典是数据库的重要组成部分之一,它随着数据库的产生而产生, 随着数据库的变化而变化, 
体现为sys用户下的一些表和视图。数据字典名称是大写的英文字符。 

    数据字典里存有用户信息、用户的权限信息、所有数据对象信息、表的约束条件、统计分析数据库的视图等。 
我们不能手工修改数据字典里的信息。 

很多时候,一般的ORACLE用户不知道如何有效地利用它。 

dictionary   全部数据字典表的名称和解释,它有一个同义词dict 
    dict_column   全部数据字典表里字段名称和解释 

    如果我们想查询跟索引有关的数据字典时,可以用下面这条SQL语句: 

    SQL>select * from dictionary where instr(comments,'index')>0; 

    如果我们想知道user_indexes表各字段名称的详细含义,可以用下面这条SQL语句: 

    SQL>select column_name,comments from dict_columns where table_name='USER_INDEXES'; 

    依此类推,就可以轻松知道数据字典的详细名称和解释,不用查看ORACLE的其它文档资料了。 

    下面按类别列出一些ORACLE用户常用数据字典的查询使用方法。 

    1、用户 

            查看当前用户的缺省表空间 
            SQL>select username,default_tablespace from user_users; 

        查看当前用户的角色 
        SQL>select * from user_role_privs; 

        查看当前用户的系统权限和表级权限 
        SQL>select * from user_sys_privs; 
        SQL>select * from user_tab_privs; 

    2、表 

            查看用户下所有的表 
            SQL>select * from user_tables; 

            查看名称包含log字符的表 
            SQL>select object_name,object_id from user_objects 
                where instr(object_name,'LOG')>0; 

            查看某表的创建时间 
            SQL>select object_name,created from user_objects where object_name=upper('&table_name'); 

            查看某表的大小 
            SQL>select sum(bytes)/(1024*1024) as "size(M)" from user_segments 
                where segment_name=upper('&table_name'); 

            查看放在ORACLE的内存区里的表 
            SQL>select table_name,cache from user_tables where instr(cache,'Y')>0; 

    3、索引 

            查看索引个数和类别 
            SQL>select index_name,index_type,table_name from user_indexes order by table_name; 

            查看索引被索引的字段 
            SQL>select * from user_ind_columns where index_name=upper('&index_name'); 

            查看索引的大小 
            SQL>select sum(bytes)/(1024*1024) as "size(M)" from user_segments 
                where segment_name=upper('&index_name'); 

    4、序列号 

            查看序列号,last_number是当前值 
            SQL>select * from user_sequences; 

    5、视图 

            查看视图的名称 
            SQL>select view_name from user_views; 

            查看创建视图的select语句 
            SQL>set view_name,text_length from user_views; 
            SQL>set long 2000;                说明:可以根据视图的text_length值设定set long 的大小 
            SQL>select text from user_views where view_name=upper('&view_name'); 

    6、同义词 

            查看同义词的名称 
            SQL>select * from user_synonyms; 

    7、约束条件 

            查看某表的约束条件 
            SQL>select constraint_name, constraint_type,search_condition, r_constraint_name 
                from user_constraints where table_name = upper('&table_name'); 

        SQL>select c.constraint_name,c.constraint_type,cc.column_name 
            from user_constraints c,user_cons_columns cc 
            where c.owner = upper('&table_owner') and c.table_name = upper('&table_name') 
            and c.owner = cc.owner and c.constraint_name = cc.constraint_name 
            order by cc.position; 

    8、存储函数和过程 

            查看函数和过程的状态 
            SQL>select object_name,status from user_objects where object_type='FUNCTION'; 
            SQL>select object_name,status from user_objects where object_type='PROCEDURE'; 

            查看函数和过程的源代码 
            SQL>select text from all_source where owner=user and name=upper('&plsql_name'); 


三、查看数据库的SQL 
1、查看表空间的名称及大小 

    select t.tablespace_name, round(sum(bytes/(1024*1024)),0) ts_size 
    from dba_tablespaces t, dba_data_files d 
    where t.tablespace_name = d.tablespace_name 
    group by t.tablespace_name; 

2、查看表空间物理文件的名称及大小 

    select tablespace_name, file_id, file_name, 
    round(bytes/(1024*1024),0) total_space 
    from dba_data_files 
    order by tablespace_name; 

3、查看回滚段名称及大小 

    select segment_name, tablespace_name, r.status, 
    (initial_extent/1024) InitialExtent,(next_extent/1024) NextExtent, 
    max_extents, v.curext CurExtent 
    From dba_rollback_segs r, v$rollstat v 
    Where r.segment_id = v.usn(+) 
    order by segment_name ; 

4、查看控制文件 

    select name from v$controlfile; 

5、查看日志文件 

    select member from v$logfile; 

6、查看表空间的使用情况 

    select sum(bytes)/(1024*1024) as free_space,tablespace_name 
    from dba_free_space 
    group by tablespace_name; 

    SELECT A.TABLESPACE_NAME,A.BYTES TOTAL,B.BYTES USED, C.BYTES FREE, 
    (B.BYTES*100)/A.BYTES "% USED",(C.BYTES*100)/A.BYTES "% FREE" 
    FROM SYS.SM$TS_AVAIL A,SYS.SM$TS_USED B,SYS.SM$TS_FREE C 
    WHERE A.TABLESPACE_NAME=B.TABLESPACE_NAME AND A.TABLESPACE_NAME=C.TABLESPACE_NAME; 

7、查看数据库库对象 

    select owner, object_type, status, count(*) count# from all_objects group by owner, object_type, status; 

8、查看数据库的版本 

    Select version FROM Product_component_version 
    Where SUBSTR(PRODUCT,1,6)='Oracle'; 

9、查看数据库的创建日期和归档方式 

    Select Created, Log_Mode, Log_Mode From V$Database; 
四、ORACLE用户连接的管理 

用系统管理员,查看当前数据库有几个用户连接: 

SQL> select username,sid,serial# from v$session; 

如果要停某个连接用 

SQL> alter system kill session 'sid,serial#'; 

如果这命令不行,找它UNIX的进程数 

SQL> select pro.spid from v$session ses,v$process pro where ses.sid=21 and ses.paddr=pro.addr; 

说明:21是某个连接的sid数 

然后用 kill 命令杀此进程号。 


五、SQL*PLUS使用 
a、近入SQL*Plus 
$sqlplus 用户名/密码 

   退出SQL*Plus 
SQL>exit 

b、在sqlplus下得到帮助信息 
列出全部SQL命令和SQL*Plus命令 
SQL>help 
列出某个特定的命令的信息 
SQL>help 命令名 

c、显示表结构命令DESCRIBE 
SQL>DESC 表名 

d、SQL*Plus中的编辑命令 
显示SQL缓冲区命令 
SQL>L 

修改SQL命令 
首先要将待改正行变为当前行 
SQL>n 
用CHANGE命令修改内容 
SQL>c/旧/新 
重新确认是否已正确 
SQL>L 

使用INPUT命令可以在SQL缓冲区中增加一行或多行 
SQL>i 
SQL>输入内容 

e、调用外部系统编辑器 
SQL>edit 文件名 
可以使用DEFINE命令设置系统变量EDITOR来改变文本编辑器的类型,在login.sql文件中定义如下一行 
DEFINE_EDITOR=vi 

f、运行命令文件 
SQL>START test 
SQL>@test 

常用SQL*Plus语句 
a、表的创建、修改、删除 
创建表的命令格式如下: 
create table 表名 (列说明列表); 

为基表增加新列命令如下: 
ALTER TABLE 表名 ADD (列说明列表) 
例:为test表增加一列Age,用来存放年龄 
    sql>alter table test 
        add (Age number(3)); 

修改基表列定义命令如下: 
ALTER TABLE 表名 
MODIFY (列名 数据类型) 
例:将test表中的Count列宽度加长为10个字符 
    sql>alter atble test 
        modify (County char(10)); 

b、将一张表删除语句的格式如下: 
DORP TABLE 表名; 
例:表删除将同时删除表的数据和表的定义 
sql>drop table test 

c、表空间的创建、删除 


六、ORACLE逻辑备份的SH文件 

完全备份的SH文件:exp_comp.sh 

rq=` date +"%m%d" ` 

su - oracle -c "exp system/manager full=y inctype=complete file=/oracle/export/db_comp$rq.dmp" 

累计备份的SH文件:exp_cumu.sh 

rq=` date +"%m%d" ` 

su - oracle -c "exp system/manager full=y inctype=cumulative file=/oracle/export/db_cumu$rq.dmp" 

增量备份的SH文件: exp_incr.sh 

rq=` date +"%m%d" ` 

su - oracle -c "exp system/manager full=y inctype=incremental file=/oracle/export/db_incr$rq.dmp" 

root用户crontab文件 
/var/spool/cron/crontabs/root增加以下内容 

0 2 1 * * /oracle/exp_comp.sh 

30 2 * * 0-5 /oracle/exp_incr.sh 

45 2 * * 6 /oracle/exp_cumu.sh 

当然这个时间表可以根据不同的需求来改变的,这只是一个例子。 


七、ORACLE 常用的SQL语法和数据对象 

一.数据控制语句 (DML) 部分 

1.INSERT  (往数据表里插入记录的语句) 

INSERT INTO 表名(字段名1, 字段名2, ……) VALUES ( 值1, 值2, ……); 
INSERT INTO 表名(字段名1, 字段名2, ……)  SELECT (字段名1, 字段名2, ……) FROM 另外的表名; 

字符串类型的字段值必须用单引号括起来, 例如: ’GOOD DAY’ 
如果字段值里包含单引号’ 需要进行字符串转换, 我们把它替换成两个单引号''. 
字符串类型的字段值超过定义的长度会出错, 最好在插入前进行长度校验. 

日期字段的字段值可以用当前数据库的系统时间SYSDATE, 精确到秒 
或者用字符串转换成日期型函数TO_DATE(‘2001-08-01’,’YYYY-MM-DD’) 
TO_DATE()还有很多种日期格式, 可以参看ORACLE DOC. 
年-月-日 小时:分钟:秒 的格式YYYY-MM-DD HH24:MI:SS 

INSERT时最大可操作的字符串长度小于等于4000个单字节, 如果要插入更长的字符串, 请考虑字段用CLOB类型, 
方法借用ORACLE里自带的DBMS_LOB程序包. 

INSERT时如果要用到从1开始自动增长的序列号, 应该先建立一个序列号 
CREATE SEQUENCE 序列号的名称 (最好是表名+序列号标记) INCREMENT BY 1  START  WITH  1 
MAXVALUE  99999  CYCLE  NOCACHE; 
其中最大的值按字段的长度来定, 如果定义的自动增长的序列号 NUMBER(6) , 最大值为999999 
INSERT 语句插入这个字段值为: 序列号的名称.NEXTVAL 

2.DELETE  (删除数据表里记录的语句) 

DELETE FROM表名 WHERE 条件; 

注意:删除记录并不能释放ORACLE里被占用的数据块表空间. 它只把那些被删除的数据块标成unused. 

如果确实要删除一个大表里的全部记录, 可以用 TRUNCATE 命令, 它可以释放占用的数据块表空间 
TRUNCATE TABLE 表名; 
此操作不可回退. 

3.UPDATE  (修改数据表里记录的语句) 

UPDATE表名 SET 字段名1=值1, 字段名2=值2, …… WHERE 条件; 

如果修改的值N没有赋值或定义时, 将把原来的记录内容清为NULL, 最好在修改前进行非空校验; 
值N超过定义的长度会出错, 最好在插入前进行长度校验.. 

注意事项: 
A.        以上SQL语句对表都加上了行级锁, 
        确认完成后, 必须加上事物处理结束的命令 COMMIT 才能正式生效, 
        否则改变不一定写入数据库里. 
        如果想撤回这些操作, 可以用命令 ROLLBACK 复原. 

B.        在运行INSERT, DELETE 和 UPDATE 语句前最好估算一下可能操作的记录范围, 
        应该把它限定在较小 (一万条记录) 范围内,. 否则ORACLE处理这个事物用到很大的回退段. 
        程序响应慢甚至失去响应. 如果记录数上十万以上这些操作, 可以把这些SQL语句分段分次完成, 
        其间加上COMMIT 确认事物处理. 
二.数据定义 (DDL) 部分 

1.CREATE (创建表, 索引, 视图, 同义词, 过程, 函数, 数据库链接等) 

ORACLE常用的字段类型有 
CHAR                        固定长度的字符串 
VARCHAR2                可变长度的字符串 
NUMBER(M,N)                数字型M是位数总长度, N是小数的长度 
DATE                        日期类型 

创建表时要把较小的不为空的字段放在前面, 可能为空的字段放在后面 

创建表时可以用中文的字段名, 但最好还是用英文的字段名 

创建表时可以给字段加上默认值, 例如 DEFAULT SYSDATE 
这样每次插入和修改时, 不用程序操作这个字段都能得到动作的时间 

创建表时可以给字段加上约束条件 
例如 不允许重复 UNIQUE, 关键字 PRIMARY KEY 

2.ALTER        (改变表, 索引, 视图等) 

改变表的名称 
ALTER TABLE 表名1  TO 表名2; 

在表的后面增加一个字段 
ALTER TABLE表名 ADD 字段名 字段名描述; 

修改表里字段的定义描述 
ALTER TABLE表名 MODIFY字段名 字段名描述; 

给表里的字段加上约束条件 
ALTER TABLE 表名 ADD CONSTRAINT 约束名 PRIMARY KEY (字段名); 
ALTER TABLE 表名 ADD CONSTRAINT 约束名 UNIQUE (字段名); 

把表放在或取出数据库的内存区 
ALTER TABLE 表名 CACHE; 
ALTER TABLE 表名 NOCACHE; 

3.DROP        (删除表, 索引, 视图, 同义词, 过程, 函数, 数据库链接等) 

删除表和它所有的约束条件 
DROP TABLE 表名 CASCADE CONSTRAINTS; 

4.TRUNCATE (清空表里的所有记录, 保留表的结构) 

TRUNCATE 表名; 

三.查询语句 (SELECT) 部分 

SELECT字段名1, 字段名2, …… FROM 表名1, [表名2, ……] WHERE 条件; 

字段名可以带入函数 
  例如:  COUNT(*), MIN(字段名),  MAX(字段名),  AVG(字段名), DISTINCT(字段名), 
           TO_CHAR(DATE字段名,'YYYY-MM-DD HH24:MI:SS') 

NVL(EXPR1, EXPR2)函数 
解释: 
IF EXPR1=NULL 
                RETURN EXPR2 
ELSE 
                       RETURN EXPR1 

DECODE(AA﹐V1﹐R1﹐V2﹐R2....)函数 
解释: 
IF AA=V1 THEN RETURN R1 
IF AA=V2 THEN RETURN R2 
..… 
ELSE 
RETURN NULL 

LPAD(char1,n,char2)函数 
解释: 
字符char1按制定的位数n显示,不足的位数用char2字符串替换左边的空位 

字段名之间可以进行算术运算 
例如:  (字段名1*字段名1)/3 

查询语句可以嵌套 
例如: SELECT …… FROM 
(SELECT …… FROM表名1, [表名2, ……] WHERE 条件) WHERE 条件2; 

两个查询语句的结果可以做集合操作 
例如: 并集UNION(去掉重复记录), 并集UNION ALL(不去掉重复记录), 差集MINUS,  交集INTERSECT 

分组查询 
SELECT字段名1, 字段名2, …… FROM 表名1, [表名2, ……] GROUP BY字段名1 
[HAVING 条件] ; 

两个以上表之间的连接查询 

SELECT字段名1, 字段名2, …… FROM 表名1, [表名2, ……] WHERE 
                表名1.字段名 = 表名2. 字段名 [ AND ……] ; 

SELECT字段名1, 字段名2, …… FROM 表名1, [表名2, ……] WHERE 
                表名1.字段名 = 表名2. 字段名(+) [ AND ……] ; 

有(+)号的字段位置自动补空值 

查询结果集的排序操作, 默认的排序是升序ASC, 降序是DESC 

SELECT字段名1, 字段名2, …… FROM 表名1, [表名2, ……] 
ORDER BY字段名1, 字段名2 DESC; 

字符串模糊比较的方法 

INSTR(字段名, ‘字符串’)>0 
字段名 LIKE  ‘字符串%’  [‘%字符串%’] 

每个表都有一个隐含的字段ROWID, 它标记着记录的唯一性. 

四.ORACLE里常用的数据对象 (SCHEMA) 

1.索引 (INDEX) 

CREATE INDEX 索引名ON 表名 ( 字段1, [字段2, ……] ); 
ALTER INDEX 索引名 REBUILD; 

一个表的索引最好不要超过三个 (特殊的大表除外), 最好用单字段索引, 结合SQL语句的分析执行情况, 
也可以建立多字段的组合索引和基于函数的索引 

ORACLE8.1.7字符串可以索引的最大长度为1578 单字节 
ORACLE8.0.6字符串可以索引的最大长度为758 单字节 

2.视图 (VIEW) 

CREATE VIEW 视图名AS SELECT …. FROM …..; 
ALTER VIEW视图名 COMPILE; 

视图仅是一个SQL查询语句, 它可以把表之间复杂的关系简洁化. 

3.同义词 (SYNONMY) 
CREATE SYNONYM同义词名FOR 表名; 
CREATE SYNONYM同义词名FOR 表名@数据库链接名; 

4.数据库链接 (DATABASE LINK) 
CREATE DATABASE LINK数据库链接名CONNECT TO 用户名 IDENTIFIED BY 密码 USING ‘数据库连接字符串’; 

数据库连接字符串可以用NET8 EASY CONFIG或者直接修改TNSNAMES.ORA里定义. 

数据库参数global_name=true时要求数据库链接名称跟远端数据库名称一样 

数据库全局名称可以用以下命令查出 
SELECT * FROM GLOBAL_NAME; 

查询远端数据库里的表 
SELECT …… FROM 表名@数据库链接名; 

五.权限管理 (DCL) 语句 

1.GRANT        赋于权限 
常用的系统权限集合有以下三个: 
CONNECT(基本的连接), RESOURCE(程序开发), DBA(数据库管理) 
常用的数据对象权限有以下五个: 
ALL         ON 数据对象名,         SELECT ON 数据对象名,         UPDATE ON 数据对象名, 
DELETE         ON 数据对象名,  INSERT ON 数据对象名,   ALTER  ON 数据对象名 

GRANT CONNECT, RESOURCE TO 用户名; 
GRANT SELECT ON 表名 TO 用户名; 
GRANT SELECT, INSERT, DELETE ON表名 TO 用户名1, 用户名2; 

2.REVOKE 回收权限 

REVOKE CONNECT, RESOURCE FROM 用户名; 
REVOKE SELECT ON 表名 FROM 用户名; 
REVOKE SELECT, INSERT, DELETE ON表名 FROM 用户名1, 用户名2; 


查询数据库中第63号错误: 
select orgaddr,destaddr from sm_histable0116 where error_code='63'; 

查询数据库中开户用户最大提交和最大下发数: select MSISDN,TCOS,OCOS from ms_usertable; 


查询数据库中各种错误代码的总和: 
select error_code,count(*) from sm_histable0513 group by error_code order 
by error_code; 

查询报表数据库中话单统计种类查询。 
select sum(Successcount) from tbl_MiddleMt0411 where ServiceType2=111 
select sum(successcount),servicetype from tbl_middlemt0411 group by servicetype 

Oracle存储过程

admin 发表了文章 • 0 个评论 • 57 次浏览 • 2018-04-26 08:54 • 来自相关话题

1、定义
所谓存储过程(Stored Procedure),就是一组用于完成特定数据库功能的SQL语句集,该SQL语句集经过
编译后存储在数据库系统中。在使用时候,用户通过指定已经定义的存储过程名字并给出相应的存储过程参数
来调用并执行它,从而完成一个或一系列的数据库操作。

2、存储过程的创建
Oracle存储过程包含三部分:过程声明,执行过程部分,存储过程异常。

(1)无参存储过程语法[复制代码]
create or replace procedure NoParPro as //声明 ; begin // 执行 ; exception//存储过程异常 ; end;
[复制代码](2)带参存储过程实例[复制代码]
create or replace procedure queryempname(sfindno emp.empno%type) as sName emp.ename%type; sjob emp.job%type; begin .... exception .... end;
[复制代码] 

(3)带参数存储过程含赋值方式[复制代码]
create or replace procedure runbyparmeters (isal in emp.sal%type, sname out varchar, sjob in out varchar) as icount number; begin select count(*) into icount from emp where sal>isal and job=sjob; if icount=1 then .... else .... end if; exception when too_many_rows then DBMS_OUTPUT.PUT_LINE('返回值多于1行'); when others then DBMS_OUTPUT.PUT_LINE('在RUNBYPARMETERS过程中出错!'); end;
[复制代码]其中参数IN表示输入参数,是参数的默认模式。
OUT表示返回值参数,类型可以使用任意Oracle中的合法类型。
OUT模式定义的参数只能在过程体内部赋值,表示该参数可以将某个值传递回调用他的过程
IN OUT表示该参数可以向该过程中传递值,也可以将某个值传出去。

(4)存储过程中游标定义使用[复制代码]
as //定义(游标一个可以遍历的结果集) CURSOR cur_1 IS SELECT area_code,CMCODE,SUM(rmb_amt)/10000 rmb_amt_sn, SUM(usd_amt)/10000 usd_amt_sn FROM BGD_AREA_CM_M_BASE_T WHERE ym >= vs_ym_sn_beg AND ym <= vs_ym_sn_end GROUP BY area_code,CMCODE; begin //执行(常用For语句遍历游标) FOR rec IN cur_1 LOOP UPDATE xxxxxxxxxxx_T SET rmb_amt_sn = rec.rmb_amt_sn,usd_amt_sn = rec.usd_amt_sn WHERE area_code = rec.area_code AND CMCODE = rec.CMCODE AND ym = is_ym; END LOOP;
[复制代码] 

(5)游标的定义[复制代码]
--显示cursor的处理 declare ---声明cursor,创建和命名一个sql工作区 cursor cursor_name is select real_name from account_hcz; v_realname varchar2(20); begin open cursor_name;---打开cursor,执行sql语句产生的结果集 fetch cursor_name into v_realname;--提取cursor,提取结果集中的记录 dbms_output.put_line(v_realname); close cursor_name;--关闭cursor end;
[复制代码]3、在Oracle中对存储过程的调用 

(1)过程调用方式一[复制代码]
declare realsal emp.sal%type; realname varchar(40); realjob varchar(40); begin //过程调用开始 realsal:=1100; realname:=''; realjob:='CLERK'; runbyparmeters(realsal,realname,realjob);--必须按顺序 DBMS_OUTPUT.PUT_LINE(REALNAME||' '||REALJOB); END; //过程调用结束
[复制代码](2)过程调用方式二[复制代码]
declare realsal emp.sal%type; realname varchar(40); realjob varchar(40); begin //过程调用开始 realsal:=1100; realname:=''; realjob:='CLERK'; --指定值对应变量顺序可变 runbyparmeters(sname=>realname,isal=>realsal,sjob=>realjob); DBMS_OUTPUT.PUT_LINE(REALNAME||' '||REALJOB); END; //过程调用结束
[复制代码](3)过程调用方式三(SQL命令行方式下)1、SQL>exec proc_emp('参数1','参数2');//无返回值过程调用 2、SQL>var vsal number SQL> exec proc_emp ('参数1',:vsal);// 有返回值过程调用 或者:call proc_emp ('参数1',:vsal);// 有返回值过程调用  查看全部
1、定义
所谓存储过程(Stored Procedure),就是一组用于完成特定数据库功能的SQL语句集,该SQL语句集经过
编译后存储在数据库系统中。在使用时候,用户通过指定已经定义的存储过程名字并给出相应的存储过程参数
来调用并执行它,从而完成一个或一系列的数据库操作。

2、存储过程的创建
Oracle存储过程包含三部分:过程声明,执行过程部分,存储过程异常。

(1)无参存储过程语法[复制代码]
create or replace procedure NoParPro as //声明 ; begin // 执行 ; exception//存储过程异常 ; end;
[复制代码](2)带参存储过程实例[复制代码]
create or replace procedure queryempname(sfindno emp.empno%type) as sName emp.ename%type; sjob emp.job%type; begin .... exception .... end;
[复制代码] 

(3)带参数存储过程含赋值方式[复制代码]
create or replace procedure runbyparmeters (isal in emp.sal%type, sname out varchar, sjob in out varchar) as icount number; begin select count(*) into icount from emp where sal>isal and job=sjob; if icount=1 then .... else .... end if; exception when too_many_rows then DBMS_OUTPUT.PUT_LINE('返回值多于1行'); when others then DBMS_OUTPUT.PUT_LINE('在RUNBYPARMETERS过程中出错!'); end;
[复制代码]其中参数IN表示输入参数,是参数的默认模式。
OUT表示返回值参数,类型可以使用任意Oracle中的合法类型。
OUT模式定义的参数只能在过程体内部赋值,表示该参数可以将某个值传递回调用他的过程
IN OUT表示该参数可以向该过程中传递值,也可以将某个值传出去。

(4)存储过程中游标定义使用[复制代码]
as //定义(游标一个可以遍历的结果集) CURSOR cur_1 IS SELECT area_code,CMCODE,SUM(rmb_amt)/10000 rmb_amt_sn, SUM(usd_amt)/10000 usd_amt_sn FROM BGD_AREA_CM_M_BASE_T WHERE ym >= vs_ym_sn_beg AND ym <= vs_ym_sn_end GROUP BY area_code,CMCODE; begin //执行(常用For语句遍历游标) FOR rec IN cur_1 LOOP UPDATE xxxxxxxxxxx_T SET rmb_amt_sn = rec.rmb_amt_sn,usd_amt_sn = rec.usd_amt_sn WHERE area_code = rec.area_code AND CMCODE = rec.CMCODE AND ym = is_ym; END LOOP;
[复制代码] 

(5)游标的定义[复制代码]
--显示cursor的处理 declare ---声明cursor,创建和命名一个sql工作区 cursor cursor_name is select real_name from account_hcz; v_realname varchar2(20); begin open cursor_name;---打开cursor,执行sql语句产生的结果集 fetch cursor_name into v_realname;--提取cursor,提取结果集中的记录 dbms_output.put_line(v_realname); close cursor_name;--关闭cursor end;
[复制代码]3、在Oracle中对存储过程的调用 

(1)过程调用方式一[复制代码]
declare realsal emp.sal%type; realname varchar(40); realjob varchar(40); begin //过程调用开始 realsal:=1100; realname:=''; realjob:='CLERK'; runbyparmeters(realsal,realname,realjob);--必须按顺序 DBMS_OUTPUT.PUT_LINE(REALNAME||' '||REALJOB); END; //过程调用结束
[复制代码](2)过程调用方式二[复制代码]
declare realsal emp.sal%type; realname varchar(40); realjob varchar(40); begin //过程调用开始 realsal:=1100; realname:=''; realjob:='CLERK'; --指定值对应变量顺序可变 runbyparmeters(sname=>realname,isal=>realsal,sjob=>realjob); DBMS_OUTPUT.PUT_LINE(REALNAME||' '||REALJOB); END; //过程调用结束
[复制代码](3)过程调用方式三(SQL命令行方式下)1、SQL>exec proc_emp('参数1','参数2');//无返回值过程调用 2、SQL>var vsal number SQL> exec proc_emp ('参数1',:vsal);// 有返回值过程调用 或者:call proc_emp ('参数1',:vsal);// 有返回值过程调用 

​经典mssql语句大全

admin 发表了文章 • 0 个评论 • 94 次浏览 • 2018-04-17 16:19 • 来自相关话题

一、基础
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/cross (outer) join: 
全外连接:不仅包括符号连接表的匹配行,还包括两个连接表中的所有记录。
12、分组:Group by:
   一张表,一旦分组 完成后,查询后只能得到组相关的信息。
    组相关的信息:(统计信息) count,sum,max,min,avg  分组的标准)
    在SQLServer中分组时:不能以text,ntext,image类型的字段作为分组依据
   在selecte统计函数中的字段,不能和普通的字段放在一起;
13、对数据库进行操作:
   分离数据库: sp_detach_db; 附加数据库:sp_attach_db 后接表明,附加需要完整的路径名
14.如何修改数据库的名称:
sp_renamedb 'old_name', 'new_name' 
 
二、提升
1、说明:复制表(只复制结构,源表名:a 新表名:b) (Access可用)
法一:select * into b from a where 1<>1(仅用于SQlServer)
法二: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.排序字段
具体实现:
关于数据库分页:
  declare @start int,@end int 
  @sql  nvarchar(600)
  set @sql=’select top’+str(@end-@start+1)+’+from T where rid not in(select top’+str(@str-1)+’Rid from T where Rid>-1)’
  exec sp_executesql @sql

注意:在top后不能直接跟一个变量,所以在实际应用中只有这样的进行特殊的处理。Rid为一个标识列,如果top后还有具体的字段,这样做是非常有好处的。因为这样可以避免 top的字段如果是逻辑索引的,查询的结果后实际表中的不一致(逻辑索引中的数据有可能和数据表中的不一致,而查询时如果处在索引则首先查询索引)
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、说明:删除重复记录
1),delete from tablename where id not in (select max(id) from tablename group by col1,col2,...)
2),select distinct * into temp from tablename
  delete from tablename
  insert into tablename select * from temp
评价: 这种操作牵连大量的数据的移动,这种做法不适合大容量但数据操作
3),例如:在一个外部表中导入数据,由于某些原因第一次只导入了一部分,但很难判断具体位置,这样只有在下一次全部导入,这样也就产生好多重复的字段,怎样删除重复字段
alter table tablename
--添加一个自增列
add  column_b int identity(1,1)
 delete from tablename where column_b not in(
select max(column_b)  from tablename group by column1,column2,...)
alter table tablename drop column column_b
20、说明:列出数据库里所有的表名
select name from sysobjects where type='U' // 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
三、技巧
1、1=1,1=2的使用,在SQL语句组合时用的较多
“where 1=1” 是表示选择全部    “where 1=2”全部不选,
如:
if @strWhere !='' 
begin
set @strSQL = 'select count(*) as Total from [' + @tblName + '] where ' + @strWhere 
end
else 
begin
set @strSQL = 'select count(*) as Total from [' + @tblName + ']' 
end 
我们可以直接写成
错误!未找到目录项。
set @strSQL = 'select count(*) as Total from [' + @tblName + '] where 1=1 安定 '+ @strWhere 2、收缩数据库
--重建索引
DBCC REINDEX
DBCC INDEXDEFRAG
--收缩数据和日志
DBCC SHRINKDB
DBCC SHRINKFILE
3、压缩数据库
dbcc shrinkdatabase(dbname)
4、转移数据库给新用户以已存在用户权限
exec sp_change_users_login 'update_one','newname','oldname'
go
5、检查备份集
RESTORE VERIFYONLY from disk='E:\dvbbs.bak'
6、修复数据库
ALTER DATABASE [dvbbs] SET SINGLE_USER
GO
DBCC CHECKDB('dvbbs',repair_allow_data_loss) WITH TABLOCK
GO
ALTER DATABASE [dvbbs] SET MULTI_USER
GO
7、日志清除
SET NOCOUNT ON
DECLARE @LogicalFileName sysname,
 @MaxMinutes INT,
 @NewSize INT

USE tablename -- 要操作的数据库名
SELECT  @LogicalFileName = 'tablename_log', -- 日志文件名
@MaxMinutes = 10, -- Limit on time allowed to wrap log.
 @NewSize = 1  -- 你想设定的日志文件的大小(M)
Setup / initialize
DECLARE @OriginalSize int
SELECT @OriginalSize = size 
 FROM sysfiles
 WHERE name = @LogicalFileName
SELECT 'Original Size of ' + db_name() + ' LOG is ' + 
 CONVERT(VARCHAR(30),@OriginalSize) + ' 8K pages or ' + 
 CONVERT(VARCHAR(30),(@OriginalSize*8/1024)) + 'MB'
 FROM sysfiles
 WHERE name = @LogicalFileName
CREATE TABLE DummyTrans
 (DummyColumn char (8000) not null)

DECLARE @Counter    INT,
 @StartTime DATETIME,
 @TruncLog   VARCHAR(255)
SELECT @StartTime = GETDATE(),
 @TruncLog = 'BACKUP LOG ' + db_name() + ' WITH TRUNCATE_ONLY'
DBCC SHRINKFILE (@LogicalFileName, @NewSize)
EXEC (@TruncLog)
-- Wrap the log if necessary.
WHILE @MaxMinutes > DATEDIFF (mi, @StartTime, GETDATE()) -- time has not expired
 AND @OriginalSize = (SELECT size FROM sysfiles WHERE name = @LogicalFileName)  
 AND (@OriginalSize * 8 /1024) > @NewSize  
 BEGIN -- Outer loop.
SELECT @Counter = 0
 WHILE   ((@Counter < @OriginalSize / 16) AND (@Counter < 50000))
 BEGIN -- update
 INSERT DummyTrans VALUES ('Fill Log') DELETE DummyTrans
 SELECT @Counter = @Counter + 1
 END
 EXEC (@TruncLog)  
 END
SELECT 'Final Size of ' + db_name() + ' LOG is ' +
 CONVERT(VARCHAR(30),size) + ' 8K pages or ' + 
 CONVERT(VARCHAR(30),(size*8/1024)) + 'MB'
 FROM sysfiles 
 WHERE name = @LogicalFileName
DROP TABLE DummyTrans
SET NOCOUNT OFF 
8、说明:更改某个表
exec sp_changeobjectowner 'tablename','dbo'
9、存储更改全部表
CREATE PROCEDURE dbo.User_ChangeObjectOwnerBatch
@OldOwner as NVARCHAR(128),
@NewOwner as NVARCHAR(128)
AS
DECLARE @Name    as NVARCHAR(128)
DECLARE @Owner   as NVARCHAR(128)
DECLARE @OwnerName   as NVARCHAR(128)
DECLARE curObject CURSOR FOR 
select 'Name'    = name,
   'Owner'    = user_name(uid)
from sysobjects
where user_name(uid)=@OldOwner
order by name
OPEN   curObject
FETCH NEXT FROM curObject INTO @Name, @Owner
WHILE(@@FETCH_STATUS=0)
BEGIN     
if @Owner=@OldOwner 
begin
   set @OwnerName = @OldOwner + '.' + rtrim(@Name)
   exec sp_changeobjectowner @OwnerName, @NewOwner
end
-- select @name,@NewOwner,@OldOwner
FETCH NEXT FROM curObject INTO @Name, @Owner
END
close curObject
deallocate curObject
GO

10、SQL SERVER中直接循环写入数据
declare @i int
set @i=1
while @i<30
begin
    insert into test (userid) values(@i)
    set @i=@i+1
end
案例:
有如下表,要求就裱中所有沒有及格的成績,在每次增長0.1的基礎上,使他們剛好及格:
    Name     score
    Zhangshan   80
    Lishi       59
    Wangwu      50
    Songquan    69
while((select min(score) from tb_table)<60)
begin
update tb_table set score =score*1.01 
where score<60
if  (select min(score) from tb_table)>60
  break
 else
    continue
end
数据开发-经典

1.按姓氏笔画排序:
Select * From TableName Order By CustomerName Collate Chinese_PRC_Stroke_ci_as //从少到多
2.数据库加密:
select encrypt('原始密码')
select pwdencrypt('原始密码')
select pwdcompare('原始密码','加密后密码') = 1--相同;否则不相同 encrypt('原始密码')
select pwdencrypt('原始密码')
select pwdcompare('原始密码','加密后密码') = 1--相同;否则不相同
3.取回表中字段:
declare @list varchar(1000),
@sql nvarchar(1000) 
select @list=@list+','+b.name from sysobjects a,syscolumns b where a.id=b.id and a.name='表A'
set @sql='select '+right(@list,len(@list)-1)+' from 表A' 
exec (@sql)
4.查看硬盘分区:
EXEC master..xp_fixeddrives
5.比较A,B表是否相等:
if (select checksum_agg(binary_checksum(*)) from A)
     =
    (select checksum_agg(binary_checksum(*)) from B)
print '相等'
else
print '不相等'
6.杀掉所有的事件探察器进程:
DECLARE hcforeach CURSOR GLOBAL FOR SELECT 'kill '+RTRIM(spid) FROM master.dbo.sysprocesses
WHERE program_name IN('SQL profiler',N'SQL 事件探查器')
EXEC sp_msforeach_worker '?'
7.记录搜索:
开头到N条记录
Select Top N * From 表
-------------------------------
N到M条记录(要有主索引ID)
Select Top M-N * From 表 Where ID in (Select Top M ID From 表) Order by ID   Desc
----------------------------------
N到结尾记录
Select Top N * From 表 Order by ID Desc
案例
例如1:一张表有一万多条记录,表的第一个字段 RecID 是自增长字段, 写一个SQL语句, 找出表的第31到第40个记录。
 select top 10 recid from A where recid not  in(select top 30 recid from A)
分析:如果这样写会产生某些问题,如果recid在表中存在逻辑索引。
    select top 10 recid from A where……是从索引中查找,而后面的select top 30 recid from A则在数据表中查找,这样由于索引中的顺序有可能和数据表中的不一致,这样就导致查询到的不是本来的欲得到的数据。
解决方案
1, 用order by select top 30 recid from A order by ricid 如果该字段不是自增长,就会出现问题
2, 在那个子查询中也加条件:select top 30 recid from A where recid>-1
例2:查询表中的最后以条记录,并不知道这个表共有多少数据,以及表结构。
set @s = 'select top 1 * from T   where pid not in (select top ' + str(@count-1) + ' pid  from  T)'
print @s      exec  sp_executesql  @s
9:获取当前数据库中的所有用户表
select Name from sysobjects where xtype='u' and status>=0
10:获取某一个表的所有字段
select name from syscolumns where id=object_id('表名')
select name from syscolumns where id in (select id from sysobjects where type = 'u' and name = '表名')
两种方式的效果相同
11:查看与某一个表相关的视图、存储过程、函数
select a.* from sysobjects a, syscomments b where a.id = b.id and b.text like '%表名%'
12:查看当前数据库中所有存储过程
select name as 存储过程名称 from sysobjects where xtype='P'
13:查询用户创建的所有数据库
select * from master..sysdatabases D where sid not in(select sid from master..syslogins where name='sa')
或者
select dbid, name AS DB_NAME from master..sysdatabases where sid <> 0x01
14:查询某一个表的字段和数据类型
select column_name,data_type from information_schema.columns
where table_name = '表名' 
15:不同服务器数据库之间的数据操作
--创建链接服务器 
exec sp_addlinkedserver   'ITSV ', ' ', 'SQLOLEDB ', '远程服务器名或ip地址 ' 
exec sp_addlinkedsrvlogin  'ITSV ', 'false ',null, '用户名 ', '密码 ' 
--查询示例 
select * from ITSV.数据库名.dbo.表名 
--导入示例 
select * into 表 from ITSV.数据库名.dbo.表名 
--以后不再使用时删除链接服务器 
exec sp_dropserver  'ITSV ', 'droplogins ' 
 
--连接远程/局域网数据(openrowset/openquery/opendatasource) 
--1、openrowset 
--查询示例 
select * from openrowset( 'SQLOLEDB ', 'sql服务器名 '; '用户名 '; '密码 ',数据库名.dbo.表名) 
--生成本地表 
select * into 表 from openrowset( 'SQLOLEDB ', 'sql服务器名 '; '用户名 '; '密码 ',数据库名.dbo.表名) 
--把本地表导入远程表 
insert openrowset( 'SQLOLEDB ', 'sql服务器名 '; '用户名 '; '密码 ',数据库名.dbo.表名) 
select *from 本地表 
--更新本地表 
update b 
set b.列A=a.列A 
 from openrowset( 'SQLOLEDB ', 'sql服务器名 '; '用户名 '; '密码 ',数据库名.dbo.表名)as a inner join 本地表 b 
on a.column1=b.column1 
--openquery用法需要创建一个连接 
--首先创建一个连接创建链接服务器 
exec sp_addlinkedserver   'ITSV ', ' ', 'SQLOLEDB ', '远程服务器名或ip地址 ' 
--查询 
select * 
FROM openquery(ITSV,  'SELECT *  FROM 数据库.dbo.表名 ') 
--把本地表导入远程表 
insert openquery(ITSV,  'SELECT *  FROM 数据库.dbo.表名 ') 
select * from 本地表 
--更新本地表 
update b 
set b.列B=a.列B 
FROM openquery(ITSV,  'SELECT * FROM 数据库.dbo.表名 ') as a  
inner join 本地表 b on a.列A=b.列A 
--3、opendatasource/openrowset 
SELECT   * 
FROM   opendatasource( 'SQLOLEDB ',  'Data Source=ip/ServerName;User ID=登陆名;Password=密码 ' ).test.dbo.roy_ta 
--把本地表导入远程表 
insert opendatasource( 'SQLOLEDB ',  'Data Source=ip/ServerName;User ID=登陆名;Password=密码 ').数据库.dbo.表名 
select * from 本地表  
SQL Server基本函数
SQL Server基本函数
1.字符串函数 长度与分析用 
1,datalength(Char_expr) 返回字符串包含字符数,但不包含后面的空格
2,substring(expression,start,length) 取子串,字符串的下标是从“1”,start为起始位置,length为字符串长度,实际应用中以len(expression)取得其长度
3,right(char_expr,int_expr) 返回字符串右边第int_expr个字符,还用left于之相反
4,isnull( check_expression , replacement_value )如果check_expression為空,則返回replacement_value的值,不為空,就返回check_expression字符操作类 
5,Sp_addtype 自定義數據類型
例如:EXEC sp_addtype birthday, datetime, 'NULL'
6,set nocount {on|off}
使返回的结果中不包含有关受 Transact-SQL 语句影响的行数的信息。如果存储过程中包含的一些语句并不返回许多实际的数据,则该设置由于大量减少了网络流量,因此可显著提高性能。SET NOCOUNT 设置是在执行或运行时设置,而不是在分析时设置。
SET NOCOUNT 为 ON 时,不返回计数(表示受 Transact-SQL 语句影响的行数)。

SET NOCOUNT 为 OFF 时,返回计数
常识
 
在SQL查询中:from后最多可以跟多少张表或视图:256
在SQL语句中出现 Order by,查询时,先排序,后取
在SQL中,一个字段的最大容量是8000,而对于nvarchar(4000),由于nvarchar是Unicode码。  
        
SQLServer2000同步复制技术实现步骤
一、 预备工作
1.发布服务器,订阅服务器都创建一个同名的windows用户,并设置相同的密码,做为发布快照文件夹的有效访问用户
--管理工具
--计算机管理
--用户和组
--右键用户
--新建用户
--建立一个隶属于administrator组的登陆windows的用户(SynUser)
2.在发布服务器上,新建一个共享目录,做为发布的快照文件的存放目录,操作:
我的电脑--D:\ 新建一个目录,名为: PUB
--右键这个新建的目录
--属性--共享
--选择"共享该文件夹"
--通过"权限"按纽来设置具体的用户权限,保证第一步中创建的用户(SynUser) 具有对该文件夹的所有权限
 
--确定
3.设置SQL代理(SQLSERVERAGENT)服务的启动用户(发布/订阅服务器均做此设置)
开始--程序--管理工具--服务
--右键SQLSERVERAGENT
--属性--登陆--选择"此账户"
--输入或者选择第一步中创建的windows登录用户名(SynUser)
--"密码"中输入该用户的密码
4.设置SQL Server身份验证模式,解决连接时的权限问题(发布/订阅服务器均做此设置)
企业管理器
--右键SQL实例--属性
--安全性--身份验证
--选择"SQL Server 和 Windows"
--确定
5.在发布服务器和订阅服务器上互相注册
企业管理器
--右键SQL Server组
--新建SQL Server注册...
--下一步--可用的服务器中,输入你要注册的远程服务器名 --添加
--下一步--连接使用,选择第二个"SQL Server身份验证"
--下一步--输入用户名和密码(SynUser)
--下一步--选择SQL Server组,也可以创建一个新组
--下一步--完成
6.对于只能用IP,不能用计算机名的,为其注册服务器别名(此步在实施中没用到)
 (在连接端配置,比如,在订阅服务器上配置的话,服务器名称中输入的是发布服务器的IP)
开始--程序--Microsoft SQL Server--客户端网络实用工具
--别名--添加
--网络库选择"tcp/ip"--服务器别名输入SQL服务器名
--连接参数--服务器名称中输入SQL服务器ip地址
--如果你修改了SQL的端口,取消选择"动态决定端口",并输入对应的端口号
二、 正式配置
1、配置发布服务器
打开企业管理器,在发布服务器(B、C、D)上执行以下步骤:
(1) 从[工具]下拉菜单的[复制]子菜单中选择[配置发布、订阅服务器和分发]出现配置发布和分发向导 
(2) [下一步] 选择分发服务器 可以选择把发布服务器自己作为分发服务器或者其他sql的服务器(选择自己)
(3) [下一步] 设置快照文件夹
采用默认\\servername\Pub
(4) [下一步] 自定义配置 
可以选择:是,让我设置分发数据库属性启用发布服务器或设置发布设置
否,使用下列默认设置(推荐)
(5) [下一步] 设置分发数据库名称和位置 采用默认值
(6) [下一步] 启用发布服务器 选择作为发布的服务器
(7) [下一步] 选择需要发布的数据库和发布类型
(8) [下一步] 选择注册订阅服务器
(9) [下一步] 完成配置
2、创建出版物
发布服务器B、C、D上
(1)从[工具]菜单的[复制]子菜单中选择[创建和管理发布]命令
(2)选择要创建出版物的数据库,然后单击[创建发布]
(3)在[创建发布向导]的提示对话框中单击[下一步]系统就会弹出一个对话框。对话框上的内容是复制的三个类型。我们现在选第一个也就是默认的快照发布(其他两个大家可以去看看帮助)
(4)单击[下一步]系统要求指定可以订阅该发布的数据库服务器类型,
SQLSERVER允许在不同的数据库如 orACLE或ACCESS之间进行数据复制。
但是在这里我们选择运行"SQL SERVER 2000"的数据库服务器
(5)单击[下一步]系统就弹出一个定义文章的对话框也就是选择要出版的表
注意: 如果前面选择了事务发布 则再这一步中只能选择带有主键的表
(6)选择发布名称和描述
(7)自定义发布属性 向导提供的选择:
是 我将自定义数据筛选,启用匿名订阅和或其他自定义属性
否 根据指定方式创建发布 (建议采用自定义的方式)
(8)[下一步] 选择筛选发布的方式 
(9)[下一步] 可以选择是否允许匿名订阅
1)如果选择署名订阅,则需要在发布服务器上添加订阅服务器
方法: [工具]->[复制]->[配置发布、订阅服务器和分发的属性]->[订阅服务器] 中添加
否则在订阅服务器上请求订阅时会出现的提示:改发布不允许匿名订阅
如果仍然需要匿名订阅则用以下解决办法 
[企业管理器]->[复制]->[发布内容]->[属性]->[订阅选项] 选择允许匿名请求订阅
2)如果选择匿名订阅,则配置订阅服务器时不会出现以上提示
(10)[下一步] 设置快照 代理程序调度
(11)[下一步] 完成配置
当完成出版物的创建后创建出版物的数据库也就变成了一个共享数据库
有数据 
srv1.库名..author有字段:id,name,phone, 
srv2.库名..author有字段:id,name,telphone,adress 
 
要求: 
srv1.库名..author增加记录则srv1.库名..author记录增加 
srv1.库名..author的phone字段更新,则srv1.库名..author对应字段telphone更新 
--*/ 
 
--大致的处理步骤 
--1.在 srv1 上创建连接服务器,以便在 srv1 中操作 srv2,实现同步 
exec sp_addlinkedserver 'srv2','','SQLOLEDB','srv2的sql实例名或ip' 
exec sp_addlinkedsrvlogin 'srv2','false',null,'用户名','密码' 
go
--2.在 srv1 和 srv2 这两台电脑中,启动 msdtc(分布式事务处理服务),并且设置为自动启动
。我的电脑--控制面板--管理工具--服务--右键 Distributed Transaction Coordinator--属性--启动--并将启动类型设置为自动启动 
go 
 
 
--然后创建一个作业定时调用上面的同步处理存储过程就行了 
 
企业管理器 
--管理 
--SQL Server代理 
--右键作业 
--新建作业 
--"常规"项中输入作业名称 
--"步骤"项 
--新建 
--"步骤名"中输入步骤名 
--"类型"中选择"Transact-SQL 脚本(TSQL)" 
--"数据库"选择执行命令的数据库 
--"命令"中输入要执行的语句: exec p_process 
--确定 
--"调度"项 
--新建调度 
--"名称"中输入调度名称 
--"调度类型"中选择你的作业执行安排 
--如果选择"反复出现" 
--点"更改"来设置你的时间安排 
 
 
然后将SQL Agent服务启动,并设置为自动启动,否则你的作业不会被执行 
 
设置方法: 
我的电脑--控制面板--管理工具--服务--右键 SQLSERVERAGENT--属性--启动类型--选择"自动启动"--确定. 
 
 
--3.实现同步处理的方法2,定时同步 
 
--在srv1中创建如下的同步处理存储过程 
create proc p_process 
as 
--更新修改过的数据 
update b set name=i.name,telphone=i.telphone 
from srv2.库名.dbo.author b,author i 
where b.id=i.id and
(b.name <> i.name or b.telphone <> i.telphone) 
 
--插入新增的数据 
insert srv2.库名.dbo.author(id,name,telphone) 
select id,name,telphone from author i 
where not exists( 
select * from srv2.库名.dbo.author where id=i.id) 
 
--删除已经删除的数据(如果需要的话) 
delete b 
from srv2.库名.dbo.author b 
where not exists( 
select * from author where id=b.id)
go 查看全部

一、基础
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/cross (outer) join: 
全外连接:不仅包括符号连接表的匹配行,还包括两个连接表中的所有记录。
12、分组:Group by:
   一张表,一旦分组 完成后,查询后只能得到组相关的信息。
    组相关的信息:(统计信息) count,sum,max,min,avg  分组的标准)
    在SQLServer中分组时:不能以text,ntext,image类型的字段作为分组依据
   在selecte统计函数中的字段,不能和普通的字段放在一起;
13、对数据库进行操作:
   分离数据库: sp_detach_db; 附加数据库:sp_attach_db 后接表明,附加需要完整的路径名
14.如何修改数据库的名称:
sp_renamedb 'old_name', 'new_name' 
 
二、提升
1、说明:复制表(只复制结构,源表名:a 新表名:b) (Access可用)
法一:select * into b from a where 1<>1(仅用于SQlServer)
法二: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.排序字段
具体实现:
关于数据库分页:
  declare @start int,@end int 
  @sql  nvarchar(600)
  set @sql=’select top’+str(@end-@start+1)+’+from T where rid not in(select top’+str(@str-1)+’Rid from T where Rid>-1)’
  exec sp_executesql @sql

注意:在top后不能直接跟一个变量,所以在实际应用中只有这样的进行特殊的处理。Rid为一个标识列,如果top后还有具体的字段,这样做是非常有好处的。因为这样可以避免 top的字段如果是逻辑索引的,查询的结果后实际表中的不一致(逻辑索引中的数据有可能和数据表中的不一致,而查询时如果处在索引则首先查询索引)
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、说明:删除重复记录
1),delete from tablename where id not in (select max(id) from tablename group by col1,col2,...)
2),select distinct * into temp from tablename
  delete from tablename
  insert into tablename select * from temp
评价: 这种操作牵连大量的数据的移动,这种做法不适合大容量但数据操作
3),例如:在一个外部表中导入数据,由于某些原因第一次只导入了一部分,但很难判断具体位置,这样只有在下一次全部导入,这样也就产生好多重复的字段,怎样删除重复字段
alter table tablename
--添加一个自增列
add  column_b int identity(1,1)
 delete from tablename where column_b not in(
select max(column_b)  from tablename group by column1,column2,...)
alter table tablename drop column column_b
20、说明:列出数据库里所有的表名
select name from sysobjects where type='U' // 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
三、技巧
1、1=1,1=2的使用,在SQL语句组合时用的较多
“where 1=1” 是表示选择全部    “where 1=2”全部不选,
如:
if @strWhere !='' 
begin
set @strSQL = 'select count(*) as Total from [' + @tblName + '] where ' + @strWhere 
end
else 
begin
set @strSQL = 'select count(*) as Total from [' + @tblName + ']' 
end 
我们可以直接写成
错误!未找到目录项。
set @strSQL = 'select count(*) as Total from [' + @tblName + '] where 1=1 安定 '+ @strWhere 2、收缩数据库
--重建索引
DBCC REINDEX
DBCC INDEXDEFRAG
--收缩数据和日志
DBCC SHRINKDB
DBCC SHRINKFILE
3、压缩数据库
dbcc shrinkdatabase(dbname)
4、转移数据库给新用户以已存在用户权限
exec sp_change_users_login 'update_one','newname','oldname'
go
5、检查备份集
RESTORE VERIFYONLY from disk='E:\dvbbs.bak'
6、修复数据库
ALTER DATABASE [dvbbs] SET SINGLE_USER
GO
DBCC CHECKDB('dvbbs',repair_allow_data_loss) WITH TABLOCK
GO
ALTER DATABASE [dvbbs] SET MULTI_USER
GO
7、日志清除
SET NOCOUNT ON
DECLARE @LogicalFileName sysname,
 @MaxMinutes INT,
 @NewSize INT

USE tablename -- 要操作的数据库名
SELECT  @LogicalFileName = 'tablename_log', -- 日志文件名
@MaxMinutes = 10, -- Limit on time allowed to wrap log.
 @NewSize = 1  -- 你想设定的日志文件的大小(M)
Setup / initialize
DECLARE @OriginalSize int
SELECT @OriginalSize = size 
 FROM sysfiles
 WHERE name = @LogicalFileName
SELECT 'Original Size of ' + db_name() + ' LOG is ' + 
 CONVERT(VARCHAR(30),@OriginalSize) + ' 8K pages or ' + 
 CONVERT(VARCHAR(30),(@OriginalSize*8/1024)) + 'MB'
 FROM sysfiles
 WHERE name = @LogicalFileName
CREATE TABLE DummyTrans
 (DummyColumn char (8000) not null)

DECLARE @Counter    INT,
 @StartTime DATETIME,
 @TruncLog   VARCHAR(255)
SELECT @StartTime = GETDATE(),
 @TruncLog = 'BACKUP LOG ' + db_name() + ' WITH TRUNCATE_ONLY'
DBCC SHRINKFILE (@LogicalFileName, @NewSize)
EXEC (@TruncLog)
-- Wrap the log if necessary.
WHILE @MaxMinutes > DATEDIFF (mi, @StartTime, GETDATE()) -- time has not expired
 AND @OriginalSize = (SELECT size FROM sysfiles WHERE name = @LogicalFileName)  
 AND (@OriginalSize * 8 /1024) > @NewSize  
 BEGIN -- Outer loop.
SELECT @Counter = 0
 WHILE   ((@Counter < @OriginalSize / 16) AND (@Counter < 50000))
 BEGIN -- update
 INSERT DummyTrans VALUES ('Fill Log') DELETE DummyTrans
 SELECT @Counter = @Counter + 1
 END
 EXEC (@TruncLog)  
 END
SELECT 'Final Size of ' + db_name() + ' LOG is ' +
 CONVERT(VARCHAR(30),size) + ' 8K pages or ' + 
 CONVERT(VARCHAR(30),(size*8/1024)) + 'MB'
 FROM sysfiles 
 WHERE name = @LogicalFileName
DROP TABLE DummyTrans
SET NOCOUNT OFF 
8、说明:更改某个表
exec sp_changeobjectowner 'tablename','dbo'
9、存储更改全部表
CREATE PROCEDURE dbo.User_ChangeObjectOwnerBatch
@OldOwner as NVARCHAR(128),
@NewOwner as NVARCHAR(128)
AS
DECLARE @Name    as NVARCHAR(128)
DECLARE @Owner   as NVARCHAR(128)
DECLARE @OwnerName   as NVARCHAR(128)
DECLARE curObject CURSOR FOR 
select 'Name'    = name,
   'Owner'    = user_name(uid)
from sysobjects
where user_name(uid)=@OldOwner
order by name
OPEN   curObject
FETCH NEXT FROM curObject INTO @Name, @Owner
WHILE(@@FETCH_STATUS=0)
BEGIN     
if @Owner=@OldOwner 
begin
   set @OwnerName = @OldOwner + '.' + rtrim(@Name)
   exec sp_changeobjectowner @OwnerName, @NewOwner
end
-- select @name,@NewOwner,@OldOwner
FETCH NEXT FROM curObject INTO @Name, @Owner
END
close curObject
deallocate curObject
GO

10、SQL SERVER中直接循环写入数据
declare @i int
set @i=1
while @i<30
begin
    insert into test (userid) values(@i)
    set @i=@i+1
end
案例:
有如下表,要求就裱中所有沒有及格的成績,在每次增長0.1的基礎上,使他們剛好及格:
    Name     score
    Zhangshan   80
    Lishi       59
    Wangwu      50
    Songquan    69
while((select min(score) from tb_table)<60)
begin
update tb_table set score =score*1.01 
where score<60
if  (select min(score) from tb_table)>60
  break
 else
    continue
end
数据开发-经典

1.按姓氏笔画排序:
Select * From TableName Order By CustomerName Collate Chinese_PRC_Stroke_ci_as //从少到多
2.数据库加密:
select encrypt('原始密码')
select pwdencrypt('原始密码')
select pwdcompare('原始密码','加密后密码') = 1--相同;否则不相同 encrypt('原始密码')
select pwdencrypt('原始密码')
select pwdcompare('原始密码','加密后密码') = 1--相同;否则不相同
3.取回表中字段:
declare @list varchar(1000),
@sql nvarchar(1000) 
select @list=@list+','+b.name from sysobjects a,syscolumns b where a.id=b.id and a.name='表A'
set @sql='select '+right(@list,len(@list)-1)+' from 表A' 
exec (@sql)
4.查看硬盘分区:
EXEC master..xp_fixeddrives
5.比较A,B表是否相等:
if (select checksum_agg(binary_checksum(*)) from A)
     =
    (select checksum_agg(binary_checksum(*)) from B)
print '相等'
else
print '不相等'
6.杀掉所有的事件探察器进程:
DECLARE hcforeach CURSOR GLOBAL FOR SELECT 'kill '+RTRIM(spid) FROM master.dbo.sysprocesses
WHERE program_name IN('SQL profiler',N'SQL 事件探查器')
EXEC sp_msforeach_worker '?'
7.记录搜索:
开头到N条记录
Select Top N * From 表
-------------------------------
N到M条记录(要有主索引ID)
Select Top M-N * From 表 Where ID in (Select Top M ID From 表) Order by ID   Desc
----------------------------------
N到结尾记录
Select Top N * From 表 Order by ID Desc
案例
例如1:一张表有一万多条记录,表的第一个字段 RecID 是自增长字段, 写一个SQL语句, 找出表的第31到第40个记录。
 select top 10 recid from A where recid not  in(select top 30 recid from A)
分析:如果这样写会产生某些问题,如果recid在表中存在逻辑索引。
    select top 10 recid from A where……是从索引中查找,而后面的select top 30 recid from A则在数据表中查找,这样由于索引中的顺序有可能和数据表中的不一致,这样就导致查询到的不是本来的欲得到的数据。
解决方案
1, 用order by select top 30 recid from A order by ricid 如果该字段不是自增长,就会出现问题
2, 在那个子查询中也加条件:select top 30 recid from A where recid>-1
例2:查询表中的最后以条记录,并不知道这个表共有多少数据,以及表结构。
set @s = 'select top 1 * from T   where pid not in (select top ' + str(@count-1) + ' pid  from  T)'
print @s      exec  sp_executesql  @s
9:获取当前数据库中的所有用户表
select Name from sysobjects where xtype='u' and status>=0
10:获取某一个表的所有字段
select name from syscolumns where id=object_id('表名')
select name from syscolumns where id in (select id from sysobjects where type = 'u' and name = '表名')
两种方式的效果相同
11:查看与某一个表相关的视图、存储过程、函数
select a.* from sysobjects a, syscomments b where a.id = b.id and b.text like '%表名%'
12:查看当前数据库中所有存储过程
select name as 存储过程名称 from sysobjects where xtype='P'
13:查询用户创建的所有数据库
select * from master..sysdatabases D where sid not in(select sid from master..syslogins where name='sa')
或者
select dbid, name AS DB_NAME from master..sysdatabases where sid <> 0x01
14:查询某一个表的字段和数据类型
select column_name,data_type from information_schema.columns
where table_name = '表名' 
15:不同服务器数据库之间的数据操作
--创建链接服务器 
exec sp_addlinkedserver   'ITSV ', ' ', 'SQLOLEDB ', '远程服务器名或ip地址 ' 
exec sp_addlinkedsrvlogin  'ITSV ', 'false ',null, '用户名 ', '密码 ' 
--查询示例 
select * from ITSV.数据库名.dbo.表名 
--导入示例 
select * into 表 from ITSV.数据库名.dbo.表名 
--以后不再使用时删除链接服务器 
exec sp_dropserver  'ITSV ', 'droplogins ' 
 
--连接远程/局域网数据(openrowset/openquery/opendatasource) 
--1、openrowset 
--查询示例 
select * from openrowset( 'SQLOLEDB ', 'sql服务器名 '; '用户名 '; '密码 ',数据库名.dbo.表名) 
--生成本地表 
select * into 表 from openrowset( 'SQLOLEDB ', 'sql服务器名 '; '用户名 '; '密码 ',数据库名.dbo.表名) 
--把本地表导入远程表 
insert openrowset( 'SQLOLEDB ', 'sql服务器名 '; '用户名 '; '密码 ',数据库名.dbo.表名) 
select *from 本地表 
--更新本地表 
update b 
set b.列A=a.列A 
 from openrowset( 'SQLOLEDB ', 'sql服务器名 '; '用户名 '; '密码 ',数据库名.dbo.表名)as a inner join 本地表 b 
on a.column1=b.column1 
--openquery用法需要创建一个连接 
--首先创建一个连接创建链接服务器 
exec sp_addlinkedserver   'ITSV ', ' ', 'SQLOLEDB ', '远程服务器名或ip地址 ' 
--查询 
select * 
FROM openquery(ITSV,  'SELECT *  FROM 数据库.dbo.表名 ') 
--把本地表导入远程表 
insert openquery(ITSV,  'SELECT *  FROM 数据库.dbo.表名 ') 
select * from 本地表 
--更新本地表 
update b 
set b.列B=a.列B 
FROM openquery(ITSV,  'SELECT * FROM 数据库.dbo.表名 ') as a  
inner join 本地表 b on a.列A=b.列A 
--3、opendatasource/openrowset 
SELECT   * 
FROM   opendatasource( 'SQLOLEDB ',  'Data Source=ip/ServerName;User ID=登陆名;Password=密码 ' ).test.dbo.roy_ta 
--把本地表导入远程表 
insert opendatasource( 'SQLOLEDB ',  'Data Source=ip/ServerName;User ID=登陆名;Password=密码 ').数据库.dbo.表名 
select * from 本地表  
SQL Server基本函数
SQL Server基本函数
1.字符串函数 长度与分析用 
1,datalength(Char_expr) 返回字符串包含字符数,但不包含后面的空格
2,substring(expression,start,length) 取子串,字符串的下标是从“1”,start为起始位置,length为字符串长度,实际应用中以len(expression)取得其长度
3,right(char_expr,int_expr) 返回字符串右边第int_expr个字符,还用left于之相反
4,isnull( check_expression , replacement_value )如果check_expression為空,則返回replacement_value的值,不為空,就返回check_expression字符操作类 
5,Sp_addtype 自定義數據類型
例如:EXEC sp_addtype birthday, datetime, 'NULL'
6,set nocount {on|off}
使返回的结果中不包含有关受 Transact-SQL 语句影响的行数的信息。如果存储过程中包含的一些语句并不返回许多实际的数据,则该设置由于大量减少了网络流量,因此可显著提高性能。SET NOCOUNT 设置是在执行或运行时设置,而不是在分析时设置。
SET NOCOUNT 为 ON 时,不返回计数(表示受 Transact-SQL 语句影响的行数)。

SET NOCOUNT 为 OFF 时,返回计数
常识
 
在SQL查询中:from后最多可以跟多少张表或视图:256
在SQL语句中出现 Order by,查询时,先排序,后取
在SQL中,一个字段的最大容量是8000,而对于nvarchar(4000),由于nvarchar是Unicode码。  
        
SQLServer2000同步复制技术实现步骤
一、 预备工作
1.发布服务器,订阅服务器都创建一个同名的windows用户,并设置相同的密码,做为发布快照文件夹的有效访问用户
--管理工具
--计算机管理
--用户和组
--右键用户
--新建用户
--建立一个隶属于administrator组的登陆windows的用户(SynUser)
2.在发布服务器上,新建一个共享目录,做为发布的快照文件的存放目录,操作:
我的电脑--D:\ 新建一个目录,名为: PUB
--右键这个新建的目录
--属性--共享
--选择"共享该文件夹"
--通过"权限"按纽来设置具体的用户权限,保证第一步中创建的用户(SynUser) 具有对该文件夹的所有权限
 
--确定
3.设置SQL代理(SQLSERVERAGENT)服务的启动用户(发布/订阅服务器均做此设置)
开始--程序--管理工具--服务
--右键SQLSERVERAGENT
--属性--登陆--选择"此账户"
--输入或者选择第一步中创建的windows登录用户名(SynUser)
--"密码"中输入该用户的密码
4.设置SQL Server身份验证模式,解决连接时的权限问题(发布/订阅服务器均做此设置)
企业管理器
--右键SQL实例--属性
--安全性--身份验证
--选择"SQL Server 和 Windows"
--确定
5.在发布服务器和订阅服务器上互相注册
企业管理器
--右键SQL Server组
--新建SQL Server注册...
--下一步--可用的服务器中,输入你要注册的远程服务器名 --添加
--下一步--连接使用,选择第二个"SQL Server身份验证"
--下一步--输入用户名和密码(SynUser)
--下一步--选择SQL Server组,也可以创建一个新组
--下一步--完成
6.对于只能用IP,不能用计算机名的,为其注册服务器别名(此步在实施中没用到)
 (在连接端配置,比如,在订阅服务器上配置的话,服务器名称中输入的是发布服务器的IP)
开始--程序--Microsoft SQL Server--客户端网络实用工具
--别名--添加
--网络库选择"tcp/ip"--服务器别名输入SQL服务器名
--连接参数--服务器名称中输入SQL服务器ip地址
--如果你修改了SQL的端口,取消选择"动态决定端口",并输入对应的端口号
二、 正式配置
1、配置发布服务器
打开企业管理器,在发布服务器(B、C、D)上执行以下步骤:
(1) 从[工具]下拉菜单的[复制]子菜单中选择[配置发布、订阅服务器和分发]出现配置发布和分发向导 
(2) [下一步] 选择分发服务器 可以选择把发布服务器自己作为分发服务器或者其他sql的服务器(选择自己)
(3) [下一步] 设置快照文件夹
采用默认\\servername\Pub
(4) [下一步] 自定义配置 
可以选择:是,让我设置分发数据库属性启用发布服务器或设置发布设置
否,使用下列默认设置(推荐)
(5) [下一步] 设置分发数据库名称和位置 采用默认值
(6) [下一步] 启用发布服务器 选择作为发布的服务器
(7) [下一步] 选择需要发布的数据库和发布类型
(8) [下一步] 选择注册订阅服务器
(9) [下一步] 完成配置
2、创建出版物
发布服务器B、C、D上
(1)从[工具]菜单的[复制]子菜单中选择[创建和管理发布]命令
(2)选择要创建出版物的数据库,然后单击[创建发布]
(3)在[创建发布向导]的提示对话框中单击[下一步]系统就会弹出一个对话框。对话框上的内容是复制的三个类型。我们现在选第一个也就是默认的快照发布(其他两个大家可以去看看帮助)
(4)单击[下一步]系统要求指定可以订阅该发布的数据库服务器类型,
SQLSERVER允许在不同的数据库如 orACLE或ACCESS之间进行数据复制。
但是在这里我们选择运行"SQL SERVER 2000"的数据库服务器
(5)单击[下一步]系统就弹出一个定义文章的对话框也就是选择要出版的表
注意: 如果前面选择了事务发布 则再这一步中只能选择带有主键的表
(6)选择发布名称和描述
(7)自定义发布属性 向导提供的选择:
是 我将自定义数据筛选,启用匿名订阅和或其他自定义属性
否 根据指定方式创建发布 (建议采用自定义的方式)
(8)[下一步] 选择筛选发布的方式 
(9)[下一步] 可以选择是否允许匿名订阅
1)如果选择署名订阅,则需要在发布服务器上添加订阅服务器
方法: [工具]->[复制]->[配置发布、订阅服务器和分发的属性]->[订阅服务器] 中添加
否则在订阅服务器上请求订阅时会出现的提示:改发布不允许匿名订阅
如果仍然需要匿名订阅则用以下解决办法 
[企业管理器]->[复制]->[发布内容]->[属性]->[订阅选项] 选择允许匿名请求订阅
2)如果选择匿名订阅,则配置订阅服务器时不会出现以上提示
(10)[下一步] 设置快照 代理程序调度
(11)[下一步] 完成配置
当完成出版物的创建后创建出版物的数据库也就变成了一个共享数据库
有数据 
srv1.库名..author有字段:id,name,phone, 
srv2.库名..author有字段:id,name,telphone,adress 
 
要求: 
srv1.库名..author增加记录则srv1.库名..author记录增加 
srv1.库名..author的phone字段更新,则srv1.库名..author对应字段telphone更新 
--*/ 
 
--大致的处理步骤 
--1.在 srv1 上创建连接服务器,以便在 srv1 中操作 srv2,实现同步 
exec sp_addlinkedserver 'srv2','','SQLOLEDB','srv2的sql实例名或ip' 
exec sp_addlinkedsrvlogin 'srv2','false',null,'用户名','密码' 
go
--2.在 srv1 和 srv2 这两台电脑中,启动 msdtc(分布式事务处理服务),并且设置为自动启动
。我的电脑--控制面板--管理工具--服务--右键 Distributed Transaction Coordinator--属性--启动--并将启动类型设置为自动启动 
go 
 
 
--然后创建一个作业定时调用上面的同步处理存储过程就行了 
 
企业管理器 
--管理 
--SQL Server代理 
--右键作业 
--新建作业 
--"常规"项中输入作业名称 
--"步骤"项 
--新建 
--"步骤名"中输入步骤名 
--"类型"中选择"Transact-SQL 脚本(TSQL)" 
--"数据库"选择执行命令的数据库 
--"命令"中输入要执行的语句: exec p_process 
--确定 
--"调度"项 
--新建调度 
--"名称"中输入调度名称 
--"调度类型"中选择你的作业执行安排 
--如果选择"反复出现" 
--点"更改"来设置你的时间安排 
 
 
然后将SQL Agent服务启动,并设置为自动启动,否则你的作业不会被执行 
 
设置方法: 
我的电脑--控制面板--管理工具--服务--右键 SQLSERVERAGENT--属性--启动类型--选择"自动启动"--确定. 
 
 
--3.实现同步处理的方法2,定时同步 
 
--在srv1中创建如下的同步处理存储过程 
create proc p_process 
as 
--更新修改过的数据 
update b set name=i.name,telphone=i.telphone 
from srv2.库名.dbo.author b,author i 
where b.id=i.id and
(b.name <> i.name or b.telphone <> i.telphone) 
 
--插入新增的数据 
insert srv2.库名.dbo.author(id,name,telphone) 
select id,name,telphone from author i 
where not exists( 
select * from srv2.库名.dbo.author where id=i.id) 
 
--删除已经删除的数据(如果需要的话) 
delete b 
from srv2.库名.dbo.author b 
where not exists( 
select * from author where id=b.id)
go

ORACLE 日期加减操作

admin 发表了文章 • 0 个评论 • 80 次浏览 • 2018-04-17 11:26 • 来自相关话题

无论是DATE还是timestamp都可以进行加减操作。
可以对当前日期加年、月、日、时、分、秒,操作不同的时间类型,有三种方法:

1 使用内置函数numtodsinterval增加小时,分钟和秒
2 加一个简单的数来增加天
3 使用内置函数add_months来增加年和月

例:
对当前日期增加一个小时:
SQL> select sysdate, sysdate+numtodsinterval(1,’hour’) from dual ;

SYSDATE             SYSDATE+NUMTODSINTE
——————- ——————-
2010-10-14 21:38:19 2010-10-14 22:38:19
对当前日期增加50分种
SQL> select sysdate, sysdate+numtodsinterval(50,’minute’) from dual ;

SYSDATE             SYSDATE+NUMTODSINTE
——————- ——————-
2010-10-14 21:39:12 2010-10-14 22:29:12
对当前日期增加45秒
SQL> select sysdate, sysdate+numtodsinterval(45,’second’) from dual ;

SYSDATE             SYSDATE+NUMTODSINTE
——————- ——————-
2010-10-14 21:40:06 2010-10-14 21:40:51
对当前日期增加3天
SQL> select sysdate, sysdate+3 from dual ;

SYSDATE             SYSDATE+3
——————- ——————-
2010-10-14 21:40:46 2010-10-17 21:40:46
对当前日期增加4个月
SQL> select sysdate, add_months(sysdate,4) from dual ;

SYSDATE             ADD_MONTHS(SYSDATE,
——————- ——————-
2010-10-14 21:41:43 2011-02-14 21:41:43

当前日期增加2年
SQL> select sysdate, add_months(sysdate,12*2) from dual ;

SYSDATE             ADD_MONTHS(SYSDATE,
——————- ——————-
2010-10-14 21:42:17 2012-10-14 21:42:17

timestamp的操作方法与上面类似;
求两个日期之差:
例:求2007-5-23 21:23:34与当前时间之间的差值。
SQL> select sysdate-to_date(’20070523 21:23:34′,’yyyy-mm-dd hh24:mi:ss’) dt from
dual ;

DT
———-
1240.01623
如果两个日期直接相减,得到的结果是一个数据型,我们可能想要得到两个日期相差值表现形式为:
**年**月**日 **:**:**
SQL> SELECT NUMTOYMINTERVAL(MONTHS_BETWEEN(DT1, DT2), ‘month’) mon,
2         numtodsinterval(dt1-(add_months(dt2,trunc(MONTHS_BETWEEN(DT1, DT2)))
),’day’) DAY
3    FROM (SELECT SYSDATE DT1,
4                 TO_DATE(’20070523 21:23:34′, ‘yyyy-mm-dd hh24:mi:ss’) DT2
5          FROM DUAL)
6 ;

MON                  DAY
—————-     ———————-
+000000003-04        +000000021 00:40:15.999999999

即:3年 4 个月 21 天 00:40:15.99999999 查看全部


无论是DATE还是timestamp都可以进行加减操作。
可以对当前日期加年、月、日、时、分、秒,操作不同的时间类型,有三种方法:

1 使用内置函数numtodsinterval增加小时,分钟和秒
2 加一个简单的数来增加天
3 使用内置函数add_months来增加年和月

例:
对当前日期增加一个小时:
SQL> select sysdate, sysdate+numtodsinterval(1,’hour’) from dual ;

SYSDATE             SYSDATE+NUMTODSINTE
——————- ——————-
2010-10-14 21:38:19 2010-10-14 22:38:19
对当前日期增加50分种
SQL> select sysdate, sysdate+numtodsinterval(50,’minute’) from dual ;

SYSDATE             SYSDATE+NUMTODSINTE
——————- ——————-
2010-10-14 21:39:12 2010-10-14 22:29:12
对当前日期增加45秒
SQL> select sysdate, sysdate+numtodsinterval(45,’second’) from dual ;

SYSDATE             SYSDATE+NUMTODSINTE
——————- ——————-
2010-10-14 21:40:06 2010-10-14 21:40:51
对当前日期增加3天
SQL> select sysdate, sysdate+3 from dual ;

SYSDATE             SYSDATE+3
——————- ——————-
2010-10-14 21:40:46 2010-10-17 21:40:46
对当前日期增加4个月
SQL> select sysdate, add_months(sysdate,4) from dual ;

SYSDATE             ADD_MONTHS(SYSDATE,
——————- ——————-
2010-10-14 21:41:43 2011-02-14 21:41:43

当前日期增加2年
SQL> select sysdate, add_months(sysdate,12*2) from dual ;

SYSDATE             ADD_MONTHS(SYSDATE,
——————- ——————-
2010-10-14 21:42:17 2012-10-14 21:42:17

timestamp的操作方法与上面类似;
求两个日期之差:
例:求2007-5-23 21:23:34与当前时间之间的差值。
SQL> select sysdate-to_date(’20070523 21:23:34′,’yyyy-mm-dd hh24:mi:ss’) dt from
dual ;

DT
———-
1240.01623
如果两个日期直接相减,得到的结果是一个数据型,我们可能想要得到两个日期相差值表现形式为:
**年**月**日 **:**:**
SQL> SELECT NUMTOYMINTERVAL(MONTHS_BETWEEN(DT1, DT2), ‘month’) mon,
2         numtodsinterval(dt1-(add_months(dt2,trunc(MONTHS_BETWEEN(DT1, DT2)))
),’day’) DAY
3    FROM (SELECT SYSDATE DT1,
4                 TO_DATE(’20070523 21:23:34′, ‘yyyy-mm-dd hh24:mi:ss’) DT2
5          FROM DUAL)
6 ;

MON                  DAY
—————-     ———————-
+000000003-04        +000000021 00:40:15.999999999

即:3年 4 个月 21 天 00:40:15.99999999

令人难以理解的软件工程师:几千行代码能搞定的为什么要写几万行?【转]

admin 发表了文章 • 0 个评论 • 82 次浏览 • 2018-04-09 11:57 • 来自相关话题



我们公司的 Windows 版软体已经有十多年的历史,经过历代工程师的整治之后,内容已经凌乱不堪。过去三个月,我找时间自己重写了整个主程序。原本数万行的程序,被我重写的只剩下数千行,功能不变,效能更好,而且架构俨然。

前几天完成 Alpha 版之后,我不禁开怀大笑,笑声惊动整个办公室。

 



在重写这个程序的这段期间,前两个月,我每周花在这个程序上的时间应该不会超过四个小时。后来我趁着农历新年没事干,跑到公司加班数天,但是一天写程序的时间也不会超过四个小时。




通常我白天写两、三个小时的程序,遇到瓶颈就去忙别的事,或者干脆回家吃晚饭,晚上睡觉前,躺在床上用手机查一下资料,第二天上班走在路上,就会很自然的想到不错的解法。




写程序是一种创作,不是做苦工,不能每天在电脑前面枯坐十几个小时,否则超时工作,只会让自己的脑筋变得更糊涂。




我所认识的许多写程序高手,每天写程序的时间都不会太长。

 



1995 年的时候,有一天在美国盐湖城,我陪着趋势科技的创办人张明正扶着他爸爸过马路,他突然跟我说:「宜敬,我实在搞不懂,在软体这个行业,一个优秀的工程师的产出可以轻易抵得上一、二十个平庸的工程师,但是公司最多只要付他两、三倍的薪水。那为什么还有公司愿意付钱雇用那些很平庸的工程师呢?」




当时我博士刚毕业,当然不知道要如何回答他的问题;而现在过了这么多年,我还是不知道要如何回答那个问题。




而当时张明正会问我那个问题,应该是因为我介绍了几位同学跟朋友到趋势科技工作。那几位都是以一当十、以一当百的高手。趋势科技当时没有给他们十倍、百倍的薪水,但是对他们也不薄,给了他们不少的股票。




后来趋势在日本上市,我那几位朋友都成了亿万富翁,财富应该超过一般工程师的十倍、百倍吧?

 



写一个大型程序,并不是「人多好办事」。

如果是土木工程或是制造业,人越多、产出就越大。如果一个计画延误了,就多调一些人手过来帮忙。

但是在软体工程里,人越多,就越是难以协调,写出来的程序也往往品质越差、效能越糟糕。

这就是有名的”The Mythical Man-Month: Addingmanpower to a late software project makes it later"。

IBM在1960年代开发OS/360作业系统软体时,就发现了这个奇特的现象。

所以我也搞不懂,大型软体公司雇用了那么多的软体工程师干嘛?

 



我在当兵的时候,有一阵子在台中十军团的资讯中心担任资讯官。那时候我手下有两名资讯科系毕业的大专兵,但是我嫌他们两人写程序写的太慢,而解释给他们听更是费事,还不如我自己动手写比较快。

所以我就叫他们到一边凉快,所有的程序都由我来写就好。而他们两人觉得很不好意思,就泡了很好喝的奶茶给我喝。

后来我们成了很好的朋友。

 



写程序并不是写的越长越好、越厉害。

我年轻在台大资讯工程系的时候,会跟朋友炫耀说:「我写的程序语言编译程序,总共有一万多行耶。」

后来我去美国布朗大学读电脑科学博士,毕业的时候喜欢跟朋友炫耀:「我的博士论文那个程序,功能那么强大,但是我只用了七、八千行程序就搞定了耶。」

 



二流的软体工程师,喜欢把简单的问题弄的复杂,写出别人看不懂的程序。

一流的软体工程师,喜欢把复杂的问题简单化,写出架构清楚明白的程序,让人看了之后,觉得问题好像很简单。

三流的软体工程师会去崇拜二流的软体工程师,因为他们会觉得二流工程师写的程序都看不懂,一定是超级厉害;

三流的软体工程师不会去崇拜一流的软体工程师,因为他们会觉得一流工程师所做的事情都很好懂,好像都很简单。

只有一流的的软体工程师才会佩服一流的软体工程师,因为只有他们才能看的出来,其他的一流软体工程师厉害在哪里?

台湾的软体业如此,美国的软体业也大致如此。

 



直到1980年代末期,IBM一直是世界上最大的电脑公司。而当时 IBM 找了一些原来是做硬体制造的高阶主管来管软体部门。

那些高阶主管依照他们管理制造部门的经验,决定用KLOC (thousands linesof code),也就是每位软体工程师每年写出多少行程序来计算软体部门的效率。

结果软体工程师们都「短话长说」,写出一堆落落长又没有效率的软体程序。

 



要成为一流的软体工程师,必须熟悉了解电脑科学的各种基础理论,也必须累积长时间的实务经验。

我在布朗大学电脑科学系读博士修课的时候,程序作业的份量非常重。上作业系统(OperatingSystem)课的时候,教授要我们每个人独立写一个包含File System与 Process System的迷你Unix作业系统;

上编译程序(Compiler)课的时候,教授要我们每个人独立写一个 Compiler,而且每一个模组还必须用两个以上的方法写,然后互相比较;

而上 Andy Van Dam 教授的电脑图学,那简直就是人间炼狱。当时助教发问卷调查,发现每位学生每周花在写那堂课的程序的平均时间超过四十个小时,学生们几乎要群起造反。

但是修过上述那三门课而没有被当掉、又拿高分的,就成了懂理论又懂写程序的高手、高高手。

 



当年我在布朗大学读博士的时候,我估计我们系上像我这种等级的写程序高手,大概有十来个吧?

但是我们系上公认最厉害的写程序高手,还是我的指导教授 Prof. SteveReiss。他一个人大概抵得上五到十个我们这种等级的工程师。

关于他的传说很多。有一次我去他的办公室找他,看到他正在玩接龙游戏。他被我发现了,有点不好意思,赶紧跟我说,他觉得 Windows 上的接龙游戏很好玩,但是他没有 Windows 电脑,所以就花了四、五天,利用零散的时间在他自己的 Sun Work Station 上面写了一个类似的接龙游戏,包含彩色的图像接口等等。

想玩电玩就自己写一个?我很想笑,但又差点在我师父面前跪了下来。

 

十一

我在布朗大学认识的那些软体高手,后来真正以写程序为志业,然后写出伟大又广泛被使用的程序的,应该不多。

因为有些人后来去当大学教授,教授通常是不会自己写程序的。久了之后,我不知道他们的功力剩下多少?

有些人后来为了拿高薪,去一些大公司写一些很没营养又很无趣的程序。久了之后,我不知道他们的功力剩下多少?

有些人后来进入产业界工作,没多久就升上了管理职,而管理职人员通常是不会自己写程序的。久了之后,我不知道他们的功力剩下多少?

所以程序高手原本就不多,而一直继续在写程序的程序高手就更是稀有了。

 

十二

美国的软体业有一个老笑话:如果有两个工程师在同一个团队,一个很会写程序,另一个很不会写程序,那后来升上经理的,一定是那个不会写程序的。

因为团队需要那个会写程序的留下来写程序。

 

十三

我写程序的功力最高的时候,应该是二十多年前我刚拿到博士的时候,那时候我又懂理论、又累积了大量的写程序经验。我不敢说自己能以一当百,但是以一当十应该是绰绰有馀的。

只可惜,没多久之后我就升上了管理职,而当上了经理、协理、总经理之后,如果还自己写程序的话,那是会被别人笑的。

所以我就不再写程序了,而且我也学会,要在自己的部门多摆一些工程师,否则阵仗不够大,会被别的部门瞧不起,也会被我的上司瞧不起。

二十年下来,我的功力大概只剩下两三成。

 

十四

我现在终于自己当了老板。而当上了老板之后,最大好处之一,就是我高兴写程序就可以写程序。就算有人要笑我,我也可以不理他们。

 

十五

我趁过年期间重写了我们公司的 Windows 主程序,完成之后,自觉功力已经恢复到当年的三、四成,不禁大乐。

不过我还是觉得,软体工程还真是一门很难以理解的行业。虽然我本身就是一个软体工程师,虽然我的博士论文研究的就是程序开发环境(Programming Environment),主题就是我在这边所说的这些问题。 查看全部


我们公司的 Windows 版软体已经有十多年的历史,经过历代工程师的整治之后,内容已经凌乱不堪。过去三个月,我找时间自己重写了整个主程序。原本数万行的程序,被我重写的只剩下数千行,功能不变,效能更好,而且架构俨然。

前几天完成 Alpha 版之后,我不禁开怀大笑,笑声惊动整个办公室。

 



在重写这个程序的这段期间,前两个月,我每周花在这个程序上的时间应该不会超过四个小时。后来我趁着农历新年没事干,跑到公司加班数天,但是一天写程序的时间也不会超过四个小时。




通常我白天写两、三个小时的程序,遇到瓶颈就去忙别的事,或者干脆回家吃晚饭,晚上睡觉前,躺在床上用手机查一下资料,第二天上班走在路上,就会很自然的想到不错的解法。




写程序是一种创作,不是做苦工,不能每天在电脑前面枯坐十几个小时,否则超时工作,只会让自己的脑筋变得更糊涂。




我所认识的许多写程序高手,每天写程序的时间都不会太长。

 



1995 年的时候,有一天在美国盐湖城,我陪着趋势科技的创办人张明正扶着他爸爸过马路,他突然跟我说:「宜敬,我实在搞不懂,在软体这个行业,一个优秀的工程师的产出可以轻易抵得上一、二十个平庸的工程师,但是公司最多只要付他两、三倍的薪水。那为什么还有公司愿意付钱雇用那些很平庸的工程师呢?」




当时我博士刚毕业,当然不知道要如何回答他的问题;而现在过了这么多年,我还是不知道要如何回答那个问题。




而当时张明正会问我那个问题,应该是因为我介绍了几位同学跟朋友到趋势科技工作。那几位都是以一当十、以一当百的高手。趋势科技当时没有给他们十倍、百倍的薪水,但是对他们也不薄,给了他们不少的股票。




后来趋势在日本上市,我那几位朋友都成了亿万富翁,财富应该超过一般工程师的十倍、百倍吧?

 



写一个大型程序,并不是「人多好办事」。

如果是土木工程或是制造业,人越多、产出就越大。如果一个计画延误了,就多调一些人手过来帮忙。

但是在软体工程里,人越多,就越是难以协调,写出来的程序也往往品质越差、效能越糟糕。

这就是有名的”The Mythical Man-Month: Addingmanpower to a late software project makes it later"。

IBM在1960年代开发OS/360作业系统软体时,就发现了这个奇特的现象。

所以我也搞不懂,大型软体公司雇用了那么多的软体工程师干嘛?

 



我在当兵的时候,有一阵子在台中十军团的资讯中心担任资讯官。那时候我手下有两名资讯科系毕业的大专兵,但是我嫌他们两人写程序写的太慢,而解释给他们听更是费事,还不如我自己动手写比较快。

所以我就叫他们到一边凉快,所有的程序都由我来写就好。而他们两人觉得很不好意思,就泡了很好喝的奶茶给我喝。

后来我们成了很好的朋友。

 



写程序并不是写的越长越好、越厉害。

我年轻在台大资讯工程系的时候,会跟朋友炫耀说:「我写的程序语言编译程序,总共有一万多行耶。」

后来我去美国布朗大学读电脑科学博士,毕业的时候喜欢跟朋友炫耀:「我的博士论文那个程序,功能那么强大,但是我只用了七、八千行程序就搞定了耶。」

 



二流的软体工程师,喜欢把简单的问题弄的复杂,写出别人看不懂的程序。

一流的软体工程师,喜欢把复杂的问题简单化,写出架构清楚明白的程序,让人看了之后,觉得问题好像很简单。

三流的软体工程师会去崇拜二流的软体工程师,因为他们会觉得二流工程师写的程序都看不懂,一定是超级厉害;

三流的软体工程师不会去崇拜一流的软体工程师,因为他们会觉得一流工程师所做的事情都很好懂,好像都很简单。

只有一流的的软体工程师才会佩服一流的软体工程师,因为只有他们才能看的出来,其他的一流软体工程师厉害在哪里?

台湾的软体业如此,美国的软体业也大致如此。

 



直到1980年代末期,IBM一直是世界上最大的电脑公司。而当时 IBM 找了一些原来是做硬体制造的高阶主管来管软体部门。

那些高阶主管依照他们管理制造部门的经验,决定用KLOC (thousands linesof code),也就是每位软体工程师每年写出多少行程序来计算软体部门的效率。

结果软体工程师们都「短话长说」,写出一堆落落长又没有效率的软体程序。

 



要成为一流的软体工程师,必须熟悉了解电脑科学的各种基础理论,也必须累积长时间的实务经验。

我在布朗大学电脑科学系读博士修课的时候,程序作业的份量非常重。上作业系统(OperatingSystem)课的时候,教授要我们每个人独立写一个包含File System与 Process System的迷你Unix作业系统;

上编译程序(Compiler)课的时候,教授要我们每个人独立写一个 Compiler,而且每一个模组还必须用两个以上的方法写,然后互相比较;

而上 Andy Van Dam 教授的电脑图学,那简直就是人间炼狱。当时助教发问卷调查,发现每位学生每周花在写那堂课的程序的平均时间超过四十个小时,学生们几乎要群起造反。

但是修过上述那三门课而没有被当掉、又拿高分的,就成了懂理论又懂写程序的高手、高高手。

 



当年我在布朗大学读博士的时候,我估计我们系上像我这种等级的写程序高手,大概有十来个吧?

但是我们系上公认最厉害的写程序高手,还是我的指导教授 Prof. SteveReiss。他一个人大概抵得上五到十个我们这种等级的工程师。

关于他的传说很多。有一次我去他的办公室找他,看到他正在玩接龙游戏。他被我发现了,有点不好意思,赶紧跟我说,他觉得 Windows 上的接龙游戏很好玩,但是他没有 Windows 电脑,所以就花了四、五天,利用零散的时间在他自己的 Sun Work Station 上面写了一个类似的接龙游戏,包含彩色的图像接口等等。

想玩电玩就自己写一个?我很想笑,但又差点在我师父面前跪了下来。

 

十一

我在布朗大学认识的那些软体高手,后来真正以写程序为志业,然后写出伟大又广泛被使用的程序的,应该不多。

因为有些人后来去当大学教授,教授通常是不会自己写程序的。久了之后,我不知道他们的功力剩下多少?

有些人后来为了拿高薪,去一些大公司写一些很没营养又很无趣的程序。久了之后,我不知道他们的功力剩下多少?

有些人后来进入产业界工作,没多久就升上了管理职,而管理职人员通常是不会自己写程序的。久了之后,我不知道他们的功力剩下多少?

所以程序高手原本就不多,而一直继续在写程序的程序高手就更是稀有了。

 

十二

美国的软体业有一个老笑话:如果有两个工程师在同一个团队,一个很会写程序,另一个很不会写程序,那后来升上经理的,一定是那个不会写程序的。

因为团队需要那个会写程序的留下来写程序。

 

十三

我写程序的功力最高的时候,应该是二十多年前我刚拿到博士的时候,那时候我又懂理论、又累积了大量的写程序经验。我不敢说自己能以一当百,但是以一当十应该是绰绰有馀的。

只可惜,没多久之后我就升上了管理职,而当上了经理、协理、总经理之后,如果还自己写程序的话,那是会被别人笑的。

所以我就不再写程序了,而且我也学会,要在自己的部门多摆一些工程师,否则阵仗不够大,会被别的部门瞧不起,也会被我的上司瞧不起。

二十年下来,我的功力大概只剩下两三成。

 

十四

我现在终于自己当了老板。而当上了老板之后,最大好处之一,就是我高兴写程序就可以写程序。就算有人要笑我,我也可以不理他们。

 

十五

我趁过年期间重写了我们公司的 Windows 主程序,完成之后,自觉功力已经恢复到当年的三、四成,不禁大乐。

不过我还是觉得,软体工程还真是一门很难以理解的行业。虽然我本身就是一个软体工程师,虽然我的博士论文研究的就是程序开发环境(Programming Environment),主题就是我在这边所说的这些问题。

ORACLE函数获取汉字拼音首字母

admin 发表了文章 • 0 个评论 • 108 次浏览 • 2018-04-09 09:49 • 来自相关话题

/*------增加:yl--*/
oracle 中 NLSSORT函数的用法

NLSSORT(),用来进行语言排序

拼音
SELECT * FROM TEAM ORDER BY NLSSORT(排序字段名,'NLS_SORT = SCHINESE_PINYIN_M')
笔划
SELECT * FROM TEAM ORDER BY NLSSORT(排序字段名,'NLS_SORT = SCHINESE_STROKE_M')
部首
SELECT * FROM TEAM ORDER BY NLSSORT(排序字段名,'NLS_SORT = SCHINESE_RADICAL_M')
/*------增加:yl end--*/

列表一行汉字
WITH A AS
(SELECT '获取汉字拼音首字母' W FROM DUAL)
SELECT SUBSTR(W, ROWNUM, 1) FROM A
CONNECT BY ROWNUM <= (SELECT LENGTH(W) FROM A);
返回结果










用汉字字符集对这个列表进行排序
WITH A AS
(SELECT '获取汉字拼音首字母' W FROM DUAL)
SELECT SUBSTR(W, ROWNUM, 1) FROM A
CONNECT BY ROWNUM <= (SELECT LENGTH(W) FROM A)
ORDER BY NLSSORT(SUBSTR(W, ROWNUM, 1), 'NLS_SORT=SCHINESE_PINYIN_M');
返回结果










那么根据这个原理,上面输入一个拼音A打头的字"澳",后面输入一个B大头的字"吧",找到每个音节的起止的汉字是哪个
WITH A AS
(
SELECT ROWNUM RN, CHR(ROWNUM) C FROM DUAL CONNECT BY LEVEL <= 65535
)
SELECT * FROM A WHERE LENGTHB(C) = 2
AND RN > 32768
AND NLSSORT(C, 'NLS_SORT=SCHINESE_PINYIN_M') > NLSSORT('澳', 'NLS_SORT=SCHINESE_PINYIN_M')
AND NLSSORT(C, 'NLS_SORT=SCHINESE_PINYIN_M') < NLSSORT('吧', 'NLS_SORT=SCHINESE_PINYIN_M')
ORDER BY NLSSORT(C, 'NLS_SORT=SCHINESE_PINYIN_M');
根据返回的结果,就能看到,A的结束和B的开始的汉子分别是:“驁” “八”,依次类推可以找到其他的分界点,那么最后的函数就是如下:

CREATE OR REPLACE FUNCTION F_TRANS_PINYIN_CAPITAL(P_NAME IN VARCHAR2) RETURN VARCHAR2 AS
V_COMPARE VARCHAR2(100);
V_RETURN VARCHAR2(4000);

FUNCTION F_NLSSORT(P_WORD IN VARCHAR2) RETURN VARCHAR2 AS
BEGIN
RETURN NLSSORT(P_WORD, 'NLS_SORT=SCHINESE_PINYIN_M');
END;
BEGIN
FOR I IN 1..LENGTH(P_NAME) LOOP
V_COMPARE := F_NLSSORT(SUBSTR(P_NAME, I, 1));
IF V_COMPARE >= F_NLSSORT(' 吖 ') AND V_COMPARE <= F_NLSSORT('驁 ') THEN
V_RETURN := V_RETURN || 'a';
ELSIF V_COMPARE >= F_NLSSORT('八 ') AND V_COMPARE <= F_NLSSORT('簿 ') THEN
V_RETURN := V_RETURN || 'b';
ELSIF V_COMPARE >= F_NLSSORT('嚓 ') AND V_COMPARE <= F_NLSSORT('錯 ') THEN
V_RETURN := V_RETURN || 'c';
ELSIF V_COMPARE >= F_NLSSORT('咑 ') AND V_COMPARE <= F_NLSSORT('鵽 ') THEN
V_RETURN := V_RETURN || 'd';
ELSIF V_COMPARE >= F_NLSSORT('妸 ') AND V_COMPARE <= F_NLSSORT('樲 ') THEN
V_RETURN := V_RETURN || 'e';
ELSIF V_COMPARE >= F_NLSSORT('发 ') AND V_COMPARE <= F_NLSSORT('猤 ') THEN
V_RETURN := V_RETURN || 'f';
ELSIF V_COMPARE >= F_NLSSORT('旮 ') AND V_COMPARE <= F_NLSSORT('腂 ') THEN
V_RETURN := V_RETURN || 'g';
ELSIF V_COMPARE >= F_NLSSORT('妎 ') AND V_COMPARE <= F_NLSSORT('夻 ') THEN
V_RETURN := V_RETURN || 'h';
ELSIF V_COMPARE >= F_NLSSORT('丌 ') AND V_COMPARE <= F_NLSSORT('攈 ') THEN
V_RETURN := V_RETURN || 'j';
ELSIF V_COMPARE >= F_NLSSORT('咔 ') AND V_COMPARE <= F_NLSSORT('穒 ') THEN
V_RETURN := V_RETURN || 'k';
ELSIF V_COMPARE >= F_NLSSORT('垃 ') AND V_COMPARE <= F_NLSSORT('擽 ') THEN
V_RETURN := V_RETURN || 'l';
ELSIF V_COMPARE >= F_NLSSORT('嘸 ') AND V_COMPARE <= F_NLSSORT('椧 ') THEN
V_RETURN := V_RETURN || 'm';
ELSIF V_COMPARE >= F_NLSSORT('拏 ') AND V_COMPARE <= F_NLSSORT('瘧 ') THEN
V_RETURN := V_RETURN || 'n';
ELSIF V_COMPARE >= F_NLSSORT('筽 ') AND V_COMPARE <= F_NLSSORT('漚 ') THEN
V_RETURN := V_RETURN || 'o';
ELSIF V_COMPARE >= F_NLSSORT('妑 ') AND V_COMPARE <= F_NLSSORT('曝 ') THEN
V_RETURN := V_RETURN || 'p';
ELSIF V_COMPARE >= F_NLSSORT('七 ') AND V_COMPARE <= F_NLSSORT('裠 ') THEN
V_RETURN := V_RETURN || 'q';
ELSIF V_COMPARE >= F_NLSSORT('亽 ') AND V_COMPARE <= F_NLSSORT('鶸 ') THEN
V_RETURN := V_RETURN || 'r';
ELSIF V_COMPARE >= F_NLSSORT('仨 ') AND V_COMPARE <= F_NLSSORT('蜶 ') THEN
V_RETURN := V_RETURN || 's';
ELSIF V_COMPARE >= F_NLSSORT('侤 ') AND V_COMPARE <= F_NLSSORT('籜 ') THEN
V_RETURN := V_RETURN || 't';
ELSIF V_COMPARE >= F_NLSSORT('屲 ') AND V_COMPARE <= F_NLSSORT('鶩 ') THEN
V_RETURN := V_RETURN || 'w';
ELSIF V_COMPARE >= F_NLSSORT('夕 ') AND V_COMPARE <= F_NLSSORT('鑂 ') THEN
V_RETURN := V_RETURN || 'x';
ELSIF V_COMPARE >= F_NLSSORT('丫 ') AND V_COMPARE <= F_NLSSORT('韻 ') THEN
V_RETURN := V_RETURN || 'y';
ELSIF V_COMPARE >= F_NLSSORT('帀 ') AND V_COMPARE <= F_NLSSORT('咗 ') THEN
V_RETURN := V_RETURN || 'z';
END IF;
END LOOP;
RETURN V_RETURN;
END;

测试一下:
SELECT F_TRANS_PINYIN_CAPITAL('罗华') FROM DUAL  
返回 lh
使用的时候这样查询:
select name from users t1 where (t1.name = ? or F_TRANS_PINYIN_CAPITAL(t1.name) = ?)
如果里面的?参数传递的是“罗华”,就是查询用户名是落花的人,如果传递的是lh的话,查询的就是拼音是lh的人 查看全部

/*------增加:yl--*/
oracle 中 NLSSORT函数的用法

NLSSORT(),用来进行语言排序

拼音
SELECT * FROM TEAM ORDER BY NLSSORT(排序字段名,'NLS_SORT = SCHINESE_PINYIN_M')
笔划
SELECT * FROM TEAM ORDER BY NLSSORT(排序字段名,'NLS_SORT = SCHINESE_STROKE_M')
部首
SELECT * FROM TEAM ORDER BY NLSSORT(排序字段名,'NLS_SORT = SCHINESE_RADICAL_M')
/*------增加:yl end--*/

列表一行汉字
WITH A AS
(SELECT '获取汉字拼音首字母' W FROM DUAL)
SELECT SUBSTR(W, ROWNUM, 1) FROM A
CONNECT BY ROWNUM <= (SELECT LENGTH(W) FROM A);
返回结果










用汉字字符集对这个列表进行排序
WITH A AS
(SELECT '获取汉字拼音首字母' W FROM DUAL)
SELECT SUBSTR(W, ROWNUM, 1) FROM A
CONNECT BY ROWNUM <= (SELECT LENGTH(W) FROM A)
ORDER BY NLSSORT(SUBSTR(W, ROWNUM, 1), 'NLS_SORT=SCHINESE_PINYIN_M');
返回结果










那么根据这个原理,上面输入一个拼音A打头的字"澳",后面输入一个B大头的字"吧",找到每个音节的起止的汉字是哪个
WITH A AS
(
SELECT ROWNUM RN, CHR(ROWNUM) C FROM DUAL CONNECT BY LEVEL <= 65535
)
SELECT * FROM A WHERE LENGTHB(C) = 2
AND RN > 32768
AND NLSSORT(C, 'NLS_SORT=SCHINESE_PINYIN_M') > NLSSORT('澳', 'NLS_SORT=SCHINESE_PINYIN_M')
AND NLSSORT(C, 'NLS_SORT=SCHINESE_PINYIN_M') < NLSSORT('吧', 'NLS_SORT=SCHINESE_PINYIN_M')
ORDER BY NLSSORT(C, 'NLS_SORT=SCHINESE_PINYIN_M');
根据返回的结果,就能看到,A的结束和B的开始的汉子分别是:“驁” “八”,依次类推可以找到其他的分界点,那么最后的函数就是如下:

CREATE OR REPLACE FUNCTION F_TRANS_PINYIN_CAPITAL(P_NAME IN VARCHAR2) RETURN VARCHAR2 AS
V_COMPARE VARCHAR2(100);
V_RETURN VARCHAR2(4000);

FUNCTION F_NLSSORT(P_WORD IN VARCHAR2) RETURN VARCHAR2 AS
BEGIN
RETURN NLSSORT(P_WORD, 'NLS_SORT=SCHINESE_PINYIN_M');
END;
BEGIN
FOR I IN 1..LENGTH(P_NAME) LOOP
V_COMPARE := F_NLSSORT(SUBSTR(P_NAME, I, 1));
IF V_COMPARE >= F_NLSSORT(' 吖 ') AND V_COMPARE <= F_NLSSORT('驁 ') THEN
V_RETURN := V_RETURN || 'a';
ELSIF V_COMPARE >= F_NLSSORT('八 ') AND V_COMPARE <= F_NLSSORT('簿 ') THEN
V_RETURN := V_RETURN || 'b';
ELSIF V_COMPARE >= F_NLSSORT('嚓 ') AND V_COMPARE <= F_NLSSORT('錯 ') THEN
V_RETURN := V_RETURN || 'c';
ELSIF V_COMPARE >= F_NLSSORT('咑 ') AND V_COMPARE <= F_NLSSORT('鵽 ') THEN
V_RETURN := V_RETURN || 'd';
ELSIF V_COMPARE >= F_NLSSORT('妸 ') AND V_COMPARE <= F_NLSSORT('樲 ') THEN
V_RETURN := V_RETURN || 'e';
ELSIF V_COMPARE >= F_NLSSORT('发 ') AND V_COMPARE <= F_NLSSORT('猤 ') THEN
V_RETURN := V_RETURN || 'f';
ELSIF V_COMPARE >= F_NLSSORT('旮 ') AND V_COMPARE <= F_NLSSORT('腂 ') THEN
V_RETURN := V_RETURN || 'g';
ELSIF V_COMPARE >= F_NLSSORT('妎 ') AND V_COMPARE <= F_NLSSORT('夻 ') THEN
V_RETURN := V_RETURN || 'h';
ELSIF V_COMPARE >= F_NLSSORT('丌 ') AND V_COMPARE <= F_NLSSORT('攈 ') THEN
V_RETURN := V_RETURN || 'j';
ELSIF V_COMPARE >= F_NLSSORT('咔 ') AND V_COMPARE <= F_NLSSORT('穒 ') THEN
V_RETURN := V_RETURN || 'k';
ELSIF V_COMPARE >= F_NLSSORT('垃 ') AND V_COMPARE <= F_NLSSORT('擽 ') THEN
V_RETURN := V_RETURN || 'l';
ELSIF V_COMPARE >= F_NLSSORT('嘸 ') AND V_COMPARE <= F_NLSSORT('椧 ') THEN
V_RETURN := V_RETURN || 'm';
ELSIF V_COMPARE >= F_NLSSORT('拏 ') AND V_COMPARE <= F_NLSSORT('瘧 ') THEN
V_RETURN := V_RETURN || 'n';
ELSIF V_COMPARE >= F_NLSSORT('筽 ') AND V_COMPARE <= F_NLSSORT('漚 ') THEN
V_RETURN := V_RETURN || 'o';
ELSIF V_COMPARE >= F_NLSSORT('妑 ') AND V_COMPARE <= F_NLSSORT('曝 ') THEN
V_RETURN := V_RETURN || 'p';
ELSIF V_COMPARE >= F_NLSSORT('七 ') AND V_COMPARE <= F_NLSSORT('裠 ') THEN
V_RETURN := V_RETURN || 'q';
ELSIF V_COMPARE >= F_NLSSORT('亽 ') AND V_COMPARE <= F_NLSSORT('鶸 ') THEN
V_RETURN := V_RETURN || 'r';
ELSIF V_COMPARE >= F_NLSSORT('仨 ') AND V_COMPARE <= F_NLSSORT('蜶 ') THEN
V_RETURN := V_RETURN || 's';
ELSIF V_COMPARE >= F_NLSSORT('侤 ') AND V_COMPARE <= F_NLSSORT('籜 ') THEN
V_RETURN := V_RETURN || 't';
ELSIF V_COMPARE >= F_NLSSORT('屲 ') AND V_COMPARE <= F_NLSSORT('鶩 ') THEN
V_RETURN := V_RETURN || 'w';
ELSIF V_COMPARE >= F_NLSSORT('夕 ') AND V_COMPARE <= F_NLSSORT('鑂 ') THEN
V_RETURN := V_RETURN || 'x';
ELSIF V_COMPARE >= F_NLSSORT('丫 ') AND V_COMPARE <= F_NLSSORT('韻 ') THEN
V_RETURN := V_RETURN || 'y';
ELSIF V_COMPARE >= F_NLSSORT('帀 ') AND V_COMPARE <= F_NLSSORT('咗 ') THEN
V_RETURN := V_RETURN || 'z';
END IF;
END LOOP;
RETURN V_RETURN;
END;

测试一下:
SELECT F_TRANS_PINYIN_CAPITAL('罗华') FROM DUAL  
返回 lh
使用的时候这样查询:
select name from users t1 where (t1.name = ? or F_TRANS_PINYIN_CAPITAL(t1.name) = ?)
如果里面的?参数传递的是“罗华”,就是查询用户名是落花的人,如果传递的是lh的话,查询的就是拼音是lh的人