sql server与oracle的区别
更新时间:2023-10-17 08:16:01 阅读量: 综合文库 文档下载
- sql server推荐度:
- 相关推荐
第1页
疯狂SQL之魔兽争霸
本人平时比较沉默,但朋友们都说我很疯狂—疯狂地学习、疯狂地工作。很久就有写点东西的打算啦,一直懒于打字,近来稍有空闲,决定杜撰此文,献给现些喜欢或不喜欢沉默的朋友。
----自序
网上已经有很多SQL与ORACLE的对比 ,但本人要讲的即不是单纯的SQL,也不是单纯的ORACLE,更不是评价谁好谁坏(意思不大),而是两种数据库之相同和异同,本人曾讲授过SQL与ORACLE的课程,讲SQL时说SQL好,讲ORACLE时又说ORACLE棒,现在终于可以平心而评啦。
估计有人现在会嘿嘿冷笑(又一个误人子弟的骗子),老实说,当初每次讲完课,就有这种感觉—教的人不得其法,学的人不得其道。说点严肃的事吧,据说比尔与艾里森在洗手间相遇,两个又是拥抱,又是KISS,不多久就吵了起来,比尔对查询分析器(SQL QUERY ANALYZE)赞不经绝口,艾里森嘿嘿冷笑,只说了一句话—SQL PLUS内秀。 言归正传,且听我一一道来
1. SQL与ORACLE的内存分配
ORACLE的内存分配大部分是由INIT.ORA来决定的,一个数据库实例可以有N种分配方案,不同的应用(OLTP、OLAP)它的配置是有侧重的。SQL概括起来说,只有两种内存分配方式:动态内存分配与静态内存分配,动态内存分配充许SQL自己调整需要的内存,静态内存分配限制了SQL对内存的使用。
1. 002、SQL与ORACLE的物理结构
总得讲,它们的物理结构很相似,SQL的数据库相当于ORACLE的模式(方案),SQL的文件组相当于ORACLE的表空间,作用都是均衡DISK I/O,SQL创建表时,可以指定表在不同的文件组,ORACLE则可以指定不同的表空间。 CREATE TABLE A001(ID DECIMAL(8,0)) ON [文件组]
-------------------------------------------------------------------------------------------- CREATE TABLE A001(ID NUMBER(8,0)) TABLESPACE 表空间
注:以后所有示例,先SQL,后ORACLE
2. 003、SQL与ORACLE的日志模式
SQL对日志的控制有三种恢复模型:SIMPLE、FULL、BULK-LOGGED;ORACLE对日志的控制有二种模式:NOARCHIVELOG、ARCHIVELOG。SQL的SIMPLE相当于ORACLE的NOARCHIVELOG,FULL相当于ARCHIVELOG,BULK-LOGGED相当于ORACLE大批量数据装载时的NOLOGGING。经常有
不足之处,敬请指正 xzhui@vip.sina.com QQ 77056803
第2页
网友抱怨SQL的日志庞大无比且没法处理,最简单的办法就是先切换到SIMPLE模式,收缩数据库后再切换到FULL,记住切换到FULL之后要马上做完全备份。
3. 004、SQL与ORACLE的备份类型
SQL的备份类型分的极杂:完全备份、增量备份、日志备份、文件或文件组备份;ORACLE的备份类型就清淅多啦:物理备份、逻辑备份;ORACLE的逻辑备份(EXP)相当于SQL的完全备份与增量备份,ORACLE的物理备份相当于SQL的文件与文件组备份。SQL的各种备份都密切相关,以完全备份为基础,配合其它的备份方式,就可以灵活地备分数据;ORACLE的物理备份与逻辑备份各司其职。SQL可以有多个日志,相当于ORACLE日志组,ORACLE的日志自动切换并归档,SQL的日志不停地膨胀??SQL有附加数据库,可以将数据库很方便地移到别一个服务器,ORACLE有可传输表空间,可操作性就得注意啦。
4. 005、SQL与ORACLE的恢复类型
SQL有完全恢复与基于时间点的不完全恢复;ORACLE有完全恢复与不完全恢复,不完全恢复有三种方式:基于取消的、基于时间的、基于修改的(SCN)的恢复。不完全恢复可以恢复数据到某个稳定的状态点。
5. 006、SQL与ORACLE的事务隔离
SET TRANSACTION ISOLATION LEVEL
SQL有四种事务隔离级别:
READ COMMITTED、READ UNCOMMITTED、REPEATABLE READ、SERIALIZABLE ORACLE有两种事务隔离级别 READ COMMITTED、SERIALIZABLE
SQL虽然有四种事务隔离,事务之间还是经常发生阻塞;ORACLE则利用回退段很好地实现了事务隔离,不会产生阻塞。SQL与ORACLE如果发生死锁,都可以很快地识别并将之处理掉。
6. 007 SQL与ORACLE的外键约束
SQL的外键约束可以实现级联删除与级联更新,ORACLE则只充许级联删除。 CREATE TABLE A001(ID INT PRIMARY KEY,NAME VARCHAR(20))
CREATE TABLE A002(ID INT REFERENCES A001(ID)ON DELETE CASCADE ON UPDATE CASCADE,AGE TINYINT)
CREATE TABLE A001(ID INT PRIMAY KEY,NAME VARCHAR2(20))
CREATE TABLE A002(ID INT REFERENCES A001(ID)ON DELETE CASCADE,AGE NUMBER(2,0))
不足之处,敬请指正 xzhui@vip.sina.com QQ 77056803
第3页
7. 008、SQL与ORACLE的临时表
SQL的临时表用#或##开头,使用完后自动释放,ORACLE的临时表则存在数据库中,每个会话的数据都互不干涉。oracle临时表中的纪录可以被定义为自动删除(分commit方式和transaction方式),而表结构不会被自动删除。临时表的DML,DDL操作和标准表一样。 CREATE TABLE #TEMP(ID INT,NAME VARCHAR(20))
------------------------------------------------------- CREATE GLOBAL TEMPORARY TABLE TEMP(ID INT,VARCHAR2(20))
8. 009、SQL与ORACLE的类型转换
SQL常用类型转换函数有:CAST、CONVERT、STR
ORACLE常用类型转换函数有:TO_CHAR、TO_NUMBER、TO_DATE
SELECT CONVERT(VARCHAR(20),GETDATE(),112)
------------------------------------------------------------------------------------------------
SELECT TO_CHAR(SYSDATE,‘YYYYMMDD’)FROM DUAL
9. 010、SQL与ORACLE的自动编号
SQL的编号一般由IDENTITY字段来提供,可以灵活地设定种子值,增量,取值范围有BIGINT、INT、SMALLINT、TINYINT、DEIMAL等;ORACLE的编号一般由SEQUENCE来提供,由NEXTVAL与CURVAL函数从SEQUENCES取值。
CREATE TABLE A003(ID INT IDENTITY(-9999,9),NAME VARCHAR(20))
-------------------------------------------------------------------------------------------------------
CREATE SEQUENCE SEQ_001 START 9999 INCREMENT BY 9 CREATE TABLE A004(ID INT)
INSERT INTO A004 VALUES(SEQ_001.NEXTVAL) INSERT INTO A004 VALUES(SEQ_001.CURVAL+1)
10. 011、SQL与ORACLE的分区表
从严格意思上来讲,SQL还没有分区表,它的分区表是以UNION为基础,将多个结果集串起来,实际上是视图;ORACLE的分区表有多种:PARTITION BY RANGE、PARTITION BY HASH、PARTITION BY LIST,其它就是混合分区,以上三种基础分区的混合使用。当然ORACLE也可以象SQL那样分区视图。
CREATE TABLE A1999(ID INT,NAME VARCHAR(20))
不足之处,敬请指正 xzhui@vip.sina.com QQ 77056803
第4页
CREATE TABLE A2000(ID INT,NAME VARCHAR(20)) CREATE VIEW V_PART AS
SELECT * FROM A1999 UNION SELECT * FROM A2000
-------------------------------------------------- CREATE TABLE A_PART1(ID INT,NAME VARCHAR2(20))
PARTITON BY RANGE(ID)(
PARTITION P1 VALUES LESS THEN (2000000) PATITION P2 VALUES LESS THEN (MAXVALUE)) CREATE TABLE A_PART2(ID INT,NAME VARCHAR2(20))
PARTITION BY HASH(ID) PARTITIONS 2 STORE IN (USERS01,USERS02) CREATE TABLE A_PART3(ID INT,NAME VARCHAR2(20)) PARTITION BY LIST(ID)(
PARTIION P1 VALUES(‘01’,’03’,’05’) PARTITON P2 VALUES(‘02’,’04’))
11. 012、SQL与ORACLE的存储过程
SQL的存储过程可以很方便地返回结果集,ORACLE的存储过程只有通过游标类型返回结果集,这种结果集ADO不可识别,如果想使用ORACLE存储过程的结果集,只有使用ODAC开发包(DELPHI/BCB控件组 www.51delphi.com 与www.playicq.com有下载),SQL的过程参数如果是字符必须指定参数长度,ORACLE的过程则不充许指定字符参数的长度。 CREATE PROCEDURE UP_001(@ID INT) AS BEGIN
SELECT ID ,SUM(QTY) FROM A_TEST WHERE ID=@ID GROUP BY @ID END
------------------------------------------------------------ CREATE OR REPLACE PACKAGE UP_002 AS TYPE MYCURSOR IS REF CURSOR;
FUNCTION GETRECORD RETURN MYCURSOR; END;
CEEATE OR REPLACE PACKAGE BODY UP_002 AS FUNCTION GETRECORD RETURN MYCURSOR AS MC MYCURSOR; SL VARCHAR2(999); BEGIN OPEN MC FOR SELECT * FROM A001; RETURN MC; END;
END;
ORACLE的存储函数返回结果这么艰难,但SQL的触发器竟然也充许返回结果集就令人费解啦,触发器的调试比较麻烦,在SQL实际开发中,一般都将触发器要执行的代码放到过程中进行调试,在查询分析器中可以对过程进行设断点调试。
不足之处,敬请指正 xzhui@vip.sina.com QQ 77056803
第5页
12. 013、SQL与ORACLE的触发器
触发器的事务是引起触发动作事务的延续,在SQL的触发器中是可以无BEGIN TRAN而可以直接COMMIT TRAN的。SQL的触发器是表级触发器,DML影响一行或无数行触发动作只触发一次,ORACLE分表级触发器与行级触发器,触发的粒度更细腻一些,SQL在处理多行时就必须使用CURSOR啦。ORACLE使用INSERTING、DELTING、UPDATING判断执行了什么DML操作,SQL只有判断INSERTED、DELETED的记录数来判断执行了什么操作,只有INSERTED映象表记录数大于0表示INSERT,只有DELETED映象表记录数大于0表示DELETE,若两个表记录数都大于0表示UPDATE。
用SQL的触发器实现级联添加、级联删除、级联更新 CREATE TABLE A1(ID INT,NAME VARCHAR(20)) CREATE TABLE A2(ID INT,NAME VARCHAR(20)) CREATE TRIGGER TRI_A1_INS ON A1 FOR INSERT , DELETE , UPDATE AS BEGIN DECLARE @I INT,@D INT,@ID INT SELECT @I=COUNT(*) FROM INSERTED
SELECT @D=COUNT(*) FROM DELETED
--IF (@I>0 AND @D>0) 执行更新,由于用到游标,故略去 IF @I>0
INSERT INTO A2 SELECT * FROM INSERTED IF @D>0
DELETE FROM A2 WHERE ID=@ID END
---------------------------------------------------------------------- 用ORACLE的触发器实现级联添加、级联删除、级联更新 CREATE OR REPLACE TRI_A1_INS
AFTER INSERT OR DELETE OR UPDATE ON A1 FOR EACH ROW BEGIN
IF INSERTING THEN INSERT INTO A2 SELECT * FROM :NEW; IF DELETING THEN DELETE FROM A2 WHERE ID = :OLD.ID ;
END IF;
END IF; IF UPDATING THEN
UPATE A2 SET ID = :NEW.ID , NAME = :NEW.NAME WHERE ID = :OLD.ID ; END IF; END
不足之处,敬请指正 xzhui@vip.sina.com QQ 77056803
第11页
24. 25、SQL与ORACLE快速建表的方法?
SELECT * INTO 新表名称 FROM 子查询|表名 ----------------------------------------- CREATE TABLE 新表名称 AS 子查询
说明 快速建表可以有效地消除碎片,速度极快。
25. 26、如何实现有一组有规则的编号(如200305310001?200305310999)?
declare @i int,@c varchar(20) select @i=1
while @i<1000 begin
select @c=case when @i<10 then '000'+cast(@i as char(1))
when @i between 10 and 99 then '00'+cast(@i as char(2)) when @i between 100 and 999 then '0'+cast(@i as char(3)) end
select @c=convert(varchar(20),getdate(),112)+@c select @c --在查询分析器中输出 select @i=@i+1 end
--------------------------------------------------------- declare
c varchar2(20); begin
for i in 1 .. 999 loop
dbms_output.put_line(to_char(sysdate,'yyyymmdd')||lpad(i,4,'0')); end loop; end;
说明 虽然都可以实现,但ORACLE的LPAD果然身手不凡,可怜的MS还没有类似LPAD的函数,只有用CASE进行判断组合,真得很蠢,如果你有好的办法,请明示,甚至连循环结构,SQL稍也不慎,就死循环啦(如果注释掉加蓝显示那条语句的话)。
26. 27、关于SQL与ORACLE的分布式结构
SQL在分布式方面做得不错,不仅提供了链接服务器的方式供初级用户使用,还提供了OPENDATASOURCE、OPENXML、OPENQUERY、OPENROWSET等行集函数,可以方便地通过SQL语句从*.TXT、*.XLS、*.XML、*.MDB、*.DBF等介质获取数据,还可以从ORACLE、DB2、SYBASE等数据库获取数据;ORACLE在同构数据库之间提供了DB LINK,异构数据库之间提供了透明网关软件。
不足之处,敬请指正 xzhui@vip.sina.com QQ 77056803
第12页
27. 28、现在有三个表,结构如下
Score(FScoreId 成绩记录号,FSubID 课程号,FStdID 学生号,FScore 成绩) student:(FID 学生号,FName 姓名)
subject:(FSubID 课程号,FSubName 课程名), 怎么能实现这个表:
姓名 英语 数学 语文 历史 张萨 78 67 89 76 王强 89 67 84 96 李三 70 87 92 56 李四 80 78 97 66
SELECT a.FName AS 姓名,
英语 = SUM(CASE b.FSubName WHEN '英语' THEN c.FScore END), 数学 = SUM(CASE b.FSubName WHEN '数学' THEN c.FScore END), 语文 = SUM(CASE b.FSubName WHEN '语文' THEN c.FScore END), 历史 = SUM(CASE b.FSubName WHEN '历史' THEN c.FScore END) FROM Student a, Subject b, Score c
WHERE a.FID = c.FStdId AND b.FSubID = c.FsubID GROUP BY a.FName
------------------------------------------------------------------------ SELECT a.FName AS 姓名,
英语 = SUM(DECODE(B.FsubName,’ 英语’,C.Fsore)), 数学 = SUM(DECODE(B.FsubName,’ 数学’,C.Fsore)), 语文 = SUM(DECODE(B.FsubName,’ 语文’,C.Fsore)), 历史 = SUM(DECODE(B.FsubName,’ 历史’,C.Fsore)), FROM Student a, Subject b, Score c
WHERE a.FID = c.FStdId AND b.FSubID = c.FsubID GROUP BY a.FName 说明 这个案例主要是运用CASE与DECODE,当然也涉及GROUP BY的用法。
28. 29、有两个表,用一条SQL语句算出商品A,B目前还剩多少?表结构如下:
商品名称mc 商品总量sl 表一(AAA) A 100 B 120
商品名称mc 出库数量sl 表二(BBB) A 10 A 20 B 10 B 20
select TA.商品名称,A-B AS 剩余数量 FROM
(select 商品名称,sum(商品总量) AS A from AAA group by 商品名称)TA, (select 商品名称,sum(出库数量) AS B from BBB group by 商品名称)TB
不足之处,敬请指正 xzhui@vip.sina.com QQ 77056803
第13页
where TA.商品名称=TB.商品名称
---------------------------------------------------------- select 商品名称,sum(商品总量)剩余数量 from (select * from aaa union ALL
select 商品名称,-出库数量 from bbb)a group by 商品名称
29. 30、如何将A表的某个字段更新到表B的某个字段?
UPDATE A SET QTY=B.QTY FROM B WHERE A.CODE=B.CODE --------------------------------------------------- UPDATE A SET QTY=(SELECT QTY FROM B WHERE B.CODE=A.CODE)
说明 这两道题在语法上SQL与ORACLE没有发别,只不过是两种思路而已。
30. 31、有一个商品销售表,记载了某月商品的销售数量,现在要为所有商品排名次,放
到一个单独的字段中,就是说达到右边显示的效果,如何作?
BU1032 5 PS2091 3 NULL BU1032 5 2 NULL PS2092 3 3
PC8888 50 NULL PC8888 50 1
UPDATE x set ord=(select count(*)+1 from x b where b.qty>x.qty) ----------------------------------------------------------------
select code,qty,rank() over (order by qty) ord from a_test
说明 SQL中的排序是通过UPDATE更新,然后再显示出来,而ORACLE使用了RANK OVER函数,直接将数据集显示出来,而且RANK OVER函数还可以通过PARTITION BY对分组中的数据进行排序。
31. 32、SQL与ORACLE的文件结构
SQL文件被格式化为8K为单位的页,每8个相邻的页称为盘区(64K),若该盘区分配给一个对象,称为一致盘区,若分配给多个对象等为混合盘区,SQL有全局分配页面、数据页面、索引页页、BLOB页面、TEXT页面。ORACLE的文件最小逻辑单位是由INIT.ORA中的BLOCK_SIZE的值决定的,可以取2K、4K、6K、8K、16K、32K等,ORACLE的盘区是由一些块组成的,ORACLE的段是由盘区组成的,ORACLE有数据段、索引段、回退段(UNDO段)、临时段、CLOB/BLOB段、CLUSTER段等。
不足之处,敬请指正 xzhui@vip.sina.com QQ 77056803
第14页
32. 33、SQL与ORACLE如何取得一个全局唯一标识标(GUID)
SELECT NEWID()
---------------------------------- SELECT SYS_GUID() FROM DUAL
33. 34、本人有一张表单, 要求统计col1~col6中不等于2的列的个数,数据如下:
———————————————————————————————— row_id | col1 | col2 | col3 | col4 | col5 | col6 | 1 | 2 | 1 | 1 | 2 | 3 | 2 | 2 | 1 | 1 | 2 | 2 | 2 | 2 | 3 | 2 | 3 | 2 | 2 | 1 | 2 | 4 | 2 | 2 | 2 | 2 | 1 | 2 | 5 | 1 | 2 | 2 | 2 | 2 | 2 | 6 | 2 | 2 | 2 | 2 | 2 | 1 | ———————————————————————————————— 要求结果如下: ————————— row_id | count | 1 | 3 | 2 | 2 | 3 | 2 | 4 | 1 | 5 | 1 |
6 | 1 |
select row_id,(6-(case when col1=2 then col1 / 2 else 0 end) -(case when col2=2 then col2 / 2 else 0 end) -(case when col3=2 then col3 / 2 else 0 end) -(case when col4=2 then col4 / 2 else 0 end) -(case when col5=2 then col5 / 2 else 0 end)
-(case when col6=2 then col6 / 2 else 0 end))as count from table_A
说明 本例摘自WWW.DELPHIBBS.COM,有名的DELPHI开发网站,本人不拥有版权。该SQL的实现方法与ORACLE的实现写法完全一样,不在多述。
34. 35、有一客户表,数据如下:
客户 日期 资金 F001 2003-03-05 123.00 F002 2003-03-04 1223.00
不足之处,敬请指正 xzhui@vip.sina.com QQ 77056803
第15页
F002 2003-03-02 1123.00
F003 2003-03-05 1231.00 F003 2003-03-04 1232.00
要求选出每个客户最新的哪条记录 组成一个结果集,结果如下: F001 2003-03-05 123.00 F002 2003-03-04 1223.00 F003 2003-03-05 1231.00
实现方法:
select a.客户, b.日期, a.资金 from 客户资金表 a,
(select 客户, max(日期) 日期 from 客户资金表 group by 客户 ) b where a.客户 = b.客户 and a.日期 = b.日期
说明 ORACLE的写法与SQL一样,本例也摘自WWW.DELPHIBBS.COM,本人不拥有版权。
35. 36 现在看一个高难度的作业,后来解决办法和本例不同,请看需求。
视图1 CITYWATER_VIEW 行政区划名称 城市用水量(亿M3) 。。。 北京市 上海市 天津市 重庆市
表1 DICTIONARY 字段别名 字段全名 区划 代码
表1-2是数据库public中的基表,表3是数据库water中的基表;在数据库water中创建视图1,用T-SQL语句怎样实现?把查询结果的“字段别名”修改为视图中的“字段全名”,如果采用T-SQL中的常用修改列标题方式(SELECT column_name AS expression或者SELECT expression= column_name ),很烦,每个基表里的字段太多,并且基表有近200个,字段近3000个。
说明:其实现在要作的就是将表3中的“代码“、“城市用水”替代成表1中的行政区划代码、城市用户量(亿M3)等。 create view v_god as
from code a,fa01p b where a.[200000]=b.[200000] declare cur_col cursor local for
不足之处,敬请指正 xzhui@vip.sina.com QQ 77056803
15000 9000 5400 9500 ? ? ? ? 表2 CODE 区划 北京市 上海市 代码 100000 200000 300000 表3 CITYWATER 代码 100000 200000 300000 城市用水 15000 9000 5400 行政区划名称 行政区划代码 城市用水 城市用水量(亿M3) 天津市 select
A.[100000],b.[310000],b.[114011],b.[114111],b.[114421],b.[114311],b.[114321]
第16页
select name from syscolumns where id=object_id('v_god') declare @col varchar(20),@sql varchar(999),
@col_total varchar(8000),@alias varchar(99), @source varchar(8000) open cur_col
fetch cur_col into @col while @@fetch_status=0
begin
select @alias=字段名 from dictionary where 段码=@col if @col_total is null select @col_total=@alias else
select @col_total=@col_total+','+@alias fetch cur_col into @col end
close cur_col
select @source=rtrim(text) from syscomments where id=object_id('v_god')
select @source=rtrim(substring(@source,charindex('as',@source),len(@source))) select @source='alter view v_god('+@col_total+') '+@source
exec(@source)
说明 由于该实例需要的表有两个已没有记录,所以大家只有看看T-SQL的语法及动态SQL的编写,ORACLE也类似。
36. 37、如何用SQL操作一段XML文件?
create procedure up_xml_test(@doc varchar(7999)) as
begin
declare @idoc int
exec sp_xml_preparedocument @idoc OUTPUT, @doc SELECT *
FROM OPENXML (@idoc, '/root/dataset/books',2) with(title varchar(32) 'title', author varchar(20) 'author', price decimal(9,2) 'price') exec sp_xml_removedocument @idoc end
create function uf_xml_test(@doc varchar(7999)) returns @t table(title varchar(32), author varchar(20), price decimal(9,2)) as
不足之处,敬请指正 xzhui@vip.sina.com QQ 77056803
第17页
begin end
declare @doc varchar(7999) select @doc= '
'
exec up_xml_test @doc
--select * from dbo.uf_xml_test(@doc)
说明 用过程可以方便地对XML进行操作,但编写成FUNCTION时就报错,大概MS的函数内部不充许执行OPENXML等这类行集函数。另一个重要的问题是,SQL的这种语法竟然不支持汉字字串,真是要命。
declare @idoc int
exec sp_xml_preparedocument @idoc OUTPUT, @doc insert into @t SELECT *
FROM OPENXML (@idoc, '/root/dataset/books',2) with(title varchar(32) 'title', author varchar(20) 'author', price decimal(9,2) 'price') exec sp_xml_removedocument @idoc return
37. 38、使用DBMS_REPAIR检测与修复破损的BLOCK?
ADMIN_TABLES CHECK_OBJECT DUMP_ORPHAN_KEYS 提供管理函数修复或孤立关键表,包含创建、净化与删除函数。 检测并报告表或索引的破损块。 导出破损块的数据 FIX_CORRUPT_BLOCKS 在CHECK_OBJECT检测出的破损块上做标记 REBUILD_FREELISTS 重建对象的FREELISTS 不足之处,敬请指正 xzhui@vip.sina.com QQ 77056803
第18页
SKIP_CORRUPT_BLOCKS 设置在表或索引扫描时是否不扫描被做了破损标记的块。 SEGMENT_FIX_STATUS 整理BITMAP实体上的破损标志 上表列举了DBMS_REPAIR包所有的过程,下边将对这些过程要引入的参数的枚举值进行 说明,这引些参数将在过程应用中起决定作用。
object_type TABLE_OBJECT, INDEX_OBJECT, CLUSTER_OBJECT action table_type flags
CREATE_ACTION, DROP_ACTION, PURGE_ACTION REPAIR_TABLE, ORPHAN_TABLE SKIP_FLAG, NOSKIP_FLAG SQL> exec dbms_repair.admin_tables('scott.emp',dbms_repair.repair_table,- dbms_repair.create_action,'USERS');
ORA-24129: 表名 scott.emp 没有以前缀 REPAIR_ 开始
SQL> exec dbms_repair.admin_tables('REPAIR_EMP',dbms_repair.repair_table,- dbms_repair.create_action,'USERS');
SQL> select object_name from REPAIR_EMP;
SQL> exec dbms_repair.admin_tables('ORPHAN_EMP',dbms_repair.ORPHAN_table,- dbms_repair.create_action,'USERS'); SQL> select table_name from orphan_emp;
ADMIN_TABLES过程可以创建DBMS_REPAIR包的使用中需要的一些辅助表。 SQL> declare m integer; begin
dbms_repair.check_object(schema_name=>'SCOTT', object_name=>'EMP',
repair_table_name =>'REPAIR_EMP', corrupt_count=>m); dbms_output.put_line(m);
end;
说明 统计SCOTT模式的EMP表有多少破损块。其它的过程本人就不再一一举例说明啦,引用方法类似与上边的实例,其它一些过程的参数列表可以通用SQL>DESC DBMS_REPAIR来查看。
38. 39、关于UTL_FILE包的使用方法
使用UTL_FILE时有个地方要注意:INIT.ORA文件中的UTL_FILE_DIR参数必须指定路径,即UTL_FILE包只有在UTL_FILE_DIR所指的目录中有权限读写,以下的实例表示本人已经修改UTL_FILE_DIR=C:\\啦。 SQL>DESC UTL_FILE
可以查看UTL_FILE包的所有类型与过程。 例将表中数据输出到文件:
create or replace procedure up_filew is
不足之处,敬请指正 xzhui@vip.sina.com QQ 77056803
第19页
id number;
name varchar2(20);
handle utl_file.file_type;
cursor region_cur is select * from a_job; begin
handle :=utl_file.fopen('c:\\','job.out','w'); open region_cur;
fetch region_cur into id,name; while region_cur%found loop
utl_file.putf(handle,'%s,%s\\n',id,name); fetch region_cur into id,name; end loop;
close region_cur;
utl_file.fflush(handle); utl_file.fclose(handle); end up_filew;
例将文件中数据写入到表中
create or replace procedure up_filer is Str Varchar(200); id number;
name varchar2(20);
handle utl_file.file_type; pos number(6); begin
handle :=utl_file.fopen('c:\\','job.out','r'); Utl_file.Get_line(Handle,Str);
while Length(Str)>0 loop pos:=instr(str,',');
id := to_number(substr(str,1,pos-1)); name:=substr(str,pos+1,length(str));
--dbms_output.put_line(to_char(id)||name); insert into a_job values(id,name); Utl_file.Get_line(Handle,Str); end loop; Exception when others then
utl_file.fclose(handle); end up_filer;
说明:由于没办法判断文件是否结束,所以本例就使用EXCEPTION处理,在文件读完时触发异常,并关闭文件。utl_file.file_type是文件句柄,就象C或PASCAL中读写文件的方式是一样的。
不足之处,敬请指正 xzhui@vip.sina.com QQ 77056803
第20页
39. 40、关于DBMS_JOB包的使用方法?
首先在SQL>DESC DBMS_JOB来查看DBMS_JOB的一些过程,然后可以在RDBMS目录中找到DBMSJOB.SQL,这个文件就是DBMS_JOB包的源程序,并有参数说明,本例就给出来实例与常用的数据字典(USER_JOBS、DBA_JOBS、ALL_JOBS)。 创建测试表
SQL> create table a_job(dt date);
创建一个自定义过程
SQL> create or replace procedure up_test as
begin
insert into a_job values(sysdate); end; /
创建JOB
SQL> variable job1 number; SQL>
SQL> begin
dbms_job.submit(:job1,'up_test;',sysdate,'sysdate+1/(24*60)'); --每天1440分钟,即一分钟运行test过程一次 end; / 运行JOB
SQL> begin
dbms_job.run(:job1); end; /
查看结果
SQL> select to_char(dt,'yyyy/mm/dd hh24:mi:ss') 时间 from a_job; 时间
------------------- 2001/01/07 23:51:21 2001/01/07 23:52:22 2001/01/07 23:53:24 删除JOB SQL> begin
2 dbms_job.remove(:job1); 3 end; 4 /
说明:job1是BIND VARIABLE(绑定变量),相当于一个常局变量,在当前会话的生命期内可以引用,如果我们要删除一个JOB,通常是从USER_JOBS字典中找到JOB的ID。 SQL> select job from user_jobs;
SQL>EXEC DBMS_JOB.REMOVE(上一句查出来的JOB号);
不足之处,敬请指正 xzhui@vip.sina.com QQ 77056803
第21页
40. 41、关于DBMS_SQL包的使用方法?
DBMS_SQL包是动态执行SQL语句的一个包,它使用方法比EXECUTE IMMEDIATE复杂,但功能更强大一些,最主要的是它执行的SQL可以超出64K的限制,DBMSSQL.SQL是该包的SQL源程序(RDBMS目录内)。 DECLARE
t_c1_tname user_tables.table_name%TYPE; t_command varchar2(200); t_cid integer; t_total_records number(10); stat integer; row_count integer; t_limit integer := 0; --限制只取出记录大于0的表的情况
cursor c1 is select table_name from user_tables order by table_name; --查出所有表的名字 BEGIN
t_limit := 0;
open c1; loop
--取出一个表名
fetch c1 into t_c1_tname;
--如果游标记录取完,退出循环
exit when c1%NOTFOUND;
t_command := 'SELECT COUNT(0) FROM '||t_c1_tname; t_cid := DBMS_SQL.OPEN_CURSOR; --创建一个游标
DBMS_SQL.PARSE(t_cid,t_command,dbms_sql.native); --向服务器发出一个语句并检查这个语句的语法和语义错误
DBMS_SQL.DEFINE_COLUMN(t_cid,1,t_total_records); --定义将从FetchRows()函数接收数据的变量的 stat := DBMS_SQL.EXECUTE(t_cid);
--执行此语句,必须跟着Fetch_Rows函数并为单个行检索数据 row_count := DBMS_SQL.FETCH_ROWS(t_cid);
--取回一行数据放入局部缓冲区
DBMS_SQL.COLUMN_VALUE(t_cid,1,t_total_records); --返回调用FetchRows()取回的值,值存储在t_total_records中 if t_total_records > t_limit then
DBMS_OUTPUT.PUT_LINE(rpad(t_c1_tname,55,' ')|| to_char(t_total_records,'99999999')||' record(s)'); end if;
DBMS_SQL.CLOSE_CURSOR(t_cid); end loop;
不足之处,敬请指正 xzhui@vip.sina.com QQ 77056803
第22页
close c1; END;
41. 42、SQL与ORACLE取随机数的方法,本例要求从65到90之间的随机数?
select 65+floor(rand()*26)
------------------------------------------- select floor(dbms_random.value(65,90)) from dual
42. 43、SQL与ORACLE取系统时间的方法
SELECT GETDATE()
-------------------------------------------
select to_char(sysdate,'yyyy-mm-dd hh24:mm:ss') from dual
43. 44、关于DBMS_FLASHBACK包的使用方法?
DBMS_FLASHBACK包处理ORACLE的闪回功能,它是ORACLE9i新增的一个功能,可以方便地提取表中数据的前映象。你不要指望闪回功能帮你找回所有有意或无意删除的数据,它最多只能得到5天内的前映象而不用回退日志。 SQL>DESC DBMS_FLASHBACK 现在看示例如下
SQL>CREATE TABLE A_TEST(ID INT);/*创建表后请退出SQL PLUS再进来做测试*/ SQL>insert into a_test values(1);
SQL>COmmit;
SQL>select dbms_flashback.get_system_change_number from dual;
此处显示SCN号1(77056701) SQL>insert into a_test values(2); SQL>commit;
SQL>select dbms_flashback.get_system_change_number from dual; 此处显示SCN号2 (77056801)
SQL>SELECT * FROM a_test as of SCN 77056701 SQL>SELECT * FROM a_test as of SCN 77056801 SQL>select * froM A_test
说明:如果创建表A_TEST后立即使用SELECT * FROM AS OF SCN 这种语法,ORACLE
会返回ORA-01466: 无法读数据 - 表定义已更改,这是正常的,只有退出再进来就可以使用闪回语法啦,SYS用户无法使用闪回语法。
相关链接:http://www.itpub.net/showthread.php?s=&threadid=116321
不足之处,敬请指正 xzhui@vip.sina.com QQ 77056803
第23页
44. 45、有一个表,记录数据较多,要求对同一分类的数据进行排序?
工號 姓名 時間 序號 001 abc 08:00 1 001 abc 12:01 2 001 abc 13:28 3 001 abc 17:40 4 002 def 07:30 1 002 def 22:59 2
SQL的解决方法如下:
create table a_test(id varchar(10),sj varchar(20),ord int) insert into a_test values('001','07',0) insert into a_test values('001','08',0) insert into a_test values('001','09',0) insert into a_test values('002','07',0) insert into a_test values('002','08',0) insert into a_test values('002','09',0) insert into a_test values('003','07',0)
insert into a_test values('003','08',0) insert into a_test values('003','09',0) update a_test set ord=(
select count(*)+1 from a_test b where b.sj
45. 46、SQL与ORACLE如何延时执行程序?
Waitfor DELAY ‘00:01:00’ --延时一分钟 waitfor TIME ’12:00:00’ --定时到12点整
------------------------------------------------ SQL>EXEC DBMS_LOCK.SLEEP(1)
说明:DBMS_LOCK.SLEEP延时一分钟与SQL第一条语法作用相当。
46. 47、SQL与ORACLE如何返回服务器的IP地址?
create procedure GetIP as begin
create table m(demo varchar(7999)) declare @sql varchar(99)
select @sql='xp_cmdshell '+'''ipconfig''' insert into m exec(@sql)
不足之处,敬请指正 xzhui@vip.sina.com QQ 77056803
第24页
declare @s varchar(99),@ip varchar(24),@p int,@l int
select @s=rtrim(ltrim(demo)) from m where demo like '%IP Address%' select @l=len(@s),@p=charindex(':',@s,1) select @ip=rtrim(ltrim(right(@s,@l-@p))) select @ip drop table m end
exec getip
------------------------------------------------------------ select SYS_CONTEXT('USERENV','IP_ADDRESS') from dual; exec dbms_output.put_line(utl_inaddr.get_host_address); 说明 SYS_CONTEXT求客户端IP地址,一般在触发器中使用
47. 48、SQL与ORACLE中对象是如何重命名的?
EXEC SP_RENAME ‘旧表名’,’新表名’
EXEC SP_RENAME ‘表名.字段名’,’新字段名’
EXEC SP_RENAMEDB ‘旧数据库名’,’新数据库名’
------------------------------------------------------------ RENAME 旧表名 to 新表名
数据库重命名可以用NID(从9i开始),字段重命名暂缺。
48. 49、ORACLE9i中INSERT 的新语法,源表的结构与数据示例如下:
SQL>SELECT * FROM sales_input_table;
PRODUCT_ID CUSTOMER_ID WEEKLY_ST SALES_SUN SALES_MON SALES_TUE SALES_WED SALES_THU SALES_FRI SALES_SAT
---------- ----------- --------- ---------- ---------- ---------- -------------------- ---------- ----------
111 222 01-OCT-00 100 200 300 400 500 600 700
222 333 08-OCT-00 200 300 400 500 600 700 800
333 444 15-OCT-00 300 400 500 600 700 800 900
sales_input_table表存储了商品每周的销售明细,将它转成如下所示? PROD_ID CUST_ID TIME_ID C PROMO_ID QUANTITY_SOLD AMOUNT COST ---------- ---------- --------- - ---------- ------------- ---------- ---------- 111 222 01-OCT-00 100 111 222 02-OCT-00 200
不足之处,敬请指正 xzhui@vip.sina.com QQ 77056803
第25页
111 222 03-OCT-00 300 111 222 04-OCT-00 400 111 222 05-OCT-00 500 111 222 06-OCT-00 600 111 222 07-OCT-00 700 222 333 08-OCT-00 200 222 333 09-OCT-00 300 222 333 10-OCT-00 400 222 333 11-OCT-00 500 222 333 12-OCT-00 600 222 333 13-OCT-00 700 222 333 14-OCT-00 800 333 444 15-OCT-00 300 333 444 16-OCT-00 400 333 444 17-OCT-00 500 333 444 18-OCT-00 600 333 444 19-OCT-00 700 333 444 20-OCT-00 800 333 444 21-OCT-00 900 请看下边的这组SQL语句,成功而方便地解决这个问题 SQL> INSERT ALL
INTO sales (prod_id, cust_id, time_id, amount)
VALUES (product_id, customer_id, weekly_start_date, sales_sun) INTO sales (prod_id, cust_id, time_id, amount)
VALUES (product_id, customer_id, weekly_start_date+1, sales_mon) INTO sales (prod_id, cust_id, time_id, amount)
VALUES (product_id, customer_id, weekly_start_date+2, sales_tue) INTO sales (prod_id, cust_id, time_id, amount)
VALUES (product_id, customer_id, weekly_start_date+3, sales_wed) INTO sales (prod_id, cust_id, time_id, amount)
VALUES (product_id, customer_id, weekly_start_date+4, sales_thu) INTO sales (prod_id, cust_id, time_id, amount)
VALUES (product_id, customer_id, weekly_start_date+5, sales_fri) INTO sales (prod_id, cust_id, time_id, amount)
VALUES (product_id, customer_id, weekly_start_date+6, sales_sat) SELECT product_id, customer_id, weekly_start_date, sales_sun, sales_mon, sales_tue, sales_wed, sales_thu, sales_fri, sales_sat FROM sales_input_table;
刚才看了INSERT ALL的用法,现在再看看INSERT ALL与WHEN的用法: CREATE TABLE small_orders
(order_id NUMBER(12) NOT NULL, customer_id NUMBER(6) NOT NULL, order_total NUMBER(8,2), sales_rep_id NUMBER(6) );
不足之处,敬请指正 xzhui@vip.sina.com QQ 77056803
第26页
CREATE TABLE medium_orders AS SELECT * FROM small_orders; CREATE TABLE large_orders AS SELECT * FROM small_orders; CREATE TABLE special_orders
(order_id NUMBER(12) NOT NULL, customer_id NUMBER(6) NOT NULL, order_total NUMBER(8,2), sales_rep_id NUMBER(6), credit_limit NUMBER(9,2),
cust_email VARCHAR2(30) );
现在已经创建了四个表,将测试的环境搭起来啦。 INSERT ALL
WHEN order_total < 1000000 THEN
INTO small_orders
WHEN order_total > 1000000 AND order_total < 2000000 THEN INTO medium_orders
WHEN order_total > 2000000 THEN
INTO large_orders
SELECT order_id, order_total, sales_rep_id, customer_id FROM orders;
当然,我们也可以使用ELSE来替代最后一个WHEN?THEN INSERT ALL
WHEN order_total < 100000 THEN INTO small_orders
WHEN order_total > 100000 AND order_total < 200000 THEN INTO medium_orders ELSE
INTO large_orders
SELECT order_id, order_total, sales_rep_id, customer_id FROM orders; 以上两组SQL功能是一样的。现在再看一下INSERT FIRST的用法: INSERT FIRST
WHEN ottl < 100000 THEN INTO small_orders
VALUES(oid, ottl, sid, cid)
WHEN ottl > 100000 and ottl < 200000 THEN INTO medium_orders
VALUES(oid, ottl, sid, cid) WHEN ottl > 290000 THEN INTO special_orders WHEN ottl > 200000 THEN
INTO large_orders
VALUES(oid, ottl, sid, cid)
SELECT o.order_id oid, o.customer_id cid, o.order_total ottl, o.sales_rep_id sid, c.credit_limit cl, c.cust_email cem
FROM orders o, customers c WHERE o.customer_id = c.customer_id;
不足之处,敬请指正 xzhui@vip.sina.com QQ 77056803
第27页
说明:Large_Orders表中将不含有OTT1>290000这部分数据。 INSERT ALL
WHEN ottl < 100000 THEN
INTO small_orders VALUES(oid, ottl, sid, cid) WHEN ottl > 100000 and ottl < 200000 THEN
INTO medium_orders VALUES(oid, ottl, sid, cid) WHEN ottl > 200000 THEN
into large_orders VALUES(oid, ottl, sid, cid) WHEN ottl > 290000 THEN INTO special_orders
SELECT o.order_id oid, o.customer_id cid, o.order_total ottl, o.sales_rep_id sid, c.credit_limit cl, c.cust_email cem
FROM orders o, customers c WHERE o.customer_id = c.customer_id;
说明:Large_Orders表中将含有OTT1>290000这部分数据,这就是INSERT ALL与INSERT FIRST的区别。
49. 50、ORACLE9i中WITH的新用法。可以理解成WITH是用来对ORACLE9i子查询定义别名
SQL> with total as ( select deptno,sum(sal) from emp group by deptno) select count(*) from total;
50. 51、ORACLE9i中MERGE的用法,若目录表中有匹配数据就更新,否则就添加新数据
MERGE INTO table_name AS table_alias
USING (table|view|sub_query) AS alias
ON (join condition)
WHEN MATCHED THEN UPDATE SET col1 = col_val1,col2 = col2_val
WHEN NOT MATCHED THEN INSERT (column_list) VALUES (column_values); 用SCOTT/TIGER登录测试 SQL> select * from dept; SQL>create table bbb
as
select * from dept where deptno in (10,20); SQL>merge into bbb
using dept on (dept.deptno=bbb.deptno)
WHEN MATCHED THEN UPDATE SET dname=dept.dname,loc=dept.loc when not matched then (dept.deptno,dept.dname,dept.loc);
insert
(deptno,dname,loc)
values
不足之处,敬请指正 xzhui@vip.sina.com QQ 77056803
第28页
51. 52、ORACLE系统触发器的类型与使用介绍(SQL没有系统触发器)
系统级触发器事件:
AFTER SERVERERROR 服务器错误触发 AFTER LOGON 登录后触发
BEFORE LOGOFF 退出登录前触发 AFTER STARTUP 启动数据库后触发
AFTER SUSPEND 数据库挂起后触发(9i新增) BEFORE SHUTDOWN 数据库关闭前触发
猜想,即然有SUSPEND事件,应该就唤醒事件,不知如何写?创建系统触发器时需要指定作用范围:ON DATABASE或ON SCHEMA。 CREATE OR REPLACE TRIGGER TRIGGER_NAME TIMING
DATABASE_EVENT1 or DATABSE_EVENT2 ON DATABASE|SCHEMA TRIGGER BODY
52. 53、DBMS_SPACE包的使用方法?(在RDBMS\\ADMIN\\DBMSSPC.SQL文件中)
SQL>DESC DBMS_SPACE可以看到DBMS_SPACE包提供了三个过程: PROCEDURE FREE_BLOCKS 对象未使用的块计算
PROCEDURE SPACE_USAGE 对象使用的空间计算 PROCEDURE UNUSED_SPACE 对象未使用空间计算 以FREE_BLOCKS过程为例:
SQL>select freelists,freelist_groups,num_freelist_blocks from dba_tables
input where table_name='EMP';
SQL> declare fblks number; begin
dbms_space.free_blocks('SCOTT','EMP','TABLE',0,fblks); dbms_output.put_line(fblks); end;
说明:0是从DBA_TABLES字典表中求得的EMP表的FREELIST_GROUP_ID,FBLKS就是求得的EMP表的未使用的BLOCK NUMBER。
53. 54、sql server 2000一個表裡有一個id字段和若干int字段,能不能用一個sql語
句對這些int求和。表结构如下:id int1 int2 int3 int4(C,I,I,I,I)
如這樣的表
不足之处,敬请指正 xzhui@vip.sina.com QQ 77056803
第29页
a b c 最後的出的是 a b c 總數 1 2 5 1 2 5 8 2 3 7 12 2 3 7 3 4 10 17 3 4 10 4 6 11 21 4 6 11 10 15 33 58 create table a_sum(id varchar(20),i1 int,i2 int) insert into a_sum values('01',2,3) insert into a_sum values('02',3,4)
select id,i1,i2,i1+i2 total from a_sum union
select '汇总',sum(i1), sum(i2),sum(i1)+sum(i2) from a_sum
54. 55、表A只有一列LANE。现在A中有如下行表示一些城市对 ,数据如下:
LANE
------------------------------------------- 上海-北京 北京-上海 上海-南京 南京-上海
广州-长沙-武汉 武汉-长沙-广州 北京-东京
我希望通过一条SQL查询,能将其中“重复”的城市对过滤掉,即形成如下结果。至于出现的是“上海-北京”还是“北京-上海”我倒不在意。 LANE
------------------------------------------- 北京-上海 上海-南京 武汉-长沙-广州 北京-东京
网友nyfor的解决方法如下:
create table a(lane varchar2(255)); insert into a values('上海-北京'); insert into a values('北京-上海'); insert into a values('上海-南京'); insert into a values('南京-上海');
不足之处,敬请指正 xzhui@vip.sina.com QQ 77056803
第30页
insert into a values('广州-长沙-武汉');
insert into a values('武汉-长沙-广州'); insert into a values('北京-东京');
create or replace function normalize(str varchar2) return varchar2 as
ltab tab_str := tab_str(); ls varchar2(255) := str; pos number := 0; cursor cur is
select column_value from table(cast(ltab as tab_str)) order by 1; begin
pos := instr(ls,'-'); while pos > 0 loop
ltab.extend;
ltab(ltab.count) := substr(ls,1,pos-1); ls := substr(ls,pos+1); pos := instr(ls,'-'); end loop;
ltab.extend;
ltab(ltab.count) := ls;
ls := '';
for c in cur loop
ls := ls || '-' || c.column_value; end loop;
return substr(ls,2); end;
SQL> select distinct normalize(lane) lane from a;
说明:原贴地址http://www.itpub.net/showthread.php?s=&threadid=126747 请看mouse_jacky网友的解决,一句话搞定: select lane from (
select lane,RANK() OVER (PARTITION BY col_id ORDER BY lane) as rk from (select lane,
DBMS_UTILITY.GET_HASH_VALUE(substr(lane,1,instr(lane,'-') -1),1000,2048) * DBMS_UTILITY.GET_HASH_VALUE(substr(substr(lane,instr(lane,'-')+1),1,instr(lane,'-') -1),1000,2048) *
DBMS_UTILITY.GET_HASH_VALUE(substr(substr(lane,instr(lane,'-')+1),instr(lane,'-') +1),1000,2048) col_id from a)) where rk=1
55.
56、关于ORACLE中的UTL_ENCODE包的使用方法
UTL_ENCODE包是加密解密包,使用64的加密方法,把RAW类型的数值进行加密,解密
不足之处,敬请指正 xzhui@vip.sina.com QQ 77056803
第31页
时返回十六进制的,两个数字为一个字节,若长度不足则补0。通过DESC UTL_ENCODE可以显示包中所有的过程,简单举例: SQL> select utl_encode.base64_encode('111') from dual; SQL> select utl_encode.base64_decode('4152453D') from dual;
56. 57、SQL实现交叉表的方法?
交叉一般来讲是分组统计的一种,形式更复杂,显示更清淅,但数据库本身并没有提供实现交叉表的功能,自己创建交叉表不仅要对过程、游标、临时表、动态SQL等非常熟悉,而且思路也要清淅,本例以PUBS.DBO.SALES表的数据做样本: create procedure up_test( @t1 varchar(30),@t2 varchar(30),
@t3 varchar(30),@t4 varchar(30)) as
--t1 表名,t2,t3是交叉表的两上分类字段,t4是汇总字段 --t2是行字段,t3列字段 begin
declare @sql varchar(7999),@field varchar(30)
select @sql='select distinct '+@t3+' from '+@t1 create table #field(field varchar(30)) --将列字段提取到临时表#FIELD中 insert into #field exec(@sql)
select @sql='create table cross_test('+@t2+' varchar(30),' declare cur_field cursor local for select * from #field open cur_field
fetch cur_field into @field while @@fetch_status=0 begin select @field='['+@field+']'
select @sql=@sql+@field+' decimal(8,2) default 0,' fetch cur_field into @field
end
select @sql=left(@sql,len(@sql)-1)+')' --创建临时交叉表cross_test
exec(@sql)
select @sql='insert into cross_test('+@t2+') select distinct '+@t2+' from '+@t1 --将行数据存入交叉表#cross_test exec(@sql)
--创建分组数据表TEMP
select @sql='create table temp('+@t2+' varchar(30),'+@t3+' varchar(30),'+@t4+' decimal(8,2))'
exec(@sql)
--将交叉汇总数据放入交叉表
select @sql='select '+@t2+','+@t3+', sum(qty) qty from '+@t1 +' group by '+@t2+','+@t3
不足之处,敬请指正 xzhui@vip.sina.com QQ 77056803
第32页
insert into temp exec(@sql)
--将汇总数据写入交叉表
declare cur_sum cursor local for select * from temp
declare @f1 varchar(30),@f2 varchar(30),@qty decimal(8,2),@q1 varchar(30) open cur_sum
fetch cur_sum into @f1,@f2,@qty while @@fetch_status=0 begin
select @f2='['+@f2+']',@q1=cast(@qty as varchar(30))
select @sql='update cross_test set '+@f2+'='+@q1+' where '+@t2+'='''+@f1+'''' exec(@sql)
fetch cur_sum into @f1,@f2,@qty end
close cur_sum
select * from cross_test drop table temp
drop table cross_test
drop table #field end
--------------------------------------------------------
exec up_test 'sales','title_id','stor_id','qty' 说明:字段加中括号为了处理字段中含有特殊字符,值得注意得是要实现交叉表的表必须有两个分类,本例只支持分类字段的数据类型是字符型的,最大的问题就是高亮显示这行的WHERE条件啦,字符类型字段查询时条件必须加单引号,如果是数值类型就可以直接写,所以数值类型的分类字段更容易实现一些,更可以融合在一个过程中。通常大家看到的交叉表都有行汇总与列汇总等信息,本例就没有实现,最后一点工作大家自己练练手吧。
57. 58、有表结构如下,要求对部门进行汇总,把ysdm相同的fs相加,
得到右图所示:
bmbm 0301 0302 0301 0302
ysdm 307 307 308 308 fs 1000 2000 100 200 03 03 03 307 308 309 3000 300 200 0301 309 200 这样的语法SQL与ORACLE如何实现呢? select substring(bmbm,1,2) ,ysdm,sum(fs) from A group substring(bmbm,1,2) ,ysdm -------------------------------------------------------------------------------------------------------------------
select substr(bmbm,1,2) ,ysdm,sum(fs) from A group by substr(bmbm,1,2) ,ysdm 原贴地址:http://www.delphibbs.com/delphibbs/DispQ.asp?LID=1929393
不足之处,敬请指正 xzhui@vip.sina.com QQ 77056803
第33页
58. 59、关于ORACLE的DBMS_TTS包的使用?
DBMS_TTS是主要用于检测要传输的表空间是否是自包含的,有二个重要的存储对象。 PROCEDURE TRANSPORT_SET_CHECK
FUNCTION ISSELFCONTAINED RETURNS BOOLEAN 在用EXP执行导出表空间时,要用上面两个存储对象啦,TRANSPORT_SET_CHECK执行后,不符合传输的表被放到transport_set_violations表。ISSELFCONTAINED返回值是TRUE,表示是自包含的,可以用EXP导出表空间,否则不行。 SQL> exec dbms_tts.transport_set_check('USERS');
SQL> select * from transport_set_violations;
第二种方法就是使用ISSELFCONTAINED检测表空间的自包含性: declare
ic boolean;fc boolean;rslt boolean; begin
ic := true;fc := true;
rslt := dbms_tts.isSelfContained('USERS',ic,fc);
end; exp SYS/SYS AS SYSDBA FILE=USERS.dmp TRANSPORT_TABLESPACE=y TABLESPACES=sales_ts TRIGGERS=N CONSTRAINTS=N
imp SYS/SYS AS SYSDBA FILE=USERS.dmp TRANSPORT_TABLESPACE=y DATAFILES=(/disk1/sales01.dbf, /disk2/sales02.dbf)
说明:如果RSLT返回TRUE就可以用EXP导出啦,请看EXP导出表空间的语法。导入导出表空间时要注意,必须使用SYS AS SYSDBA的权限,而且在导入时,不仅要拷贝*.DMP,而且还要拷贝导出表空间的相关数据文件。
59. 60、关于MS SQL SERVER的扩展存储过程的用法?
如何将SQL的查询结果保存到OS的文件中? DECLARE @cmd sysname, @var sysname
SET @var = 'dir /p'
SET @cmd = 'echo ' + @var + ' > dir_out.txt' EXEC master..xp_cmdshell @cmd , no_output
说明:必须把查询数据用游标组织成一个字符串或CLOB字段,然后写入*.TXT中。 Declare @strReturn varchar(500)
exec @strReturn = master..xp_cmdshell 'cd c:\\winnt' IF @strReturn='0'
PRINT 'The path exists.' else
PRINT 'The path doesn''t exist.'
不足之处,敬请指正 xzhui@vip.sina.com QQ 77056803
第34页
说明:SQL的文件I/o功能很弱,但可以通过扩展存储过程来实现,用户也可以自己开发扩展存储过程来实现SQL的功能。上边第一例是输出数据到OS的文件,另一例是判断磁盘上的目录是否存在,NO_OUTPUT选项限制不产生输出信息。
60. 61、现在有一个表T,数据是这样的(左图)。即表的特点如下:col_1的值相同
的的话,col_2的值就一定相等,反之不然。现在查询的结果要求是这样的(右图):
col_1 col_2 col_3 --------------------- 111 123 abc 111 123 bca 222 123 hik 222 123 kih 333 223 ikh 333 223 ikh
111 123 ABC BCA 222 123 HIK KIH 333 223 IKH IKH -------------------------------------------------------------------------- create table d(col_1 varchar2(20),col_2 varchar2(20),col_3 varchar(20)); insert into d values('111','xzh','abc'); insert into d values('111','xzh','DEF'); insert into d values('222','YYH','abc');
insert into d values('222','YYh','DEF');
select decode(rn,1,col_1) col_1,decode(rn,1,col_2) col_2,col_3 from
(select col_1,col_2,col_3,row_number() over (partition by col_1,col_2 order by col_1,col_2) rn from D);
说明:ROW_NUMBER() OVER(PARTITION BY?ORDER BY?) ALIAS_NAME作用与GROUP BY很类似,GROUP BY不充许非分组字段出现在字段列表,ROW_NUMBER() OVER则充许非分组字段出现在字段列表中,单独ROW_NUMBER() OVER()的作用就是为分组内的数据进行编号及排序,DECODE的作用就是相同数据不显示。
61. 62、如何实现如下功能,有表TEST(ID INT,NAME VARCHAR2(20)),ID最多只有
两重复的,相同ID的NAME显示在一行中,该ID就不要显示。
1 1 2 3 3 aaa bbb ccc ddd eee 1 2 3 aaa ccc ddd bbb NULL eee 相同id的数据最多两行,我想要结果如上图(右):
不足之处,敬请指正 xzhui@vip.sina.com QQ 77056803
第35页
解决方案一(差)
select aa.id,aa.name,bb.name from test aa,test bb where aa.id=bb.id(+) and aa.name<>bb.name(+) and ((aa.name < bb.name and bb.name is not null) or bb.name is null )
解决方案一(优)
select id, max(name), decode(min(name), max(name), null, min(name)) from test group by id
说明:通过使用GROUP BY与DECODE,在数据量大的情况下,可以比JOIN更快地返回结果,如果ID重复的数据多于2,想来第一种语法比第二种语法会更差,但更重要地是在第二种想来出来时能写出第一种语法。
62. 63、有表TEST,其结构如下所示:
TEST(NAME VARCHAR2(20),DEPT VARCHAR2(20),EMP VARCHAR2(20)),示例数据与要求见下页的图,将部门号相同的员工放在同一行上。
公司名 部门名 员工 公司名 部门名 员工
微软 开发 张三 微软 开发 张三,立四,...... 微软 开发 李四 微软 销售 赵三,刘六,......
微软 销售 赵三 微软 销售 刘六
用一条语句能不能做到?无论用MSSQL语法还是ORACLE的语法,请大家踊跃测试。本人先谢谢啦,如果你有好的解决方案,请发给我一份。
63. 64、缺少的记录怎样补齐? 有一张表如下:
SQL> select * from test; 1001 1003 1004
字段A固定为四条记录,值也是固定的(1001,1002,1003,1004)现在我要补缺了的1002,请问用sql怎样写?当然,缺少的记录可能是其它值,如1004,或缺二条、三条,或全部缺失。
适用于ORACLE所有版本,ITPUB的jlandzpa版主解决方案: (select '1001' from dual union
select '1002' from dual union select '1003' from dual union
select '1004' from dual) minus
select * from test;
不足之处,敬请指正 xzhui@vip.sina.com QQ 77056803
正在阅读:
sql server与oracle的区别10-17
关于印发《合肥高新区孵化企业用房租金补贴实施办法》的通知04-11
要用 七年级数学下册_2.1_两条直线的位置关系(二)课件08-07
大学生党员的先进性在学校生活中如何体现08-07
电子科技大学14秋《C语言(专科)》在线作业2答案10-08
国有土地使用权招拍挂出让流程及收费事项03-29
最新三年级下册口语交际教学反思04-14
婚礼程序册10-15
七年级班主任工作总结(最新3篇)03-22
- 多层物业服务方案
- (审判实务)习惯法与少数民族地区民间纠纷解决问题(孙 潋)
- 人教版新课标六年级下册语文全册教案
- 词语打卡
- photoshop实习报告
- 钢结构设计原理综合测试2
- 2014年期末练习题
- 高中数学中的逆向思维解题方法探讨
- 名师原创 全国通用2014-2015学年高二寒假作业 政治(一)Word版
- 北航《建筑结构检测鉴定与加固》在线作业三
- XX县卫生监督所工程建设项目可行性研究报告
- 小学四年级观察作文经典评语
- 浅谈110KV变电站电气一次设计-程泉焱(1)
- 安全员考试题库
- 国家电网公司变电运维管理规定(试行)
- 义务教育课程标准稿征求意见提纲
- 教学秘书面试技巧
- 钢结构工程施工组织设计
- 水利工程概论论文
- 09届九年级数学第四次模拟试卷
- 区别
- oracle
- server
- sql
- 2018年中国木工行业分析报告-市场深度分析与发展趋势预测(目录)
- 猪病防治教案1 - 图文
- 普通地质学习题
- 军理参考答案
- 南理工操作系统综合练习题
- 石牌村
- 上市公司财务造假动因分析与对策
- 16位算术逻辑运算实验 - 图文
- 信息化部职责及岗位说明书
- 基于零件参数化建模的THG型斗式提升机设计 - 图文
- 警惕去除车内异味的误区 选对方法才能真正除味 - 图文
- 学生课程设计总结
- 黄山市屯溪二中 外国语学校基础教育课程改革十年来的主要经验总结
- 美容院5.1活动方案
- 小学生如何实现海量阅读?
- FLAC3D 施加锚杆命令流
- 团代会召集人会议主持词
- 借名行为的法律效果探析
- 安全生产管理中的不足及对策
- 关于中国人民解放军院校学历证书实行统一制作和管理的通知