??xml version="1.0" encoding="utf-8" standalone="yes"?>
Q?Q?nbsp; 选择最有效率的表名序(只在Z规则的优化器中有?Q?br />
ORACLE的解析器按照从右到左的顺序处理FROM子句中的表名QFROM子句中写在最后的?基础?driving table)被最先处理,在FROM子句中包含多个表的情况下,你必选择记录条数最的表作为基表。如果有3个以上的表连接查? 那就需要选择交叉?intersection table)作ؓ基础? 交叉表是指那个被其他表所引用的表.
Q?Q?nbsp; WHERE子句中的q接序Q:
ORACLE采用自下而上的顺序解析WHERE子句,Ҏq个原理,表之间的q接必须写在其他WHERE条g之前, 那些可以qo掉最大数量记录的条g必须写在WHERE子句的末?
Q?Q?nbsp; SELECT子句中避免?‘ * ‘Q?br />
ORACLE在解析的q程? 会将'*' 依次转换成所有的列名, q个工作是通过查询数据字典完成? q意味着耗费更多的时?br />
Q?Q?nbsp; 减少讉K数据库的ơ数Q?br />
ORACLE在内部执行了许多工作: 解析SQL语句, 估算索引的利用率, l定变量 , L据块{;
Q?Q?nbsp; 在SQL*Plus , SQL*Forms和Pro*C中重新设|ARRAYSIZE参数, 可以增加每次数据库访问的索数据量 ,gؓ200
Q?Q?nbsp; 使用DECODE函数来减处理时_
使用DECODE函数可以避免重复扫描相同记录或重复连接相同的?
Q?Q?nbsp; 整合?无关联的数据库访问:
如果你有几个单的数据库查询语?你可以把它们整合C个查询中(即它们之间没有关系)
Q?Q?nbsp; 删除重复记录Q?br />
最高效的删除重复记录方?( 因ؓ使用了ROWID)例子Q?br />
DELETE FROM EMP E WHERE E.ROWID > (SELECT MIN(X.ROWID)
FROM EMP X WHERE X.EMP_NO = E.EMP_NO);
Q?Q?nbsp; 用TRUNCATE替代DELETEQ?br />
当删除表中的记录?在通常情况? 回滚D?rollback segments ) 用来存放可以被恢复的信息. 如果你没有COMMIT事务,ORACLE会将数据恢复到删除之前的状?准确地说是恢复到执行删除命o之前的状? 而当q用TRUNCATE? 回滚D不再存放Q何可被恢复的信息.当命令运行后,数据不能被恢?因此很少的资源被调用,执行旉也会很短. (译者按: TRUNCATE只在删除全表适用,TRUNCATE是DDL不是DML)
Q?0Q?量多用COMMITQ?br />
只要有可?在程序中量多用COMMIT, q样E序的性能得到提高,需求也会因为COMMIT所释放的资源而减?
COMMIT所释放的资?
a. 回滚D上用于恢复数据的信?
b. 被程序语句获得的?
c. redo log buffer 中的I间
d. ORACLE为管理上q?U资源中的内部花?br />
Q?1Q?用Where子句替换HAVING子句Q?br />
避免使用HAVING子句, HAVING 只会在检索出所有记录之后才对结果集q行qo. q个处理需要排?总计{操? 如果能通过WHERE子句限制记录的数?那就能减这斚w的开销. (非oracle?on、where、havingq三个都可以加条件的子句中,on是最先执行,whereơ之Qhaving最后,因ؓon是先把不W合条g的记录过滤后才进行统计,它就可以减少中间q算要处理的数据Q按理说应该速度是最快的Qwhere也应该比having快点的,因ؓ它过滤数据后才进行sumQ在两个表联接时才用on的,所以在一个表的时候,剩下where跟having比较了。在q单表查询统计的情况下,如果要过滤的条g没有涉及到要计算字段Q那它们的结果是一LQ只是where可以使用rushmore技术,而having׃能,在速度上后者要慢如果要涉及到计的字段Q就表示在没计算之前Q这个字D늚值是不确定的Q根据上写的工作流E,where的作用时间是在计之前就完成的,而having是在计后才v作用的,所以在q种情况下,两者的l果会不同。在多表联接查询Ӟon比where更早起作用。系l首先根据各个表之间的联接条Ӟ把多个表合成一个时表后,再由whereq行qoQ然后再计算Q计完后再由havingq行qo。由此可见,要想qo条g起到正确的作用,首先要明白这个条件应该在什么时候v作用Q然后再军_攑֜那里
Q?2Q?减少对表的查询:
在含有子查询的SQL语句?要特别注意减对表的查询.例子Q?br />
SELECT TAB_NAME FROM TABLES WHERE (TAB_NAME,DB_VER) = ( SELECT
TAB_NAME,DB_VER FROM TAB_COLUMNS WHERE VERSION = 604)
Q?3Q?通过内部函数提高SQL效率.Q?br />
复杂的SQL往往牺牲了执行效? 能够掌握上面的运用函数解决问题的Ҏ在实际工作中是非常有意义?br />
Q?4Q?使用表的别名(Alias)Q?br />
当在SQL语句中连接多个表? 请用表的别名ƈ把别名前~于每个Column?q样一?可以减解析的旉q减那些由Column歧义引v的语法错?
Q?5Q?用EXISTS替代IN、用NOT EXISTS替代NOT INQ?br />
在许多基于基表的查询?Z满一个条?往往需要对另一个表q行联接.在这U情况下, 使用EXISTS(或NOT EXISTS)通常提高查询的效率. 在子查询?NOT IN子句执行一个内部的排序和合q? 无论在哪U情况下,NOT IN都是最低效?(因ؓ它对子查询中的表执行了一个全表遍?. Z避免使用NOT IN ,我们可以把它改写成外q接(Outer Joins)或NOT EXISTS.
例子Q?br />
Q高效)SELECT * FROM EMP (基础? WHERE EMPNO > 0 AND EXISTS (SELECT ‘X' FROM DEPT WHERE DEPT.DEPTNO = EMP.DEPTNO AND LOC = ‘MELB')
(低效)SELECT * FROM EMP (基础? WHERE EMPNO > 0 AND DEPTNO IN(SELECT DEPTNO FROM DEPT WHERE LOC = ‘MELB')
Q?6Q?识别'低效执行'的SQL语句Q?br />
虽然目前各种关于SQL优化的图形化工具层出不穷,但是写出自己的SQL工具来解决问题始l是一个最好的ҎQ?br />
SELECT EXECUTIONS , DISK_READS, BUFFER_GETS,
ROUND((BUFFER_GETS-DISK_READS)/BUFFER_GETS,2) Hit_radio,
ROUND(DISK_READS/EXECUTIONS,2) Reads_per_run,
SQL_TEXT
FROM V$SQLAREA
WHERE EXECUTIONS>0
AND BUFFER_GETS > 0
AND (BUFFER_GETS-DISK_READS)/BUFFER_GETS < 0.8
ORDER BY 4 DESC;
Q?7Q?用烦引提高效率:
索引是表的一个概念部?用来提高索数据的效率QORACLE使用了一个复杂的自^衡B-treel构. 通常,通过索引查询数据比全表扫描要? 当ORACLE扑և执行查询和Update语句的最佌\径时, ORACLE优化器将使用索引. 同样在联l多个表时用烦引也可以提高效率. 另一个用烦引的好处?它提供了主键(primary key)的唯一性验?。那些LONG或LONG RAW数据cd, 你可以烦引几乎所有的? 通常, 在大型表中用烦引特别有? 当然,你也会发? 在扫描小表时,使用索引同样能提高效? 虽然使用索引能得到查询效率的提高,但是我们也必L意到它的代h. 索引需要空间来存储,也需要定期维? 每当有记录在表中增减或烦引列被修Ҏ, 索引本n也会被修? q意味着每条记录的INSERT , DELETE , UPDATEؓ此多付出4 , 5 ơ的盘I/O . 因ؓ索引需要额外的存储I间和处?那些不必要的索引反而会使查询反应时间变?。定期的重构索引是有必要?Q?br />
ALTER INDEX <INDEXNAME> REBUILD <TABLESPACENAME>
Q?8Q?用EXISTS替换DISTINCTQ?br />
当提交一个包含一对多表信?比如部门表和雇员?的查询时,避免在SELECT子句中用DISTINCT. 一般可以考虑用EXIST替换, EXISTS 使查询更?因ؓRDBMS核心模块在子查询的条g一旦满_,立刻q回l果. 例子Q?br />
(低效):
SELECT DISTINCT DEPT_NO,DEPT_NAME FROM DEPT D , EMP E
WHERE D.DEPT_NO = E.DEPT_NO
(高效):
SELECT DEPT_NO,DEPT_NAME FROM DEPT D WHERE EXISTS ( SELECT ‘X'
FROM EMP E WHERE E.DEPT_NO = D.DEPT_NO);
Q?9Q?sql语句用大写的Q因为oracleL先解析sql语句Q把写的字母{换成大写的再执行
Q?0Q?在java代码中尽量少用连接符“Q?#8221;q接字符Ԍ
Q?1Q?避免在烦引列上用NOT 通常Q
我们要避免在索引列上使用NOT, NOT会生在和在索引列上使用函数相同的媄? 当ORACLE”遇到”NOT,他就会停止用烦引{而执行全表扫?
Q?2Q?避免在烦引列上用计.
WHERE子句中,如果索引列是函数的一部分Q优化器不使用索引而用全表扫描.
举例:
低效Q?
SELECT … FROM DEPT WHERE SAL * 12 > 25000;
高效:
SELECT … FROM DEPT WHERE SAL > 25000/12;
Q?3Q??gt;=替代>
高效:
SELECT * FROM EMP WHERE DEPTNO >=4
低效:
SELECT * FROM EMP WHERE DEPTNO >3
两者的区别在于, 前者DBMS直接蟩到第一个DEPT{于4的记录而后者将首先定位到DEPTNO=3的记录ƈ且向前扫描到W一个DEPT大于3的记?
Q?4Q?用UNION替换OR (适用于烦引列)
通常情况? 用UNION替换WHERE子句中的OR会起到较好的效? 对烦引列使用OR造成全表扫描. 注意, 以上规则只针对多个烦引列有效. 如果有column没有被烦? 查询效率可能会因Z没有选择OR而降? 在下面的例子? LOC_ID 和REGION上都建有索引.
高效:
SELECT LOC_ID , LOC_DESC , REGION
FROM LOCATION
WHERE LOC_ID = 10
UNION
SELECT LOC_ID , LOC_DESC , REGION
FROM LOCATION
WHERE REGION = “MELBOURNE”
低效:
SELECT LOC_ID , LOC_DESC , REGION
FROM LOCATION
WHERE LOC_ID = 10 OR REGION = “MELBOURNE”
如果你坚持要用OR, 那就需要返回记录最的索引列写在最前面.
Q?5Q?用IN来替换OR
q是一条简单易记的规则Q但是实际的执行效果q须验,在ORACLE8i下,两者的执行路径g是相同的Q
低效:
SELECT…. FROM LOCATION WHERE LOC_ID = 10 OR LOC_ID = 20 OR LOC_ID = 30
高效
SELECT… FROM LOCATION WHERE LOC_IN IN (10,20,30);
Q?6Q?避免在烦引列上用IS NULL和IS NOT NULL
避免在烦引中使用M可以为空的列QORACLE无法用该索引Q对于单列烦引,如果列包含空|索引中将不存在此记录. 对于复合索引Q如果每个列都ؓI,索引中同样不存在此记? 如果臛_有一个列不ؓI,则记录存在于索引中.举例: 如果唯一性烦引徏立在表的A列和B列上, q且表中存在一条记录的A,Bgؓ(123,null) , ORACLE不接受下一条具有相同A,B|123,nullQ的记录(插入). 然而如果所有的索引列都为空QORACLE认为整个键gؓI空不等于空. 因此你可以插?000 条具有相同键值的记录,当然它们都是I? 因ؓIg存在于烦引列?所以WHERE子句中对索引列进行空值比较将使ORACLE停用该烦?
低效: (索引失效)
SELECT … FROM DEPARTMENT WHERE DEPT_CODE IS NOT NULL;
高效: (索引有效)
SELECT … FROM DEPARTMENT WHERE DEPT_CODE >=0;
Q?7Q?L使用索引的第一个列Q?br />
如果索引是徏立在多个列上, 只有在它的第一个列(leading column)被where子句引用?优化器才会选择使用该烦? q也是一条简单而重要的规则Q当仅引用烦引的W二个列?优化器用了全表扫描而忽略了索引
Q?8Q?用UNION-ALL 替换UNION ( 如果有可能的?Q?br />
当SQL语句需要UNION两个查询l果集合?q两个结果集合会以UNION-ALL的方式被合ƈ, 然后在输出最l结果前q行排序. 如果用UNION ALL替代UNION, q样排序׃是必要了. 效率׃因此得到提高. 需要注意的是,UNION ALL 重复输Z个结果集合中相同记录. 因此各位q是要从业务需求分析用UNION ALL的可行? UNION 对l果集合排序,q个操作会用到SORT_AREA_SIZEq块内存. 对于q块内存的优化也是相当重要的. 下面的SQL可以用来查询排序的消耗量
低效Q?
SELECT ACCT_NUM, BALANCE_AMT
FROM DEBIT_TRANSACTIONS
WHERE TRAN_DATE = '31-DEC-95'
UNION
SELECT ACCT_NUM, BALANCE_AMT
FROM DEBIT_TRANSACTIONS
WHERE TRAN_DATE = '31-DEC-95'
高效:
SELECT ACCT_NUM, BALANCE_AMT
FROM DEBIT_TRANSACTIONS
WHERE TRAN_DATE = '31-DEC-95'
UNION ALL
SELECT ACCT_NUM, BALANCE_AMT
FROM DEBIT_TRANSACTIONS
WHERE TRAN_DATE = '31-DEC-95'
Q?9Q?用WHERE替代ORDER BYQ?br />
ORDER BY 子句只在两种严格的条件下使用索引.
ORDER BY中所有的列必d含在相同的烦引中q保持在索引中的排列序.
ORDER BY中所有的列必d义ؓ非空.
WHERE子句使用的烦引和ORDER BY子句中所使用的烦引不能ƈ?
例如:
表DEPT包含以下?
DEPT_CODE PK NOT NULL
DEPT_DESC NOT NULL
DEPT_TYPE NULL
低效: (索引不被使用)
SELECT DEPT_CODE FROM DEPT ORDER BY DEPT_TYPE
高效: (使用索引)
SELECT DEPT_CODE FROM DEPT WHERE DEPT_TYPE > 0
Q?0Q?避免改变索引列的cd.:
当比较不同数据类型的数据? ORACLE自动对列q行单的cd转换.
假设 EMPNO是一个数值类型的索引?
SELECT … FROM EMP WHERE EMPNO = ‘123'
实际?l过ORACLEcd转换, 语句转化?
SELECT … FROM EMP WHERE EMPNO = TO_NUMBER(‘123')
q运的是,cd转换没有发生在烦引列?索引的用途没有被改变.
现在,假设EMP_TYPE是一个字W类型的索引?
SELECT … FROM EMP WHERE EMP_TYPE = 123
q个语句被ORACLE转换?
SELECT … FROM EMP WHERETO_NUMBER(EMP_TYPE)=123
因ؓ内部发生的类型{? q个索引不会被用到! Z避免ORACLE对你的SQLq行隐式的类型{? 最好把cd转换用显式表现出? 注意当字W和数值比较时, ORACLE会优先{换数值类型到字符cd
Q?1Q?需要当心的WHERE子句:
某些SELECT 语句中的WHERE子句不用烦? q里有一些例?
在下面的例子? (1)‘!=' 不使用索引. C, 索引只能告诉你什么存在于表中, 而不能告诉你什么不存在于表? (2) ‘||'是字W连接函? p其他函数那样, 停用了烦? (3) ‘+'是数学函? p其他数学函数那样, 停用了烦? (4)相同的烦引列不能互相比较,q将会启用全表扫?
Q?2Q?a. 如果索数据量过30%的表中记录数.使用索引没有显著的效率提高.
b. 在特定情况下, 使用索引也许会比全表扫描? 但这是同一个数量上的区别. 而通常情况?使用索引比全表扫描要块几倍乃臛_千?
Q?3Q?避免使用耗费资源的操?
带有DISTINCT,UNION,MINUS,INTERSECT,ORDER BY的SQL语句会启动SQL引擎
执行耗费资源的排?SORT)功能. DISTINCT需要一ơ排序操? 而其他的臛_需要执行两ơ排? 通常, 带有UNION, MINUS , INTERSECT的SQL语句都可以用其他方式重写. 如果你的数据库的SORT_AREA_SIZE调配得好, 使用UNION , MINUS, INTERSECT也是可以考虑? 毕竟它们的可L很?br />
Q?4Q?优化GROUP BY:
提高GROUP BY 语句的效? 可以通过不需要的记录在GROUP BY 之前qo?下面两个查询q回相同l果但第二个明显快了许?
低效:
SELECT JOB , AVG(SAL)
FROM EMP
GROUP JOB
HAVING JOB = ‘PRESIDENT'
OR JOB = ‘MANAGER'
高效:
SELECT JOB , AVG(SAL)
FROM EMP
WHERE JOB = ‘PRESIDENT'
OR JOB = ‘MANAGER'
GROUP JOB
本文来自CSDN博客Q{载请标明出处Qhttp://blog.csdn.net/fuwei2241/archive/2006/09/06/1185198.aspx
LONG: 可变长的字符?/font>数据Q最?GQLONGhVARCHAR2列的Ҏ,可以存储长文本一个表中最多一个LONG?br />
LONG RAW: 可变?font color="#993300">二进?/font>数据Q最?G
CLOB: 字符大对?font size="+0">Clob 用来存储单字节的字符数据
NCLOB: 用来存储多字节的字符数据
BLOB: 用于存储二进?/font>数据
BFILE: 存储在文件中?font color="#993300">二进?/font>数据Q这个文件中的数据只能被只读ѝ但该文件不包含在数据库内?/font>
bfile字段实际的文件存储在文gpȝ?字段中存储的是文件定位指?bfile对oracle来说是只ȝ,也不参与事务性控制和数据恢复.
CLOBQNCLOBQBLOB都是内部?font color="#993300">LOB(Large Object)cdQ最?GQ没有LONG只能有一列的限制
要保存图片、文本文件、Word文g各自最好用哪种数据cd?
--BLOB最好,LONG RAW也不错,但Long是oracle要废弃的类型,因此用BLOB?/font>
本文来自CSDN博客Q{载请标明出处Qhttp://blog.csdn.net/fuwei2241/archive/2006/09/06/1185198.aspx
insert into t_test12 (ID, NO)
values (1, 'lin');
insert into t_test12 (ID, NO)
values (2, '13800162');
insert into t_test12 (ID, NO)
values (3, '13800163');
insert into t_test12 (ID, NO)
values (4, '13800164');
insert into t_test12 (ID, NO)
values (5, '13800165');
insert into t_test12 (ID, NO)
values (6, '13800166');
控制台抛个异常:java.sql.SQLException: ORA-00911: invalid character select count(t.id) as onerowc,t.id as areatravelid ,b.id as airpotid from base_areatravel t inner join base_airpot b on b.areaid=t.id group by t.id ,b.id; 以上是完完整整的输出l果Q然后我语句复制到PL/SQL中执行是完全可以的,没有M异常的。?/p> 而我在程序中定义的sql如下Q?/p> String sql="select count(t.id) as onerowc,t.id as areatravelid ,b.id as airpotid from base_areatravel t"+ 呵呵Q花费了半个多小时终于找到原因:Q:Q?/p> 哈哈Q,定义语句中sql后面多了一个分受(“Q?#8221;Q晕菜。。这L话在PL/SQL中是无所谓的Q可是Java 的数据库驱动却不识别q样的语句了。汗Q,Q太大意了。记录下来防止再ơ犯错,呵呵。。?/p> |
一.引用文章
SELECT /*+ FIRST_ROWS */ * FROM
(
SELECT A.*, ROWNUM RN
FROM (SELECT * FROM TABLE_NAME) A --不排?br />
WHERE ROWNUM <= 40
)
WHERE RN >= 21;
SELECT /*+ FIRST_ROWS */ *
FROM (SELECT a.*, row_number() over(ORDER BY 1) rn--假排序,速度同上
FROM t1 a)
WHERE rn BETWEEN 21 AND 40;
SELECT *
FROM (SELECT a.*, row_number() over(ORDER BY c1) rn --真实排序Q无法比较速度
FROM t1 a)
WHERE rn BETWEEN 21 AND 40;
Oracle的分|询语句基本上可以按照本文l出的格式来q行套用?br /> 分页查询格式Q?/p>
SELECT * FROM
(
SELECT A.*, ROWNUM RN
FROM (SELECT * FROM TABLE_NAME) A
WHERE ROWNUM <= 40
)
WHERE RN >= 21
其中最内层的查询SELECT * FROM TABLE_NAME表示不进行翻늚原始查询语句。ROWNUM <= 40和RN >= 21控制分页查询的每늚范围?/p>
上面l出的这个分|询语句,在大多数情况拥有较高的效率。分늚目的是控制输出l果集大,结果尽快的q回。在上面的分|询语句中Q这U考虑主要体现在WHERE ROWNUM <= 40q句上?/p>
选择W?1?0条记录存在两U方法,一U是上面例子中展C的在查询的W二层通过ROWNUM <= 40来控制最大|在查询的最外层控制最倹{而另一U方式是L查询W二层的WHERE ROWNUM <= 40语句Q在查询的最外层控制分页的最值和最大倹{这是,查询语句如下Q?/p>
SELECT * FROM
(
SELECT A.*, ROWNUM RN
FROM (SELECT * FROM TABLE_NAME) A
)
WHERE RN BETWEEN 21 AND 40
Ҏq两U写法,l大多数的情况下Q第一个查询的效率比第二个高得多?/p>
q是׃CBO优化模式下,Oracle可以外层的查询条g推到内层查询中,以提高内层查询的执行效率。对于第一个查询语句,W二层的查询条gWHERE ROWNUM <= 40可以被Oracle推入到内层查询中Q这样Oracle查询的结果一旦超q了ROWNUM限制条gQ就l止查询结果返回了?/p>
而第二个查询语句Q由于查询条件BETWEEN 21 AND 40是存在于查询的第三层Q而Oracle无法第三层的查询条件推到最内层Q即使推到最内层也没有意义,因ؓ最内层查询不知道RN代表什么)。因此,对于W二个查询语句,Oracle最内层q回l中间层的是所有满x件的数据Q而中间层q回l最外层的也是所有数据。数据的qo在最外层完成Q显然这个效率要比第一个查询低得多?/p>
上面分析的查询不仅仅是针对单表的单查询,对于最内层查询是复杂的多表联合查询或最内层查询包含排序的情况一h效?/p>
q里׃对包含排序的查询q行说明了,下一文章会通过例子来详l说明。下面简单讨Z下多表联合的情况。对于最常见的等Dq接查询QCBO一般可能会采用两种q接方式NESTED LOOP和HASH JOINQMERGE JOIN效率比HASH JOIN效率低,一般CBO不会考虑Q。在q里Q由于用了分页Q因此指定了一个返回的最大记录数QNESTED LOOP在返回记录数过最大值时可以马上停止q将l果q回l中间层Q而HASH JOIN必须处理完所有结果集QMERGE JOIN也是Q。那么在大部分的情况下,对于分页查询选择NESTED LOOP作ؓ查询的连接方法具有较高的效率Q分|询的时候绝大部分的情况是查询前几页的数据,靠后面的页数访问几率越)?/p>
因此Q如果不介意在系l中使用HINT的话Q可以将分页的查询语句改写ؓQ?/p>
SELECT /*+ FIRST_ROWS */ * FROM
(
SELECT A.*, ROWNUM RN
FROM (SELECT * FROM TABLE_NAME) A
WHERE ROWNUM <= 40
)
WHERE RN >= 21
?我的存储q程
create or replace package CJ_PageData is
TYPE type_cur IS REF CURSOR; --建立游标
PROCEDURE CJ_GetDataByPage
(
tblName in varchar2,
strGetFields in varchar2,
fldName in varchar2,
PageSize in number,
PageIndex in number,
doCount in number,
OrderType in number,
strWhere in varchar2,
DataCount out number,
DataSet out type_cur
);
end CJ_PageData;
CREATE OR REPLACE PACKAGE BODY CJ_PageData
AS
PROCEDURE CJ_GetDataByPage
(
tblName in varchar2, --表名
strGetFields in varchar2, --q回字段
fldName in varchar2, --排序字段?/p>
PageSize in number, --分页大小
PageIndex in number, --늠
doCount in number, --是否l计(0?1?
OrderType in number, --排序cd(0?1?
strWhere in varchar2, --{选条?/p>
DataCount out number, --q回记录L
DataSet out type_cur --q回游标(指针)
)
as
strSQL varchar2(5000) ; -- 临时记录Sql语句
strOrder varchar2(400) ; -- 临时记录排序语句
begin
if doCount <> 0 then
begin
if strWhere <> ' ' then
strSQL := 'select count(*) as total from ' || tblName || ' where '||strWhere;
else
strSQL := 'select count(*) as total from ' || tblName;
end if;
execute immediate strSQL into DataCount;--取出记录L攑օq回变量DataCount
end;
else
begin
strSQL := 'select ' ||strGetFields||' from (select T2.*,rownum rn from (select T1.* from ' || tblName||' T1 ';
--得到排序cd语句
if OrderType <> 0 then
begin
strOrder := ' order by ' || fldName ||' asc';
end;
else
begin
strOrder := ' order by ' || fldName ||' desc';
end;
end if;
begin
--l装SQl语句
if strWhere <> ' ' then
strSQL := strSQL || ' where ' || strWhere || ') T2 where rownum <=' || TO_CHAR(PageIndex*PageSize) || ')'
|| ' where rn >' || TO_CHAR((PageIndex-1)*PageSize) || strOrder;
else
strSQL := strSQL || ' ) T2 where rownum <=' || TO_CHAR(PageIndex*PageSize) || ')'
|| ' where rn >' || TO_CHAR((PageIndex-1)*PageSize) || strOrder;
end if;
end;
end;
end if;
open DataSet for strSQL;
end;
end CJ_PageData;
?.Net中调用存储过E?/p>
1.Ҏ
/// <summary>
/// 获得记录L和所有记录{q接字符?存储q程,?q回字段,排序字段,分页大小,늠,l计(1?0不是),排序(1升序,0降序),条g}
/// </summary>
/// <param name="strConn"></param>
/// <param name="strSPName">存储q程名字</param>
/// <param name="strTableName">表名</param>
/// <param name="strGetFields">q回字段字符?lt;/param>
/// <param name="strFieldName">排序字段</param>
/// <param name="iPageIndex">늠</param>
/// <param name="iPageSize">分页大小</param>
/// <param name="iDoCount">是否l计记录L(1l计,0不统?</param>
/// <param name="iOrderType">排序cd(0升序,1降序)</param>
/// <param name="strWhere">{选条?不带where)</param>
protected void BuildData(string strConn,string strSPName,string strTableName,string strGetFields,string strFieldName,int iPageSize,int iPageIndex,int iDoCount,int iOrderType,string strWhere)
{
System.Data.OracleClient.OracleConnection conn = new OracleConnection();
System.Data.OracleClient.OracleCommand cmd = new OracleCommand();
System.Data.OracleClient.OracleDataReader dr;
conn.ConnectionString = strConn;
cmd.Connection = conn;
cmd.CommandType = CommandType.StoredProcedure;
conn.Open();
cmd.CommandText = strSPName;
cmd.Parameters.Add("tblName",OracleType.VarChar);//表名
cmd.Parameters.Add("strGetFields",OracleType.VarChar);//q回字段?br />
cmd.Parameters.Add("fldName",OracleType.VarChar);//排序字段?br />
cmd.Parameters.Add("PageSize",OracleType.Number);//分页大小
cmd.Parameters.Add("PageIndex",OracleType.Number);//늠
cmd.Parameters.Add("doCount",OracleType.Number);//是否l计总记录数
cmd.Parameters.Add("OrderType",OracleType.Number);//排序cd
cmd.Parameters.Add("strWhere",OracleType.VarChar);//{选条?br />
cmd.Parameters.Add("DataCount",OracleType.Number);//q回得记录L
cmd.Parameters.Add("DataSet",OracleType.Cursor);//q回得记录集
cmd.Parameters["tblName"].Value = strTableName;
cmd.Parameters["strGetFields"].Value = strGetFields;
cmd.Parameters["fldName"].Value = strFieldName;
cmd.Parameters["PageSize"].Value = iPageSize;
cmd.Parameters["PageIndex"].Value = ( iOrderType == 0 ) ? (pager.PageCount+1-iPageIndex) : iPageIndex;//因ؓOracle中不支持子查询排?所以在q里如果需要倒序,则将늠按反序取数据,"以假q".嘿嘿!
cmd.Parameters["doCount"].Value = iDoCount;
cmd.Parameters["OrderType"].Value = iOrderType;
cmd.Parameters["strWhere"].Value = strWhere;
cmd.Parameters["DataCount"].Direction = ParameterDirection.Output;
cmd.Parameters["DataSet"].Direction = ParameterDirection.Output;
cmd.Parameters["tblName"].Size = 100;
cmd.Parameters["strGetFields"].Size = 1000;
cmd.Parameters["fldName"].Size = 100;
cmd.Parameters["strWhere"].Size = 1000;
//try
{
switch (iDoCount)
{
case 0:
{
dr = cmd.ExecuteReader();
dgData.DataSource = dr;
dgData.DataBind();//l定数据?br />
dr.Close();
break;
}
case 1:
{
cmd.ExecuteOracleScalar();
pager.RecordCount = int.Parse(cmd.Parameters["DataCount"].Value.ToString());
break;
}
}
}
//catch
{
}
conn.Close();
}
2.调用
A.面加蝲时候取得总记录数,以绑定分|?/p>
private void Page_Load(object src,EventArgs e)
{
if(!Page.IsPostBack)
{
string conn = "password=cqcj;user id=cqcj;data source=cqc1";
this.BuildData(conn,"CJ_PageData.CJ_GetDataByPage","CJ_Log","","",0,0,1,0,"UserID = 'xxr'");
BindData();//q里l分|?如DataGridl定数据?br />
}
}
B.BindData()
protected void BindData()
{
string conn = "password=cqcj;user id=cqcj;data source=cqc1";
this.BuildData(conn,"CJ_PageData.CJ_GetDataByPage","CJ_Log","*","LoginTime",pager.PageSize,pager.CurrentPageIndex,0,1,"UserID = 'xxr'");
pager.CustomInfoText="记录LQ?lt;font color=\"blue\"><b>"+pager.RecordCount.ToString()+"</b></font>";
pager.CustomInfoText+=" 总页敎ͼ<font color=\"blue\"><b>"+pager.PageCount.ToString()+"</b></font>";
pager.CustomInfoText+=" 当前:<font color=\"red\"><b>"+pager.CurrentPageIndex.ToString()+"</b></font>";
}
?ȝ
Oracle中无法直接返回记录集,需利用游标q回.Oracle中不支持子查询排?临时表耗费资源不推荐?
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=940779
if exists (select name from sysobjects where name='v_order' and type='p')
DROP PROCEDURE v_order
go
create procedure v_order
@serverid varchar(30),
@jtype int
as
select * from
order_form
where jtype= @jtype and serverid=@serverid
select * from sysobjects where type='p' and name='v_order'
exec v_order 'hcair','3'
go
exec v_order hcair,3
exec v_order @serverid=hcair,@jtype=3
drop proc v_order_in
go
create procedure v_order_in
@user_name varchar(20),
@pnr_list varchar(20),
@air_list varchar(20),
@arri_list varchar(20),
@dp_time timestamp,
@lxname varchar(20)
as
insert into order_form(user_name,pnr_list,air_list,arri_list,dp_time,lxname) values (@user_name,@pnr_list,@air_list,@arri_list,@dp_time,@lxname )
go
exec v_order_in 0000,rksts,MF8587,'KHN,PEK,',convert('2006-7-16 13:03:53'),linsanfu
-------------------------------------------------------------------------------------------------------------------------------------------------------
CZ
A. 使用带有复杂 SELECT 语句的简单过E?br />下面的存储过E从四个表的联接中返回所有作者(提供了姓名)、出版的书籍以及出版C。该存储q程不用Q何参数?/p>
USE pubs
IF EXISTS (SELECT name FROM sysobjects
WHERE name = 'au_info_all' AND type = 'P')
DROP PROCEDURE au_info_all
GO
CREATE PROCEDURE au_info_all
AS
SELECT au_lname, au_fname, title, pub_name
FROM authors a INNER JOIN titleauthor ta
ON a.au_id = ta.au_id INNER JOIN titles t
ON t.title_id = ta.title_id INNER JOIN publishers p
ON t.pub_id = p.pub_id
GO
au_info_all 存储q程可以通过以下Ҏ执行Q?/p>
EXECUTE au_info_all
-- Or
EXEC au_info_all
如果该过E是批处理中的第一条语句,则可使用Q?/p>
au_info_all
B. 使用带有参数的简单过E?br />下面的存储过E从四个表的联接中只q回指定的作者(提供了姓名)、出版的书籍以及出版C。该存储q程接受与传递的参数_匚w的倹{?/p>
USE pubs
IF EXISTS (SELECT name FROM sysobjects
WHERE name = 'au_info' AND type = 'P')
DROP PROCEDURE au_info
GO
USE pubs
GO
CREATE PROCEDURE au_info
@lastname varchar(40),
@firstname varchar(20)
AS
SELECT au_lname, au_fname, title, pub_name
FROM authors a INNER JOIN titleauthor ta
ON a.au_id = ta.au_id INNER JOIN titles t
ON t.title_id = ta.title_id INNER JOIN publishers p
ON t.pub_id = p.pub_id
WHERE au_fname = @firstname
AND au_lname = @lastname
GO
au_info 存储q程可以通过以下Ҏ执行Q?/p>
EXECUTE au_info 'Dull', 'Ann'
-- Or
EXECUTE au_info @lastname = 'Dull', @firstname = 'Ann'
-- Or
EXECUTE au_info @firstname = 'Ann', @lastname = 'Dull'
-- Or
EXEC au_info 'Dull', 'Ann'
-- Or
EXEC au_info @lastname = 'Dull', @firstname = 'Ann'
-- Or
EXEC au_info @firstname = 'Ann', @lastname = 'Dull'
如果该过E是批处理中的第一条语句,则可使用Q?/p>
au_info 'Dull', 'Ann'
-- Or
au_info @lastname = 'Dull', @firstname = 'Ann'
-- Or
au_info @firstname = 'Ann', @lastname = 'Dull'
C. 使用带有通配W参数的单过E?br />下面的存储过E从四个表的联接中只q回指定的作者(提供了姓名)、出版的书籍以及出版C。该存储q程对传递的参数q行模式匚wQ如果没有提供参敎ͼ则用预讄默认倹{?/p>
USE pubs
IF EXISTS (SELECT name FROM sysobjects
WHERE name = 'au_info2' AND type = 'P')
DROP PROCEDURE au_info2
GO
USE pubs
GO
CREATE PROCEDURE au_info2
@lastname varchar(30) = 'D%',
@firstname varchar(18) = '%'
AS
SELECT au_lname, au_fname, title, pub_name
FROM authors a INNER JOIN titleauthor ta
ON a.au_id = ta.au_id INNER JOIN titles t
ON t.title_id = ta.title_id INNER JOIN publishers p
ON t.pub_id = p.pub_id
WHERE au_fname LIKE @firstname
AND au_lname LIKE @lastname
GO
au_info2 存储q程可以用多U组合执行。下面只列出了部分组合:
EXECUTE au_info2
-- Or
EXECUTE au_info2 'Wh%'
-- Or
EXECUTE au_info2 @firstname = 'A%'
-- Or
EXECUTE au_info2 '[CK]ars[OE]n'
-- Or
EXECUTE au_info2 'Hunter', 'Sheryl'
-- Or
EXECUTE au_info2 'H%', 'S%'
D. 使用 OUTPUT 参数
OUTPUT 参数允许外部q程、批处理或多?Transact-SQL 语句讉K在过E执行期间设|的某个倹{下面的CZ创徏一个存储过E?(titles_sum)Qƈ使用一个可选的输入参数和一个输出参数?/p>
首先Q创E:
USE pubs
GO
IF EXISTS(SELECT name FROM sysobjects
WHERE name = 'titles_sum' AND type = 'P')
DROP PROCEDURE titles_sum
GO
USE pubs
GO
CREATE PROCEDURE titles_sum @@TITLE varchar(40) = '%', @@SUM money OUTPUT
AS
SELECT 'Title Name' = title
FROM titles
WHERE title LIKE @@TITLE
SELECT @@SUM = SUM(price)
FROM titles
WHERE title LIKE @@TITLE
GO
接下来,该 OUTPUT 参数用于控制语a?
说明 OUTPUT 变量必须在创和用该变量旉q行定义?/p>
参数名和变量名不一定要匚wQ不q数据类型和参数位置必须匚wQ除非?@@SUM = variable 形式Q?
DECLARE @@TOTALCOST money
EXECUTE titles_sum 'The%', @@TOTALCOST OUTPUT
IF @@TOTALCOST < 200
BEGIN
PRINT ' '
PRINT 'All of these titles can be purchased for less than $200.'
END
ELSE
SELECT 'The total cost of these titles is $'
+ RTRIM(CAST(@@TOTALCOST AS varchar(20)))
下面是结果集Q?/p>
Title Name
------------------------------------------------------------------------
The Busy Executive's Database Guide
The Gourmet Microwave
The Psychology of Computer Cooking
(3 row(s) affected)
Warning, null value eliminated from aggregate.
All of these titles can be purchased for less than $200.
E. 使用 OUTPUT 游标参数
OUTPUT 游标参数用来存储过E的局部游标传递回调用批处理、存储过E或触发器?/p>
首先Q创Z下过E,?titles 表上声明q打开一个游标:
USE pubs
IF EXISTS (SELECT name FROM sysobjects
WHERE name = 'titles_cursor' and type = 'P')
DROP PROCEDURE titles_cursor
GO
CREATE PROCEDURE titles_cursor @titles_cursor CURSOR VARYING OUTPUT
AS
SET @titles_cursor = CURSOR
FORWARD_ONLY STATIC FOR
SELECT *
FROM titles
OPEN @titles_cursor
GO
接下来,执行一个批处理Q声明一个局部游标变量,执行上述q程以将游标赋值给局部变量,然后从该游标提取行?/p>
USE pubs
GO
DECLARE @MyCursor CURSOR
EXEC titles_cursor @titles_cursor = @MyCursor OUTPUT
WHILE (@@FETCH_STATUS = 0)
BEGIN
FETCH NEXT FROM @MyCursor
END
CLOSE @MyCursor
DEALLOCATE @MyCursor
GO
F. 使用 WITH RECOMPILE 选项
如果E提供的参数不是典型的参敎ͼq且新的执行计划不应高速缓存或存储在内存中QWITH RECOMPILE 子句会很有帮助?/p>
USE pubs
IF EXISTS (SELECT name FROM sysobjects
WHERE name = 'titles_by_author' AND type = 'P')
DROP PROCEDURE titles_by_author
GO
CREATE PROCEDURE titles_by_author @@LNAME_PATTERN varchar(30) = '%'
WITH RECOMPILE
AS
SELECT RTRIM(au_fname) + ' ' + RTRIM(au_lname) AS 'Authors full name',
title AS Title
FROM authors a INNER JOIN titleauthor ta
ON a.au_id = ta.au_id INNER JOIN titles t
ON ta.title_id = t.title_id
WHERE au_lname LIKE @@LNAME_PATTERN
GO
G. 使用 WITH ENCRYPTION 选项
WITH ENCRYPTION 子句对用户隐藏存储过E的文本。下例创建加密过E,使用 sp_helptext pȝ存储q程获取关于加密q程的信息,然后试直接?syscomments 表中获取关于该过E的信息?/p>
IF EXISTS (SELECT name FROM sysobjects
WHERE name = 'encrypt_this' AND type = 'P')
DROP PROCEDURE encrypt_this
GO
USE pubs
GO
CREATE PROCEDURE encrypt_this
WITH ENCRYPTION
AS
SELECT *
FROM authors
GO
EXEC sp_helptext encrypt_this
下面是结果集Q?/p>
The object's comments have been encrypted.
接下来,选择加密存储q程内容的标识号和文本?/p>
SELECT c.id, c.text
FROM syscomments c INNER JOIN sysobjects o
ON c.id = o.id
WHERE o.name = 'encrypt_this'
下面是结果集Q?/p>
说明 text 列的输出昄在单独一行中。执行时Q该信息与 id 列信息出现在同一行中?/p>
id text
---------- ------------------------------------------------------------
1413580074 ?????????????????????????????????e??????????????????????????????????????????????????????????????????????????
(1 row(s) affected)
H. 创徏用户定义的系l存储过E?br />下面的示例创Z个过E,昄表名?emp 开头的所有表及其对应的烦引。如果没有指定参敎ͼ该过E将q回表名?sys 开头的所有表Q及索引Q?/p>
IF EXISTS (SELECT name FROM sysobjects
WHERE name = 'sp_showindexes' AND type = 'P')
DROP PROCEDURE sp_showindexes
GO
USE master
GO
CREATE PROCEDURE sp_showindexes
@@TABLE varchar(30) = 'sys%'
AS
SELECT o.name AS TABLE_NAME,
i.name AS INDEX_NAME,
indid AS INDEX_ID
FROM sysindexes i INNER JOIN sysobjects o
ON o.id = i.id
WHERE o.name LIKE @@TABLE
GO
USE pubs
EXEC sp_showindexes 'emp%'
GO
下面是结果集Q?/p>
TABLE_NAME INDEX_NAME INDEX_ID
---------------- ---------------- ----------------
employee employee_ind 1
employee PK_emp_id 2
(2 row(s) affected)
I. 使用延迟名称解析
下面的示例显C四个过E以及gq名U解析的各种可能使用方式。尽引用的表或列在~译时不存在Q但每个存储q程都可创徏?/p>
IF EXISTS (SELECT name FROM sysobjects
WHERE name = 'proc1' AND type = 'P')
DROP PROCEDURE proc1
GO
-- Creating a procedure on a nonexistent table.
USE pubs
GO
CREATE PROCEDURE proc1
AS
SELECT *
FROM does_not_exist
GO
-- Here is the statement to actually see the text of the procedure.
SELECT o.id, c.text
FROM sysobjects o INNER JOIN syscomments c
ON o.id = c.id
WHERE o.type = 'P' AND o.name = 'proc1'
GO
USE master
GO
IF EXISTS (SELECT name FROM sysobjects
WHERE name = 'proc2' AND type = 'P')
DROP PROCEDURE proc2
GO
-- Creating a procedure that attempts to retrieve information from a
-- nonexistent column in an existing table.
USE pubs
GO
CREATE PROCEDURE proc2
AS
DECLARE @middle_init char(1)
SET @middle_init = NULL
SELECT au_id, middle_initial = @middle_init
FROM authors
GO
-- Here is the statement to actually see the text of the procedure.
SELECT o.id, c.text
FROM sysobjects o INNER JOIN syscomments c
ON o.id = c.id
WHERE o.type = 'P' and o.name = 'proc2'
4.3.2 点数据cd
点数据cd用于存储十进制小数。QҎ值的数据在SQL Server 中采用上舍入QRound up 或称为只入不舍)方式q行存储。所谓上舍入是指Q当Q且仅当Q要舍入的数是一个非零数Ӟ对其保留数字部分的最低有效位上的数值加1 Qƈq行必要的进位。若一个数是上舍入敎ͼ其绝对g会减。如Q对3.14159265358979 分别q行2 位和12位舍入,l果?.15 ?.141592653590?br /> 1、REAL 数据cd
REAL数据cd可精到W? 位小敎ͼ其范围ؓ?3.40E -38 ?.40E +38?每个REALcd的数据占? 个字节的存储I间?br /> 2、FLOAT
FLOAT数据cd可精到W?5 位小敎ͼ其范围ؓ?1.79E -308 ?.79E +308?每个FLOAT cd的数据占? 个字节的存储I间?FLOAT数据cd可写为FLOAT[ n ]的Ş式。n 指定FLOAT 数据的精度。n ??5 之间的整数倹{当n ? ? Ӟ实际上是定义了一个REAL cd的数据,pȝ? 个字节存储它Q当n ? ?5 Ӟpȝ认ؓ其是FLOAT cdQ用8 个字节存储它?br /> 3、DECIMAL
DECIMAL数据cd可以提供数所需要的实际存储I间Q但也有一定的限制Q您可以? ?7 个字节来存储?10?8ơ方-1 ?0?8ơ方-1 之间的数倹{可其写ؓDECIMAL[ p [s] ]的Ş式,p 和s 定了精的比例和数位。其中p 表示可供存储的值的M敎ͼ不包括小数点Q,~省gؓ18Q?s 表示数点后的位敎ͼ~省gؓ0?例如Qdecimal Q?5 5Q,表示共有15 位数Q其中整?0 位,数5?位表4-3 列出了各_度所需的字节数之间的关pR?br />
4、NUMERIC
NUMERIC数据cd与DECIMAL数据cd完全相同?br />注意QSQL Server Z和前端的开发工具配合,其所支持的数据精度默认最大ؓ28位。但可以通过使用命o来执行sqlserver.exeE序以启动SQL ServerQ可改变默认_ֺ。命令语法如下:SQLSERVR[/D master_device_path][/P precisim_leve1]
?-4: 用最大数据精?8 启动SQL Server
sqlservr /d c:\ Mssql2000\data\master.dat /p38
/*在用了/P 参数?如果其后没有指定具体的精度数?则默认ؓ38 ?/*
4.3.3 二进制数据类?br /> 1、BINARY
BINARY 数据cd用于存储二进制数据。其定义形式为BINARYQ?nQ, n 表示数据的长度,取gؓ1 ?000 。在使用时必L定BINARY cd数据的大,臛_应ؓ1 个字节。BINARY cd数据占用n+4 个字节的存储I间。在输入数据时必d数据前加上字W?X?作ؓ二进制标识,如:要输入“abc ”则应输入?xabc ”。若输入的数据过长将会截掉其出部分。若输入的数据位Cؓ奇数Q则会在起始W号?X ”后d一?Q如上述的?xabc ”会被系l自动变为?x0abc”?
2、VARBINARY
VARBINARY数据cd的定义Ş式ؓVARBINARYQnQ?它与BINARY cd怼Qn 的取g? ?000Q?若输入的数据q长Q将会截掉其出部分。不同的是VARBINARY数据cdh变动长度的特性,因ؓVARBINARY数据cd的存储长度ؓ实际数值长?4个字节。当BINARY数据cd允许NULL 值时Q将被视为VARBINARY数据cd?br />一般情况下Q由于BINARY 数据cd长度固定Q因此它比VARBINARY cd的处理速度快?/p>
4.3.4 逻辑数据cd
BITQ?BIT数据cd占用1 个字节的存储I间Q其gؓ0 ? 。如果输? ? 以外的|被视ؓ1?BIT cd不能定义为NULL |所谓NULL 值是指空值或无意义的|?/p>
4.3.5 字符数据cd
字符数据cd是用最多的数据cd。它可以用来存储各种字母、数字符受特D符受一般情况下Q用字W类型数据时d其前后加上单引号’或双引号??
1 CHAR
CHAR 数据cd的定义Ş式ؓCHAR[ QnQ?]?以CHAR cd存储的每个字W和W号占一个字节的存储I间。n 表示所有字W所占的存储I间Qn 的取gؓ1 ?000Q?卛_容纳8000 个ANSI 字符。若不指定n |则系l默认gؓ1?若输入数据的字符数小于nQ则pȝ自动在其后添加空格来填满讑֮好的I间。若输入的数据过长,会截掉其超出部分?br /> 2、NCHAR
NCHAR数据cd的定义Ş式ؓNCHAR[ QnQ?]?它与CHAR cd怼。不同的是NCHAR数据cdn 的取gؓ1 ?000?因ؓNCHAR cd采用UNICODE 标准字符集(CharacterSetQ?UNICODE 标准规定每个字符占用两个字节的存储空_所以它比非UNICODE 标准的数据类型多占用一倍的存储I间。用UNICODE 标准的好处是因其使用两个字节做存储单位,其一个存储单位的容纳量就大大增加了,可以全世界的语a文字都囊括在内,在一个数据列中就可以同时出现中文、英文、法文、d文等Q而不会出现编码冲H?br /> 3、VARCHAR
VARCHAR数据cd的定义Ş式ؓVARCHAR [ QnQ?]?它与CHAR cd怼Qn 的取g? ?000Q?若输入的数据q长Q将会截掉其出部分。不同的是,VARCHAR数据cdh变动长度的特性,因ؓVARCHAR数据cd的存储长度ؓ实际数值长度,若输入数据的字符数小于n Q则pȝ不会在其后添加空格来填满讑֮好的I间?br />一般情况下Q由于CHAR 数据cd长度固定Q因此它比VARCHAR cd的处理速度快?br /> 4、NVARCHAR
NVARCHAR数据cd的定义Ş式ؓNVARCHAR[ QnQ?]?它与VARCHAR cd怼。不同的是,NVARCHAR数据cd采用UNICODE 标准字符集(Character SetQ, n 的取gؓ1 ?000?/p>
4.3.6 文本和图形数据类?br /> q类数据cd用于存储大量的字W或二进制数据?br /> 1、TEXT
TEXT数据cd用于存储大量文本数据Q其定w理论上ؓ1 ??1ơ方-1 Q?Q?147Q?483Q?647Q个字节Q在实际应用旉要视盘的存储空间而定?br />SQL Server 2000 以前的版本中Q数据库中一个TEXT 对象存储的实际上是一个指针,它指向一个个?KB Q?192 个字节)为单位的数据(Data PageQ?q些数据|动态增加ƈ被逻辑链接h的。在SQL Server 2000 中,则将TEXT 和IMAGE cd的数据直接存攑ֈ表的数据行中Q而不是存攑ֈ不同的数据页中?q就减少了用于存储TEXT 和IMA- GE cd的空_q相应减了盘处理q类数据的I/O 数量?br /> 2 NTEXT
NTEXT数据cd与TEXT.cd怼不同?是NTEXT cd采用UNICODE 标准字符?Character Set), 因此其理论容量ؓ230-1(1, 073, 741, 823)个字节?br /> 3 IMAGE
IMAGE数据cd用于存储大量的二q制数据Binary Data?其理论容量ؓ2?1ơ方-1(2,147,483,647)个字节。其存储数据的模式与TEXT 数据cd相同。通常用来存储囑Ş{OLE Object Linking and EmbeddingQ对象连接和嵌入Q对象。在输入数据时同BINARY数据cd一P必须在数据前加上字符?X”作Zq制标识
4.3.7 日期和时间数据类?br /> 1 DATETIME
DATETIME 数据cd用于存储日期和时间的l合体。它可以存储从公?753 q? ? 日零时v到公?999 q?2 ?1 ?3 ?9 ?9 U之间的所有日期和旉Q其_度可达三癑ֈ之一U,?.33 毫秒。DATETIME 数据cd所占用的存储空间ؓ8 个字节。其中前4 个字节用于存?900 q? ? 日以前或以后的天敎ͼ数值分正负Q正数表C在此日期之后的日期Q负数表C在此日期之前的日期。后4 个字节用于存储从此日零时h指定的时间经q的毫秒数。如果在输入数据时省略了旉部分Q则pȝ?2:00:00:000AM作ؓ旉~省|如果省略了日期部分,则系l将1900 q? ? 日作为日期缺省倹{?br /> 2 SMALLDATETIME
SMALLDATETIME 数据cd与DATETIME 数据cd怼Q但其日期时间范围较,Z1900 q? ? 日到2079 q? ?Q日_ֺ较低Q只能精到分钟Q其分钟个位上ؓҎU数四舍五入的?即以30 Uؓ界四舍五入。如QDATETIME 旉?4:38:30.283
时SMALLDATETIME 认ؓ?4:39:00 SMALLDATETIME 数据cd使用4 个字节存储数据。其中前2 个字节存储从基础日期1900 q? ? 日以来的天数Q后两个字节存储此日零时h指定的时间经q的分钟数?br /> 下面介绍日期和时间的输入格式
日期输入格式
日期的输入格式很多大致可分ؓ三类Q?
英文+数字格式
此类格式中月份可用英文全名或~写Q且不区分大写Q年和月日之间可不用逗号Q?br />q䆾可ؓ4 位或2 位;当其Z位时Q若值小?0 则视?0xx q_若大于或{于50 ?br />视ؓ19xx q_若日部分省略Q则视ؓ当月?受以下格式均为正的日期格式Q?br />June 21 2000 Oct 1 1999 January 2000 2000 February
2000 May 1 2000 1 Sep 99 June July 00
数字+分隔W格?br />允许把斜杠(/Q、连接符Q?Q和数点(.Q作为用数字表示的年、月、日之间的分
隔符。如Q?br />YMDQ?000/6/22 2000-6-22 2000.6.22
MDYQ?/5/2000 3-5-2000 3.5.2000
DMYQ?1/12/1999 31-12-1999 31.12.2000
U数字格?br />U数字格式是以连l的4 ?、位? 位数字来表示日期。如果输入的? 位或8 ?br />数字Q系l将按年、月、日来识别,即YMD 格式Qƈ且月和日都是用两位数字来表示Q?br />如果输入的数字是4 位数Q系l认4 位数代表q䆾,其月份和日缺省ؓ此年度的1 ?br />1 日。如:
20000601---2000 q? ? ?991212---1999 q?2 ?2 ?1998---1998 q?
????
旉输入格式
在输入时间时必须按“小时、分钟、秒、毫U”的序来输入。在光用冒号“:”隔开。但可将毫秒部分用小数点??分,隔其后第一位数字代表十分之一U,W二位数字代表百分之一U,W三位数字代表千分之一U。当使用12 时制时用AM。am 和PMQpmQ分别指定时间是午前或午后,若不指定Q系l默认ؓAM。AM 与PM 均不区分大小写。如Q?br /> 3:5:7.2pm---下午3 ? ? U?00 毫秒
10:23:5.123Am---上午10 ?3 ? U?23 毫秒
可以使用SET DATEFORMAT 命o来设定系l默认的日期-旉格式?
4.3.8 货币数据cd
货币数据cd用于存储货币倹{在使用货币数据cdӞ应在数据前加上货币符Ppȝ才能辨识其ؓ哪国的货币,如果不加货币W号Q则默认为“E”。各货币W号如图4-2所C?br /> 1 MONEY
MONEY 数据cd的数据是一个有4 位小数的DECIMAL |其取g-2?3ơ方Q?922Q?37Q?03Q?85Q?77.5808??3ơ方-1Q?922Q?37Q?03Q?85Q?77.5807Q,数据_ֺZ分之一货币单位。MONEY 数据cd使用8个字节存储?br />
2 SMALLMONEY
SMALLMONEY数据cdcM于MONEY cdQ但其存储的货币D围比MONEY数据cd?其取g-214,748.3648?214,748.3647,存储I间? 个字节?/p>
4.3.9 特定数据cd
SQL Server 中包含了一些用于数据存储的Ҏ数据cd?br /> 1 TIMESTAMP
TIMESTAMP数据cd提供数据库范围内的惟一值此cd相当于BINARY8或VARBINARYQ?Q,但当它所定义的列在更新或插入数据行时Q此列的g被自动更斎ͼ一个计数值将自动地添加到此TIMESTAMP数据列中。每个数据库表中只能有一个TIMESTAMP数据列。如果徏立一个名为“TIMESTAMP”的列,则该列的cd被自动设ؓTIMESTAMP数据cd?/p>
2 UNIQUEIDENTIFIER
UNIQUEIDENTIFIER 数据cd存储一?6 位的二进制数字。此数字UCؓQGUIDGlobally Unique Identifier Q即全球惟一鉴别P。此数字由SQLServer 的NEWID函数产生的全球惟一的编码,在全球各地的计算机经由此函数产生的数字不会相同?/p>
4.3.10 用户自定义数据类?br />SYSNAME SYSNAME 数据cd是系l提供给用户的,便于用户自定义数据类型。它被定义ؓNVARCHARQ?28Q,卛_可存?28个UNICODE字符?56个一般字W。其具体使用Ҏ请参见第7章“管理数据库表”中的“自定义数据cd”章节?/p>
4.3.11 新数据类?br />SQL Server 2000 中增加了3 U数据类型:BIGINT、SQL_VARIANT和TABLE。其中BIGINT数据cd已在整数cd中介l,下面介绍其余两种Q?br /> 1 SQL_VARIANT
SQL_VARIANT数据cd可以存储除文本、图形数据(TEXT、NTEXT、IMAGEQ和TIMESTAMPcd数据外的其它M合法的SQL Server数据。此数据cd大大方便了SQL Server的开发工作?br /> 2 TABLE
TABLE 数据cd用于存储对表或视囑֤理后的结果集。这一新类型得变量可以存储一个表Q从而函数或过E返回查询结果更加方便快、捷其、用请参见W?3章“游标、视囑֒自定义函数”?/p>