PowerDesigner 11 使用心得(转)
1、安装PD v11.0版
2、由pdm生成建表脚本时,字段超过15字符就发生错误(oracle)
原因未知,解决办法是打开PDM后,会出现Database的菜单栏,进入Database - Edit Current DBMS -script-objects-column-maxlen,把value值调大(原为30),比如改成60。出现表或者其它对象的长度也有这种错误的话都可以选择对应的objects照此种方法更改!
或者使用下面的这种方法:
生成建表脚本时会弹出Database generation提示框:把options - check model的小勾给去掉,就是不进行检查(不推荐)!
或者可以修改C:Program FilesSybasePowerDesigner Trial 11Resource FilesDBMSoracl9i2.xdb文件
修改好后,再cdm转为pdm时,选择“Copy the DBMS definition in model”把把这个资源文件拷贝到模型中。
3、生成的建表脚本中如何把对象的双引号去掉?
打开cdm的情况下,进入Tools-Model Options-Naming Convention,把Name和Code的标签的Charcter case选项设置成Uppercase或者Lowercase,只要不是Mixed Case就行!
或者选择Database->Edit current database->Script->Sql->Format,有一项CaseSensitivityUsingQuote,它的comment为“Determines if the case sensitivity for identifiers is managed using double quotes”,表示是否适用双引号来规定标识符的大小写,可以看到右边的values默认值为“YES”,改为“No”即可!
或者在打开pdm的情况下,进入Tools-Model Options-Naming Convention,把Name和Code的标签的Charcter case选项设置成Uppercase就可以!
4、建立一个表后,为何检测出现Existence of index的警告
A table should contain at least one column, one index, one key, and one reference.
可以不检查 Existence of index 这项,也就没有这个警告错误了!
意思是说没有给表建立索引,而一个表一般至少要有一个索引,这是一个警告,不用管也没有关系!
5、创建一个表在修改字段的时候,一修改name的内容,code也跟着变化,如何让code不随着name变化
Name和Code 的右侧都有一个按钮“=”,如果需要不同步的话,把这个按钮弹起来就可以了。
Tools->General Options->Dialog->Name to Code Mirroring (去掉)
6、由CDM生成PDM时,自动生成的外键的重命名
PDM Generation Options->Detail->FK index names默认是%REFR%_FK,改为FK_%REFRCODE%,其中%REFRCODE%指的就是CDM中Relationship的code!另外自动生成的父字段的规则是PDM Generation Options->Detail->FK column name template中设置的,默认是%.3:PARENT%_%COLUMN%,可以改为Par%COLUMN%表示是父字段!
7、如何防止一对一的关系生成两个引用(外键)
要定义关系的支配方向,占支配地位的实体(有D标志)变为父表。
在cdm中双击一对一关系->Detail->Dominant role选择支配关系
8、修改报表模板中一些术语的定义
即文件:C:Program FilesSybasePowerDesigner Trial 11Resource FilesReport LanguagesChinese.xrl
Tools-Resources-Report Languages-选择Chinese-单击Properties或双击目标
修改某些对象的名称:Object AttributesPhysical Data ModelColumn
ForeignKey:外键
Mandatory:为空
Primary:主键
Table:表
用查找替换,把“表格”替换成“表”
修改显示的内容为别的:Values MappingListsStandard,添加TRUE的转化列为是,FALSE的转化列为空
另外Report-Title Page里可以设置标题信息
=============================
1。pd中复制一列是,实际上是一个链接。源列的变动同时体现在复制列上
2。数据库设计通常步骤:CDM缺定主要结构--》生成PDM--》在PDM上修改,必要时生成CDM
3。若由pdm生成cdm再生成pdm,在pdm中修改过的外键名将被改回到默认值
4。必要时可以通过修改模板(Database-Edit Current DataBase)改变脚本的格式。例如:
Script-Objects-Column-Add的Value中开头增加一行“--%COLNNAME%”以便在脚本中显示列的中英文对照
5。去掉讨厌的name、code映射:Tools-General Options-clear the Name to Code mirroring check box
6。对于大小写不敏感的数据库(如Oracle),PowerDesign在创建脚本时自动给表名和字段名加上双引号,以“强字符串”形式来获取区分大小写,这样给sql语句的编写制造很多麻烦。去掉这个添足的功能:
Database -〉Edit Current DBMS -〉Script -〉Sql -〉Format -〉CaseSensitivityUsingQuote
右边面板参数值 Value 选择No
7。由cdm生成pdm,可以控制是否将关系生成引用;由pdm生成脚本,可以控制是否将引用生成外键
8。对于oracle而言,为表设置选项(如tablespace GPSSYSTEM)可使其创建到正确的表空间;为主键设置选项(using index tablespace GPSINDEX)使索引创建到正确的表空间中
9。使数据模型图上显示中文:Tools-Model Options-Naming Convertion,在右侧Display处选择Name
=======================================================================
1、修改建表脚本生成规则。如果每个表格都有相同的字段,可以如下修改:
Database -> Edit Current DBMS 展开 Script -> Object -> Table -> Create 见右下的Value值,可以直接修改如下:
/* tablename: %TNAME% */
create table [%QUALIFIER%]%TABLE% (
%TABLDEFN%
ts char(19) null default convert(char(19),getdate(),20),
dr smallint null default 0
)
[%OPTIONS%]
其中的 ts、dr 两列会在生成SQL脚本的时候自动的插入每个表格中,其中的%TNAME% 变量是给每个表格的SQL添加一个该表的Name值注释。
2、修改字段生成规则。要给每个字段都添加一个注释的话,同一窗口中展开 Script -> Object -> Column -> Add 的 Value修改为:
%20:COLUMN% [%COMPUTE%?AS (%COMPUTE%):%20:DATATYPE% [%IDENTITY%?%IDENTITY%:[%NULL%][%NOTNULL%]][ default %DEFAULT%]
[[constraint %CONSTNAME%] check (%CONSTRAINT%)]]/*%COLNNAME%*/
其中的%COLNNAME%就是列的Name值(可以是中文)
3、修改外键命名规则。选择Database—>Edit Current DBMS
选择Scripts-》Objects-》Reference-》ConstName
可以发现右侧的Value为:
FK_%.U8:CHILD%_%.U9:REFR%_%.U8:PARENT%
可见,该命名方法是:'FK_'+8位子表名+9位Reference名+8位父表名,你可以根据这中模式自定义为:
FK_%.U7:CHILD%_RELATIONS_%.U7:PARENT%,
可以使FK名称变为FK_TABLE_2_RELATIONS_TABLE_1
掌握这种方法后就可以按照自己的想法修改了
生成建库脚本SQL文件中的表头注释很讨厌,可以在 Databse -> Generate Database (Ctrl+G)窗口中,选择Options卡片,去掉Usage的Title钩选项即可。
4、添加外键
Model -> References新建一条外键后,双击进入外键属性,在“Joins”卡片中可以选择子表的外键字段
要生成建库脚本即Databse -> Generate Database (Ctrl+G)窗口中确定即可。
5、双引号
对于大小写不敏感的数据库(如Oracle),PowerDesign在创建脚本时自动给表名和字段名加上双引号,以“强字符串”形式来获取区分大小写,这样给sql语句的编写制造很多麻烦。去掉这个添足的功能:
Database -〉Edit Current DBMS -〉Script -〉Sql -〉Format -〉CaseSensitivityUsingQuote
右边面板参数值 Value 选择No
16:20 浏览 (770) 评论 (0) 分类: 数据库 2007-09-25
缩略显示Oracle中如何计算时间差
计算时间差是Oracle DATA数据类型的一个常见问题。Oracle支持日期计算,你可以创建诸如“日期1-日期2”这样的表达式来计算这两个日期之间的时间差。
一旦你发现了时间差异,你可以使用简单的技巧来以天、小时、分钟或者秒为单位来计算时间差。为了得到数据差,你必须选择合适的时间度量单位,这样就可以进行数据格式隐藏。
使用完善复杂的转换函数来转换日期是一个诱惑,但是你会发现这不是最好的解决方法。
round(to_number(end-date-start_date))- 消逝的时间(以天为单位)
round(to_number(end-date-start_date)*24)- 消逝的时间(以小时为单位)
round(to_number(end-date-start_date)*1440)- 消逝的时间(以分钟为单位)
显示时间差的默认模式是什么?为了找到这个问题的答案,让我们进行一个简单的SQL *Plus查询。
SQL> select sysdate-(sysdate-3) from dual;
SYSDATE-(SYSDATE-3)
-------------------
3
这里,我们看到了Oracle使用天来作为消逝时间的单位,所以我们可以很容易的使用转换函数来把它转换成小时或者分钟。然而,当分钟数不是一个整数时,我们就会遇到放置小数点的问题。
Select
(sysdate-(sysdate-3.111))*1440
from
dual;
(SYSDATE-(SYSDATE-3.111))*1440
------------------------------
4479.83333
当然,我们可以用ROUND函数(即取整函数)来解决这个问题,但是要记住我们必须首先把DATE数据类型转换成NUMBER数据类型。
Select
round(to_number(sysdate-(sysdate-3.111))*1440)
from
dual;
ROUND(TO_NUMBER(SYSDATE-(SYSDATE-3.111))*1440)
----------------------------------------------
4480
我们可以用这些函数把一个消逝时间近似转换成分钟并把这个值写入Oracle表格中。在这个例子里,我们有一个离线(logoff)系统级触发机制来计算已经开始的会话时间并把它放入一个Oracle STATSPACK USER_LOG扩展表格之中。
Update
perfstat.stats$user_log
set
elapsed_minutes =
round(to_number(logoff_time-logon_time)*1440)
where
user = user_id
and
elapsed_minutes is NULL;
12:43 浏览 (273) 评论 (0) 分类: 数据库 2007-06-15
缩略显示MYSQL和ORACLE的一些区别
有很多应用项目, 刚起步的时候用MYSQL数据库基本上能实现各种功能需求,随着应用用户的增多,数据量的增加,MYSQL渐渐地出现不堪重负的情况:连接很慢甚至宕机,于是就有把数据从MYSQL迁到ORACLE的需求,应用程序也要相应做一些修改。总结出以下几点注意事项。
1.自动增长的数据类型处理
MYSQL有自动增长的数据类型,插入记录时不用操作此字段,会自动获得数据值。ORACLE没有自动增长的数据类型,需要建立一个自动增长的序列号,插入记录时要把序列号的下一个值赋于此字段。
CREATE SEQUENCE 序列号的名称 (最好是表名+序列号标记) INCREMENT BY 1 START WITH 1 MAXVALUE 99999 CYCLE NOCACHE;
其中最大的值按字段的长度来定, 如果定义的自动增长的序列号 NUMBER(6) , 最大值为999999
INSERT 语句插入这个字段值为: 序列号的名称.NEXTVAL
2. 单引号的处理
MYSQL里可以用双引号包起字符串,ORACLE里只可以用单引号包起字符串。在插入和修改字符串前必须做单引号的替换:把所有出现的一个单引号替换成两个单引号。
3. 翻页的SQL语句的处理
MYSQL处理翻页的SQL语句比较简单,用LIMIT 开始位置, 记录个数;PHP里还可以用SEEK定位到结果集的位置。ORACLE处理翻页的SQL语句就比较繁琐了。每个结果集只有一个ROWNUM字段标明它的位置, 并且只能用ROWNUM<100, 不能用ROWNUM>80。
以下是经过分析后较好的两种ORACLE翻页SQL语句( ID是唯一关键字的字段名 ):
语句一:
SELECT ID, [FIELD_NAME,...] FROM TABLE_NAME WHERE ID IN ( SELECT ID FROM (SELECT ROWNUM AS NUMROW, ID FROM TABLE_NAME WHERE 条件1 ORDER BY 条件2) WHERE NUMROW > 80 AND NUMROW < 100 ) ORDER BY 条件3;
语句二:
SELECT * FROM (( SELECT ROWNUM AS NUMROW, c.* from (select [FIELD_NAME,...] FROM TABLE_NAME WHERE 条件1 ORDER BY 条件2) c) WHERE NUMROW > 80 AND NUMROW < 100 ) ORDER BY 条件3;
4.长字符串的处理
长字符串的处理ORACLE也有它特殊的地方。INSERT和UPDATE时最大可操作的字符串长度小于等于4000个单字节, 如果要插入更长的字符串, 请考虑字段用CLOB类型,方法借用ORACLE里自带的DBMS_LOB程序包。插入修改记录前一定要做进行非空和长度判断,不能为空的字段值和超出长度字段值都应该提出警告,返回上次操作。
5. 日期字段的处理
MYSQL日期字段分DATE和TIME两种,ORACLE日期字段只有DATE,包含年月日时分秒信息,用当前数据库的系统时间为SYSDATE, 精确到秒,或者用字符串转换成日期型函数TO_DATE(‘2001-08-01’,’YYYY-MM-DD’)年-月-日 24小时:分钟:秒的格式YYYY-MM-DD HH24:MI:SS TO_DATE()还有很多种日期格式, 可以参看ORACLE DOC.日期型字段转换成字符串函数TO_CHAR(‘2001-08-01’,’YYYY-MM-DD HH24:MI:SS’)
日期字段的数学运算公式有很大的不同。MYSQL找到离当前时间7天用 DATE_FIELD_NAME > SUBDATE(NOW(),INTERVAL 7 DAY)ORACLE找到离当前时间7天用 DATE_FIELD_NAME >SYSDATE - 7;
6. 空字符的处理
MYSQL的非空字段也有空的内容,ORACLE里定义了非空字段就不容许有空的内容。按MYSQL的NOT NULL来定义ORACLE表结构, 导数据的时候会产生错误。因此导数据时要对空字符进行判断,如果为NULL或空字符,需要把它改成一个空格的字符串。
7. 字符串的模糊比较
MYSQL里用字段名 like '%字符串%',ORACLE里也可以用字段名 like '%字符串%' 但这种方法不能使用索引, 速度不快,用字符串比较函数 instr(字段名,'字符串')>0 会得到更精确的查找结果。
8. 程序和函数里,操作数据库的工作完成后请注意结果集和指针的释放。
11:49 浏览 (420) 评论 (0) 分类: 数据库 2007-06-05
缩略显示mysql 时间函数用法集合
对于每个类型拥有的值范围以及并且指定日期何时间值的有效格式的描述见7.3.6 日期和时间类型。
这里是一个使用日期函数的例子。下面的查询选择了所有记录,其date_col的值是在最后30天以内:
mysql> SELECT something FROM table
WHERE TO_DAYS(NOW()) - TO_DAYS(date_col) <= 30;
DAYOFWEEK(date)
返回日期date的星期索引(1=星期天,2=星期一, ……7=星期六)。这些索引值对应于ODBC标准。
mysql> select DAYOFWEEK('1998-02-03');
-> 3
WEEKDAY(date)
返回date的星期索引(0=星期一,1=星期二, ……6= 星期天)。
mysql> select WEEKDAY('1997-10-04 22:23:00');
-> 5
mysql> select WEEKDAY('1997-11-05');
-> 2
DAYOFMONTH(date)
返回date的月份中日期,在1到31范围内。
mysql> select DAYOFMONTH('1998-02-03');
-> 3
DAYOFYEAR(date)
返回date在一年中的日数, 在1到366范围内。
mysql> select DAYOFYEAR('1998-02-03');
-> 34
MONTH(date)
返回date的月份,范围1到12。
mysql> select MONTH('1998-02-03');
-> 2
DAYNAME(date)
返回date的星期名字。
mysql> select DAYNAME("1998-02-05");
-> 'Thursday'
MONTHNAME(date)
返回date的月份名字。
mysql> select MONTHNAME("1998-02-05");
-> 'February'
QUARTER(date)
返回date一年中的季度,范围1到4。
mysql> select QUARTER('98-04-01');
-> 2
WEEK(date)
WEEK(date,first)
对于星期天是一周的第一天的地方,有一个单个参数,返回date的周数,范围在0到52。2个参数形式WEEK()允许你指定星期是否开始于星期天或星期一。如果第二个参数是0,星期从星期天开始,如果第二个参数是1,从星期一开始。
mysql> select WEEK('1998-02-20');
-> 7
mysql> select WEEK('1998-02-20',0);
-> 7
mysql> select WEEK('1998-02-20',1);
-> 8
YEAR(date)
返回date的年份,范围在1000到9999。
mysql> select YEAR('98-02-03');
-> 1998
HOUR(time)
返回time的小时,范围是0到23。
mysql> select HOUR('10:05:03');
-> 10
MINUTE(time)
返回time的分钟,范围是0到59。
mysql> select MINUTE('98-02-03 10:05:03');
-> 5
SECOND(time)
回来time的秒数,范围是0到59。
mysql> select SECOND('10:05:03');
-> 3
PERIOD_ADD(P,N)
增加N个月到阶段P(以格式YYMM或YYYYMM)。以格式YYYYMM返回值。注意阶段参数P不是日期值。
mysql> select PERIOD_ADD(9801,2);
-> 199803
PERIOD_DIFF(P1,P2)
返回在时期P1和P2之间月数,P1和P2应该以格式YYMM或YYYYMM。注意,时期参数P1和P2不是日期值。
mysql> select PERIOD_DIFF(9802,199703);
-> 11
DATE_ADD(date,INTERVAL expr type)
DATE_SUB(date,INTERVAL expr type)
ADDDATE(date,INTERVAL expr type)
SUBDATE(date,INTERVAL expr type)
这些功能执行日期运算。对于MySQL 3.22,他们是新的。ADDDATE()和SUBDATE()是DATE_ADD()和DATE_SUB()的同义词。
在MySQL 3.23中,你可以使用+和-而不是DATE_ADD()和DATE_SUB()。(见例子)date是一个指定开始日期的
DATETIME或DATE值,expr是指定加到开始日期或从开始日期减去的间隔值一个表达式,expr是一个字符串;它可以以
一个“-”开始表示负间隔。type是一个关键词,指明表达式应该如何被解释。EXTRACT(type FROM date)函数从日期
中返回“type”间隔。下表显示了type和expr参数怎样被关联: type值含义期望的expr格式
SECOND 秒 SECONDS
MINUTE 分钟 MINUTES
HOUR 时间 HOURS
DAY 天 DAYS
MONTH 月 MONTHS
YEAR 年 YEARS
MINUTE_SECOND 分钟和秒 "MINUTES:SECONDS"
HOUR_MINUTE 小时和分钟 "HOURS:MINUTES"
DAY_HOUR 天和小时 "DAYS HOURS"
YEAR_MONTH 年和月 "YEARS-MONTHS"
HOUR_SECOND 小时, 分钟, "HOURS:MINUTES:SECONDS"
DAY_MINUTE 天, 小时, 分钟 "DAYS HOURS:MINUTES"
DAY_SECOND 天, 小时, 分钟, 秒 "DAYS HOURS:MINUTES:SECONDS"
MySQL在expr格式中允许任何标点分隔符。表示显示的是建议的分隔符。如果date参数是一个DATE值并且你的计算仅仅包含YEAR、MONTH和DAY部分(即,没有时间部分),结果是一个DATE值。否则结果是一个DATETIME值。
mysql> SELECT "1997-12-31 23:59:59" + INTERVAL 1 SECOND;
-> 1998-01-01 00:00:00
mysql> SELECT INTERVAL 1 DAY + "1997-12-31";
-> 1998-01-01
mysql> SELECT "1998-01-01" - INTERVAL 1 SECOND;
-> 1997-12-31 23:59:59
mysql> SELECT DATE_ADD("1997-12-31 23:59:59",
INTERVAL 1 SECOND);
-> 1998-01-01 00:00:00
mysql> SELECT DATE_ADD("1997-12-31 23:59:59",
INTERVAL 1 DAY);
-> 1998-01-01 23:59:59
mysql> SELECT DATE_ADD("1997-12-31 23:59:59",
INTERVAL "1:1" MINUTE_SECOND);
-> 1998-01-01 00:01:00
mysql> SELECT DATE_SUB("1998-01-01 00:00:00",
INTERVAL "1 1:1:1" DAY_SECOND);
-> 1997-12-30 22:58:59
mysql> SELECT DATE_ADD("1998-01-01 00:00:00",
INTERVAL "-1 10" DAY_HOUR);
-> 1997-12-30 14:00:00
mysql> SELECT DATE_SUB("1998-01-02", INTERVAL 31 DAY);
-> 1997-12-02
mysql> SELECT EXTRACT(YEAR FROM "1999-07-02");
-> 1999
mysql> SELECT EXTRACT(YEAR_MONTH FROM "1999-07-02 01:02:03");
-> 199907
mysql> SELECT EXTRACT(DAY_MINUTE FROM "1999-07-02 01:02:03");
-> 20102
如果你指定太短的间隔值(不包括type关键词期望的间隔部分),MySQL假设你省掉了间隔值的最左面部分。例如,如果你指定一个type是DAY_SECOND,值expr被希望有天、小时、分钟和秒部分。如果你象"1:10"这样指定值,MySQL假设日子和小时部分是丢失的并且值代表分钟和秒。换句话说,"1:10" DAY_SECOND以它等价于"1:10" MINUTE_SECOND的方式解释,这对那MySQL解释TIME值表示经过的时间而非作为一天的时间的方式有二义性。如果你使用确实不正确的日期,结果是NULL。如果你增加MONTH、YEAR_MONTH或YEAR并且结果日期大于新月份的最大值天数,日子在新月用最大的天调整。
mysql> select DATE_ADD('1998-01-30', Interval 1 month);
-> 1998-02-28
注意,从前面的例子中词INTERVAL和type关键词不是区分大小写的。
TO_DAYS(date)
给出一个日期date,返回一个天数(从0年的天数)。
mysql> select TO_DAYS(950501);
-> 728779
mysql> select TO_DAYS('1997-10-07');
-> 729669
TO_DAYS()
不打算用于使用格列高里历(1582)出现前的值。
FROM_DAYS(N)
给出一个天数N,返回一个DATE值。
mysql> select FROM_DAYS(729669);
-> '1997-10-07'
DATE_FORMAT(date,format)
根据format字符串格式化date值。下列修饰符可以被用在format字符串中: %M 月名字(January……December)
%W 星期名字(Sunday……Saturday)
%D 有英语前缀的月份的日期(1st, 2nd, 3rd, 等等。)
%Y 年, 数字, 4 位
%y 年, 数字, 2 位
%a 缩写的星期名字(Sun……Sat)
%d 月份中的天数, 数字(00……31)
%e 月份中的天数, 数字(0……31)
%m 月, 数字(01……12)
%c 月, 数字(1……12)
%b 缩写的月份名字(Jan……Dec)
%j 一年中的天数(001……366)
%H 小时(00……23)
%k 小时(0……23)
%h 小时(01……12)
%I 小时(01……12)
%l 小时(1……12)
%i 分钟, 数字(00……59)
%r 时间,12 小时(hh:mm:ss [AP]M)
%T 时间,24 小时(hh:mm:ss)
%S 秒(00……59)
%s 秒(00……59)
%p AM或PM
%w 一个星期中的天数(0=Sunday ……6=Saturday )
%U 星期(0……52), 这里星期天是星期的第一天
%u 星期(0……52), 这里星期一是星期的第一天
%% 一个文字“%”。
所有的其他字符不做解释被复制到结果中。
mysql> select DATE_FORMAT('1997-10-04 22:23:00', '%W %M %Y');
-> 'Saturday October 1997'
mysql> select DATE_FORMAT('1997-10-04 22:23:00', '%H:%i:%s');
-> '22:23:00'
mysql> select DATE_FORMAT('1997-10-04 22:23:00',
'%D %y %a %d %m %b %j');
-> '4th 97 Sat 04 10 Oct 277'
mysql> select DATE_FORMAT('1997-10-04 22:23:00',
'%H %k %I %r %T %S %w');
-> '22 22 10 10:23:00 PM 22:23:00 00 6'
MySQL3.23中,在格式修饰符字符前需要%。在MySQL更早的版本中,%是可选的。
TIME_FORMAT(time,format)
这象上面的DATE_FORMAT()函数一样使用,但是format字符串只能包含处理小时、分钟和秒的那些格式修饰符。其他修饰符产生一个NULL值或0。
CURDATE()
CURRENT_DATE
以'YYYY-MM-DD'或YYYYMMDD格式返回今天日期值,取决于函数是在一个字符串还是数字上下文被使用。
mysql> select CURDATE();
-> '1997-12-15'
mysql> select CURDATE() + 0;
-> 19971215
CURTIME()
CURRENT_TIME
以'HH:MM:SS'或HHMMSS格式返回当前时间值,取决于函数是在一个字符串还是在数字的上下文被使用。
mysql> select CURTIME();
-> '23:50:26'
mysql> select CURTIME() + 0;
-> 235026
NOW()
SYSDATE()
CURRENT_TIMESTAMP
以'YYYY-MM-DD HH:MM:SS'或YYYYMMDDHHMMSS格式返回当前的日期和时间,取决于函数是在一个字符串还是在数字的上下文被使用。
mysql> select NOW();
-> '1997-12-15 23:50:26'
mysql> select NOW() + 0;
-> 19971215235026
UNIX_TIMESTAMP()
UNIX_TIMESTAMP(date)
如果没有参数调用,返回一个Unix时间戳记(从'1970-01-01 00:00:00'GMT开始的秒数)。如果UNIX_TIMESTAMP()用一个date参数被调用,它返回从'1970-01-01 00:00:00' GMT开始的秒数值。date可以是一个DATE字符串、一个DATETIME字符串、一个TIMESTAMP或以YYMMDD或YYYYMMDD格式的本地时间的一个数字。
mysql> select UNIX_TIMESTAMP();
-> 882226357
mysql> select UNIX_TIMESTAMP('1997-10-04 22:23:00');
-> 875996580
当UNIX_TIMESTAMP被用于一个TIMESTAMP列,函数将直接接受值,没有隐含的“string-to-unix-timestamp”变换。
FROM_UNIXTIME(unix_timestamp)
以'YYYY-MM-DD HH:MM:SS'或YYYYMMDDHHMMSS格式返回unix_timestamp参数所表示的值,取决于函数是在一个字符串还是或数字上下文中被使用。
mysql> select FROM_UNIXTIME(875996580);
-> '1997-10-04 22:23:00'
mysql> select FROM_UNIXTIME(875996580) + 0;
-> 19971004222300
FROM_UNIXTIME(unix_timestamp,format)
返回表示 Unix 时间标记的一个字符串,根据format字符串格式化。format可以包含与DATE_FORMAT()函数列出的条目同样的修饰符。
mysql> select FROM_UNIXTIME(UNIX_TIMESTAMP(),
'%Y %D %M %h:%i:%s %x');
-> '1997 23rd December 03:43:30 x'
SEC_TO_TIME(seconds)
返回seconds参数,变换成小时、分钟和秒,值以'HH:MM:SS'或HHMMSS格式化,取决于函数是在一个字符串还是在数字上下文中被使用。
mysql> select SEC_TO_TIME(2378);
-> '00:39:38'
mysql> select SEC_TO_TIME(2378) + 0;
-> 3938
TIME_TO_SEC(time)
返回time参数,转换成秒。
mysql> select TIME_TO_SEC('22:23:00');
-> 80580
mysql> select TIME_TO_SEC('00:39:38');
常用函数:
NOW()函数以`'YYYY-MM-DD HH:MM:SS'返回当前的日期时间,可以直接存到DATETIME字段中。
CURDATE()以’YYYY-MM-DD’的格式返回今天的日期,可以直接存到DATE字段中。
CURTIME()以’HH:MM:SS’的格式返回当前的时间,可以直接存到TIME字段中。
例:insert into tablename (fieldname) values (now())
-> 2378
13:28 浏览 (306) 评论 (0) 分类: 数据库 2007-06-04
缩略显示Oracle DATE和TIMESTAMP数据类型的比较
如果你想在ORACLE中存储DATE和时间信息的话,实际上你由两种字段数据类型的选择的话,就让我们看看这两种数据类型的差别和它们提供了些什么。
DATE数据类型
这个数据类型我们实在是太熟悉了,当我们需要表示日期和时间的话都会想到date类型。它可以存储月,年,日,世纪,时,分和秒。它典型地用来表示什么时候事情已经发生或将要发生。DATE数据类型的问题在于它表示两个事件发生时间间隔的度量粒度是秒。这个问题将在文章稍后讨论timestamp的时候被解决。可以使用TO_CHAR函数把DATE数据进行传统地包装,达到表示成多种格式的目的。
SQL> SELECT TO_CHAR(date1,MM/DD/YYYY HH24:MI:SS) "Date" FROM date_table;Date---------------------------06/20/2003 16:55:1406/26/2003 11:16:36
我见到的大多数人陷入的麻烦就是计算两个时间间的间隔年数、月数、天数、小时数和秒数。你需要明白的是,当你进行两个日期的相减运算的时候,得到的是天数。你需要乘上每天的秒数(1天=86400秒),然后,你可以再次计算得到你想要的间隔数。下面就是我的解决方法,可以精确计算出两个时间的间隔。我明白这个例子可以更简短些,但是我是为了显示所有的数字来强调计算方式。
1 SELECT TO_CHAR(date1,MMDDYYYY:HH24:MI:SS) date1, 2 TO_CHAR(date2,MMDDYYYY:HH24:MI:SS) date2, 3 trunc(86400*(date2-date1))- 4 60*(trunc((86400*(date2-date1))/60)) seconds, 5 trunc((86400*(date2-date1))/60)- 6 60*(trunc(((86400*(date2-date1))/60)/60)) minutes, 7 trunc(((86400*(date2-date1))/60)/60)- 8 24*(trunc((((86400*(date2-date1))/60)/60)/24)) hours, 9 trunc((((86400*(date2-date1))/60)/60)/24) days, 10 trunc(((((86400*(date2-date1))/60)/60)/24)/7) weeks 11* FROM date_tableDATE1 DATE2 SECONDS MINUTES HOURS DAYS WEEKS----------------- ----------------- ---------- ---------- ---------- ---------- ----------06202003:16:55:14 07082003:11:22:57 43 27 18 17 206262003:11:16:36 07082003:11:22:57 21 6 0 12 1
TIMESTAMP 数据类型
DATE数据类型的主要问题是它粒度不能足够区别出两个事件哪个先发生。ORACLE已经在DATE数据类型上扩展出来了TIMESTAMP数据类型,它包括了所有DATE数据类型的年月日时分秒的信息,而且包括了小数秒的信息。如果你想把DATE类型转换成TIMESTAMP类型,就使用CAST函数。
SQL> SELECT CAST(date1 AS TIMESTAMP) "Date" FROM t;Date-----------------------------------------------------20-JUN-03 04.55.14.000000 PM26-JUN-03 11.16.36.000000 AM
正如你看到的,在转换后的时间段尾部有了一段“.000000”。这是因为从date转换过来的时候,没有小数秒的信息,缺省为0。而且显示格式是按照参数NLS_TIMESTAMP_FORMAT定的缺省格式显示。当你把一个表中date类型字段的数据移到另一个表的timestamp类型字段中去的时候,可以直接写INSERT SELECT语句,oracle会自动为你做转换的。
1 SELECT TO_CHAR(time1,MM/DD/YYYY HH24:MI:SS) "Date" FROM date_tableDate-------------------06/20/2003 16:55:1406/26/2003 11:16:36
TIMESTAMP数据的格式化显示和DATE 数据一样。注意,to_char函数支持date和timestamp,但是trunc却不支持
TIMESTAMP数据类型。这已经清楚表明了在当两个时间的差别极度重要的情况下,使用TIMESTAMP数据类型要比DATE数据类型
更确切。如果你想显示TIMESTAMP的小数秒信息,参考下面:1 SELECT TO_CHAR(time1,@#MM/DD/YYYY HH24:MI:SS:FF3@#) "Date" FROM date_tableDate-----------------------06/20/2003 16:55:14:00006/26/2003 11:16:36:000在上例中,我只现实了小数点后3位的内容。计算timestamp间的数据差别要比老的date数据类型更容易。当你直接相减的话,看看会发生什么。结果将更容易理解,
第一行的17天,18小时,27分钟和43秒。1 SELECT time1, 2 time2, 3 substr((time2-time1),instr((time2-time1),@# @#)+7,2) seconds, 4 substr((time2-time1),instr((time2-time1),@# @#)+4,2) minutes, 5 substr((time2-time1),instr((time2-time1),@# @#)+1,2) hours, 6 trunc(to_number(substr((time2-time1),1,instr(time2-time1,@# @#)))) days, 7 trunc(to_number(substr((time2-time1),1,instr(time2-time1,@# @#)))/7) weeks 8* FROM date_tableTIME1 TIME2 SECONDS MINUTES HOURS DAYS WEEKS------------------------- -------------------------- ------- ------- ----- ---- -----06/20/2003:16:55:14:000000 07/08/2003:11:22:57:000000 43 27 18 17 206/26/2003:11:16:36:000000 07/08/2003:11:22:57:000000 21 06 00 12 1这就意味着不再需要关心一天有多少秒在麻烦的计算中。因此,得到天数、月数、天数、时数、分钟数和秒数就成为用substr
函数摘取出数字的事情了。系统日期和时间为了得到系统时间,返回成date数据类型。你可以使用sysdate函数。SQL> SELECT SYSDATE FROM DUAL;为了得到系统时间,返回成timestamp数据类型。你可以使用systimpstamp函数。SQL> SELECT SYSTIMESTAMP FROM DUAL;你可以设置初始化参数FIXED_DATE指定sysdate函数返回一个固定值。这用在测试日期和时间敏感的代码。注意,这个参数
对于systimestamp函数无效。SQL> ALTER SYSTEM SET fixed_date = @#2003-01-01-10:00:00@#;System altered. SQL> select sysdate from dual;SYSDATE---------01-JAN-03 SQL> select systimestamp from dual;SYSTIMESTAMP---------------------------------------------------------09-JUL-03 11.05.02.519000 AM -06:00当使用date和timestamp类型的时候,选择是很清楚的。你可以随意处置date和timestamp类型。当你试图转换到更强大的
timestamp的时候,需要注意,它们既有类似的地方,更有不同的地方,而足以造成破坏。两者在简洁和间隔尺寸方面各有优
势,请合理地选择。
17:16 浏览 (676) 评论 (0) 分类: 数据库 2007-06-04
缩略显示在java中对Oracle 日期类型字段的操作
表 book 中有name varchar2(20)//书籍名称,buydate Date //购买日期两个字段。
已经创建了数据库连接Connection conn;
方法一、使用java.sql.Date实现比较简单的yyyy-mm-dd格式日期。
java.sql.Date不支持时间格式。切记不要使用new java.sql.Date(int year,int month,int date),因为还要处理时间差问题。
PreparedStatement pstmt = conn.prepareStatement("insert into book (name,buydate) values (?,?)");
java.sql.Date buydate=java.sql.Date.valueOf("2005-06-08");
pstmt.setString(1, "Java编程思想");
pstmt.setDate(2,buydate );
pstmt.execute();
方法二、使用java.sql.Timestamp,同上不使用new Timestamp(....)
PreparedStatement pstmt = conn.prepareStatement("insert into book (name,buydate) values (?,?)");
java.sql.Timestamp buydate=java.sql.Timestamp.valueOf("2004-06-08 05:33:99");
pstmt.setString(1, "Java编程思想");
pstmt.setTimestamp(2,buydate );
pstmt.execute();
方法三、使用oracle 的to_date内置函数
PreparedStatement pstmt = conn.prepareStatement("insert into book (name,buydate) values (?,to_date(?, 'yyyy-mm-dd hh24:mi:ss')");
String buydate="2004-06-08 05:33:99";
pstmt.setString(1, "Java编程思想");
pstmt.setString(2,buydate );
pstmt.execute();
附:oracle日期格式参数含义说明
d: 一周中的星期几
day: 天的名字,使用空格填充到9个字符
dd: 月中的第几天
ddd: 年中的第几天
dy: 天的简写名
iw: ISO标准的年中的第几周
iyyy: ISO标准的四位年份
yyyy: 四位年份
yyy,yy,y: 年份的最后三位,两位,一位
hh: 小时,按12小时计
hh24: 小时,按24小时计
mi: 分
ss: 秒
mm: 月
mon: 月份的简写
month: 月份的全名
w: 该月的第几个星期
ww: 年中的第几个星期
17:14 浏览 (355) 评论 (0) 分类: 数据库 2007-06-04
缩略显示ORACLE中date类型字段的处理
ORACLE/JSP技术涉及日期、时间问题的处理
(1)在英文版本的ORACLE中默认日期格式为'DD-MON-YY',例如'01-JAN-98'
在汉化的中文版本中ORACLE默认日期格式为'日-月-年',例如'21-8月-2003'或'21-8月-03'
(2)转换字符串为日期
使用ORACLE内部函数to_date()
to_date()函数的参数是to_char()函数参数的反转。
to_date(string_value , date_format)
变量定义如下:
string_value :为字符串直接值(字符串本身)、字符串列(数据库中定义的某个表的某列)或某字符串内部函数的返回值。
date_format为合法的Oracle日期格式。
下列更新语句均符合ORACLE的日期格式,更新成功:
create table student (name varchar2(10) not null primary key , enrolldate date not null);//创建student表
insert into student values('mark',to_date('08-21-2003','MM-DD-YYYY'));
insert into student values('mark1',to_date('21-08-2003','DD-MM-YYYY'));
insert into student values('mark2','21-8月-2003');
insert into xiongxiaomin.student values('mark3','21-8月-03');
(3)转换日期为字符串
使用ORACLE内部函数to_char()
to_char(date_value,date_format)
变量定义如下:
date_value :为日期型直接值(日期本身)、日期型列值(数据库中定义的某个表的某列)或某内部函数的返回的日期型值。
date_format为合法的Oracle日期格式。
选择enrolldate字段的时间部分:
select (to_char(enrolldate,'HH24:MI:SS'))enrolldate from student;
(4)注意:ORACLE中的date数据类型定义的列包含日期和时间。
1、系统当前日期为2003年8月21日,之后执行下列语句
insert into student values('mark5',to_date('09:28:03','HH:MI:SS'));//注意此种在一条记录的date类型字段中插入时间的方法,系统默认的日期为系统当前日期所在月份的第一天,因此得到的记录为
Name enrolldate
mark5 01-八月 -2003 09:28:03 AM
2、修改系统当前日期为2003年7月21日,之后执行下列语句
insert into student values('mark6',to_date('09:28:03','HH:MI:SS'));
得到的记录为
Name enrolldate
mark6 01-七月 -2003 09:28:03 AM
insert into student values('mark8',to_date('20:28:03','HH24:MI:SS'));
3、同时在一条记录中插入日期和时间的方法
insert into student values('mark9',to_date('21-08-2003
20:28:03','DD-MM-YYYY HH24:MI:SS'));//同时在一条记录中插入日期和时间的方法
insert into student values('mark',to_date('21-08-2003
09:52:03','DD-MM-YYYY HH:MI:SS'));//同时在一条记录中插入日期和时间的方法
注意不能使用下列方法同时插入日期和时间
insert into student values('mark2','21-8月-2003'+to_date('
09:52:03','HH:MI:SS'));//无效插入记录方法
4、在SQL*Plus Worksheet中执行下列SQL语句
select * from student;
得到的记录结果如下:注意date类型字段中只显示了日期,时间并未显示
NAME ENROLLDATE
mark 18-8月 -03
mark1 21-8月 -03
mark2 21-8月 -03
已选择3行。
5、但在JSP程序中同样执行select * from student order by enrolldate
显示结果见下图(既显示了日期,又显示了时间)
JSP页面中的显示结果
6、在SQL*Plus Worksheet中执行下列SQL语句
select name,to_char(enrolldate,'DD-MM-YYYY HH:MI:SS') from student;
得到的记录结果如下:注意date类型字段中显示了日期和时间
NAME TO_CHAR(ENROLLDATE,'DD-MM-YYYYHH:MI:SS
mark 21-08-2003 12:00:00
mark1 21-08-2003 12:00:00
已选择2行
注意:5和6中的不同,时间到秒时,JSP页面中显示时多出了". 0"
7、在SQL*Plus Worksheet中执行下列SQL语句
select name,to_char(enrolldate,'DD-MM-YYYY HH24:MI:SS') from student;
得到的记录结果如下:注意date类型字段中显示了日期,时间
NAME TO_CHAR(ENROLLDATE,'DD-MM-YYYYHH24:MI:
mark 18-08-2003 17:40:20
mark1 21-08-2003 00:00:00
mark2 21-08-2003 00:00:00
已选择3行。
注意:6和7中的SELECT中的"HH:MI:SS"和"HH24:MI:SS"两者的不同是"HH"为小时制,值的范围为0-12;"HH24"为24小时制,值的范围为0-23。
看下列例子:
①insert into student values('南太里',to_date('08-19-2003
13:54:05','MM-DD-YYYY HH24:MI:SS'));
ORACLE中的记录结果为:
NAME enrolldate
南太里 19-八月 -2003 01:54:05 PM
②insert into student values('南太里2',to_date('08-19-2003
13:54:05','MM-DD-YYYY HH:MI:SS'));//插入错误
错误提示为:
insert into student values('南太里2',to_date('08-19-2003 13:54:05','MM-DD
*
ERROR 位于第 1 行:
ORA-01849: 小时值必须介于 1 和 12 之间
即应用"HH"时,不能应用"13:54:05",而应改为"01:54:05"
正确语句如下:
insert into student values('南太里2',to_date('08-19-2003
01:54:05','MM-DD-YYYY HH:MI:SS'));
ORACLE中的记录结果为:
NAME enrolldate
南太里2 19-八月 -2003 01:54:05 AM
注意上述两种方式得出的结果一种为PM,另一种为AM。
为了提高正确性,建议都是用地一种方式"HH24"
8、但在JSP程序中同样执行select name,to_char(enrolldate,'DD-MM-YYYY HH:MI:SS') from student
显示结果见下图。(其结果与在SQL*Plus Worksheet中执行下列SQL语句
select name,to_char(enrolldate,'DD-MM-YYYY HH:MI:SS') from student;相同)
9、在SQL*Plus Worksheet中执行下列SQL语句
select name,to_char(enrolldate,'month dd,yyyy HH24:MI:SS') from student;
得到的记录结果如下:注意date类型字段中显示了日期,时间
NAME TO_CHAR(ENROLLDATE,'MONTHDD,YYYYHH24:MI:SS')
mark 8月 18,2003 17:40:20
mark1 8月 21,2003 00:00:00
mark2 8月 21,2003 00:00:00
已选择3行。
10、to_char()函数,'DD-MM-YYYY'格式及'MM-DD-YYYY'格式和'month dd,yyyy'格式的不同
'DD-MM-YYYY'格式:21-08-2003
'month dd,yyyy'格式:8月 21,2003
11、注意:在日期和时间格式中非常容易混淆的是月份和秒的格式(即MM和MI)
在SQLPlus*Worksheet中执行下列语句,不报错。
insert into student values('王嘉',to_date('08:05','HH24:MM'));//08被认为是小时,05被认为是月份。
commit;
在表编辑器中查看:实际插入值为
NAME ENROLLDATE
王嘉 01-五月 -2003 08:00:00 AM
select name,to_char(enrolldate,'DD-MM-YYYY HH24:MI:SS')enrolldate from
student where name='王嘉';
NAME ENROLLDATE
王嘉 01-05-2003 08:00:00
已选择 1 行。
insert into student values('汪嘉2',to_date('08-19-2003
13:54:05','MM-DD-YYYY HH24:MI:SS'));
12、使用Oracle的date数据类型的另一个优点是:它支持日期的运算。可以对已经存在的
日期加上或减去若干天,例如:
insert into student values('熊',sysdate+7);
17:12 浏览 (735) 评论 (0) 分类: 数据库 2007-06-01
缩略显示oracle8的ROWID结构
1、为什么使用ROWID
ORACLE把ROWID作为B-树和其内部算法标示ROW的唯一标示。
在ORACLE8以前的版本中,ROWID标示FILE、BLOCK、ROW NUMBER,只用一个数
字代
表FILE号。
在ORACLE8中,一个DATAFILE有两个数字代表:
一个绝对值,是整个数据库唯一的。可以看DBA_DATA_FILES中的FILE_ID。
一个相对值,在TABLESPACE中是唯一的,可以看DBA_DATA_FILES中的
RELATIVE_
FNO。
新的ROWID使用相对值,所以必须存放SEGMENT的标示,否则就会混淆。所以
ORAC
LE8在ROWID中加入对象的SEGMENT号,用来标示TABLE或者PARTITION。
2、ROWID的结构
使用base-64代码,包括a-z,A-Z,0-9,+,-。一共18位。
1-6位:代表OBJECT
7-9位:文件相对值
10-15:文件中的BLOCK
16-18:BLOCK中的SLOT值
3、TABLESPACE-Relative寻址方式
使用的是TABLESPACE-Relative寻址方式,多个文件可以有相同的相对值,因
为它
们属于不同的TABLESPACE,所以不能从新的ROWID得到绝对地址,但是这没有
问题
,因为当要处理某个OBJECT时,已经能确定它属于哪个TABLESAPCE了。在
TABLES
PACE中,文件相对值是唯一的,所以ROWID还是可以唯一标示一个OBJECT。
TABLE
SPACE-Relative寻址方式是ORACLE8中支持超大数据库的关键技术。
4、DATA OBJECT NUMBER
DATA OBJECT NUMBER用于指示SEGMENT,所有SEGMENT都有DATA OBJECT NUMBER
,
存放在每个DATA BLOCK中,而且不重复。
最开始的时候,DBA_OBJECTS.OBJECT_ID=DBA_OBJECTS.DATA-OBJECT_ID,但是
在
上述情况下DATA-OBJECT_ID会在如下情况下增加
TRUNCATE TABLE
MOVE PARTITION
ORACLE会检查ROWID中的DATA OBJECT NUMBER和BLOCK中的DATA OBJECT NUMBER
,
保证他们之间的版本是一致的。
ORACLE也使用DATA OBJECT NUMBER以确保ROLLBACK的纪录和最新的SEGMENT纪
录一
致。
要注意的是DATA OBJECT NUMBER不是OBJECT 的标志
5、RESTRICTED ROWID
ORACLE7的ROWID格式是
1-8位:BLOCK NUMBER
9-12位:ROW NUMBER
13-16位:FILE NUMBER
ORACLE8支持短的、旧格式的ROWID,作用是
对NOPARTITION TABLE的INDEX ENTRY
对PARTITION TABLE的LOCAL INDEX ENTRY
ROW Piece CHain pointer
受限ROWID的内部存放是6BYTE,
4BYTE=DATA BLOCK NUMBER
2BYTE=ROW NUMBER
这就是说,INDEX ENTRY使用6BYTE存放该ROWID,这对大多数INDEX足够了。但
是
这种短ROWID不能使用在PATITION TABLE的GLOBAL INDEX上,因为PARTITION可
能
跨TABLESPACE。显示这种ROWID依然是18位的
6、扩展的ROWID
ORACLE在内部存放时候是10 BYTE,包括(DATA OBJECT NUMBER,DATA BLOCK
NU
MBER,ROW NUMBER)
ORACLE8使用扩展的ROWID:
PARTITION TABLE 的GLOBAL INDEX
SERVER 算法
扩展的ROWID在SELECT时,依然是18位的显示,存放在ROWID字段中。
7、在ORACLE8中使用ORACLE7的ROWID
从ORACLE8的DB中查询ORACLE7的ROWID时候,ROWID返回的是ORACLE7的格式,
也可
以用在WHERE语句中。
从ORACLE7的DB中查询ORACLE8的ROWID时候,ROWID返回的是ORACLE8的格式,
也可
以用在WHERE语句中,但是不能存放在ROWID字段中。但是你要用DBMS_ROWID
包来
解释之。
如果包含扩展的ORACLE8 ROWID,这不能把ORACLE8的数据IMPORT到ORACLE7中
。从
ORACLE7中可以IMPORT到ORACLE8中。
8、APPLICATION的移植问题
一般程序的移植应该没有问题。只有在下面情况下才考虑移植问题:
application使用了rowid
table包括ROWID类型的字段
如果程序有如下情况,必须使用DBMS_ROWID包:
自己组合ROWID
自己分解ROWID
如果仅仅是传递ROWID到变量、或者仅仅做为一个整体使用,则可以不受影响
。
9、数据的移植问题
无论使用EXPORT/IMPORT还使用移植工具,ORACLE7中的ROWID字段到了ORACLE8
中
就自动扩展。
如果在某个字段内容中包含ROWID,则必须手工用DBMS_ROWID包来转换。
10、DBMS_ROWID包
由$ORACLE_HOME/rdbms/admin/dbmsutil.sql创建,其实在catproc.sql中包含
着
。提供处理ROWID的一些函数。
ROWID_CREATE
ROWID_INFO
ROWID_TYPE
ROWID_OBJECT
ROWID_RELATIVE_FNO
ROWID_BLOCK_NUMBER
ROWID_TO_ABSOLUTE_FNO
ROWID_TO_EXTENDED
ROWID_TO_RESTRICTED
ROWID_VERIFY
DBMS_ROWID.ROWID_TO_EXTENDED
(old_rowid in ROWID,
schema_name in varchar2,
object_name in varchar2,
conversion_type in number
)
RETURN ROWID;
转换受限rowid到扩展rowid,用于转换旧的ROWID到ORACLE8的格式。
DBMS_ROWID.ROWID_TO_RESTRICTED
转换扩展的ROWID到受限的ROWID。
DBMS_ROWID.ROWID_VERIFY
判断一个受限的ROWID是否可以转换到扩展的格式
DBMS_ROWID.ROW_INFO
用于解释ROWID,可以得到DATA OBJECT NUMBER,RELATIVE FILE
NUMBER,BLOCK
NUMBER和ROW NUMBER。
DBMS_ROWID.CREATE
生成ROWID。
18:02 浏览 (219) 评论 (0) 分类: 数据库 2007-06-01
缩略显示ORACLE分页方法
1、rownum是oracle系统顺序分配为从查询返回的行的编号,返回的第一行分配的是1,第二行是2,依此类推,这个伪字段可以用于限制查询返回的总行数。
2、rownum不能以任何基表的名称作为前缀。
--自定义表phone
Name Type Nullable
----- ------------ --------
ID NUMBER
NAME VARCHAR2(20) Y
PHONE VARCHAR2(20) Y
ZIP NUMBER Y
--插入数据
ID NAME PHONE ZIP
---------- -------------------- -------------------- ----------
1 e
2 c 101
3 a 102
4 o 103
5 f 103
6 z 103
7 p 103
8 m 104
9 g 102
--显示所有记录,按zip和name排序
select rownum, p.zip, p.name from phone p order by zip, name;
ROWNUM ZIP NAME ROWID
---------- ---------- -------------------- ------------------
2 101 c AAAH3vAABAAAPD6AAB
3 102 a AAAH3vAABAAAPD6AAC
9 102 g AAAH3vAABAAAPD6AAI
5 103 f AAAH3vAABAAAPD6AAE
4 103 o AAAH3vAABAAAPD6AAD
7 103 p AAAH3vAABAAAPD6AAG
6 103 z AAAH3vAABAAAPD6AAF
8 104 m AAAH3vAABAAAPD6AAH
1 e AAAH3vAABAAAPD6AAA
可见,rownum由系统按照记录入库时的顺序排的号,不可以改变,rowid也是的,如果要重排rownum,需要这样...
--按zip和name排序后,显示前5条记录(对照上面的结果),外层的rownum重排了,是我们需要的顺序
select rownum, p.*
from (select zip, name from phone group by zip, name) p
where rownum <= 5;
或者...
select rownum, p.*
from (select t.zip, t.name from phone t order by t.zip, t.name) p
where rownum <= 5;
ROWNUM ZIP NAME
---------- ---------- --------------------
1 101 c
2 102 a
3 102 g
4 103 f
5 103 o
--按zip和name排序后,显示第5-第9条记录(对照上上面的结果)
select *
from (select rownum row_id, p.*
from (select zip, name from phone group by zip, name) p)
where row_id between 5 and 9;
ROW_ID ZIP NAME
---------- ---------- --------------------
5 103 o
6 103 p
7 103 z
8 104 m
9 e
17:46 浏览 (249) 评论 (0) 分类: 数据库 2007-06-01
缩略显示[转贴]解析oracle的rownum
原文出处:http://www.cnblogs.com/zjrstar/archive/2006/08/31/491090.html
对于rownum来说它是oracle系统顺序分配为从查询返回的行的编号,返回的第一行分配的是1,第二行是2,依此类推,这个伪字段可以用于限制查询返回的总行数,而且rownum不能以任何表的名称作为前缀。
举例说明:
例如表:student(学生)表,表结构为:
ID char(6) --学号
name VARCHAR2(10) --姓名
create table student (ID char(6), name VARCHAR2(100));
insert into sale values('200001',‘张一’);
insert into sale values('200002',‘王二’);
insert into sale values('200003',‘李三’);
insert into sale values('200004',‘赵四’);
commit;
(1) rownum 对于等于某值的查询条件
如果希望找到学生表中第一条学生的信息,可以使用rownum=1作为条件。但是想找到学生表中第二条学生的信息,使用rownum=2结果查不到数据。因为rownum都是从1开始,但是1以上的自然数在rownum做等于判断是时认为都是false条件,所以无法查到rownum = n(n>1的自然数)。
SQL> select rownum,id,name from student where rownum=1;(可以用在限制返回记录条数的地方,保证不出错,如:隐式游标)
SQL> select rownum,id,name from student where rownum=1;
ROWNUM ID NAME
---------- ------ ---------------------------------------------------
1 200001 张一
SQL> select rownum,id,name from student where rownum =2;
ROWNUM ID NAME
---------- ------ ---------------------------------------------------
(2)rownum对于大于某值的查询条件
如果想找到从第二行记录以后的记录,当使用rownum>2是查不出记录的,原因是由于rownum是一个总是从1开始的伪列,Oracle 认为rownum> n(n>1的自然数)这种条件依旧不成立,所以查不到记录
SQL> select rownum,id,name from student where rownum >2;
ROWNUM ID NAME
---------- ------ ---------------------------------------------------
那如何才能找到第二行以后的记录呀。可以使用以下的子查询方法来解决。注意子查询中的rownum必须要有别名,否则还是不会查出记录来,这是因为rownum不是某个表的列,如果不起别名的话,无法知道rownum是子查询的列还是主查询的列。
SQL>select * from(select rownum no ,id,name from student) where no>2;
NO ID NAME
---------- ------ ---------------------------------------------------
3 200003 李三
4 200004 赵四
SQL> select * from(select rownum,id,name from student)where rownum>2;
ROWNUM ID NAME
---------- ------ ---------------------------------------------------
(3)rownum对于小于某值的查询条件
如果想找到第三条记录以前的记录,当使用rownum<3是能得到两条记录的。显然rownum对于rownum1的自然数)的条件认为是成立的,所以可以找到记录。
SQL> select rownum,id,name from student where rownum <3;
ROWNUM ID NAME
---------- ------ ---------------------------------------------------
1 200001 张一
2 200002 王二
综上几种情况,可能有时候需要查询rownum在某区间的数据,那怎么办呀从上可以看出rownum对小于某值的查询条件是人为true的,rownum对于大于某值的查询条件直接认为是false的,但是可以间接的让它转为认为是true的。那就必须使用子查询。例如要查询rownum在第二行到第三行之间的数据,包括第二行和第三行数据,那么我们只能写以下语句,先让它返回小于等于三的记录行,然后在主查询中判断新的rownum的别名列大于等于二的记录行。但是这样的操作会在大数据集中影响速度。
SQL> select * from (select rownum no,id,name from student where rownum<=3 ) where no >=2;
NO ID NAME
---------- ------ ---------------------------------------------------
2 200002 王二
3 200003 李三
(4)rownum和排序
Oracle中的rownum的是在取数据的时候产生的序号,所以想对指定排序的数据去指定的rowmun行数据就必须注意了。
SQL> select rownum ,id,name from student order by name;
ROWNUM ID NAME
---------- ------ ---------------------------------------------------
3 200003 李三
2 200002 王二
1 200001 张一
4 200004 赵四
可以看出,rownum并不是按照name列来生成的序号。系统是按照记录插入时的顺序给记录排的号,rowid也是顺序分配的。为了解决这个问题,必须使用子查询
SQL> select rownum ,id,name from (select * from student order by name);
ROWNUM ID NAME
---------- ------ ---------------------------------------------------
1 200003 李三
2 200002 王二
3 200001 张一
4 200004 赵四
这样就成了按name排序,并且用rownum标出正确序号(有小到大)
17:32 浏览 (269) 评论 (0) 分类: 数据库 2007-04-12
缩略显示sql之join用法完全版【转载】
SQL中大概有这么几种JOIN:
cross joininner joinleft outer join right outer join full outer join 首先都是基于cross join(笛卡尔乘积),然后是inner join,在笛卡尔乘积的结果集中去掉不符合连接条件的行。left outer join 是在inner join的结果集上加上左表中没被选上的行,行的右表部分每个字段都用NUll填充。right outer join 是在inner join的结果集上加上右表中没被选上的行,行的左表部分全用NULL填充。
SQL 之JOIN 用法完全版一、各种JOIN的含义SQL中大概有这么几种JOIN:cross joininner joinleft outer join right outer join full outer join 首先都是基于cross join(笛卡尔乘积),然后是inner join,在笛卡尔乘积的结果集中去掉不符合连接条件的行。left outer join 是在inner join的结果集上加上左表中没被选上的行,行的右表部分每个字段都用NUll填充。right outer join 是在inner join的结果集上加上右表中没被选上的行,行的左表部分全用NULL填充。outer的意思就是"没有关联上的行"。二、旧式写法和标准写法: 1、INNER Join code as the following: Select * from A a, B b where a.categoryID = b.categoryID;Equals:Select * from A a inner join B b on a.categoryID = b.categoryID; 2、OUTER Join code as the following select * from A a full(left/right) outer join B b on a on a.categoryID = b.categoryID;Equals::Select * from A a, B b where a.categoryID *= b.categoryID;Select * from A a, B b where a.categoryID =* b.categoryID; 三、例子Table A have 12( 8+4) entries, 8 entries have valid relation with BTable B have 80(77+3) entries , 77 entries have valid relation with A. then the return amount of join is :cross join : 12*80inner join : 77full outer join : 77+4+3left outer join: 77 + 4right outrer join: 77 + 316:37 浏览 (572) 评论 (0) 分类: 数据库 2007-04-12
缩略显示SQL Union和SQL Union All用法
SQL Union和SQL Union All用法
UNION 指令的目的是将两个 SQL 语句的结果合并起来。从这个角度来看, UNION 跟 JOIN 有些许类似,因为这两个指令都可以由多个表格中撷取资料。 UNION 的一个限制是两个 SQL 语句所产生的栏位需要是同样的资料种类。另外,当我们用 UNION这个指令时,我们只会看到不同的资料值 (类似 SELECT DISTINCT)。 union只是将两个结果联结起来一起显示,并不是联结两个表………… UNION 的语法如下: [SQL 语句 1]
UNION
[SQL 语句 2] 假设我们有以下的两个表格, Store_Information 表格 store_name Sales Date
Los Angeles $1500 Jan-05-1999
San Diego $250 Jan-07-1999
Los Angeles $300 Jan-08-1999
Boston $700 Jan-08-1999
Internet Sales 表格 Date Sales
Jan-07-1999 $250
Jan-10-1999 $535
Jan-11-1999 $320
Jan-12-1999 $750
而我们要找出来所有有营业额 (sales) 的日子。要达到这个目的,我们用以下的 SQL 语句: SELECT Date FROM Store_Information
UNION
SELECT Date FROM Internet_Sales 结果: Date
Jan-05-1999
Jan-07-1999
Jan-08-1999
Jan-10-1999
Jan-11-1999
Jan-12-1999
有一点值得注意的是,如果我们在任何一个 SQL 语句 (或是两句都一起) 用 "SELECT DISTINCT Date" 的话,那我们会得到完全一样的结果。
SQL Union All
UNION ALL 这个指令的目的也是要将两个 SQL 语句的结果合并在一起。 UNION ALL 和 UNION 不同之处在于 UNION ALL 会将每一笔符合条件的资料都列出来,无论资料值有无重复。 UNION ALL 的语法如下: [SQL 语句 1]
UNION ALL
[SQL 语句 2] 我们用和上一页同样的例子来显示出 UNION ALL 和 UNION 的不同。同样假设我们有以下两个表格, Store_Information 表格 store_name Sales Date
Los Angeles $1500 Jan-05-1999
San Diego $250 Jan-07-1999
Los Angeles $300 Jan-08-1999
Boston $700 Jan-08-1999
Internet Sales 表格 Date Sales
Jan-07-1999 $250
Jan-10-1999 $535
Jan-11-1999 $320
Jan-12-1999 $750
而我们要找出有店面营业额以及网络营业额的日子。要达到这个目的,我们用以下的 SQL 语句: SELECT Date FROM Store_Information
UNION ALL
SELECT Date FROM Internet_Sales 结果: Date
Jan-05-1999
Jan-07-1999
Jan-08-1999
Jan-08-1999
Jan-07-1999
Jan-10-1999
Jan-11-1999
Jan-12-1999
使用PowerDesigner升级维护数据库
做项目难免要升级维护之前的数据库,PowerDesigner里的操作稍微比创建时麻烦点,还是继续以上面会员为例子,假如我现在已经创建好了数据库,但是需求的变化我需要在会员表上面增加一个区域编号,并引用新建的区域表,那用PowerDesigner模型该如何操作呢?首先开打pdm工程文件,在以前模型基础上直接进行修改,这里的操作就是新建一个区域表在再会员表添加一个区域字段引用它的外键,所有的修改完成后在Database工具栏Modify Database里面进行生成修改后的SQL语句,仍然建议设置生成sql语句的目录放在之前建立的sql目录下面,但是现在的文件名应该叫update2.0.sql,或者加在后面加上括号简要描述,如update2.0(add area).sql。注意记得指定Backup tables和Automatic archive选项,选中Backup tables将在修改表结构之前把原表改名加个tmp_前缀,创建好新的表结构后再insert into from select tmp_表插入以前表内的数据,起到备份以前表内数据功能,这就是为什么有时候用PowerDesigner升级数据库后会多一些tmp开头的临时表了,Automatic archive是在生成升级sql语句后提示保存当前记录的选项。由于这次修改是针对上创建数据库时候的修改,注意指定Get database schema选项里的Using a archive model文件,这里这个文件的路径应该是log目录下面的create1.0.apm文件,因为这次升级是针对上次创建数据库时的一次升级,PowerDesigner会自动拿当前模型和create1.0.apm之前保存的历史存档模型比较生成升级的sql语句,并显示确切的修改对比变化,很清晰一目了然,