SQL语句集锦

/*
  数据库简介
*/
/*
  关系型数据库
*/
(1) 一个关系型数据库就是由二维表及其之间的联系组成的一个数据组织.下面列出了关系模型中的常用概念:
关系    : 可以理解为一张二维表,每个关系都具有一个关系名,就是通常说的表名.
元组    : 可以理解为二维表中的一行,在数据库中经常被称为记录.
属性    : 可以理解为二维表中的一列,在数据库中经常被称为字段.
域      : 属性的取值范围,也就是数据库中某一列的取值限制.
关键字  : 一组可以唯一标识元组的属性;数据库中常称为主键,由一个或多个列组成.
关系模式: 指对关系的描述,其格式为:关系名(属性1,属性2,...,属性N).在数据库中通常称为表结构.

(2) 简单理解,关系型数据库以行和列的形式存储数据.这一系列的行和列被称为表,一组表组成了数据库.用户用查询(Query)来检索数据库中的数据.一个Query是一个用于指定数据库中行和列的SELECT语句.
关系型数据库通常包含下列组件: 

. 客户端应用程序(Client) 
. 数据库服务器(Server) 
. 数据库(Database) 

Structured Query Language(SQL),客户端和服务器端的桥梁,客户端用SQL来向服务器端发送请求,服务器返回客户端要求的结果.
现在流行的大型关系型数据库有IBM DB2,Oracle,SQL Server,SyBase,Informix等.

/*
  关系型数据库的三个范式
*/
构造数据库必须遵循一定的规则.在关系数据库中,这种规则就是范式.范式是符合某一种级别的关系模式的集合.
关系数据库中的关系必须满足一定的要求,即满足不同的范式.目前关系数据库有六种范式:第一范式(1NF),第二范式(2NF),第三范式(3NF),第四范式(4NF),第五范式(5NF)和第六范式(6NF).
满足最低要求的范式是第一范式(1NF),在第一范式的基础上进一步满足更多要求的称为第二范式(2NF),其余范式以次类推.一般说来,数据库只需满足第三范式(3NF)就行了.

第一范式(1NF): 指数据库表的每一列都是不可分割的基本数据项,同一列中不能有多个值.简而言之,第一范式就是无重复的列.
第二范式(2NF): 必须先满足第一范式(1NF).第二范式(2NF)要求数据库表中的每个实例或行必须可以被惟一地区分.简而言之,第二范式每个非主属性要完全依赖于主键.
第三范式(3NF): 必须先满足第二范式(2NF).第三范式(3NF)要求一个数据库表中不包含已在其它表中包含的非主键信息.简而言之,第三范式就是属性不依赖于其它非主属性.

/*
  Oracle数据库开发工具
*/
开发基于Oracle数据库的应用程序,主要可以选择两类工具:
1. 通用数据库开发技术,例如:ODBC(Open Database Connectivity 微软提供支持), JDBC(Java Database Connectivity standard Java核心组件)等.
2. Oracle公司提供的专门开发工具,例如:Pro C_C++, OCI(Oracle Call Interface)等.

前者因为是通用技术,开发起来比较容易,但有一个致命的弱点就是速度太慢.相比之下,OCI虽然开发起来难度较大,但它速度极快,而且是一种底层接口,几乎可以操纵Oracle数据库的任何对象.

/*
  SQL语句集锦
*/
/*
  SQL常用语法
*/

--关键字           功 能 
--数据操作 
SELECT             --从数据库表中检索数据行和列 
INSERT             --向数据库表添加新数据行 
DELETE             --从数据库表中删除数据行 
UPDATE             --更新数据库表中的数据

--数据定义
--表 
CREATE TABLE      --创建一个数据库表 
DROP TABLE         --从数据库中删除表 
ALTER TABLE        --修改数据库表结构
--视图 
CREATE VIEW        --创建一个视图      
DROP VIEW          --从数据库中删除视图
--索引  
CREATE INDEX      --为数据库表创建一个索引  
DROP INDEX         --从数据库中删除索引
--过程  
CREATE PROCEDURE   --创建一个存储过程  
DROP PROCEDURE     --从数据库中删除存储过程
--触发器  
CREATE TRIGGER     --创建一个触发器    
DROP TRIGGER       --从数据库中删除触发器
--模式  
CREATE SCHEMA      --向数据库添加一个新模式  
DROP SCHEMA        --从数据库中删除一个模式
--序列
CREATE SEQUENCE    --向数据库添加一个新序列
DROP SEQUENCE      --从数据库中删除一个序列
--值域  
CREATE DOMAIN      --创建一个数据值域 
ALTER DOMAIN       --改变域定义  
DROP DOMAIN        --从数据库中删除一个域 
--数据控制 
GRANT              --授予用户访问权限 
DENY               --拒绝用户访问  
REVOKE             --解除用户访问权限  
--事务控制 
COMMIT             --提交当前事务  
ROLLBACK           --撤销当前事务  
SET TRANSACTION    --定义当前事务数据访问特征  
--程序化SQL 
DECLARE			   --为查询设定游标  
EXPLAIN			   --为查询描述数据访问计划   
OPEN               --检索查询结果打开一个游标 
FETCH              --检索一行查询结果  
CLOSE              --关闭游标
PREPARE            --为动态执行准备SQL语句  
EXECUTE            --动态地执行SQL语句 
DESCRIBE           --描述准备好的查询  
---局部变量 
declare @id char(10) 
--set @id = '10010001' 
select @id = '10010001' 
---全局变量 
---必须以@@开头 

--IF ELSE 
declare @x int @y int @z int 
select @x = 1 @y = 2 @z=3 
if @x > @y 
print 'x > y' --打印字符串'x > y' 
else if @y > @z 
print 'y > z' 
else print 'z > y' 

--CASE 
use pangu 
update employee 
set e_wage = 
case 
  when job_level = '1' then e_wage*1.08 
  when job_level = '2' then e_wage*1.07 
  when job_level = '3' then e_wage*1.06 
  else e_wage*1.05 
end
end
 
--WHILE CONTINUE BREAK 
declare @x int @y int @c int 
select @x = 1 @y=1 
while @x < 3 
begin 
 print @x --
  while @y < 3 
   begin 
    select @c = 100*@x + @y 
  print @c --
    select @y = @y + 1 
  end 
  select @x = @x + 1 
  select @y = 1 
end

--WAITFOR 
--例 等待1 小时2 分零3 秒后才执行SELECT 语句 
waitfor delay '01:02:03' 
select * from employee 
--例 等到晚上11 点零8 分后才执行SELECT 语句 
waitfor time '23:08:00' 
select * from employee
 
--SELECT-- 
select *(列名) from table_name(表名) where column_name operator value 

--ex:
select *from stock_information where stockid = str(nid) 
   stockname = 'str_name' 
   stockname like '% find this %' 
   stockname like '[a-zA-Z]%'       --([]指定值的范围) 
   stockname like '[^F-M]%'        --(^排除指定范围) 
                                    --(只能在使用like关键字的where子句中使用通配符) 
   or stockpath = 'stock_path' 
   or stocknumber < 1000 
   and stockindex = 24 
   not stocksex = 'man' 
   stocknumber between 20 and 100 
   stocknumber in(10,20,30) 
   order by stockid desc(asc)       -- 排序,desc-降序,asc-升序 
   order by 1,2                     -- by列号 
   stockname = (select stockname from stock_information where stockid = 4)  -- 子查询 
                                                                             -- 除非能确保内层select只返回一个行的值,否则应在外层where子句中用一个in限定符 
select distinct column_name from table_name -- distinct指定检索独有的列值,不重复 
select stocknumber ,"stocknumber + 10" = stocknumber + 10 from table_name 
select stockname , count(*) from table_name group by stockname  -- group by 将表按行分组,指定列中有相同的值 
       having count(*) = 2 -- having 
select *from table1, table2   
    where table1.id *= table2.id -- 左外部连接,table1中有的而table2中没有得以NULL表示 
          table1.id =* table2.id -- 右外部连接 

select stockname from table1 
       union [all] -- union合并查询结果集,all-保留重复行 
select stockname from table2 

-- select 查重
select msisdn from radreply GROUP BY msisdn having count(*) > 1;    -- 查询表radreply中msisdn字段的重复记录

--insert-- 
insert into table_name (Stock_name,Stock_number) values ('xxx','xxxx') 
       values (select Stockname , Stocknumber from Stock_table2) --value为select语句 

--update-- 
update table_name set Stockname = "xxx" [where Stockid = 3] 
       tockname = default 
       tockname = NULL 
       tocknumber = Stockname + 4 

--delete-- 
delete from table_name where Stockid = 3 
truncate table_name                            -- 删除表中所有行,仍保持表的完整性 
drop table table_name                          -- 完全删除表 
drop table table_name cascade constraints      -- 忽略约束关系,强制删除表

--alter table-- 
--修改数据库表结构 
alter table database.owner.table_name add column_name char(2) NULL ... 
sp_help table_name -- 显示表已有特征 
create table table_name (name char(20), age smallint, lname varchar(30)) 
insert into table_name select ... -- 实现删除列的方法(创建新表) 
alter table table_name drop constraint Stockname_default -- 删除Stockname的default约束 
alter table table_name drop column column_name -- 删除表中的某一列数据

--表A中某一列B,数据类型为Integrated,需要将其数据类型修改为Vchar,操作方法如下:
--(1)修改表,新建一列C,数据类型为Vchar;
--(2)将列B中数据赋予列C,即 update A set C = B;
--(3)将原列B删除掉;
--(4)将列C重新命名为B;

--function
--常用函数

----统计函数---- 
AVG    --求平均值 
COUNT  --统计数目 
MAX    --求最大值 
MIN    --求最小值 
SUM    --求和 

--AVG 
use pangu 
select avg(e_wage) as dept_avgWage 
from employee 
group by dept_id 

--MAX 
--求工资最高的员工姓名 
use pangu 
select e_name from employee where e_wage = C (select max(e_wage) from employee) 

--STDEV() 
--STDEV()函数返回表达式中所有数据的标准差 

--STDEVP() 
--STDEVP()函数返回总体标准差 
--VAR() 
--VAR()函数返回表达式中所有值的统计变异数 
--VARP() 
--VARP()函数返回总体变异数 

----算术函数---- 
--三角函数-- 
SIN(float_expression)                      --
COS(float_expression)                      --
TAN(float_expression)                      --
COT(float_expression)                      --

--反三角函数--
ASIN(float_expression)                     --返回正弦是FLOAT 值的
ACOS(float_expression)                     --返回余弦是FLOAT 值的
ATAN(float_expression)                     --返回正切是FLOAT 值的
ATAN2(float_expression1,float_expression2) --返回正切是float_expression1/float_expres-sion2
DEGREES(numeric_expression)                --
RADIANS(numeric_expression)                --
EXP(float_expression)                      --返回表达式的指数值 
LOG(float_expression)                      --返回表达式的自然对数值 
LOG10(float_expression)                    --返回表达式的以10 为底的对数值 
SQRT(float_expression)                     --返回表达式的平方根 

--取近似值函数-- 
CEILING(numeric_expression) --返回>=表达式的最小整数返回的数据类型与表达式相同可为 
                        --INTEGER/MONEY/REAL/FLOAT 类型 
FLOOR(numeric_expression)  --返回 <=表达式的最小整数返回的数据类型与表达式相同可为 
                        --INTEGER/MONEY/REAL/FLOAT 类型 
ROUND(numeric_expression)  --返回以integer_expression 为精度的四舍五入值返回的数据 
                        --类型与表达式相同可为INTEGER/MONEY/REAL/FLOAT 类型 
ABS(numeric_expression)   --返回表达式的绝对值返回的数据类型与表达式相同可为 
                        --INTEGER/MONEY/REAL/FLOAT 类型 
SIGN(numeric_expression)    --测试参数的正负号返回0 零值1 正数或-1 负数返回的数据类型 
                        --与表达式相同可为INTEGER/MONEY/REAL/FLOAT 类型 
PI()                     --返回值为π 即3.1415926535897936 
RAND([integer_expression])  --用任选的[integer_expression]做种子值得出0-1 间的随机浮点数 

----字符串函数---- 
ASCII()                 --函数返回字符表达式最左端字符的ASCII 码值 
CHAR()                     --函数用于将ASCII 码转换为字符 
                            --如果没有输入0 ~ 255 之间的ASCII 码值CHAR 函数会返回一个NULL 值 
LOWER()                    --函数把字符串全部转换为小写 
UPPER()                    --函数把字符串全部转换为大写 
STR()                      --函数把数值型数据转换为字符型数据 
LTRIM()                    --函数把字符串头部的空格去掉 
RTRIM()                    --函数把字符串尾部的空格去掉 
LEFT(),RIGHT(),SUBSTRING()  --函数返回部分字符串 
CHARINDEX(),PATINDEX()     --函数返回字符串中某个指定的子串出现的开始位置 
SOUNDEX()                  --函数返回一个四位字符码C 
                          --SOUNDEX函数可用来查找声音相似的字符串但SOUNDEX函数对数字和汉字均只返回0 值 
DIFFERENCE()              --函数返回由SOUNDEX 函数返回的两个字符表达式的值的差异 
                            --0 两个SOUNDEX 函数返回值的第一个字符不同 
                            --1 两个SOUNDEX 函数返回值的第一个字符相同 
                            --2 两个SOUNDEX 函数返回值的第一二个字符相同 
                            --3 两个SOUNDEX 函数返回值的第一二三个字符相同 
                            --4 两个SOUNDEX 函数返回值完全相同 
QUOTENAME()                --函数返回被特定字符括起来的字符串
-- eg: 
select quotename('abc', '{') quotename('abc') 
运行结果如下 
---------------------------------- 
{abc} [abc]*/ 

REPLICATE()               --函数返回一个重复character_expression 指定次数的字符串
-- eg:
select replicate('abc', 3) replicate( 'abc', -2) 
运行结果如下 
----------- ----------- 
abcabcabc NULL*/ 

REVERSE()                --函数将指定的字符串的字符排列顺序颠倒 
REPLACE()                --函数返回被替换了指定子串的字符串
-- eg: 
select replace('abc123g', '123', 'def') 
运行结果如下 
----------- ----------- 
abcdefg*/ 

SPACE()                    --函数返回一个有指定长度的空白字符串 
STUFF()                    --函数用另一子串替换字符串指定位置长度的子串 

----数据类型转换函数---- 
CAST() 函数语法如下 
CAST() ( <expression> AS <data_ type>[ length ]) 
CONVERT() 函数语法如下 
CONVERT() ( <data_ type>[ length ], <expression> [, style]) 

select cast(100+99 as char) convert(varchar(12), getdate()) 
运行结果如下 
------------------------------ ------------ 
199  Jan 15 2000 

----日期函数---- 
DAY()                                       --函数返回date_expression中的日期值 
MONTH()                                    --函数返回date_expression中的月份值 
YEAR()                                     --函数返回date_expression中的年份值 
DATEADD( <datepart> , <number> , <date>)    --函数返回指定日期date 加上指定的额外日期间隔number产生的新日期 
DATEDIFF( <datepart> , <number> , <date>)   --函数返回两个指定日期在datepart方面的不同之处 
DATENAME( <datepart> , <date>)              --函数以字符串的形式返回日期的指定部分 
DATEPART( <datepart> , <date>)              --函数以整数值的形式返回日期的指定部分 
GETDATE()                                   --函数以DATETIME 的缺省格式返回系统当前的日期和时间 

----系统函数---- 
APP_NAME()      --函数返回当前执行的应用程序的名称 
COALESCE()     --函数返回众多表达式中第  

/*
  SQL中查询关键字(SELECT)
*/
查询中用到的关键词主要包含六个,顺序依次为:
SELECT FROM <WHERE> <GROUP BY> <HAVING> <ORDER BY>  --其中SELECT和FROM是必须的,其它关键词可选.
这六个关键词的执行顺序与SQL语句的书写顺序并不是一样的,而是按照下面的顺序来执行:
FROM -> WHERE -> GROUP BY -> HAVING -> SELECT -> ORDER BY

FROM     : 需要从哪个数据表检索数据
WHERE    : 过滤表中数据的条件
GROUP BY : 根据某列内容将上面过滤出的数据分组
           利用GROUP BY是有限制的,即SELECT后面跟的列只能是两种情况:
           (1) 按照该列分组
           (2) 其它使用了分组函数(count sum max min avg stddev variance)的列
           --eg:
           SELECT count(*), avg(sal), deptno FROM emp GROUP BY deptno;

HAVING   : 对上面已经分组的数据进行过滤的条件
SELECT   : 查看结果集中的哪个列或列的计算结果
ORDER BY : 按照什么样的顺序来查看返回的数据

/*
  SQL中连接关键字(JOIN)  
*/
SQL语句中涉及联表查询(多个表查询)时,经常需要借助JOIN关键字.JOIN常用于FROM子句中,其基本格式如下:

FROM table1 join_op table2 ON table1.field1 comp_op table2.field2   

说明:
table1, table2  : 指定需要联合查询的表名称.  
field1, field2  : 指定需要联合查询的表的字段名称.它需要满足下列条件:
                  (1) 不同表的字段必须定义为相同的数据类型,并且包含相同类型的数据.
                  (2) 不同表的字段不需要有相同的名称.  
comp_op         : 指定关系比较运算符: 
                  "=", "<", ">", "<=", ">=" 或 "<>"
join_op         : 连接关键字,可选参数如下:
                  JOIN(INNER JOIN)              内连接
                  LEFT JOIN(LEFT OUTER JOIN)    左连接
                  RIGHT JOIN(RIGHT OUTER JOIN)  右连接
                  FULL JOIN(FULL OUTER JOIN)    完全连接

特别注意:
(1) 如果在INNER JOIN操作中要联接包含Memo或OLE Object数据类型的字段,将会发生错误.   
(2) INNER JOIN 属于内连接.
    (LEFT,RIGHT,FULL) JOIN 属于外连接.
(3) 各种连接属性如下:
INNER JOIN  : 如果联表中至少有一个匹配,则返回行.
LEFT  JOIN  : 即使右表中没有匹配,也从左表返回所有的行.
RIGHT JOIN  : 即使左表中没有匹配,也从右表返回所有的行.
FULL  JOIN  : 只要其中一个表中存在匹配,就返回所有的行.

-- eg:
假设有A,B两张表.  

表A记录如下:  
aID     aNum  
1     a20050111  
2     a20050112  
3     a20050113  
4     a20050114  
5     a20050115  

表B记录如下:  
bID     bName  
1     2006032401  
2     2006032402  
3     2006032403  
4     2006032404  
8     2006032408  
--------------------------------------------  
1. LEFT JOIN 
SQL语句如下:   
select *from A left join B on A.aID = B.bID  

结果如下:  
aID     aNum       bID     bName  
1     a20050111    1     2006032401  
2     a20050112    2     2006032402  
3     a20050113    3     2006032403  
4     a20050114    4     2006032404  
5     a20050115    NULL     NULL  

(查询结果行数为5行)  
结果说明:  
left join是以A表的记录为基础的,A可以看成左表,B可以看成右表,left join是以左表为准的.  
换句话说,左表(A)的记录将会全部表示出来,而右表(B)只会显示符合搜索条件的记录(例子中为: A.aID = B.bID).  
B表记录不足的地方均为NULL.  
--------------------------------------------  
2. RIGHT JOIN
SQL语句如下:   
select *from A right join B on A.aID = B.bID  

结果如下:  
aID     aNum       bID     bName  
1     a20050111    1     2006032401  
2     a20050112    2     2006032402  
3     a20050113    3     2006032403  
4     a20050114    4     2006032404  
NULL     NULL      8     2006032408  

(查询结果行数为5行)  
结果说明:  
仔细观察一下,就会发现,和left join的结果刚好相反,这次是以右表(B)为基础的,A表不足的地方用NULL填充.  
--------------------------------------------
3. FULL JOIN
SQL语句如下:   
select *from A full join B on A.aID = B.bID  

结果如下:  
aID     aNum       bID     bName  
1     a20050111    1     2006032401  
2     a20050112    2     2006032402  
3     a20050113    3     2006032403  
4     a20050114    4     2006032404
5     a20050115    NULL     NULL    
NULL     NULL      8     2006032408  

(查询结果行数为6行)  
结果说明:  
full join的返回结果相当于将left join,right join做了一个综合处理.因此上述三种JOIN统称为外连接.
--------------------------------------------  
4. INNER JOIN  
SQL语句如下:   
select *from A inner join B on A.aID = B.bID  

结果如下:  
aID     aNum       bID     bName  
1     a20050111    1     2006032401  
2     a20050112    2     2006032402  
3     a20050113    3     2006032403  
4     a20050114    4     2006032404  

(查询结果行数为4行)
结果说明:  
很明显,这里只显示出了A.aID = B.bID的记录.这说明inner join并不以谁为基础,它只显示符合条件的记录.  

/*
  SQL中索引(INDEX)
*/
索引创建语法:
CREATE [UNIQUE | BITMAP] INDEX [schema.]index ON [schema.]table (column [ASC | DESC] [,column [ASC | DESC] ] ... )
[CLUSTER [schema.]cluster]
[INITRANS n]
[MAXTRANS n]
[PCTFREE n]
[STORAGE storage_settings]
[TABLESPACE tablespace_name]
[LOGGING | NOLOGGING]
[NOCOMPRESS | COMPRESS n]
[NOSORT | REVERSE]
[COMPUTE STATISTICS]
[NOPARTITION | PARTITION | GLOBAL PARTITION partition_setting]

其中:
UNIQUE             : 设置为唯一值索引.默认的索引是非唯一索引.
BITMAP             : 设置为位图索引.默认的索引是B-Tree索引.
schema             : ORACLE用户.默认即为当前帐户.
index              : 索引名
table              : 创建索引的基表名
column             : 基表中的列名
                     一个索引最多有16列.long列,long raw列不能建索引列.
DESC               
ASC                : 默认为ASC,即升序排序.
CLUSTER            : 指定一个聚簇(Hash cluster不能建索引)
INITRANS           
MAXTRANS           : 指定初始和最大事务入口数
PCTFREE            : 索引数据块空闲空间的百分比(不能指定pctused)
STORAGE            : 存储参数,同CREATE TABLE中的storage.
TABLESPACE         : 表空间名
LOGGING            
NOLOGGING          : 是否对索引产生重做日志(对大表尽量使用NOLOGGING来减少空间占用并提高效率)
NOCOMPRESS         : 不使用键压缩
COMPRESS           :使用键压缩. 参数n表示将之前第n个column列中出现的重复值进行删除.
NOSORT             : 使用与表中数据相同的顺序创建索引
REVERSE            : 使用反向索引.该值不能与NOSORT同时使用.
COMPUTE STATISTICS : 创建新索引时收集统计信息
NOPARTITION
PARTITION          : 在未分区表和分区表上对创建的索引进行分区

删除索引:
DROP INDEX index_name ON talbe_name;
ALTER TABLE table_name DROP INDEX index_name;

数据库中建立索引常用的规则如下: 
1. 表的主键,外键必须有索引.        -- Oracle数据库会自动创建主键,外键的索引.
2. 数据量超过300的表应该有索引.
3. 经常与其它表进行连接的表,在连接字段上应该建立索引.
4. 经常出现在WHERE子句中的字段,特别是大表的字段,应该建立索引.
5. 索引应该建在选择性高的字段上.
6. 索引应该建在小字段上,对于大的文本字段甚至超长字段,不要建索引.
7. 复合索引的建立需要进行仔细分析,尽量考虑用单字段索引代替: 
   A. 正确选择复合索引中的主列字段,一般是选择性较好的字段.
   B. 复合索引的几个字段是否经常同时以AND方式出现在WHERE子句中?
      单字段查询是否极少甚至没有?如果是,则可以建立复合索引.否则考虑单字段索引.
   C. 如果复合索引中包含的字段经常单独出现在WHERE子句中,则分解为多个单字段索引. 
   D. 如果复合索引所包含的字段超过3个,那么仔细考虑其必要性,考虑减少复合的字段.
   E. 如果既有单字段索引,又有这几个字段上的复合索引,一般可以删除复合索引.
8. 频繁进行数据操作的表,不要建立太多的索引.
9. 删除无用的索引,避免对执行计划造成负面影响.

综上:
1. 索引的建立必须慎重.每个索引都要有建立的依据.
2. 过多的索引,不充分或不正确的索引对性能毫无益处.在表上建的每个索引都会增加存储开销.索引对于插入,删除,更新等操作也会增加开销. 
3. 过多的复合索引,在有单字段索引的情况下,一般都是没有存在价值的.
   相反,还会降低数据增加删除操作时的性能.特别是对频繁更新的表来说,负面影响更大. 

/*
  PL/SQL中的序列(SEQUENCE)
*/
PL/SQL中的序列(SEQUENCE)在ORACLE中应用十分广泛,它可以自动增加指定变数,如逐次增加1或者其它数值.
1. 创建序列  CREATE SEQUENCE

首先要确保有CREATE SEQUENCE或者CREATE ANY SEQUENCE权限
-- eg:
CREATE SEQUENCE CUX_DEMO_SEQUENCE
MINVALUE 1
MAXVALUE 99999999999
START WITH 10000
INCREMENT BY 1
NOCYCLE
CACHE 20
ORDER;

注释:
MINVALUE 1              --最小值(必须小于或等于START WITH,并且必须小于MAXVALUE),默认值:NOMINVALUE
MAXVALUE 99999999999    --最大值(必须大于或等于START WITH,并且必须大于MINVALUE),默认值:NOMAXVALUE
START WITH 10000        --起始数值(当序列号顺序递增时默认值为序列号的最小值,当序列号顺序递减时默认值为序列号的最大值)
INCREMENT BY 1          --每次增加1(默认值:1).如果指定的是正整数,则序列号自动递增;如果指定的是负数,则自动递减.
NOCYCLE                 --累加不循环(默认值)
CACHE 20                --缓存(默认值:20)
ORDER;

还有一些其它参数,例如:
CYCLE                   --循环累加
NOCACHE                 --不设置缓存
SEQUENCE_CACHE_ENTRIES  --能同时被cache的SEQUENCE数目.

如果指定CACHE值,ORACLE就可以预先在内存里面放置一些SEQUENCE,这样存取效率较高.CACHE里面的取完后,ORACLE会自动再取一组到CACHE.
使用CACHE或许会跳号,比如数据库突然不正常down掉(shutdown abort),CACHE中的SEQUENCE就会丢失,可以在CREATE SEQUENCE的时候用NOCACHE防止上述情况.

2. 使用序列
SEQUENCE中主要有CURRVAL,NEXTVAL两个函数可以供调用:

CURRVAL --返回SEQUENCE当前值
NEXTVAL --增加SEQUENCE的值,然后返回SEQUENCE值

-- eg:
CUX_DEMO_SEQUENCE.CURRVAL
CUX_DEMO_SEQUENCE.NEXTVAL

可以使用SEQUENCE的地方:
(1) 不包含子查询,snapshot,VIEW的SELECT语句;
(2) INSERT语句的VALUES中;
(3) UPDATE语句的SET中;

-- eg:
INSERT INTO CUX_DEMO_TABLE VALUES(CUX_DEMO_SEQUENCE.NEXTVAL, 123, 'IBAD', 'MARK', 'Y');
SELECT CUX_DEMO_SEQUENCE.CURRVAL FROM DUAL;

注意:
(1) 第一次调用NEXTVAL返回的是初始值,随后的NEXTVAL会自动增加定义的INCREMENT BY值,然后返回增加后的值.
(2) CURRVAL总是返回当前SEQUENCE的值.
(3) 第一次NEXTVAL初始化之后才能使用CURRVAL,否则会出错.
(4) 一次NEXTVAL会增加一次SEQUENCE的值,如果在同一个语句里面使用多个NEXTVAL,其值就是不一样的.

3. 修改序列 ALTER SEQUENCE
要确保是该SEQUENCE的owner,或者有ALTER ANY SEQUENCE权限才能修改SEQUENCE. 
可以ALTER除START WITH以外的所有SEQUENCE参数.如果想要改变START WITH,必须DROP SEQUENCE重新创建SEQUENCE.

-- eg:
ALTER SEQUENCE CUX_DEMO_SEQUENCE
INCREMENT BY 10
MAXVALUE 10000
CYCLE           -- 到10000后从头开始
NOCACHE;

4.删除序列 DROP SEQUENCE
-- eg:
DROP SEQUENCE CUX_DEMO_SEQUENCE;

5. 应用实例
综合运用序列,触发器功能实现自增的主键序列.
-- 创建t_prov_anaaa_ispp表,并进行分区处理及创建索引.
CREATE TABLE t_prov_anaaa_ispp (
  id NUMBER(12) NOT NULL,
  req_date NUMBER(12) NOT NULL,
  req_time NUMBER(12) NOT NULL,
  user_name VARCHAR2(255) NOT NULL,
  imsi VARCHAR2(64) default NULL,
  mdn VARCHAR2(64) default NULL,
  status NUMBER(11)	default NULL,
  action NUMBER(11) default NULL,
  res_code NUMBER(11) default NULL,
  PRIMARY KEY (id)
)
PARTITION BY RANGE (req_date) INTERVAL (1) (
   PARTITION t_prov_anaaa_ispp_p1 VALUES LESS THAN (20120101) 
);
-- NOTE!!上述PARTITION与最近的)之间没有空行,否则会报错.

-- INDEX
CREATE INDEX ind_t_prov_anaaa_ispp_imsi ON t_prov_anaaa_ispp(imsi) LOCAL;
CREATE INDEX ind_t_prov_anaaa_ispp_mdn ON t_prov_anaaa_ispp(mdn) LOCAL;

-- SEQUENCE
CREATE SEQUENCE t_prov_anaaa_ispp_seq START WITH 1 INCREMENT BY 1;
-- TRIGGER
CREATE OR REPLACE TRIGGER t_prov_anaaa_ispp_seq_trigger
    BEFORE INSERT OR UPDATE OF id ON t_prov_anaaa_ispp
    FOR EACH ROW
    BEGIN
        IF ( :new.id = 0 OR :new.id is null ) THEN
            SELECT t_prov_anaaa_ispp_seq.nextval INTO :new.id FROM dual;
        END IF;
    END;
/

COMMIT WORK;

上述自增序列与触发器也可以这样实现(参数配置略有不同):
-- SEQUENCE
CREATE SEQUENCE t_prov_anaaa_ispp_seq
MINVALUE 1
MAXVALUE 99999999999999
START WITH 1
INCREMENT BY 1
NOCACHE
ORDER;
-- TRIGGER
CREATE OR REPLACE TRIGGER t_prov_anaaa_ispp_seq_trigger
    BEFORE INSERT ON t_prov_anaaa_ispp                  --针对插入整条数据,而不是某一个字段.
    FOR EACH ROW
DECLARE
  nextid NUMBER;
BEGIN
    IF :new.id is NULL OR :new.id = 0 THEN              --id为主键序列
        SELECT t_prov_anaaa_ispp_seq.nextval
        INTO nextid
        FROM sys.dual;
        :new.id := nextid;                              --NOTE!! 是':='(赋值),不是'='(比较)
    END IF;
END t_prov_anaaa_ispp_seq_trigger;
/                                                       
--此处的正斜线已经保证SQL正常执行并创建触发器成功.

COMMIT WORK;

-- 补充
-- 使用PL/SQL调试触发器
1. 右键点击要调试的触发器,选择编辑,在行号位置上点击一下设置断点.
2. 在菜单的新建中选择'测试窗口',打开一个如下块,在begin和end中间添加能触发触发器的语句:
-- Created on 2012-10-11 by HUANGYE 
declare 
  -- Local variables here
  i integer;
begin
  -- Test statements here
  insert into t_prov_anaaa_ispp(req_date, req_time, user_name, imsi, mdn, status, action, res_code) values(20120927, 20120927124600, 'user', 'imsi', 'mdn', 3, 10, 2001);
end;

3. 按F9或者点击调试菜单中的开始菜单,进入运行调试状态.
4. 点击运行图标跳到触发器中断点位置.
5. 鼠标放到变量上可以显示变量值.

/*
  SQL语句分类
*/
SQL语句可以分为下列三种:
1. DML(DATA MANAGE LANGUAGE)
对数据常见的增删改查操作(INSERT,DELETE,UPDATE,SELECT).

2. DDL(DATA DEFINE LANGUAGE)
定义或改变表(TABLE)的结构,数据类型,表之间的链接和约束等初始化工作,大多在建立表时使用.常见命令:CREATE,ALTER,DROP,TRUNCATE.

3. DCL(DATA CONTROL LANGUAGE)
用来设置或更改数据库用户或角色权限的语句,常见命令:GRANT,REVOKE.

其中只有DML需要输入COMMIT WORK,表示提交执行事务.DDL,DCL会自动提交执行这些语句前面的事务.

-------------------------------------------------------------------------------------------------------------------
/*
  MySQL集锦
*/
/*
  引言 
*/
MySQL与Oracle同为关系型数据库,但是内部的架构层次略有不同:

Oracle: 首先创建表空间(TABLESPACE,可理解为数据库文件),基于表空间显式创建用户(USER)(等价于数据库),然后通过USER登录,创建表结构(TABLE).
        也可以先创建用户(USER),再通过USER登录,然后创建表空间(TABLESPACE).
MySQL : 首先显式创建数据库(DATABASE)(等价于创建用户USER),然后切换到数据库后,再创建表结构(TABLE).

/*
  MySQL建表类型
*/
'InnoDB'和'MyISAM'是使用MySQL最常用的两种表类型,各有优缺点,视具体应用而定.基本的差别为:
'MyISAM'强调的是性能,其执行速度比'InnoDB'类型更快,但是不提供事务支持.而'InnoDB'提供事务支持以及外键等高级数据库功能.

/*
  Windows下配置使用免安装版MySQL
*/
1.从MySQL官方网站http://mysql.stu.edu.tw/Downloads/MySQL-4.1/mysql-noinstall-4.1.22-win32.zip下载MySQL(推荐用免安装版)
--以下方法未经过实践校验,仅作为参考资料.另外如果不用mysqld-nt.exe文件,直接使用mysqld.exe进行操作也可以
2.解压后打开文件my-huge.ini另存为my.ini,在my.ini文件中加入如下配置,再放到E:/share/下
[mysqld]
basedir=E:/share/mysql
#bind-address=127.0.0.1
datadir=E:/share/mysql/data
#language=D:/usr/local/mysql/share/your language directory
#slow query log#=
#tmpdir#=
#port=3306
#set-variable=key_buffer=16M

[WinMySQLadmin]
Server=E:/share/mysql/bin/mysqld-nt.exe
user=root
password=mysql

路径根据个人情况修正.

2.开始--运行中输入:E:/share/mysql/bin/mysqld-nt.exe -install 即可启动MySQL服务而且是自启,如果没有重启电脑看有没有.

如果将MYSQL已经安装为Windows的服务,可以通过启动服务方式启动MYSQL.方法如下:
依次点击'控制面板'->'管理工具'->'服务',选中'MYSQL',直接启动该服务.

3.设置MySQL中文字符集(MySQL正常显示中文)

(1)配置服务器端,修改my.ini文件,使用中文字符集存储记录,同时用中文排序比较方式.
[mysqld]
# set character set
default-character-set=gbk
# set character collation
default-collation=gbk_chinese_ci
(2)如果要在中文环境的服务器端使用mysql命令行,改变my.ini文件中mysql的默认字符集.
[mysql]
# set character set
default-character-set=gbk
(3)在客户端程序中,设置中文字符集.以Delphi + ADO + MyODBC为例:
procedure InitConn;
var
  nRows: Integer;
begin
  ...
end
--改变当前MySQL连接session的字符集
ADOConnection1.Execute('set character_set_client=''gbk''', nRows);
ADOConnection1.Execute('set character_set_connection=''gbk''', nRows);
ADOConnection1.Execute('set character_set_results=''gbk''', nRows);

/*
  Windows下升级MySQL
*/
步骤:
1. 停止MySQL服务.
2. 将<MySQL directory>/data文件夹以及<MySQL directory>/my.ini配置文件复制出来进行备份.
3. 删除掉<MySQL directory>下的所有文件.
4. 下载http://mysql.stu.edu.tw/Downloads/MySQL-5.1/mysql-noinstall-5.1.22-win32.zip,将其解压到原有的MySQL文件夹中.
5. 将备份的data文件夹和my.ini配置文件复制回<MySQL directory>.
6. 启动MySQL服务.

/*
  Solaris下安装MySQL(二进制程序安装)
*/
1. 下载Solaris版本的MySQL软件.
下载链接如下:
http://downloads.mysql.com/archives/mysql-5.5/mysql-5.5.28-solaris10-sparc-64bit.tar.gz

2. 创建mysql用户及用户组.
# groupadd mysql                                     -- 创建mysql用户组
# useradd -d /export/home/mysql -g mysql -m mysql    -- 创建mysql用户,并将路径'/export/home/mysql'作为其主目录
# passwd mysql                                       -- 为mysql用户创建密码
# chown -R mysql:mysql /export/home/mysql            -- 改变mysql用户主目录及子目录的属主
# chmod -R 775 /export/home/mysql                    -- 改变mysql用户主目录及子目录的读写权限

3. 以mysql用户身份登录上传安装文件并解压
$ cd /export/home/mysql
$ gunzip < mysql-5.5.28-solaris10-sparc-64bit.tar.gz | tar -xvf -
$ ln -sf mysql-5.5.28-solaris10-sparc-64bit/ mysql                      -- 做一个软连接

4. 导出环境变量
export PATH=/export/home/mysql/mysql/bin:$PATH

5. 创建MySQL授权表
$ cd /export/home/mysql
$ cp scripts/mysql_install_db .
$ ./mysql_install_db                                 -- 执行MySQL初始化脚本
$ ./bin/mysqld_safe &                                -- 启动MySQL数据库(后台启动)

6. 清理临时表格,修改root用户密码
$ ./bin/mysql_secure_installation                    -- 一路按照提示操作

如果上述操作过程中未能修改root密码,也可以使用下列命令进行修改:
$ ./bin/mysqladmin -u root password 'root'           -- 将root用户的密码设定为root.密码字符串root也可以不加单引号.

7. 常用操作     -- 注意:如果已经配置过环境变量,可以直接输入mysqladmin或者mysql命令,而不必指定绝对路径.
$ ./bin/mysqladmin -uroot -proot shutdown            -- 关闭MySQL数据库
$ ./bin/mysql -uroot -proot                          -- 正常连接登录MySQL数据库

8. 其它
(1) 使用root账号登录数据库,执行下列语句:
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'root' WITH GRANT OPTION;
保证root用户可以在其它主机直接连接MySQL数据库.

(2) 有关重启Mysql的说明
如果使用上述的'./bin/mysqld_safe &'命令启动Mysql,默认会启动监控进程实时监控mysqld服务是否运转.此时,如果需要重启Mysql,只需要调用'kill'命令杀掉mysqld进程,监控进程就会自动将mysqld进程拉起,从而完成重启Mysql的操作.

如果需要彻底关掉Mysql服务,可以直接调用上述的'./bin/mysqladmin -uroot -proot shutdown'命令,该命令除了杀掉mysqld进程之外,连同监控进程也会杀掉.

/*
  Suse下安装MySQL(源代码安装)
*/
以'mysql-5.5.25.tar.gz'进行安装为例,相通的操作可以参考solaris下的操作过程.

首先安装cmake工具,以保证编译正常进行.
创建mysql用户,同时创建安装路径:
# mkdir -p /usr/local/mysql/var
# chown -R mysql:mysql /usr/local/mysql/var

切换到mysql账号下,解压mysql-5.5.25.tar.gz,然后依次执行下列命令进行编译安装:
$ cd mysql-5.5.25/BUILD
$ cmake ..
$ make && make install

复制配置文件
# cp mysql-5.5.25/support-files/my-medium.cnf /etc/my.cnf
# cp mysql-5.5.25/support-files/mysql.server /etc/init.d/mysqld
# chmod +x /etc/init.d/mysqld                                       -- 添加可执行权限

执行mysql的初始化脚本
$ sh /usr/local/mysql/scripts/mysql_install_db --user=mysql

之后可参考上文内容修改mysql默认的root密码(默认情况下root密码为空),然后启动mysql正常使用.

-- BC: 2016.02.18
SUSE11.3系统自带的mysql有可能有一些问题导致无法正常启动,可以考虑依次做如下操作进行排查:
# chown -R mysql:mysql /var/lib/mysql/
# chown -R mysql:mysql /etc/my.cnf

执行完上述操作后,mysql_install_db(初始安装脚本)应该可以正常执行.

/*
  Suse11.3(x86_x64)系统下自带MySQL启动关闭操作说明
*/
默认情况下,Suse11.3自带的mysql使用的配置文件是/etc/my.cnf,如果没有该文件可以直接拷贝一个过来.
其中的下列配置项比较重要:
[mysqld]
# The TCP/IP Port the MySQL Server will listen on
port=3306                                               -- mysql服务端监听端口
basedir="/usr/local/capitek/aaa/system/database"        -- mysql服务端主程序路径
datadir="/usr/local/capitek/aaa/data/database/data"     -- mysql服务端数据文件路径

上述的basedir,datadir路径如果不确定的话,可以考虑直接删除掉配置项.这样Mysql启动时,可以选择默认路径进行加载(便于排查).

-- 启动mysql服务(启动脚本通常默认安装在'/usr/bin'路径下)
$ /usr/bin/mysqld_safe &

或者更具体一些,加上一些必要的参数,例如:
$ /usr/bin/mysqld_safe --defaults-file=/etc/my.cnf --user=root &

-- 关闭mysql服务(假设mysql管理员用户名和密码都为'root')
$ /usr/bin/mysqladmin -uroot -proot shutdown

-- BC: 2016.12.01
理论上使用下列两组命令也可以完成mysql的启动与关闭(有可能需要切换至root权限):
$ /etc/init.d/mysql start
$ /etc/init.d/mysql stop

或者
$ service mysql start
$ service mysql stop

但是,很多情况下上述的两组命令会有各种问题,不推荐使用.

/*
  Linux下Mysql数据库支持中文显示
*/
首先登陆Mysql查看Mysql原有的字符集.在Linux下执行下列命令($ 表示Linux命令提示符):
$ mysql -uroot -proot

登陆进入Mysql界面后执行下列命令(mysql> 表示Mysql命令提示符):
mysql> show variables like 'character_set_%';

查看到的信息如下:
+--------------------------+----------------------------+
| Variable_name            | Value                      |
+--------------------------+----------------------------+
| character_set_client     | latin1                     | 
| character_set_connection | latin1                     | 
| character_set_database   | utf8                       | 
| character_set_filesystem | binary                     | 
| character_set_results    | latin1                     | 
| character_set_server     | latin1                     | 
| character_set_system     | utf8                       | 
| character_sets_dir       | /usr/share/mysql/charsets/ | 
+--------------------------+----------------------------+

说明原来的字符集为'latin1',即不支持中文显示.

修改方法:
1. 使用vi命令打开Mysql配置文件'/etc/my.cnf'(可能需要使用root权限).
在其中下列段落[client],[mysqld],[mysql]分别添加对应的utf8字符集信息.如下:
[client]
default-character-set=utf8

[mysqld]
character-set-server=utf8

[mysql]
default-character-set=utf8

2. 重启Mysql数据库

此后重新登录Mysql查看对应的字符集信息如下:
+--------------------------+----------------------------+
| Variable_name            | Value                      |
+--------------------------+----------------------------+
| character_set_client     | utf8                       | 
| character_set_connection | utf8                       | 
| character_set_database   | utf8                       | 
| character_set_filesystem | binary                     | 
| character_set_results    | utf8                       | 
| character_set_server     | utf8                       | 
| character_set_system     | utf8                       | 
| character_sets_dir       | /usr/share/mysql/charsets/ | 
+--------------------------+----------------------------+

说明utf8字符集变更成功.可以正常进行中文显示了.

PS:
如果上面都修改了还乱码,那剩下问题就一定在connection连接层上.解决方法是在发送查询前执行一下下面的语句(直接写在SQL文件的最前面):
SET NAMES 'utf8';

它相当于下面的三句指令:
SET character_set_client = utf8;
SET character_set_results = utf8;
SET character_set_connection = utf8;

/*
  Linux下Mysql数据库开启日志监控功能
*/
如果需要对Mysql的相关操作(配置参数等)开启日志监控功能,操作如下:
使用root身份登录mysql,执行下列查询命令:
mysql> show VARIABLES like '%general_log%';
+------------------+------------------------------+
| Variable_name    | Value                        |
+------------------+------------------------------+
| general_log      | OFF                          |
| general_log_file | /var/lib/mysql/linux-158.log |
+------------------+------------------------------+

说明日志功能没有开启.日志默认保存路径和日志名称为'/var/lib/mysql/linux-158.log'.

如果需要开启上述功能,执行下列命令:
mysql> SET GLOBAL general_log = ON;

如果不添加GLOBAL关键字,执行上述操作会提示下列信息:
ERROR 1229 (HY000): Variable 'general_log' is a GLOBAL variable and should be set with SET GLOBAL

另外,上述操作只能使用root用户操作,如果是普通用户执行上述命令,会有下列告警:
ERROR 1227 (42000): Access denied; you need (at least one of) the SUPER privilege(s) for this operation

也可以重新定义监控日志的保存路径和名称,例如:执行下列命令:  
mysql> SET general_log_file = /tmp/general.log

执行成功后,需要提交生效:
mysql> COMMIT WORK;

/*
  MySQL常用命令
*/
一. 连接MYSQL
格式: mysql -h主机地址 -u用户名 -p用户密码 -P端口号

1. 例1: 连接到本机上的MYSQL.
首先在打开DOS窗口,然后进入目录mysqlbin,再键入命令:
mysql -uroot -p
回车后提示输密码,如果刚安装好MYSQL,超级用户root是没有密码的,故直接回车即可进入到MYSQL中了,MYSQL的提示符是:mysql>

2. 例2: 连接到远程主机上的MYSQL.假设远程主机的IP为:110.110.110.110,用户名为root,密码为abcd123.则键入以下命令:
mysql -h110.110.110.110 -uroot -pabcd123  -- 注意: '-u'与root之间加不加空格都可以,但是'-p'与实际密码之间一定不可以加空格)

3. 退出MYSQL命令:
exit(回车)

二. 修改密码
格式: mysqladmin -u用户名 -p旧密码 password 新密码

1. 例1:给root加个密码ab12.
首先在DOS下进入目录mysqlbin,然后键入以下命令:
mysqladmin -uroot password ab12
--注:
--1. 如果MySQL初始化时root没有密码,那么-p旧密码一项可以直接省略.
--2. password与旧密码之间仅有一个空格分隔,旧密码无需用单引号或双引号标注,否则会产生歧义.     

2. 例2:再将root的密码改为djg345.
mysqladmin -uroot -pab12 password djg345

--补充:
除使用mysqladmin外,还有两种常用方法修改mysql用户(包括root用户)密码.
--注意:下面是MYSQL环境中的命令,所以后面都带一个分号作为命令结束符.
方法一:
先登入MYSQL,然后切换到mysql用户下(mysql用户相当于管理员用户),执行update命令进行密码更新.
mysql> use mysql;
mysql> update user set password = password('new_password') where user = 'user_name' and host = 'host_name';
mysql> flush privileges;

该方法其实就是更新一条数据库记录,与普通update语句不同的是,密码加密存储,需用password()函数来生成.另一个不同点是需要刷新权限表.
对应的如果需要新增用户可以执行下列语句:
mysql> use mysql;
mysql> insert into user(host,user,password) values('%','user_name',password('new_password'));
mysql> flush privileges;

方法二:
在数据库中运行set password
mysql> set password for user_name@host_name = password('new_password');
mysql> flush privileges;

上述两种方法中,host_name如果是本机访问配置成localhost,如果是任何主机都可以访问配置成'%'.

注意:
如果忘记root用户的密码,可以修改my.ini配置文件,在[mysqld]字段下面加入'skip-grant-tables'信息,然后重启Mysql.mysql.此时不需要输入密码即可登录数据库.然后修改root用户的密码就可以了.       -- 暂未经过时间校验

三. 增加新用户
格式: 
grant 权限 on 数据库.* to 用户名@登录主机 identified by '密码'
1. 例1:增加一个用户test1密码为abc,让它可以在任何主机上登录,并对所有数据库有查询,插入,修改,删除,创建,销毁的权限.
首先用以root用户连入MYSQL,然后键入以下命令:
mysql> grant select,insert,update,delete,create,drop on *.* to test1@'%' identified by 'abc';

上述命令等价于:
mysql> grant all on *.* to test1@'%' identified by 'abc';

但例1增加的用户是十分危险的,如某个人知道test1的密码,那么他就可以在internet上的任何一台电脑上登录mysql数据库并对数据可以为所欲为了,解决办法见例2.

2. 例2:增加一个用户test2密码为abc,让它只可以在localhost上登录,并可以对数据库mydb进行查询,插入,修改,删除的操作(localhost指本地主机,即MYSQL数据库所在的那台主机),这样用户即使知道test2的密码,他也无法从internet上直接访问数据库,只能通过MYSQL主机上的web页来访问了.
mysql> grant select,insert,update,delete on mydb.* to test2@localhost identified by 'abc';

如果不想test2有密码,可以再打一个命令将密码消掉.     
mysql> grant select,insert,update,delete on mydb.* to test2@localhost identified by '';

/*
  MySQL使用技巧
*/
一. 操作技巧
--注意:必须首先登录到MYSQL中,以下操作都是在MYSQL的提示符下进行的,而且每个命令以分号结束.
1.如果打命令时,回车后发现忘记加分号,无须重打一遍命令,只要打个分号回车就可以了.也就是说可以把一个完整的命令分成几行来打,完后用分号作结束标志就OK.

2.可以使用光标上下键调出以前的命令.但以前的MYSQL旧版本可能不支持.现在用的是mysql-3.23.27-beta-win.

二. 显示命令     
1. 显示数据库列表.
show databases;

刚开始时才两个数据库:mysql和test.mysql库很重要它里面有MYSQL的系统信息,我们改密码和新增用户,实际上就是用这个库进行操作.

2. 显示库中的数据表:
use mysql;               --打开库,学过FOXBASE的一定不会陌生吧     
show tables;     

3. 显示数据表的结构:     
describe 表名;     

4. 建库:     
create database 库名;     

5. 建表:     
use 库名;     
create table 表名 (字段设定列表);     

6. 删库和删表:     
drop database 库名;     
drop table 表名;     

7. 将表中记录清空:     
delete from 表名;             -- 注意: Mysql中执行delete操作时,不可以对表进行'重命名'操作.只能用原始名称.

8. 显示表中的记录:     
select * from 表名;

9. 显示数据库中存储过程名称:
方法一:
select `name` from mysql.proc where db = '库名' and `type` = 'PROCEDURE';
方法二:
show procedure status;

10. 显示数据库中存储过程或者函数的创建代码:
show create procedure 存储过程名称;
show create function 函数名称;

11. 显示数据库表中创建的索引(查询索引)
show index from table_name;

-- 2016.07.21 Mysql的NULL索引与DEFAULT默认值
在Mysql中,如果某个字段中没有指定DEFAULT修饰符,MySQL会依据这个字段是NULL还是NOT NULL自动设置默认值.
(1) 如果指定字段可以为NULL,则MySQL为其设置默认值为NULL(空值).
(2) 如果指定字段是NOT NULL,则MySQL对于数值类型(INT)插入0,字符串类型(VARCHAR)插入空字符串(''),时间戳类型(TIMESTAMP)插入当前日期和时间.

三. 一个建库和建表以及插入数据的实例     
drop database if exists school;       --如果存在SCHOOL则删除     
create database school;               --建立库SCHOOL     
use school;                           --打开库SCHOOL     
create table teacher                  --建立表TEACHER     
(     
  id int(3) auto_increment not NULL primary key,     
  name char(10) not NULL,     
  address varchar(50) default '深圳',     
  year date     
);                                     --建表结束     

--以下为插入字段     
insert into teacher values('','glchengang','深圳一中','1976-10-10');     
insert into teacher values('','jack','深圳一中','1975-12-23');     

注:在建表中
(1) 将 id 设为'显示长度'为3的数字字段:int(3),并让它每个记录自动加1:auto_increment,并不能为空:not NULL,而且让它成为主字段primary key;
(2) 将 name 设为长度为10的字符字段;
(3) 将 address 设为长度为50的字符字段,而且缺省值为深圳;
(4) 将 year 设为日期字段.     

可以直接在mysql提示符键入上面的命令,但不方便调试.可以将以上命令原样写入一个文本文件中假设为school.sql,然后复制到c:\下,并在DOS状态进入目录\mysql\bin,然后键入以下命令:     

mysql -uroot -p密码 < c:\school.sql     

如果成功,空出一行无任何显示;如有错误,会有提示.(以上命令已经调试,只要将注释去掉即可使用).     

四. 将文本数据转到数据库中     
1.文本数据应符合的格式:字段数据之间用tab键隔开,NULL值用\n来代替.     
举例:     
3 rose 深圳二中 1976-10-10     
4 mike 深圳一中 1975-12-23     

2.数据传入命令   
load data local infile "文件名" into table 表名;

注意:最好将文件复制到\mysql\bin目录下,并且要先用use命令打表所在的库.     

五. 备份数据库(命令在DOS的\mysql\bin目录下执行,如果是linux系统执行目录也与之相类似)
可以使用mysqldump工具进行数据库的备份操作.该工具的常用选项如下:
--compatible=name
告诉mysqldump,导出的数据将和哪种数据库或哪个旧版本的MySQL服务器相兼容.
值可以为ansi,mysql323,mysql40,postgresql,oracle,mssql,db2,maxdb,no_key_options,no_tables_options,no_field_options等,要使用几个值,用逗号将它们隔开.但并不保证能完全兼容,而是尽量兼容.

--complete-insert,-c
导出的数据采用包含字段名的完整INSERT方式,也就是把所有的值都写在一行.
这么做能提高插入效率,但可能会受max_allowed_packet参数的影响而导致插入失败.
因此,需要谨慎使用该参数,不推荐.

--default-character-set=charset
指定导出数据时采用何种字符集,如果数据表不是采用默认的latin1字符集的话,那么导出时必须指定该选项,否则再次导入数据后将产生乱码问题.

--disable-keys
告诉mysqldump在INSERT语句的开头和结尾增加/*!40000 ALTER TABLE table DISABLE KEYS */;和/*!40000 ALTER TABLE table ENABLE KEYS */; 语句,这能大大提高插入语句的速度,因为它是在插入完所有数据后才重建索引的.该选项只适用于MyISAM表.

--extended-insert = true|false
默认情况下,mysqldump开启--complete-insert模式,因此不想用它的的话,就使用本选项,设定它的值为false即可.

--hex-blob
使用十六进制格式导出二进制字符串字段.如果有二进制数据就必须使用本选项.影响到的字段类型有BINARY,VARBINARY,BLOB.

--lock-all-tables,-x
在开始导出之前,提交请求锁定所有数据库中的所有表,以保证数据的一致性.这是一个全局读锁,并且自动关闭--single-transaction和--lock-tables选项.

--lock-tables
它和--lock-all-tables类似,不过是锁定当前导出的数据表,而不是一下子锁定全部库下的表.本选项只适用于MyISAM表,如果是Innodb表可以用--single-transaction选项.

--no-create-info,-t
只导出数据,而不添加CREATE TABLE语句.

--no-data,-d
不导出任何数据,只导出数据库表结构.

--opt 
这只是一个快捷选项,等同于同时添加--add-drop-tables --add-locking --create-option --disable-keys --extended-insert --lock-tables --quick --set-charset选项.
本选项能让mysqldump很快的导出数据,并且导出的数据能很快导回.该选项默认开启,但可以用--skip-opt禁用.注意,如果运行mysqldump没有指定--quick或--opt选项,则会将整个结果集放在内存中.如果导出大数据库的话可能会出现问题.

--quick,-q 
该选项在导出大表时很有用,它强制mysqldump从服务器查询取得记录直接输出而不是取得所有记录后将它们缓存到内存中.

--routines,-R 
导出存储过程以及自定义函数.

--single-transactio
该选项在导出数据之前提交一个BEGIN SQL语句,BEGIN不会阻塞任何应用程序且能保证导出时数据库的一致性状态.它只适用于事务表,例如InnoDB和 BDB.本选项和--lock-tables选项是互斥的,因为LOCK TABLES会使任何挂起的事务隐含提交.要想导出大表的话,应结合使用--quick选项.

--中断符,无意义
end
end

--triggers 
同时导出触发器.该选项默认启用,用--skip-triggers禁用它.

具体的备份操作步骤如下:
1. 首先以root身份登入MYSQL,命令如下:
./mysql -h主机地址 -uroot -p用户密码 -P端口号          --端口号默认为3306,如果未作修改可以忽略'-P'选项

2. 查看现有数据库名称列表,命令如下(注意:行首的'mysql-> '是操作提示符):
mysql> show databases;
显示结果示例如下:
+--------------------+
| Database           |
+--------------------+
| information_schema |
| cdcol              |
| mysql              |
| performance_schema |
| phpmyadmin         |
| test               |
| testlink           |
+--------------------+
7 rows in set (0.01 sec)

3. 切换到需要备份数据库,命令如下(以数据库testlink为例):
mysql> use testlink;

4. 查看数据库编码格式,命令如下:
mysql-> show create database testlink; 
显示结果示例如下:
+----------+-------------------------------------------------------------------+
| Database | Create Database                                                   |
+----------+-------------------------------------------------------------------+
| testlink | CREATE DATABASE `testlink` /*!40100 DEFAULT CHARACTER SET utf8 */ |
+----------+-------------------------------------------------------------------+
1 row in set (0.00 sec)

结果中的'CHARACTER SET utf8'表示编码格式采用默认的utf8(也可能是gbk或者其它).

5. 查看当前数据库中数据表,命令如下:
mysql-> show tables;
显示结果示例如下:
+-------------------------------+
| Tables_in_testlink            |
+-------------------------------+
| assignment_status             |
| assignment_types              |
| attachments                   |
| user_group                    |
| user_group_assign             |
| user_testplan_roles           |
| user_testproject_roles        |
| users                         |
+-------------------------------+
8 rows in set (0.00 sec)

6. 查看任意表的类型,命令如下(以上述的users表为例):
mysql-> show create table users;
显示结果示例如下:
| users | CREATE TABLE `users` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `login` varchar(30) NOT NULL DEFAULT '',
  `password` varchar(32) NOT NULL DEFAULT '',
  `role_id` int(10) unsigned NOT NULL DEFAULT '0',
  `email` varchar(100) NOT NULL DEFAULT '',
  `first` varchar(30) NOT NULL DEFAULT '',
  `last` varchar(30) NOT NULL DEFAULT '',
  `locale` varchar(10) NOT NULL DEFAULT 'en_GB',
  `default_testproject_id` int(10) DEFAULT NULL,
  `active` tinyint(1) NOT NULL DEFAULT '1',
  `script_key` varchar(32) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `users_login` (`login`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='User information' |

其中'ENGINE=InnoDB'一项说明MYSQL表类型为InnoDB(另一种常用表类型为'MyISAM').

7. 执行备份命令,操作如下:
首先退出MYSQL:
mysql> quit;
回到shell环境中继续执行.

(1) 如果MYSQL表类型为InnoDB,使用以下SQL来备份:
./mysqldump -uroot -p用户root密码 --default-character-set=utf8 --opt --extended-insert=false --triggers -R --hex-blob --single-transaction testlink > /opt/lampp/testlink.sql

上述命令表示使用mysqldump工具,通过MYSQL的root用户和密码,将数据库testlink备份到/opt/lampp路径下,备份文件名称为testlink.sql.

如果备份文件数据较大,可以直接通过gzip命令进行压缩处理.命令如下:
./mysqldump -uroot -p用户root密码 --default-character-set=utf8 --opt --extended-insert=false --triggers -R --hex-blob --single-transaction testlink | gzip > /opt/lampp/testlink.sql.gz

(2) 如果MYSQL表类型为MyISAM,使用以下SQL来备份:
./mysqldump -uroot -p用户root密码 --default-character-set=utf8 --opt --extended-insert=false --triggers -R --hex-blob -x testlink > /opt/lampp/testlink.sql

如果需要导出所有数据库,只需要在mysqldump命令参数中添加'--all-databases'选项.

六. 导入数据库
以root用户身份登入MYSQL,创建新的数据库,例如:
mysql> create database testlink character set utf8 collate utf8_general_ci;
然后执行导入命令:
./mysql -uroot -p testlink < /opt/lampp/testlink.sql

-- BC: 2016.08.05
执行mysqldump时,不一定非要使用root权限,普通用户权限也可以.根据需要选择使用.

/*
  Mysql基础语法
*/
1. DISTINCT关键字
如果查询语句(SELECT)仅查出某一个字段,并且该字段被DISTINCT修饰的话,则直接将该字段进行去重处理.
如果查询语句(SELECT)查出多个字段,其中某一字段被DISTINCT修饰的话,则需要对'多个字段综合判断'进行去重处理.

例如:
原始数据如下:
username        msisdn  groupname       status
460030740002023 NULL    100125-baodao   active
460030740002023 NULL    100010-mbs      active

如果分别执行下列2条SQL语句:
SELECT DISTINCT(username) FROM radreply;
SELECT DISTINCT(username), msisdn FROM radreply;

则上述原始数据都只会选出一条(因为两条记录的username与msisdn字段都相同,所以是重复数据).

但如果执行下列SQL语句:
SELECT DISTINCT(username), msisdn, groupname FROM radreply;

则上述原始数据会选出2条(因为两条记录的groupname字段不相同.所以不能去重,需要作为独立的2条记录).

/*
  Mysql报错汇总
*/
1. ERROR 1130: Host '192.168.1.3' is not allowed to connect to this MySQL server
如果远程连接Mysql数据库时系统提示上述报错,说明Mysql数据库出于安全方面的考虑不允许从远程连接.此时可以考虑使用授权法解决上述问题:
在localhost登陆Mysql界面后,输入下属语句:

GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'bj2008.' WITH GRANT OPTION;

这样就可以在任意一台机器上使用root帐号和bj2008.的密码远程登陆Mysql数据库了

2. ERROR 1093 (HY000): You can't specify target table 'user_autz' for update in FROM clause'
Mysql下编写SQL语句时,如果出现上述报错,主要是因为在SQL语句中采用了update主句与select子集配合使用的情况.例如:
UPDATE user_autz SET autz_value='255' WHERE autz_attr='Framed-IP-Netmask' AND user_id in(select user_id from user_autz where autz_attr='Framed-IP-Address' AND autz_value is not null);

这样的用法在Oracle中合法,但是Mysql不支持.

解决方法:
将上述语句中的select子句进行适当调整,采用临时表空间的方法处理.例如:(两种例句都满足条件)
UPDATE user_autz SET autz_value='255' WHERE autz_attr='Framed-IP-Netmask' AND user_id IN(SELECT a.user_id FROM (SELECT tmp.* FROM user_autz tmp) a WHERE a.autz_attr='Framed-IP-Address' AND a.autz_value is not null);

UPDATE user_autz SET autz_value='255' WHERE autz_attr='Framed-IP-Netmask' AND user_id IN(SELECT a.user_id FROM (SELECT tmp.* FROM user_autz AS tmp) AS a WHERE a.autz_attr='Framed-IP-Address' AND a.autz_value is not null);

2017.02.16 补充:
上述语句报错的原因其实就是针对表user_autz,同时在UPDATE和SELECT中对它做了操作.改进的方法其实就是把表user_autz封装一下:
user_autz <=> (SELECT tmp.* FROM user_autz tmp) a
user_autz <=> (SELECT tmp.* FROM user_autz AS tmp) AS a

3. ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock' (111) '
表示mysql数据库没有正常启动,无法连接操作.正常启动数据库后,即可解决.

4. ERROR 2013 (HY000): Lost connection to MySQL server at 'reading initial communication packet', system error: 104
上述报错出现的时候,基本表现为,通过navicat,或者其它mysql客户端软件无法从远程连接Mysql(但是在本机可以登录).

解决方法:
修改Mysql的配置文件'/etc/my.cnf',在其中的[mysqld]配置部分,添加下列内容:
skip-name-resolve

然后重启Mysql.

5. The error means mysqld does not have the access rights to XXXX
个别情况下,如果Mysql无法正常启动,有可能出现上述报错提示.该情况下一般是因为缺少相关启动参数导致的.例如:
参考启动命令如下(2016.06.27 普天重庆网监项目):
/usr/bin/mysqld_safe --defaults-file=/etc/my.cnf --user=root &

6. 1093 - You can't specify target table 'users' for update in FROM clause  '
情况描述:
在Mysql中删除重复数据(例如:表users中user_name字段有重复记录),执行下列SQL语句:
delete from users where user_id in (select user_id from users group by user_name having count(*) > 1);
会有上述报错.

报错原因:
低版本的Mysql中不允许在同一个SQL语句中同时使用update和select操作.

解决方法(三选一):
(1) 升级Mysql至较高版本(该方法可以解决SQL语法的限制,但是涉及数据导入导出的问题,可操作性不强).
(2) 修改SQL语句,改变对于语法冲突的限制.例如,改成下列两种格式:
delete from users where user_id in (select a.user_id from (select tmp.* from users tmp) a group by user_name having count(*) > 1);
delete from users where user_id in (select a.user_id from (select *from users) a group by user_name having count(*) > 1);
该方法在数据库中数据较多的情况下,效率成问题.
(3) 使用临时表完成.
-- 标准解决办法
create table tmp_table (
user_name  VARCHAR(36) NOT NULL  primary key
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
insert into tmp_table (select user_name from users group by user_name having count(*) > 1);
delete from users where users.user_name in (select * from tmp_table);
truncate table tmp_table;
drop table tmp_table;
commit work;

或者可以将上述SQL语句保存为sql脚本文件,在Mysql命令行中通过'source'命令执行.
该方法可操作性较高,推荐使用(但是,该方法是将所有的重复数据都直接删除掉了.并没有真正保存仅有的一条数据'去重').
还可以将上述SQL语句中的in关键字用EXISTS替代,这样SQL执行效率可能更高(通常SELECT查询操作中EXISTS效率高,但是DELETE删除操作中未必).

-- BC: 2016.07.04
上述重复数据所在的字段'user_name'是varchar类型,所以去重操作复杂一些.如果是int型数据,可以考虑直接通过比对数据值的方式来进行去重.

7. ERROR 1010 (HY000): Error dropping database (can't rmdir './aaa3_cq/', errno: 17)  ')
在Mysql中执行删除数据库操作(例如: DROP database aaa3_cq)时,提示上述报错.

错误原因:
有可能是数据库数据文件所在路径下存在冗余文件,导致了DROP操作异常.

解决方法:
(1) 查询Mysql数据库数据文件保存路径.
查看my.cnf配置文件:
cat /etc/my.cnf

查看'datadir'配置项对应的数据文件路径,例如:
datadir = /var/lib/mysql

(2) 进入上述路径,将提示的冗余文件(或者文件夹),比如上述的aaa3_cq/文件夹整个删除掉.即可解决问题(如果不成功,可以再执行一遍DROP database aaa3_cq).

8. 启动Mysql服务时提示下列报错:
161201 16:32:49 [ERROR] Failed to open log (file './mysql-bin.000026', errno 2)
161201 16:32:49 [ERROR] Could not open log file
161201 16:32:49 [ERROR] Can't init tc log       '
161201 16:32:49 [ERROR] Aborting

错误原因:
默认情况下,mysql需要将运行日志写入形如'mysql-bin.XXXX'格式的文件中.后面的'XXXX'应该是自动增加的数字编号.如果某次关闭Mysql的时候,因为某些未知原因导致对应路径下的上述文件('mysql-bin.XXXX')统一被删除掉,就可能导致下一次Mysql的启动无法正常进行(不知道本次启动需要加载哪个编号的'mysql-bin.XXXX'文件).

解决方法:
重新生成一个日志文件.

修改配置文件/etc/my.cnf,下列配置项:
log-bin=mysql-bin

把'mysql-bin'修改成不同的文件前缀名称,最简单的修改如下:
log-bin=mysql-b

这样Mysql启动时会自动在对应路径下重新生成形如'mysql-b.XXXX'格式的日志文件.启动也会正常执行.

9. 启动Mysql服务时提示下列报错:
ib_logfile0 is of different size

错误原因:
可能是InnoDB格式的日志文件容量配置有误.

解决方法:
修改配置文件/etc/my.cnf,调整下列配置项:
innodb_log_file_size=5M

然后可以正常启动Mysql.

10. 执行数据导出的时候如果有下列报错:
ERROR 1 (HY000) at line 1: Can't create/write to file '/home/mysql/users.txt' (Errcode: 13)     '
是因为对于目录'/home/mysql/'没有对应的读写权限.使用'chmod'命令添加上写权限就可以了.

/*
  Mysql存储过程
*/
调试MySQL存储过程可以使用'Debugger.for.MySQL'工具.使用教程参考下列链接:
http://mydebugger.com/quick_start.php

1. 查看存储过程的名称(使用root权限登陆,查看数据库'aaa3'下属的存储过程名称)
select `name` from mysql.proc where db = 'aaa3' and `type` = 'PROCEDURE';

其它方法(普通账户权限也可以执行):
show procedure status;

2. 查看存储过程的具体代码(普通账户权限可以执行)
show create procedure proc_name;

/*
  Mysql获取随机整数
*/
如果需要在[i, j]范围内获得一个随机整数,则可以执行下列SQL语句:
SELECT FLOOR(i + (RAND() * (j - i + 1)));

例如:
若要在7到12的范围内(包括7和12)内得到一个随机整数,可使用以下SQL语句:
SELECT FLOOR(7 + (RAND() * 6));

/*
  Mysql时间戳处理函数
*/
1. 将时间转换为时间戳
SELECT UNIX_TIMESTAMP('2016-03-15 17:36:07');

该语句等价于:
SELECT UNIX_TIMESTAMP('20160315173607');
SELECT UNIX_TIMESTAMP('2016-03-15 17-36-07');

2. 将时间戳转换为时间
SELECT FROM_UNIXTIME(1458034567);

3. 选取当前时间与'2016-01-15 01:12:31'之间的随机时间
SELECT FROM_UNIXTIME(UNIX_TIMESTAMP('2016-01-15 01:12:31') + ROUND(RAND() * (UNIX_TIMESTAMP() - UNIX_TIMESTAMP('2016-01-15 01:12:31'))));

------------------------------------------------------------------------------------------------------------------------------------

/*
  DB2集锦
*/
--DB2数据库的备份与恢复

--前提:E:\NCAUDIT. D:\NCAUDIT目录已经存在.如果修改路径,则保证修改后的路径存在.
--在服务机系统dos下运行(输入后命令回车,不用分号):

db2cmd
--备份现场数据库到D:盘
db2stop force
db2start
db2 backup db ncaudit to d:  
db2 drop db ncaudit         -- 摧毁目前的数据库,准备开始恢复

--开始恢复,要求备份文件在E盘根目录下,或者修改下面这条命令的E:到备份文件存放路径 //db2 create db ncaudit创建db2数据库命令
RESTORE DB NCAUDIT FROM E: INTO NCAUDIT REDIRECT
SET TABLESPACE CONTAINERS FOR 0 USING (FILE 'E:\NCAUDIT\SYSCAT.DBF'  65536)  --E:\NCAUDIT\路径是指恢复完的数据库文件所存放的途径
SET TABLESPACE CONTAINERS FOR 1 USING (FILE 'E:\NCAUDIT\TEMP1.DBF'  65536)    
SET TABLESPACE CONTAINERS FOR 2 USING (FILE 'E:\NCAUDIT\USER1.DBF'  65536)    
SET TABLESPACE CONTAINERS FOR 3 USING (FILE 'E:\NCAUDIT\SYSTOOL.DBF'  65536)  
SET TABLESPACE CONTAINERS FOR 4 USING (FILE 'E:\NCAUDIT\MPSPACE.DBF'  65536)  
SET TABLESPACE CONTAINERS FOR 5 USING (FILE 'E:\NCAUDIT\COMSPACE.DBF'  65536) 
SET TABLESPACE CONTAINERS FOR 6 USING (FILE 'E:\NCAUDIT\TSKSPACE.DBF'  65536) 
SET TABLESPACE CONTAINERS FOR 7 USING (FILE 'E:\NCAUDIT\TEMPSPACE.DBF'  65536)
SET TABLESPACE CONTAINERS FOR 8 USING (FILE 'E:\NCAUDIT\CASESPACE.DBF'  65536)
SET TABLESPACE CONTAINERS FOR 9 USING (FILE 'E:\NCAUDIT\IDX4K.DBF'  65536)    
SET TABLESPACE CONTAINERS FOR 10 USING (FILE 'E:\NCAUDIT\IDX8K.DBF'  65536)   
SET TABLESPACE CONTAINERS FOR 11 USING (PATH 'D:\NCAUDIT')                   
RESTORE DB NCAUDIT CONTINUE;                                                  

--最后一条命令成功就恢复完成了.

/*
  网通收入稽核管理项目清空数据库记录
*/
delete from nc_database_logs;

/*
  网通收入稽核管理项目删除数据库中缓存报表语句
*/

1. 使用SQL语句时要注意登录数据库时使用的帐号. 密码是否准确:
如果使用Toad登录一般无须考虑上述问题,但如果使用DB2自带的SQL工具进行操作,需要注意上述问题,例如:

db2cmd
db2 connect to ncaudit user 'ncaudit' using '!qAz@wSx'  //第一个ncaudit是数据库名. 第二个ncaudit是登录用户名. !qAz@wSx是登录密码

2. 其它DB2操作语句
describe table af_departments    --查询表结构
select *from matrix_point_data where first_dept_id=102100 and point_audit_date='2008-04-24' 
select *from af_departments  A where A.dept_name like '%西宁%'      --其中A相当于数据库中表af_departments的别名
select *from report_submit_info RS where RS.submit_group_id=102100  --其中RS相当于数据库中表report_submit_info的别名
select *from matrix where belong_to =102100  --查询matrix表中在青海西宁市是否有当前正在失效的矩阵

--清理工作任务与工作组数据库
delete from audit_task_point;
delete from audit_task_operation;
delete from audit_task;
delete from task_group;
delete from relation_group_task;

delete from notice;

--清理报表
delete from report_audit_complete;
delete from report_area_audit;
delete from report_audit_dir;
delete from report_exception_detail;
delete from report_income_rate;
delete from report_redeem_avoid_income;
delete from report_submit_info;
delete from matrix_point_summary;
delete from matrix_point_summary_detail;

delete from import_data_audit;

--清理稽核管理
delete from matrix_point_data_error where matrix_point_data_id in ( select matrix_point_data_id from temp_matrix_point_data);
delete from temp_matrix_point_data;
delete from temp_matrix_point;

--快捷清空数据
delete  from matrix_point_data;

SELECT * FROM NCAUDIT.AF_AREA aa where aa.parent_id=1 order by aa.area_order --按照area_order顺序选取

/*
  DB2存储过程语法
*/
创建SQL存储过程(CREATE PROCEDURE (SQL) statement )
 
语法格式如下:
 
>>-CREATE PROCEDURE--procedure-name----------------------------->
>--+----------------------------------------------------+--*---->
   '-(--+------------------------------------------+--)-'
        | .-,------------------------------------. |
        | V .-IN----.                            | |
        '---+-------+--parameter-name--data-type-+-'
            +-OUT---+
            '-INOUT-'
>--+-------------------------+--*------------------------------->
   '-SPECIFIC--specific-name-'
   .-DYNAMIC RESULT SETS 0--------.     .-MODIFIES SQL DATA-.
>--+------------------------------+--*--+-------------------+--->
   '-DYNAMIC RESULT SETS--integer-'     +-CONTAINS SQL------+
                                        '-READS SQL DATA----'
      .-NOT DETERMINISTIC-.     .-CALLED ON NULL INPUT-.
>--*--+-------------------+--*--+----------------------+--*----->
      '-DETERMINISTIC-----'
   .-INHERIT SPECIAL REGISTERS-.     .-7 OLD SAVEPOINT LEVEL-.
>--+---------------------------+--*--+---------------------+---->
                                     '-7 NEW SAVEPOINT LEVEL-'
      .-LANGUAGE SQL-.     .-7 EXTERNAL ACTION----.
>--7 *--+--------------+--*--+--------------------+--*------------>
                           '-7 NO EXTERNAL ACTION-'
>--+------------------------------+--3 *-------------------------->
   '-3 PARAMETER CCSID--+-3 ASCII---+-'
                      '-3 UNICODE-'
>--| SQL-procedure-body |--------------------------------------><
SQL-procedure-body:
|--SQL-procedure-statement--------------------------------------|
 
语法说明

1. procedure-name: 存储过程的名字,在同一个数据库的同一模式下,不能存在存储过程名相同参数数目相同的存储过程,即使参数的类型不同也不行.
 
2. (IN | OUT | INOUT parameter-name data-type,...) :传入参数
    IN:输入参数
 OUT:输出参数
 INOUT:作为输入输出参数
    parameter-name:参数名字,在此存储过程中唯一的标识符.
 data-type:参数类型,可以接收SQL类型和创建的表.不支持LONG VARCHAR, LONG VARGRAPHIC, DATALINK, REFERENCE和用户自定义类型.

3. SPECIFIC specific-name:唯一的特定名称(别名),可以用存储过程名代替,这个特定名称用于dorp存储过程,或者给存储过程添加注视用,但不能调用存储过程.如果不指定,则数据库会自动生成一个yymmddhhmmsshhn时间戳的名字.推荐给出别名.

4. DYNAMIC RESULT SETS integer:指定存储过程返回结果的最大数量.存储过程中虽然没有return语句,但是却能返回结果集.

5. CONTAINS SQL, READS SQL DATA, MODIFIES SQL DATA: 指定存储过程中的SQL访问级别
    CONTAINS SQL: 表示存储过程可以执行中,既不可读取 SQL 数据,也不可修改 SQL 数据.
    READS SQL DATA: 表示存储过程可以执行中,可读取SQL,但不可修改 SQL 数据.
    MODIFIES SQL DATA: 表示存储过程可以执行任何 SQL 语句.可以对数据库中的数据进行增加. 删除和修改.
 
6. DETERMINISTIC or NOT DETERMINISTIC:表示存储过程是动态或者非动态的.动态的返回的值是不确定的.非动态的存储过程每次执行返回的值是相同的.

7. CALLED ON NULL INPUT:表示可以调用存储过程而不管任何的输入参数是否为NULL,并且,任何的OUT或者INOUT参数可以返回一个NULL或者非空值.检验参数是否为NULL是在过程中进行的.

8. INHERIT SPECIAL REGISTERS:表示继承专用寄存器.

9. OLD SAVEPOINT LEVEL or NEW SAVEPOINT LEVEL:建立存储点.OLD SAVEPOINT LEVEL是默认的存储点.

10. LANGUAGE SQL:指定程序的主体用的是SQL语言.

11. EXTERNAL ACTION or NO EXTERNAL ACTION:表示存储过程是否执行一些改变理数据库状态的活动,而不通过数据库管理器管.默认是 EXTERNAL ACTION.如果指定为NO EXTERNAL ACTION ,则数据库会确定最最佳优化方案.

12. PARAMETER CCSID:指定所有输出字符串数据的编码,默认为UNICODE编码数据库为PARAMETER CCSID UNICODE ,其它的数据库默认为PARAMETER CCSID 3 ASCII.

13. SQL-procedure-body:存储过程的主体

例子1:产生一个SQL存储过程,返回员工的平均薪水. 返回所有员工超过平均薪水的数额,结果集包括name, position, and salary字段(参考数据库为db2的示例数据库sample).
----------------------------------------------------------------------------------------------------------------------------------
  CREATE PROCEDURE MEDIAN_RESULT_SET (OUT medianSalary DOUBLE)
    RESULT SETS 1
    LANGUAGE SQL
  BEGIN
    DECLARE v_numRecords INT DEFAULT 1;
    DECLARE v_counter INT DEFAULT 0;
    DECLARE c1 CURSOR FOR
      SELECT CAST(salary AS DOUBLE)
        FROM staff
        ORDER BY salary;
    DECLARE c2 CURSOR WITH RETURN FOR
      SELECT name, job, CAST(salary AS INTEGER)
        FROM staff
        WHERE salary > medianSalary
        ORDER BY salary;
    DECLARE EXIT HANDLER FOR NOT FOUND
      SET medianSalary = 6666;
    SET medianSalary = 0;
    SELECT COUNT(*) INTO v_numRecords
      FROM STAFF;
    OPEN c1;
    WHILE v_counter < (v_numRecords / 2 + 1)
    DO
      FETCH c1 INTO medianSalary;
      SET v_counter = v_counter + 1;
    END WHILE;
    CLOSE c1;
    OPEN c2;
  END 
------------------------------------------------------------------------------------------------------------------------------------

/*
  Oracle集锦
*/
/*
  Oracle基础操作
*/
/*
  Linux环境下安装配置Oracle
*/
参考印象笔记中<20170816_SUSE11.3(x64)系统下安装oracle11g操作说明>的内容.

/*
  Oracle数据库编码格式(字符集)
*/
-- 方法I
登陆Oracle服务器,进行下列操作:
1. su - oracle            -- 切换为oracle账户
2. vi ~/.bash_profile     -- 在该文件中输入下列内容
export NLS_LANG=AMERICAN_AMERICA.ZHS16GBK
该环境变量即可保证Oracle数据库支持中文编码.

查看该变量时,除了直接'vi ~/.bash_profile'查看外,还推荐下列两种方式:
1. set                   -- 直接查看服务器的所有环境变量
2. echo $NLS_LANG        -- 直接查看NLS_LANG变量的内容

-- 方法II(推荐)
首先查询一下现有Oracle服务端编码格式(字符集):
SQL> select userenv('language') from dual;

如果结果如下:
USERENV('LANGUAGE')
--------------------------------------------------------------------------------
AMERICAN_AMERICA.WE8ISO8859P1

则说明现有的Oracle服务端不支持中文字符的存储与显示,需要修改编码格式.依次执行下列SQL命令:
SQL> shutdown immediate;
SQL> startup mount
SQL> ALTER SYSTEM ENABLE RESTRICTED SESSION;
SQL> ALTER SYSTEM SET JOB_QUEUE_PROCESSES = 0;
SQL> ALTER SYSTEM SET AQ_TM_PROCESSES = 0;
SQL> ALTER database OPEN;
SQL> ALTER DATABASE CHARACTER SET ZHS16GBK;

此时可能会有下列告警:
ERROR at line 1:
ORA-12712: new character set must be a superset of old character set

提示:新字符集必须为旧字符集的超集,这时可以跳过超集的检查做更改,执行下列SQL语句:
SQL> ALTER DATABASE character set INTERNAL_USE ZHS16GBK;

然后启停数据库:
SQL> shutdown immediate;
SQL> startup

此时查询一下Oracle服务端新的编码格式:
SQL> select userenv('language') from dual;

USERENV('LANGUAGE')
----------------------------------------------------
AMERICAN_AMERICA.ZHS16GBK

修改成功.理论上此时数据库可以支持中文字符的存储与显示了.

-- BC: 2016.03.10
如果想保证sqlplus导入存储过程时顺利支持中文,可能还需要将数据库编码格式更新为'SIMPLIFIED CHINESE_CHINA.ZHS16CGB231280'才可以.

/*
  项目部署Oracle数据库,登陆/创建/删除
  eg: 河北电信彩铃网关项目
*/
1. 准备工作
(1) 检查磁盘空间大小
使用命令df –k 或者du -sh <数据文件路径> 查看磁盘中目录容量是否满足安装要求. --<数据文件路径>就是数据库文件的安装路径.
(2) 上传数据库表sql脚本
使用FTP工具(最好使用oracle账号登录),将数据库表结构/基础数据sql脚本上传至数据库服务器(最好是上传至/home/oracle路径下).

2. 部署操作步骤
(1)	使用sys用户登陆数据库  --sys用户为数据库安装时设定的管理员账号
登录方法主要有三种:
① 使用Windows下的Sqlplus客户端,在CMD客户端中直接输入下列命令:
sqlplus sys/aceway@ora10g_172.16.2.87 as sysdba --其中aceway为sys账号的密码,172.16.2.87为数据库IP地址,ora10g为数据库的SID,ora10g_172.16.2.87为数据库网络服务名也叫主机字符串
也可以输入下列命令:
sqlplus sys/[email protected]:1521/ora10g as sysdba --其中1521为Oracle默认的服务端端口

② 使用Pl/Sql工具,进入Command Window,在SQL提示符下输入下列命令:
SQL>conn sys/aceway@ora10g_172.16.2.87 as sysdba;

③ 直接使用putty登录数据库所在服务器,在其本机进行数据库访问:
su - oracle               --切换为oracle账户进行操作
sqlplus / as sysdba       --以sys身份登录数据库
SQL>conn hbcrad/hbcrad    --切换为hbcrad用户

(2)	创建表空间(TABLESPACE), 在SQL提示符下执行:
SQL>CREATE SMALLFILE TABLESPACE "HBCRAD" DATAFILE '<数据文件路径>/hbcrad01' SIZE 20G , '<数据文件路径>/hbcrad02' SIZE 20G , '<数据文件路径>/hbcrad03' SIZE 20G LOGGING EXTENT MANAGEMENT LOCAL SEGMENT SPACE MANAGEMENT AUTO;

--NOTE!!
上述的<数据文件路径>必须在服务器上存在,并且oracle用户对该路径有访问权限才能把表空间的数据文件放到该目录下面.

--查看Oracle各表空间数据文件路径方法:
使用Oracle管理员身份登录,执行下列命令:
SQL>select *from dba_data_files;

(3)	创建临时表空间, 在SQL提示符下执行:
SQL>CREATE SMALLFILE TEMPORARY TABLESPACE "HBCRAD_TEMP" TEMPFILE '<数据文件路径>/hbcrad_temp01' SIZE 20G EXTENT MANAGEMENT LOCAL UNIFORM SIZE 1M;

(4)	创建索引表空间, 在SQL提示符下执行:
SQL>CREATE SMALLFILE TABLESPACE "HBCRAD_IDX" DATAFILE '<数据文件路径>/hbcrad_idx01' SIZE 20G , '<数据文件路径>/hbcrad_idx02' SIZE 20G LOGGING EXTENT MANAGEMENT LOCAL SEGMENT SPACE MANAGEMENT AUTO;

(5)	创建用户,在SQL提示符下执行:
SQL>CREATE USER "HBCRAD" PROFILE "DEFAULT" IDENTIFIED BY "HBCRAD" DEFAULT TABLESPACE "HBCRAD" TEMPORARY TABLESPACE "HBCRAD_TEMP" ACCOUNT UNLOCK;    
SQL>GRANT "CONNECT" TO "HBCRAD";
SQL>GRANT "RESOURCE" TO "HBCRAD";
SQL>GRANT CREATE ANY VIEW TO "HBCRAD";
SQL>GRANT DEBUG ANY PROCEDURE TO "HBCRAD";
SQL>GRANT DEBUG CONNECT SESSION TO "HBCRAD";     --创建HBCRAD账号并且为其设定初始密码HBCRAD,赋予相应权限

(6)	切换到hbcrad用户登陆,在SQL提示符下执行上传的建库sql脚本:
SQL>@<上传路径>/objectSql/mainhbcrad.sql --<上传路径>/objectSql/mainhbcrad.sql表示表结构sql脚本所在位置
SQL>@<上传路径>/basicData/impData.sql    --<上传路径>/basicData/impData.sql表示基础数据sql脚本所在位置

注意:
a.必须切换到hbcrad用户登陆
b.导入时报ORA-01408 错误可忽略
c.导入后的日志文件在当前执行目下文件名:mainHbcrad.log,执行完成后保留此文件.--实际操作中未发现此文件

(7)	导入完成,退出登陆.启动web应用检测是否正常.

3.删除操作步骤
(1)	使用sys用户登陆数据库:
(2)	删除用户hbcrad,在SQL提示符下执行:
SQL>DROP USER hbcrad CASCADE;
如果出现问题:ORA-01940: cannot drop a user that is currently connected

按下列方法断开所有连接:
--查看所有使用HBCRAD账号连接的session情况,注意 HBCRAD 一定要大写
SQL>select SID, SERIAL#, MACHINE, PROGRAM, STATUS from v$session where username='HBCRAD';
--查看处于INACTIVE状态的应用程序session的SPID
SQL>select a.sid,a.SERIAL#,a.MACHINE,a.PROGRAM,a.STATUS,b.SPID from v$session a,v$process b where a.PADDR=b.ADDR and a.USERNAME='HBCRAD';
--断开连接
SQL>alter system kill session 'sid,serial#'; --数据库端
或者
kill -9 SPID;                            --应用程序端

如果上述方法无效,可以直接强制重启数据库,然后立刻drop用户.

(3)	删除表空间(只有表空间建错执行此步骤,其它情况可不执行)
SQL>DROP TABLESPACE "HBCRAD" INCLUDING CONTENTS AND DATAFILES CASCADE CONSTRAINTS;
SQL>DROP TABLESPACE "HBCRAD_TEMP" INCLUDING CONTENTS AND DATAFILES CASCADE CONSTRAINTS;
SQL>DROP TABLESPACE "HBCRAD_IDX" INCLUDING CONTENTS AND DATAFILES CASCADE CONSTRAINTS;

/*
  表空间容量调整   // TODO:
*/
如果Oracle表空间不足,可能会有下列告警提示:
OCIStmtExecute failed: ORA-01653: unable to extend table AAA3.REQUEST_RESULTS by 8192 in tablespace AAA3TS

上述'AAA3TS'对应表空间名称,'AAA3'对应用户名.
可通过下列命令查询现有表空间容量情况:
SELECT file_name, tablespace_name, bytes / 1024 / 1024 "bytes MB", maxbytes / 1024 / 1024 "maxbytes MB" FROM dba_data_files WHERE tablespace_name = 'AAA3TS';

SELECT file_id, file_name, tablespace_name, autoextensible, increment_by FROM dba_data_files WHERE tablespace_name = 'AAA3TS' ORDER BY file_id desc;

SELECT *FROM dba_data_files t WHERE t.tablespace_name = 'AAA3TS';

调整表空间容量的操作如下:
ALTER TABLESPACE AAA3TS ADD DATAFILE '/ora_data/aaa31.dbf' SIZE 2000M AUTOEXTEND ON NEXT 50M MAXSIZE 4G;

或者(自动增加,容量不封顶):
ALTER TABLESPACE AAA3TS ADD DATAFILE '/ora_data/aaa31.dbf' SIZE 2000M AUTOEXTEND ON NEXT 500M MAXSIZE UNLIMITED;

/*
  查询表空间内表名称
*/
SELECT TABLE_NAME FROM ALL_TABLES WHERE TABLESPACE_NAME='AAA3TS';

/*
  Windows下,项目部署Oracle数据库
*/
1. 首先确保Windows下Oracle安装配置完毕.即:创建基础数据库,设定系统管理员(sys,system)密码,配置Oracle全局'SID'等.
2. CMD窗口下输入下列命令并回车:
   sqlplus /nolog
   然后,在SQL提示符下执行:
   SQL>conn system/admin@ora11g as sysdba
   -- 其中: 'admin'为系统管理员密码,'ora11g'为Oracle全局'SID'.
   
   上述两条语句也可以简化为直接在CMD窗口输入下列命令并回车:
   sqlplus system/admin@ora11g as sysdba
   同样可以以管理员身份登入Oracle.

3. 查询数据库文件默认存储路径,在SQL提示符下执行:
SQL>select name from v$datafile;

查询结果例如:
E:\APP\ORACLE\ORADATA\ORA11G\SYSTEM01.DBF
E:\APP\ORACLE\ORADATA\ORA11G\SYSAUX01.DBF
E:\APP\ORACLE\ORADATA\ORA11G\UNDOTBS01.DBF
E:\APP\ORACLE\ORADATA\ORA11G\USERS01.DBF

说明E:\APP\ORACLE\ORADATA\ORA11G\即为数据库文件默认存储路径(Windows下路径不区分大小写).将该路径配置入对应的表空间创建脚本直接执行.
其余操作过程与Linux下的操作相类似.

/*
  Oracle中查询启动时间,正在执行的SQL语句,SQL语句连接程序
*/
查询Oracle启动时间:
SQL> select to_char(startup_time, 'DD-MON-YYYY HH24:MI:SS')started_at, TRUNC(sysdate - (startup_time))||'day(s),'||TRUNC(24*((sysdate-startup_time) -TRUNC(sysdate-startup_time))) ||'hour(s),'||MOD(TRUNC(1440*((SYSDATE-startup_time)-TRUNC(sysdate-startup_time))),60)||'minutes(s),'||MOD(TRUNC(86400*((SYSDATE-STARTUP_TIME)-TRUNC(SYSDATE-startup_time))),60)||'seconds' uptime from v$instance;

查询Oracle正在执行的SQL语句以及执行该语句的用户:
SQL> SELECT b.sid oracleID,
       b.username ,   -- 登录Oracle用户名
       b.serial#,
       spid,          -- 操作系统ID
       paddr,
       sql_text,      -- 正在执行的SQL
       b.machine      -- 计算机名
FROM v$process a, v$session b, v$sqlarea c WHERE a.addr = b.paddr AND b.sql_hash_value = c.hash_value;
   
查询正在执行SQL发起者的连接程序:
SQL> SELECT OSUSER,  -- 电脑登录身份
       PROGRAM,      -- 发起请求的程序
       USERNAME,     -- 登录系统的用户名
       SCHEMANAME,
       B.Cpu_Time,   -- 消耗CPU的时间
       STATUS,
       B.SQL_TEXT    -- 执行的SQL
FROM V$SESSION A
LEFT JOIN V$SQL B ON A.SQL_ADDRESS = B.ADDRESS AND A.SQL_HASH_VALUE = B.HASH_VALUE ORDER BY b.cpu_time DESC;

------------------------------------------------------------------------------------------------------------------------------------
/*
  Oracle表
*/
/*
  Oracle查看数据库中所有表名称
*/
1. 以sys管理员身份登录数据库;
2. SQL> select table_name from dba_tables;   --查看数据库中所有的表名称
3. SQL> select table_name from dba_tables where owner in ('XJCRBT','XJCRBTSTAT');  --仅查看新疆项目的所有表名称

/*
  Oracle中Dual表详解
*/
1. Dual表用途
Dual是Oracle中一个实际存在的表,任何用户均可读取,常用在没有目标表的Select语句中:
--查看当前连接用户
SQL> select user from Dual;
USER
------------------------------
SYSTEM

--查看当前日期,时间
SQL> select sysdate from Dual;
SYSDATE
-----------
2007-1-24 1

SQL> select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') from Dual;
TO_CHAR(SYSDATE,'YYYY-MM-DDHH2')
------------------------------
2007-01-24 15:02:47

--当作计算器用
SQL> select 1+2 from Dual;
1+2
----------
3

--查看序列值
SQL> create sequence aaa increment by 1 start with 1;
SQL> select aaa.nextval from Dual;
NEXTVAL
----------
1
SQL> select aaa.currval from Dual;
CURRVAL
----------
1

2. 关于Dual表的测试与分析
Dual就是个一行一列的表,如果执行insert,delete,truncate操作,可能导致很多程序出问题.结果也因Sqlplus Pl/Sql等工具而异.
--查看Dual是什么OBJECT
--Dual是属于SYS schema的一个表,然后以PUBLIC SYNONYM的方式供其它数据库USER使用.
SQL> select owner, object_name, object_type from dba_objects where object_name like '%Dual%';
OWNER OBJECT_NAME OBJECT_TYPE
---------- ----------------- ------------------
SYS Dual TABLE
PUBLIC Dual SYNONYM

--查看表结构,只有一个字段DUMMY,为VARCHAR2(1)型
SQL> desc Dual
Name Type NULLable Default Comments
----- ----------- -------- ------- --------
DUMMY VARCHAR2(1) Y

--Dual表的结构:
create table SYS.Dual
(
DUMMY VARCHAR2(1)
)
tablespace SYSTEM
pctfree 10
pctused 40
initrans 1
maxtrans 255
storage
(
initial 16K
next 16K
minextents 1
maxextents 505
pctincrease 50
);

Dual表可以执行插入/更新/删除操作,还可以执行drop操作.但是不能执行drop表操作,否则会使系统不能用,数据库无法启动,直接报错Database startup crashes with ORA-1092.

3. 如果Dual表被删除后的恢复:--下列SQL语句未经过实践校验,谨供参考
①用sys用户登陆;
②创建Dual表;
③授予公众SELECT权限(最好不要赋予UPDATE,INSERT,DELETE权限);
④向Dual表插入一条记录(仅此一条): insert into Dual values('X');
⑤提交修改;
--用sys用户登陆,建表
SQL> create table 'sys'.'Dual' ('DUMMY' varchar2(1)) pctfree 10 pctused 4;
SQL> insert into Dual values('X');
SQL> commit;
SQL> Grant select on Dual to Public;
--授权成功.

/*
  Oracle查看表中是否有曾经被UNUSED的列
*/
1. 首先查找被UNUSED的列的所属用户和表:
SQL>select * from DBA_UNUSED_COL_TABS;

OWNER                          TABLE_NAME                          COUNT
------------------------------ ------------------------------ ----------
TEST                           C4                                      1
--即TEST用户的C4表中存在UNUSED列;

2. 查找这个表的对象ID号:
SQL>select OBJECT_ID from dba_objects where OWNER='TEST' and OBJECT_NAME='C4';

OBJECT_ID
----------
      6354

3. 查找这个对象被UNUSED的列:
SQL>SELECT COL# ,NAME FROM COL$ WHERE OBJ# = 6354;

      COL# NAME
---------- ------------------------------
         1 OBJ#
         2 DATAOBJ#
         3 OWNER#
         4 NAME
         5 NAMESPACE
         6 SUBNAME
         0 SYS_C00007_05010709:37:17$
         7 MTIME
         8 STIME
         9 STATUS
        10 REMOTEOWNER

      COL# NAME
---------- ------------------------------
        11 LINKNAME
        12 FLAGS
        13 OID$
        14 SPARE1
        15 SPARE2
        16 SPARE3
        17 SPARE4
        18 SPARE5
        19 SPARE6

20 rows selected.

注意:其中COL#为0的就是被UNUSED的列,后缀以被UNUSED的时间为命名规则;
0 SYS_C00007_05010709:37:17$

4. 怎样删除所有已经被UNUSED的列:
alter table test.c4 drop unused columns;
----------------------------------------------------------------------------------------------------------------------------------
/*
  Oracle函数
*/
/*
  Oracle to_date 时间函数
*/
select * from tablename where tablename.date > to_date('2008-01-01 24:23:20', 'yyyy-mm-dd hh:mi:ss') and tablename.date < to_date('2008-01-01 24:23:20', 'yyyy-mm-dd hh:mi:ss') --比较时间SQL语句,对应数据库中日期型格式字段,即利用to_date构建时间格式.

-- eg1:
select * from apn_auth_stats where to_date(apn_auth_stats.AUTH_STATS_TIMESTAMP, 'yyyy-mm-dd hh24:mi:ss') > to_date('2014-07-15 23:23:20', 'yyyy-mm-dd hh24:mi:ss');

上述'apn_auth_stats.AUTH_STATS_TIMESTAMP'字段类型为'VARCHAR2(36)',该语句查询时间晚于'2014-07-15 23:23:20'的相关记录.
时间戳格式字符:'yyyy-mm-dd hh24:mi:ss'中'hh24'表示采用24小时时值.

-- 补充:
-- 针对'VARCHAR2'类型的字段数据与时间长度的比较,也可以直接使用'< >'符号进行.如下:
select count(*) from request_results where request_results.request_time < '2014-12-23 23:59:59';

上述'request_results.request_time'字段类型为'VARCHAR2(32)',该语句查询时间早于'2014-12-23 23:59:59'的相关记录数量.

/*
  Oracle Trunc 函数
*/
1. TRUNC(for dates)
语法: trunc(date,format)
用途:返回date经过截断后的日期,截断的位置由format指定,如果省略format,则默认截断到日.--注意此处的date一定是DATE型数据,如果仅仅是字符串需要用to_date()函数进行转换
trunc(to_date('2008-11-30 10:19:20','yyyy-mm-dd hh24:mi:ss'))              截断到日,结果为: 2008-11-30 00:00:00 
trunc(to_date('2008-07-30 13:19:20','yyyy-mm-dd hh24:mi:ss'),'yyyy')       截断到年,结果为: 2008-01-01 00:00:00

实例:
--截断到月
update corp_open_services t set t.open_date = to_date('2009-05-01 18:00:00', 'yyyy-mm-dd hh24:mi:ss') where trunc(t.open_date,'mm') = to_date('2009-06-01', 'yyyy-mm-dd');
--截断到小时
select *from corp_open_services t where trunc(t.open_date,'hh24') = to_date('2009-05-01 18:00:00', 'yyyy-mm-dd hh24:mi:ss');
--截断到年
select *from corp_open_services t where trunc(t.open_date,'yyyy') = to_date('2009-01-01 00:00:00', 'yyyy-mm-dd hh24:mi:ss');
--日期加减
SQL>select trunc(sysdate,'mm')+1   from   dual;   
    
  TRUNC(SYSDATE,'MM')+1   
  ---------------------   
  2009-1-2   
    
--返回结果为日期+数字(以日为单位);

2. TRUNC(for number)
语法: trunc(number,format)
用途:返回number经过截断后的数值,其工作机制与ROUND函数极为类似,只是该函数不对指定小数点前或后的部分做相应舍入选择处理,而直接截取.
参数:number 待做截取处理的数值 format 指明需保留小数点后面的位数.可选项,忽略它则截去所有的小数部分;

实例:
TRUNC(89.985, 2)     =89.98
TRUNC(89.985)        =89
TRUNC(89.985, -1)    =80

注意:第二个参数可以为负数,表示为小数点左边指定位数后面的部分截去,即均以0记;

/*
  Oracle 清空表数据
*/
truncate table raw_bill_bak;      --raw_bill_bak表中数据将被删除清空,且无法rollbak

/*
  Oracle 中获取当前日期及日期格式转换函数 SYSDATE/TO_CHAR/TO_DATE/TO_NUMBER
*/
获取系统日期: SYSDATE
格式化日期  : TO_CHAR    把日期或数字转换为字符串
                         TO_CHAR(number, '格式')
                         TO_CHAR(date, '格式')
              TO_DATE    把字符串转换为数据库中的日期类型
                         TO_DATE(char, '格式')
              TO_NUMBER  将字符串转换为数字
                         TO_NUMBER(char, '格式')                       

上述表示格式(日期,数字)常用的配置如下:
year    : y    表示年的最后1位
          yy   表示年的最后2位
          yyy  表示年的最后3位
          yyyy 用4位数表示年

month   : mm    用2位数字表示月
          mon   用简写形式,比如11月或者nov
          month 用全称,比如11月或者november

day     : dd  表示当月第几天
          ddd 表示当年第几天
          dy  当周第几天.简写,比如星期五或者fri
          day 当周第几天.全称,比如星期五或者friday

hour    :hh   2位数表示小时 12进制 00:00:00 - 12:59:59
          hh24 2位数表示小时 24小时 00:00:00 - 23:59:59

minute  : mi 2位数表示分钟
second  : ss 2位数表示秒 60进制
quarter : q  1位数 表示季度(1-4)
week    : ww 表示当年第几周 
          w  表示当月第几周

数字格式:  
9  代表一个数字
0  强制显示0
$  放置一个$符
L  放置一个浮动本地货币符
.  显示小数点
,  显示千位指示符

--eg:
返回系统日期
select sysdate from dual;

返回系统时间,采用24小时制,精确到秒
select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') from Dual;

输出 $10,000,00
select to_char(1000000,'$99,999,99') from dual;

输出 RMB10,000,00
select to_char(1000000,'L99,999,99') from dual;

输出 1000000.12
select trunc(to_number('1000000.123'),2) from dual;

当前时间减去7分钟的时间 
select sysdate,sysdate - interval '7' MINUTE from dual; 

当前时间减去7小时的时间 
select sysdate,sysdate - interval '7' hour from dual; 

当前时间减去7天的时间 
select sysdate,sysdate - interval '7' day from dual; 

当前时间减去7月的时间 
select sysdate,sysdate - interval '7' month from dual; 

当前时间减去7年的时间 
select sysdate,sysdate - interval '7' year from dual; 

时间间隔乘以一个数字 
select sysdate,sysdate - 8*interval '7' hour from dual;

/*
  Oracle Decode 函数
*/
1. 函数格式
格式1: 
decode(条件,值1,返回值1,值2,返回值2,...值n,返回值n,缺省值)

格式1含义:	
IF    条件=值1 THEN
    RETURN(返回值1)
ELSIF 条件=值2 THEN
    RETURN(返回值2)
    ......
ELSIF 条件=值n THEN
    RETURN(返回值n)
ELSE
    RETURN(缺省值)
END IF
---------- ----------------- ------------------

格式2:
decode(字段或字段的运算,值1,值2,值3)

格式2含义:
当字段或字段运算的值等于值1时,该函数返回值2,否则返回值3;值1,值2,值3也可以是表达式,这样使得某些sql语句简单了许多.
---------- ----------------- ------------------

格式3:
SELECT DECODE(value, <if this value>, <return this value>) FROM table
---------- ----------------- ------------------

2.使用方法 
(1)比较大小
select decode(sign(变量1-变量2),-1,变量1,变量2) from dual; --取较小值
sign()函数根据某个值是0,正数还是负数,分别返回0,1,-1

例如:
变量1=10,变量2=20
则sign(变量1-变量2)返回-1,decode解码结果为'变量1',达到了取较小值的目的.

(2)表,视图结构转化
现有一个商品销售表sale,表结构为:
month    char(6)      --月份
sell    number(10,2)   --月销售金额

现有数据为:
200001  1000
200002  1100
200003  1200
200004  1300
200005  1400
200006  1500
200007  1600
200101  1100
200202  1200
200301  1300

想要转化为以下结构的数据:
year   char(4)      --年份
month1  number(10,2)   --1月销售金额
month2  number(10,2)   --2月销售金额
month3  number(10,2)   --3月销售金额
month4  number(10,2)   --4月销售金额
month5  number(10,2)   --5月销售金额
month6  number(10,2)   --6月销售金额
month7  number(10,2)   --7月销售金额
month8  number(10,2)   --8月销售金额
month9  number(10,2)   --9月销售金额
month10  number(10,2)   --10月销售金额
month11  number(10,2)   --11月销售金额
month12  number(10,2)   --12月销售金额

结构转化的SQL语句为:
create or replace view
v_sale(year, month1, month2, month3, month4, month5, month6, month7, month8, month9, month10, month11, month12)
as
 select 
 substrb(month,1,4),
 sum(decode(substrb(month,5,2),'01',sell,0)),
 sum(decode(substrb(month,5,2),'02',sell,0)),
 sum(decode(substrb(month,5,2),'03',sell,0)),
 sum(decode(substrb(month,5,2),'04',sell,0)),
 sum(decode(substrb(month,5,2),'05',sell,0)),
 sum(decode(substrb(month,5,2),'06',sell,0)),
 sum(decode(substrb(month,5,2),'07',sell,0)),
 sum(decode(substrb(month,5,2),'08',sell,0)),
 sum(decode(substrb(month,5,2),'09',sell,0)),
 sum(decode(substrb(month,5,2),'10',sell,0)),
 sum(decode(substrb(month,5,2),'11',sell,0)),
 sum(decode(substrb(month,5,2),'12',sell,0))
 from sale
 group by substrb(month,1,4); 

3. 实际应用  --下列SQL语句未经过实践校验,谨供参考
decode函数在实际开发中非常有用
(1) 结合LPAD函数,如何使主键的值自动加1并在前面补0
select LPAD(decode(count(记录编号),0,1,max(to_number(记录编号)+1)),14,'0') 记录编号 from tetdmis

例如: 
select decode(dir,1,0,1) from a1_interval;

dir 的值是1变为0,是0则变为1.

(2) 查询某班男生和女生的数量分别是多少
select decode(性别,男,1,0),decode(性别,女,1,0) from 表;

(3) 某企业进行工资调整,标准为:工资在8000元以下加薪20%;工资在8000元以上加薪15%
通常做法:
① 选出记录中的工资字段值   select salary into var-salary from employee;
② 对变量var-salary用 if-then-else 或 choose case end之类的流控制语句进行判断. 

decode函数处理:
select decode(sign(salary - 8000),1,salary*1.15,-1,salary*1.2,salary) from employee;

/*
  Oracle中decode函数和CASE语句比较
*/   
--下列SQL语句未经过实践校验,谨供参考
举两个简单的例子,对比一下这两者的区别:
1. CASE语句:
SELECT CASE SIGN(5 - 5)
            WHEN  1  THEN    'Is Positive'
            WHEN -1  THEN    'Is Negative'
            ELSE    'Is Zero'
            END
FROM   DUAL;

--中断符,无意义
END END
END END

后台实现:
if (SIGN(5 – 5) = 1) 
{
	'Is Positive';
} 
else if 
(SIGN(5 – 5) = -1 ) 
{
	'Is Negative';
}
else 
{
	'Is Zero';
}
    
2. Decode函数:
SELECT DECODE(SIGN(5 – 5), 1, 'Is Positive', -1, 'Is Negative', 'Is Zero') FROM DUAL;
后台实现:
switch (SIGN(5 – 5))
{
   case 1 :  'Is Positive';  break;
   case 2 :  'Is Negative';  break;
   default :  'Is Zero'
}

--中断符,无意义
END END
END END

在上面的例子中,两者似乎都可以实现.但是,在遇到特殊的问题时,Decode()要实现起来就相当复杂了.
例如:
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;

--中断符,无意义
END

因此,一般情况下,'CASE'语句在处理类似问题时较为灵活.当仅需要匹配少量数值时,用Decode更为简洁.

/*
  Oracle Substr 函数
*/
函数格式:substr(string, start_position, [length] )
函数用途:截取字符串中指定起始位置及长度的字符串. 
例如:
substr('This is a test', 6, 2)     would return 'is'
substr('This is a test', 6)        would return 'is a test'
substr('TechOnTheNet', -3, 3)      would return 'Net'        --从字符串尾部倒数第三个字符作为起始位置.
substr('TechOnTheNet', -6, 3)      would return 'The'
substr('Hello', -6)                would return  NULL

-- eg:
select *from user_autz where autz_attr = 'User_Month_Activation' and substr(autz_value, 6, 2) = 05 ;

/*
  Oracle Round 函数
*/
格式:SELECT ROUND(number, [decimal_places]) FROM DUAL 
用途:返回一个数值,该数值是按照指定的小数位数进行四舍五入运算的结果.
参数: 
number:待处理数值 
decimal_places:四舍五入操作,小数取几位(默认值为0) 
例如:
select round(123.456, 0)  from dual;       would return 123 
select round(123.456, 1)  from dual;       would return 123.5 
select round(123.456, 2)  from dual;       would return 123.46 
select round(123.456, 3)  from dual;       would return 123.456 
select round(-123.456, 2) from dual;       would return -123.46
------------------------------------------------------------------------------------------------------------------------------------
/*
  Oracle系统包
*/
  包名称                   包头文件	              说明                                                                                 
dbms_aleri               dbmsalrt.sql	    异步处理数据库事件                                                                           
dbms_application_info    dbmsutil.sql       注册当前运行的应用的名称(用于性能监控)                                                       
dbms_aqadm               dbmsaqad.sql	    与高级队列选项一起使用                                                                       
dbms_ddl                 dbmsutil.sql	    重新编译存储子程序和包,分析数据库对象                                                        
dbms_debug               dbmspb.sql	        PL/SQL调试器接口                                                                             
dbms_deffr               dbmsdefr.sql	    远程过程调用应用的用户接口                                                                   
dbms_describe            dbmsdesc.sql	    说明存储子程序的参数                                                                         
dbms_job                 dbmsjob.sql	    按指定的时间或间隔执行用户定义的作业                                                         
dbms_lock                dbmslock.sql	    管理数据库块                                                                                 
dbms_output              dbmsotpt.sql	    将文本行写入内存/供以后提取和显示                                                            
dbms_pipe                dbmspipe.sql	    通过内存'管道'在会话之间发送并接收数据                                                       
dbms_profiler            dbmspbp.sql	    用于配置PL/SQL脚本以鉴别瓶颈问题                                                             
dbms_refresh             dbmssnap.sql	    管理能够被同步刷新的快照组                                                                   
dbms_session             dbmsutil.sql	    程序执行alter session(改变会话)语句                                                          
dbms_shared_pool         dbmspool.sql	    查看并管理共享池内容                                                                         
dbms_snapshot            dbmssnap.sql	    刷新,管理快照,并清除快照日志                                                                 
dbms_space               dbmsutil.sql	                                          
dbms_sql                 dbmssql.sql	    执行动态SQL和PL/SQL                                                                          
dbms_system              dbmsutil.sql	    开/关给定会话的SQL追踪                                                                       
dbms_transaction         dbmsutil.sql	    管理SQL事务                                                                                  
dbms_utility             dbmsutil.sql	    多种实用工具:对于一个给定的模式,重新编译存储子程序和包/分析数据库对象/                       
                                            格式化错误信息并调用堆栈用于显示/显示实例是否以并行服务器模式运行/以10毫秒间隔获取当前时间/  
                                            决定数据库对象的全名/将一个PL/SQL表转换为一个使用逗号分割的字符串,获取数据版本/操作系统字符串
utl_raw                  utlraw.sql	        RAW数据转化为字符串                                                                          
utl_file                 utlfile.sql	    读/写基于ASCII字符的操作系统文件                                                             
utl_http                 utlhttp.sql	    从给定的URL得到HTML格式的主页                                                                
dbms_lob                 dbmslob.sql	    管理巨型对象

/*
  Oracle dbms_random 包的用法
*/
1. dbms_random.value方法
dbms_random是一个可以生成随机数值或者字符串的程序包.包中initialize(),seed(),terminate(),value(),normal(),random(),string()等几个函数,但value()是最常用的,value()的用法一般有两种:
(1) function value return number; 
这种用法没有参数,会返回一个具有38位精度的数值,范围从0.0到1.0,但不包括1.0,如下示例: 
SQL> set serverout on 
SQL> begin 
   2  for i in 1..10 loop 
   3      dbms_output.put_line(round(dbms_random.value*100)); 
   4    end loop; 
   5  end; 
   6  / 
46 
19 
45 
37 
33 
57 
61 
20 
82 
8 
  
PL/SQL 过程已成功完成. 
(2) 
第二种value带有两个参数,第一个指下限,第二个指上限,将会生成下限到上限之间的数字,但不包含上限,如下: 
SQL> begin 
   2  for i in 1..10 loop 
   3      dbms_output.put_line(trunc(dbms_random.value(1,101))); 
   4    end loop; 
   5  end; 
   6  / 
97 
77 
13 
86 
68 
16 
55 
36 
54 
46 
  
PL/SQL 过程已成功完成. 

(3)
Order By dbms_random.value;  
这条语句功能是实现记录的随机排序,该语句为结果集的每一行计算一个随机数,dbms_random.value 是结果集的一个列(虽然这个列并不在select list 中).
然后根据该列排序,得到的顺序自然就是随机的.

2. dbms_random.string方法

某些用户管理程序可能需要为用户创建随机的密码.使用10G下的dbms_random.string 可以实现该功能.

例如:
SQL> select dbms_random.string('P',8 ) from dual ;
 
DBMS_RANDOM.STRING('P',8)
--------------------------------------------------------------------------------
3q<Myf[2
 
第一个参数的含义:
'u', 'U' - returning string in uppercase alpha characters
'l', 'L' - returning string in lowercase alpha characters
'a', 'A' - returning string in mixed case alpha characters          END END --中断符,无意义
'x', 'X' - returning string in uppercase alpha-numeric characters
'p', 'P' - returning string in any printable characters.
Otherwise the returning string is in uppercase alpha characters.
P 表示 printable,即字符串由任意可打印字符构成

而第二个参数表示返回的字符串长度.

3. dbms_random.random方法
random返回的是BINARY_INTEGER类型值,产生一个任意大小的随机数;

dbms_random.value 和 dbms_random.random 两者之间的区别:
(1)value返回的是number类型,并且返回的值介于1和0之间;
(2)random返回的是BINARY_INTEGER类型(以二进制形式存储的数字,据说运算的效率高于number,但取值范围肯定小于number)

4. dbms_random.normal方法 

NORMAL函数返回服从正态分布的一组数.此正态分布标准偏差为1,期望值为0.这个函数返回的数值中有68%是介于-1与+1之间,95%介于-2与+2之间,99%介于-3与+3之间.

5. dbms_random.send方法  

用于生成一个随机数种子,设置种子的目的是可以重复生成随机数,用于调试.否则每次不同,难以调度.
------------------------------------------------------------------------------------------------------------------------------------
/*
  SQL实际应用例子
*/
/*
  实例一
*/
Student(sid,sname,age,class),SC(sid,cid,score),course(cid,cname,teacher) ,如何用一条SQL语句查询出'英语'这门课每个班级第一名的学生名字

select sname from (select sname, class, score from Student stu, SC sc where stu.sid = sc.sid) where (class, score) in (select class ,max(score) from Student stu, SC sc, course cou where (stu.sid = sc.sid and sc.cid = cou.cid and cou.cname = 'English' group by class))
  
/*
  实例二
*/
表:tblDept(ID,DeptName) 
表:tblSalary(ID,DeptID,Name,Salary) 
create table  tblDept(ID int,DeptName nvarchar(20))
create table  tblSalary(ID int,DeptID int,Name nvarchar(20),Salary decimal(10,2))
请用SQL语句写出: 
超过半数的部门员工工资大于3000元的部门

插入测试数据:

insert into tblDept
select 1,'DotNet' union all select 2,'Java'
insert into tblSalary
select 1,1,'张三',2000 union all
select 2,1,'李四',2800 union all
select 3,2,'王五',2900 union all
select 4,2,'找刘',3200 union all
select 5,2,'王启',3400 
原因:这里有两点概念没有弄清楚:count,整数相除   

1. COUNT : 和表达式的值无关

COUNT(*)                    计算数量,包括 NULL 值.
COUNT(ALL expression)       计算数量,不包括 NULL 值.
COUNT(DISTINCT expression)  计算唯一值数量,不包括 NULL 值.
--上述的expression对应数据库表中的某个字段名称

测试数据:
select count(t)
from (
select NULL t union  select 1 t  union  select 6 t 
) t
 
2. 整数相除,转换为数据必须*1.0转化
 
总结这样这个语句有两个写法:    
(1)
select * from tblDept
where id in(select DeptID from tblSalary group by DeptID having  
count(case when Salary>3000 then 1 else NULL end)*1.0/count(*)>0.5)

--中断符,无意义
END END

或: 

(2)
select * from tblDept
where id in(select DeptID from tblSalary group by DeptID having  
sum(case when Salary>3000 then 1 else 0 end)*1.0/count(*)>0.5)

--中断符,无意义
END END

(3)
select DeptName from tblDept where ID in (select DeptID from (select DeptID , count(*) counta from tblSalary where Salary > 3000 group by DeptID) a, (select DeptID , count(*) countb from tblSalary group by DeptID) b where ((a.DeptID = b.DeptID) and (a.counta * 2 > b.countb)) )

(4)
select 
a.[DeptName],sum(case when Salary>3000 then 1 else 0 end)*1.0/count(*) as 百分比 
from 
tblDept a 
join 
tblSalary b on a.ID=b.DeptID 
group by a.DeptName 
having sum(case when Salary>3000 then 1 else 0 end)*1.0/count(*) >0.5

--中断符,无意义
END END

/*
  SQL语句in用法
*/
delete from user_rings where ring_id = '102120000216' AND operate_ip in('135.224.80.121','135.224.80.122','135.224.80.185');

/*
  SQL语句关系符特定的查询
*/
select *from ring_infos where custom_num>0 order by custom_num asc;

/*
  SQL语句分组查询
*/
select mdn, count(imsi) from mdn_imsi group by mdn having count(imsi)>1; 

执行结果:查询表mdn_imsi中,查询一个mdn对应多个imsi的mdn及imsi数量.

/*
  SQL语句set用法号码解锁
*/
update crbt_users set lock_sTatus='N',LOCK_DATE=SYSDATE-1 WHERE ACCOUNTID='09918240061';

/*
  超长SQL语句
*/
-- 彩铃订购统计
-- 1.个人广告彩铃订购,需要从USER_RINGS表中统计
-- 2.集团广告彩铃订购为广告集团成员数
--  2.1:如果是当天新上传的铃声,则当天的统计数据默认为当天集团名下的成员个数.
--  2.2:如果不是当天新上传的铃音,则数字为当天新加入集团的成员的个数(从);
-- 统计非当天上传的集团广告铃音和个人广告铃音的订购数目
INSERT INTO  STAT_ADRING_ORDER_DAY(
   AD_RING_ID,
   STAT_TIME,
   CITY_CODE,
   ACCOUNT_TYPE,
   ORDER_COUNT
)
WITH  
new_adrings_order_1 AS(
  SELECT b.ad_ring_id ,c.city_code,c.account_type,COUNT(0) cnt
  FROM USER_RINGS a,AD_RING_MAP b,CRBT_USERS c
  WHERE a.ring_id=b.real_ring_id 
  AND a.user_id = c.user_id
  AND b.ad_ring_type ='0'
  AND a.operate_date >=TRUNC(SYSDATE-1,'DD')
  AND a.operate_date <TRUNC(SYSDATE,'DD')
  GROUP BY b.ad_ring_id ,c.city_code,c.account_type
UNION ALL
  SELECT a.ad_ring_id,d.city_code,d.account_type,COUNT(
    CASE
      WHEN (TRUNC(a.upload_date,'DD') = TRUNC(SYSDATE-1,'DD') AND c.register_date<TRUNC(SYSDATE,'DD') )THEN 
        1
      WHEN(TRUNC(a.upload_date,'DD') < TRUNC(SYSDATE-1,'DD') AND TRUNC(c.register_date,'DD')=TRUNC(SYSDATE,'DD') ) THEN
        1
      ELSE
        NULL
    END 
    )cnt
  FROM AD_RINGS a,AD_RING_MAP b,CORP_USER_MEMBERS c,CRBT_USERS d
  WHERE a.ad_ring_id=b.ad_ring_id
  AND b.corp_id=c.corp_id
  AND c.tel=d.accountid
  AND b.ad_ring_type='1'
  GROUP BY a.ad_ring_id,d.city_code,d.account_type  
),
new_adrings_order_2 AS(
   SELECT a.ad_ring_id,a.city_code,a.account_type,SUM(a.cnt) CNT FROM new_adrings_order_1 a
   GROUP BY a.ad_ring_id,a.city_code,a.account_type
),
ad_ring_id_city_code AS(
SELECT a.city_code,b.ad_ring_id  FROM CITY_SECTIONS_NEW a,AD_RINGS b
)
SELECT a.AD_RING_ID,TO_char(SYSDATE-1,'YYYYMMDD'),a.CITY_CODE,'G',NVL(b.CNT,0) FROM ad_ring_id_city_code a LEFT JOIN (SELECT * FROM new_adrings_order_2 WHERE account_type='G') b ON (a.city_code=b.CITY_CODE AND a.AD_RING_ID=b.AD_RING_ID) 
UNION
SELECT a.AD_RING_ID,TO_char(SYSDATE-1,'YYYYMMDD'),a.CITY_CODE,'X',NVL(b.CNT,0) FROM ad_ring_id_city_code a LEFT JOIN (SELECT * FROM new_adrings_order_2 WHERE account_type='X') b ON (a.city_code=b.CITY_CODE AND a.AD_RING_ID=b.AD_RING_ID) 
UNION
SELECT a.AD_RING_ID,TO_char(SYSDATE-1,'YYYYMMDD'),a.CITY_CODE,'C',NVL(b.CNT,0) FROM ad_ring_id_city_code a LEFT JOIN (SELECT * FROM new_adrings_order_2 WHERE account_type='C') b ON (a.city_code=b.CITY_CODE AND a.AD_RING_ID=b.AD_RING_ID) 

--中断符,无意义
END END

/*
  Oracle批量insert数据
*/
--河北网通音乐广告平台建立号码组2000条数据
insert /*+append*/ into user_group_member (MEMBER_ID,GROUP_ID,USER_ID) select SEQ_USERGROUPMEMBER_ID.nextval,(select group_id from user_group where city_code = 'BD'),user_id from crbt_users where city_code = 'BD' and rownum < 2001;
commit; --SEQ_USERGROUPMEMBER_ID为MEMBER_ID的序列名称    crbt_users/user_group_member/user_group 三张表连表处理

/*pl/sql更新Oracle数据操作*/
使用pl/sql连接操作Oracle数据库时,如果需要对某张表中的数据进行操作,除了直接使用update语句之外,可以输入例如:
select *from stat_adring_calling_dtl_day for update;
然后直接在表stat_adring_calling_dtl_day的查询结果界面中,通过对某一条数据的某一个字段进行'解锁'操作,然后直接修改该字段内容,提交保存;

/*
  Oracle中正斜线(/)
*/
正斜杠(/): 在Oracle中,用来终止SQL语句.更准确地说,是表示'运行现在位于缓冲区的SQL代码'.正斜杠也用作分隔项.

例如: 在PL/SQL中直接执行下列语句
CREATE TABLE TEMP (
    AAA VARCHAR2(36),
    BBB VARCHAR2(36)
)
INSERT INTO TEMP (AAA,BBB) VALUES ('TESTA','TESTB');
commit work;

就会报错: ORA-00922 选项缺失或无效

解决办法:
在CREATE, INSERT语句之间加入正斜杠(/)即可.例如:
CREATE TABLE TEMP (
    AAA VARCHAR2(36),
    BBB VARCHAR2(36)
)
/
INSERT INTO TEMP (AAA,BBB) VALUES ('TESTA','TESTB');
commit work;

-- 正斜杠(/)与分号(;)的区别
1. 分号表示SQL语句的结束,而正斜杠表示立刻执行当前SQL语句.
2. SQL中编写存储过程时,必须以正斜杠结束.

/*
  Oracle中NUMBER/number/INT/int数据类型
*/
Oracle NUMBER datatype 
语法:  NUMBER[(precision [, scale])]
简称:  precision --> p
       scale     --> s

NUMBER(p, s)
范围:
  1 <= p <= 38
-84 <= s <= 127

保存数据范围:
-1.0e-130 <= number value < 1.0e+126

保存在机器内部的范围:
1 ~ 22 bytes

有效位(p): 从左边第一个不为0的数算起的位数.
(s)的情况:
s > 0
   精确到小数点右边s位,并四舍五入.然后检验有效位能不能<= p
s < 0
   精确到小数点左边s位,并四舍五入.然后检验有效位能不能<= p + s
s = 0
   此时NUMBER表示整数.

eg:
Actual Data   Specified As   Stored As
----------------------------------------
123.89        NUMBER         123.89
123.89        NUMBER(3)      124
123.89        NUMBER(6,2)    123.89         -- 整数最大位数为4位(6-2=4),而小数最大位数为2位.
123.89        NUMBER(6,1)    123.9
123.89        NUMBER(4,2)    exceeds precision (有效位为5, 5 > 4)
123.89        NUMBER(6,-2)   100

-- 注意:
(1) 上述(s)为0时,NUMBER类型等价于其子类型INT.顾名思义:INT用于整型数据.其精度与NUMBER相同.
(2) NUMBER(38),最大可写9.e+37(还可以再大点,不过这是最简单的大数字).

/*
  Oracle中char/varchar/varchar2/nvarchar2数据类型区别
*/
1. char()类型:
(1) 长度固定,不足数据库规定长度,会补足长度.例如:存储字符串'abc',对于 CHAR(20),表示存储的字符将占20个字节(包括17个空字符).
(2) 一个全角认作2位长度.

2. varchar2()类型:  --varchar是varchar2的同义词
(1) 长度可变,不足数据库规定长度,不会补足长度.例如:存储字符串'abc',对于 VARCHAR2(20)只占用3个字节,20只是最大值,当存储字符小于20时,按实际长度存储.
(2) 一个全角认作2位长度.

3. nvarchar2()类型:
(1) 长度可变,不足数据库规定长度,不会补足长度.
(2) 一个全角认作1位长度.

结论:CHAR的效率比VARCHAR2的效率稍高,但是空字符浪费空间的情况也较为严重.做设计时,为节省系统资源,尽量选用varchar2()和 nvarchar2()类型.

-- 关于精度
1. 在SQL中使用varchar2来定义表时,最大长度为4000个字节.
-- eg:
drop table idb_varchar2;
create table idb_varchar2 (
    id number,
    name varchar2(4000 char)
);
insert into idb_varchar2 values(1, lpad('中',32767,'中'));
insert into idb_varchar2 values(2, lpad('a',32767,'b'));
commit work;

select id, lengthb(name), length(name) from idb_varchar2;

2. 在PL/SQL中使用varchar2来定义变量时,最大为32767个字节.
-- eg:
set serveroutput on
declare
    v_var varchar2(32767 byte);
    v_char varchar2(32767 char);
begin
    v_var := lpad('a',32767,'a');
    dbms_output.put_line(length(v_var));
    v_char := lpad('中',32767,'中');
    dbms_output.put_line(lengthb(v_var));
    v_var := lpad('中',32768,'中');
end;
/

-- 定义如果超过32768会报错
declare
    v_var varchar2(32768);
begin
    null;
end;
/

/*
  Oracle中union与union all的区别
*/
1. union 中含有 distinct 功能,会去掉重复数据.
2. union all 按原表中顺序排列,union 把数据重新排序.
3. union all 效率高于 union.

/*
  Oracle批量导入数据
*/
参考印象笔记中<20170919_Oracle常用参考资料_索引>.

猜你喜欢

转载自blog.csdn.net/yeahlow/article/details/79960379