发表于: lnmp | 作者: | 日期: 2008/11/06 03:11
标签:

什么是主键

在关系数据库中主键是用来识别和区分同一表的不同记录的一个字段,主键可以保证每条记录的唯一性。

作为主键的字段必须满足以下条件:
1:不允许为null
2:每条记录具有唯一的主键值,不允许主键值重复
3:每条主键值永远不允许改变。

当作为主键的字段有业务含义的时候,这样的主键称为“自然主键” 。
看以下的表定义语句:


CREATE TABLE student(
name varchar(20) PRIMARY KEY,
sex tinyint);

在这个表定义语句中,使用作为主键的name字段即为“自然主键” 。这样的主键定义方法是不可取的,会给后期的数据库维护带来困难。

更合理的方式是使用“代理主键”。即使用不具备业务含义的字段,这个字段一般取名为“ID”或“XID”。


CREATE TABLE student(
id int PRIMARY KEY ,
name varchar(20) ,
sex tinyint);

代理主键通常为整数类型,大部分的数据库都提供了自动生成代理主键的机制。

MySQL自动代理主键的生成机制

在MySQL数据库中,将表的主键设置为 auto_increment,则数据库会自动为主键赋值,MySQL支持多种类型的数据库表,依表类型不同其自增属性也有所差异。以下一一分析。

ISAM表
ISAM(索引顺序存储方法)是旧的MySQL标准。在版本3.23.0中,MyISAM类型代替了它(在MySQL的版本4.1中仍然可用,但不推荐)。MyISAM表类型与ISAM表类型的主要区别是前者的索引比后者要小的多。

对于ISAM表类型,如果把一个NULL插入到一个AUTO_INCREMENT数据列里去,MySQL将自动生成下一个序列编号。编号从1开始,并1为基数递增。

把0插入AUTO_INCREMENT数据列的效果与插入NULL值一样。但不建议这样做,还是以插入NULL值为好。

当插入记录时,没有为AUTO_INCREMENT明确指定值,则等同插入NULL值。

当插入记录时,如果为AUTO_INCREMENT数据列明确指定了一个数值,则会出现两种情况:情况一,如果插入的值与已有的编号重复,则会出现出错信息,因为AUTO_INCREMENT数据列的值必须是唯一的;情况二,如果插入的值大于已编号的值,则会把该插入到数据列中,并使在下一个编号将从这个新值开始递增。也就是说,可以跳过一些编号。

如果自增序列的最大值被删除了,则在插入新记录时,该值被重用。

如果用Update命令更新自增列,如果列值与已有的值重复,则会出错。如果大于已有值,则下一个编号从该值开始递增。

如果用replace命令基于AUTO_INCREMENT数据列里的值来修改数据表里的现有记录,即AUTO_INCREMENT数据列出现在了replace命令的where子句里,相应的AUTO_INCREMENT值将不会发生变化。但如果replace命令是通过其它的PRIMARY KEY or UNIQUE索引来修改现有记录的(即AUTO_INCREMENT数据列没有出现在replace命令的where子句中),相应的AUTO_INCREMENT值–如果设置其为NULL(如没有对它赋值)的话–就会发生变化。

last_insert_id()函数可获得自增列自动生成的最后一个编号。但该函数只与服务器的本次会话过程中生成的值有关。如果在与服务器的本次会话中尚未生成AUTO_INCREMENT值,则该函数返回0。

其它数据表的自动编号机制都以ISAM表中的机制为基础。

MyISAM数据表
MyISAM表类型从版本3.23.0开始使用,用来代替ISAM表类型。同ISAM表类型相比,索引要小的多。可以使用更少的资源执行带有索引的的SELECT。

删除最大编号的记录后,该编号不可重用。

可在建表时可用“AUTO_INCREMENT=n”选项来指定一个自增的初始值。

可用alter table table_name AUTO_INCREMENT=n命令来重设自增的起始值。

可使用复合索引在同一个数据表里创建多个相互独立的自增序列,具体做法是这样的:为数据表创建一个由多个数据列组成的PRIMARY KEY or UNIQUE索引,并把AUTO_INCREMENT数据列包括在这个索引里作为它的最后一个数据列。这样,这个复合索引里,前面的那些数据列每构成一种独一无二的组合,最末尾的AUTO_INCREMENT数据列就会生成一个与该组合相对应的序列编号。

HEAP数据表
HEAP数据表从MySQL4.1开始才允许使用自增列。

自增值可通过Create TABLE语句的 AUTO_INCREMENT=n选项来设置。

可通过Alter TABLE语句的AUTO_INCREMENT=n选项来修改自增始初值。

编号不可重用。

HEAP数据表不支持在一个数据表中使用复合索引来生成多个互不干扰的序列编号。

BDB数据表
不可通过Create TABLE or Alter TABLE的AUTO_INCREMENT=n选项来改变自增初始值。

可重用编号。

支持在一个数据表里使用复合索引来生成多个互不干扰的序列编号。

InnDB数据表
不可通过Create TABLE or Alter TABLE的AUTO_INCREMENT=n选项来改变自增初始值。

不可重用编号。

不支持在一个数据表里使用复合索引来生成多个互不干扰的序列编号。

在使用AUTO_INCREMENT时,应注意以下几点:

AUTO_INCREMENT是数据列的一种属性,只适用于整数类型数据列。

设置AUTO_INCREMENT属性的数据列应该是一个正数序列,所以应该把该数据列声明为UNSIGNED,这样序列的编号个可增加一倍。

AUTO_INCREMENT数据列必须有唯一索引,以避免序号重复。

AUTO_INCREMENT数据列必须具备NOT NULL属性。

AUTO_INCREMENT数据列序号的最大值受该列的数据类型约束,如TINYINT数据列的最大编号是127,如加上UNSIGNED,则最大为255。一旦达到上限,AUTO_INCREMENT就会失效。

当进行全表删除时,AUTO_INCREMENT会从1重新开始编号。全表删除的意思是发出以下两条语句时:


delete from table_name;
or
truncate table table_name

这是因为进行全表操作时,MySQL实际是做了这样的优化操作:先把数据表里的所有数据和索引删除,然后重建数据表。如果想删除所有的数据行又想保留序列编号信息,可这样用一个带where的delete命令以抑制MySQL的优化:


delete from table_name where 1;

这将迫使MySQL为每个删除的数据行都做一次条件表达式的求值操作。

强制MySQL不复用已经使用过的序列值的方法是:另外创建一个专门用来生成AUTO_INCREMENT序列的数据表,并做到永远不去删除该表的记录。当需要在主数据表里插入一条记录时,先在那个专门生成序号的表中插入一个NULL值以产生一个编号,然后,在往主数据表里插入数据时,利用LAST_Insert_ID()函数取得这个编号,并把它赋值给主表的存放序列的数据列。如:


insert into id set id = NULL;
insert into main set main_id = LAST_Insert_ID();

可用alter命令给一个数据表增加一个具有AUTO_INCREMENT属性的数据列。MySQL会自动生成所有的编号。

要重新排列现有的序列编号,最简单的方法是先删除该列,再重建该,MySQL会重新生连续的编号序列。

在不用AUTO_INCREMENT的情况下生成序列,可利用带参数的LAST_Insert_ID()函数。如果用一个带参数的LAST_Insert_ID(expr)去插入或修改一个数据列,紧接着又调用不带参数的LAST_Insert_ID()函数,则第二次函数调用返回的就是expr的值。下面演示该方法的具体操作:

先创建一个只有一个数据行的数据表:


create table seq_table (id int unsigned not null);
insert into seq_table values (0);

接着用以下操作检索出序列号:


update seq_table set seq = LAST_Insert_ID( seq + 1 );
select LAST_Insert_ID();

通过修改seq+1中的常数值,可生成不同步长的序列,如seq+10可生成步长为10的序列。

该方法可用于计数器,在数据表中插入多行以记录不同的计数值。再配合LAST_Insert_ID()函数的返回值生成不同内容的计数值。这种方法的优点是不用事务或LOCK,UNLOCK表就可生成唯一的序列编号。不会影响其它客户程序的正常表操作。

评论关闭
发表于: arch/management | 作者: | 日期: 2008/11/06 03:11

一个好的数据库产品不等于就有一个好的应用系统,如果不能设计一个合理的数据库模型,不仅会增加客户端和服务器段程序的编程和维护的难度,而且将会影响系统实际运行的性能。一般来讲,在一个MIS系统分析、设计、测试和试运行阶段,因为数据量较小,设计人员和测试人员往往只注意到功能的实现,而很难注意到性能的薄弱之处,等到系统投入实际运行一段时间后,才发现系统的性能在降低,这时再来考虑提高系统性能则要花费更多的人力物力,而整个系统也不可避免的形成了一个打补丁工程。笔者依据多年来设计和使用数据库的经验,提出以下一些设计准则,供同仁们参考。 More …

评论关闭
发表于: DB/ES | 作者: | 日期: 2008/11/06 03:11
标签: ,

TRUNCATE TABLE
与 DELETE 语句相比,TRUNCATE TABLE 具有以下优点:
所用的事务日志空间较少。
DELETE 语句每次删除一行,并在事务日志中为所删除的每行记录一项。
TRUNCATE TABLE 通过释放用于存储表数据的数据页来删除数据,并且在事务日志中只记录页释放。
使用的锁通常较少。
当使用行锁执行 DELETE 语句时,将锁定表中各行以便删除。TRUNCATE TABLE 始终锁定表和页,而不是锁定各行。
如无例外,在表中不会留有任何页。
执行 DELETE 语句后,表仍会包含空页。例如,必须至少使用一个排他 (LCK_M_X) 表锁,才能释放堆中的空表。如果执行删除操作时没有使用表锁,表(堆)中将包含许多空页。对于索引,删除操作会留下一些空页,尽管这些页会通过后台清除进程迅速释放。

与 DELETE 语句相同,使用 TRUNCATE TABLE 清空的表的定义与其索引和其他关联对象一起保留在数据库中。

DROP TABLE
删除一个或多个表定义以及这些表的所有数据、索引、触发器、约束和指定的权限。任何引用已删除表的视图或存储过程都必须使用 DROP VIEW 或 DROP PROCEDURE 显式删除。

备注
不能使用 DROP TABLE 删除被 FOREIGN KEY 约束引用的表。必须先删除引用 FOREIGN KEY 约束或引用表。如果要在同一个 DROP TABLE 语句中删除引用表以及包含主键的表,则必须先列出引用表。

可以在任何数据库中删除多个表。如果一个要删除的表引用了另一个也要删除的表的主键,则必须先列出包含该外键的引用表,然后再列出包含要引用的主键的表。

删除表时,表的规则或默认值将被解除绑定,与该表关联的任何约束或触发器将被自动删除。如果要重新创建表,则必须重新绑定相应的规则和默认值,重新创建某些触发器,并添加所有必需的约束。

如果使用 DELETE tablename 删除表中的所有行或使用 TRUNCATE TABLE 语句,则在被移除之前,表将一直存在。

注意:这里说的delete是指不带where子句的delete语句
相同点
truncate和不带where子句的delete, 以及drop都会删除表内的数据

不同点:
1. truncate和 delete只删除数据不删除表的结构(定义)
drop语句将删除表的结构被依赖的约束(constrain),触发器(trigger),索引(index); 依赖于该表的存储过程/函数将保留,但是变为invalid状态.
2.delete语句是dml,这个操作会放到rollback segement中,事务提交之后才生效;如果有相应的trigger,执行的时候将被触发.
truncate,drop是ddl, 操作立即生效,原数据不放到rollback segment中,不能回滚. 操作不触发trigger.
3.delete语句不影响表所占用的extent, 高水线(high watermark)保持原位置不动
显然drop语句将表所占用的空间全部释放
truncate 语句缺省情况下见空间释放到 minextents个 extent,除非使用reuse storage; truncate会将高水线复位(回到最开始).
4.速度,一般来说: drop>; truncate >; delete
5.安全性:小心使用drop 和truncate,尤其没有备份的时候.否则哭都来不及
使用上,想删除部分数据行用delete,注意带上where子句. 回滚段要足够大.
想删除表,当然用drop
想保留表而将所有数据删除. 如果和事务无关,用truncate即可. 如果和事务有关,或者想触发trigger,还是用delete.
如果是整理表内部的碎片,可以用truncate跟上reuse stroage,再重新导入/插入数据

个人总结,欢迎大家补充

在实际应用中,三者的区别是明确的。
当你不再需要该表时, 用 drop;
当你仍要保留该表,但要删除所有记录时, 用 truncate;
当你要删除部分记录时(always with a WHERE clause), 用 delete.

若要删除表中的所有行,则 TRUNCATE TABLE 语句是一种快速、无日志记录的方法。TRUNCATE TABLE 与不含有 WHERE 子句的 DELETE 语句在功能上相同。但是,TRUNCATE TABLE 速度更快,并且使用更少的系统资源和事务日志资源。

评论关闭
发表于: os/software | 作者: | 日期: 2008/11/05 04:11
标签:

有关某个命令的详细信息,请键入 HELP 命令名

———————-文件及目录管理——————————–
COMP 比较两个或两套文件的内容。
CHDIR 显示当前目录的名称或将其更改。
DEL 删除至少一个文件。
DIR 显示一个目录中的文件和子目录。
MD 创建目录。
MKDIR 创建目录。
XCOPY 复制文件和目录树。
TYPE 显示文本文件的内容。
MOVE 将文件从一个目录移到另一个目录。
PUSHD 保存当前目录,然后对其进行更改。
RD 删除目录。
REN 重命名文件。
RENAME 重命名文件。
REPLACE 替换文件。
RMDIR 删除目录。
COPY 将至少一个文件复制到另一个位置。
ERASE 删除至少一个文件。

FC 比较两个或两套文件,并显示不同处。
FIND 在文件中搜索文字字符串。
FINDSTR 在文件中搜索字符串。

———————-磁盘管理——————————–
COMPACT 显示或更改 NTFS 分区上文件的压缩。
CONVERT 将 FAT 卷转换成 NTFS。您不能转换当前驱动器。
CHKDSK 检查磁盘并显示状态报告。
CHKNTFS 显示或修改启动时间磁盘检查。
VERIFY 告诉 Windows 是否验证文件是否已正确写入磁盘。
VOL 显示磁盘卷标和序列号。
FORMAT 格式化磁盘,以便跟 Windows 使用。

———————-时间日期——————————–
DATE 显示或设置日期。
TIME 显示或设置系统时间。

———————-cmd配置——————————–
COLOR 设置默认控制台前景和背景颜色。
CLS 清除屏幕。
CMD 打开另一个 Windows 命令解释程序窗口。
VER 显示 Windows 版本。
HELP 提供 Windows 命令的帮助信息。
PROMPT 更改 Windows 命令提示符。
SET 显示、设置或删除 Windows 环境变量。
START 启动另一个窗口来运行指定的程序或命令。
TITLE 设置 CMD.EXE 会话的窗口标题。
PATH 显示或设置可执行文件的搜索路径。
ECHO 显示消息,或将命令回显打开或关上。
EXIT 退出 CMD.EXE 程序(命令解释程序)。

————————-调用图形化的系统工具——————————-
appwiz.cpl
添加删除程序

control userpasswords2
用户帐户设置

cleanmgr
垃圾整理

CMD
命令提示符可以当作是 Windows 的一个附件,Ping,Convert 这些不能在图形环境下 使用的功能要借助它来完成。

jview
察看Java虚拟机版本。

command.com
调用的则是系统内置的 NTVDM,一个 DOS虚拟机。它完全是一个类似 Virtual PC 的 虚拟环境,和系统本身联系不大。当我们在命令提示符下运行 DOS 程序时,实际上也 是自动转移到 NTVDM虚拟机下,和 CMD 本身没什么关系。

calc
启动计算器

chkdsk.exe
Chkdsk磁盘检查

compmgmt.msc
计算机管理

conf
启动 netmeeting

control userpasswords2
User Account 权限设置

devmgmt.msc
设备管理器

diskmgmt.msc
磁盘管理实用程序

dfrg.msc
磁盘碎片整理程序

drwtsn32
系统医生

dvdplay
启动Media Player

dxdiag
DirectX Diagnostic Tool

gpedit.msc
组策略编辑器

gpupdate /target:computer /force
强制刷新组策略

eventvwr.exe
事件查看器

explorer
打开资源管理器

logoff-
注销命令

lusrmgr.msc
本机用户和组

msinfo32
系统信息

msconfig
系统配置实用程序

net start (servicename)
启动该服务

net stop (servicename)
停止该服务

notepad
打开记事本

nusrmgr.cpl
同control userpasswords,打开用户帐户控制面板

Nslookup
IP地址侦测器

oobe/msoobe /a
检查XP是否激活

perfmon.msc
计算机性能监测程序

progman
程序管理器

regedit–
注册表编辑器

regedt32
注册表编辑器

regsvr32 /u *.dll
停止dll文件运行

route print
查看路由表

rononce -p
15秒关机

rsop.msc
组策略结果集

rundll32.exe rundll32.exe %Systemroot%System32shimgvw.dll,ImageView_Fullscreen—-
启动一个空白的Windows 图片和传真查看器

secpol.msc
本地安全策略

services.msc
本地服务设置

sfc /scannow
启动系统文件检查器

sndrec32
录音机

taskmgr
任务管理器(适用于2000/xp/2003)

tsshutdn
60秒倒计时关机命令

winchatXP
自带局域网聊天

winmsd
系统信息

winver
显示About Windows 窗口

wupdmgr
Windows Update

———————–其它命令——————————————
ASSOC 显示或修改文件扩展名关联。
AT 计划在计算机上运行的命令和程序。
ATTRIB 显示或更改文件属性。
BREAK 设置或清除扩展式 CTRL+C 检查。
CACLS 显示或修改文件的访问控制列表(ACLs)。
CALL 从另一个批处理程序调用这一个。
CD 显示当前目录的名称或将其更改。
CHCP 显示或设置活动代码页数。
DISKCOMP 比较两个软盘的内容。
DISKCOPY 将一个软盘的内容复制到另一个软盘。
DOSKEY 编辑命令行、调用 Windows 命令并创建宏。
ENDLOCAL 结束批文件中环境更改的本地化。
FOR 为一套文件中的每个文件运行一个指定的命令。
FTYPE 显示或修改用于文件扩展名关联的文件类型。
GOTO 将 Windows 命令解释程序指向批处理程序中某个标明的行。
GRAFTABL 启用 Windows 来以图像模式显示扩展字符集。
IF 执行批处理程序中的条件性处理。
LABEL 创建、更改或删除磁盘的卷标。
MODE 配置系统设备。
MORE 一次显示一个结果屏幕。
PAUSE 暂停批文件的处理并显示消息。
POPD 还原 PUSHD 保存的当前目录的上一个值。
PRINT 打印文本文件。
RECOVER 从有问题的磁盘恢复可读信息。
REM 记录批文件或 CONFIG.SYS 中的注释。
SETLOCAL 开始批文件中环境更改的本地化。
SHIFT 更换批文件中可替换参数的位置。
SORT 对输入进行分类。
SUBST 将路径跟一个驱动器号关联。
TREE 以图形模式显示驱动器或路径的目录结构。

评论关闭
发表于: other | 作者: | 日期: 2008/11/05 10:11
标签:

让我与你共同分享一段小故事,或许在这个阶段,可以很实际地让我们走出目前的困境。

一九七六年的冬天,当时我十九岁,在休斯顿太空总署的大空梭实验室里工作,同时也在总署旁边的休斯顿大学主修电脑。纵然忙于学校、睡眠与工作之间,这几乎占据了我一天二十四小时的全部时间,但只要有多余的一分钟,我总是会把所有的精力放在我的音乐创作上。

我知道写歌词不是我的专长,所以在这段日子里,我处处寻找一位善写歌词的搭档,与我一起合作创作。我认识了一位朋友,她的名字叫凡內芮(Valerie Johnson)。自从二十多年前离开德州后,就再也没听过她的消息,但是她却在我事业的起步时,给了我最大的鼓励。仅十九岁的凡內芮在德州的诗词比赛中,不知得过多少奖牌。她的写作总是让我爱不释手,当时我们的确合写了许多很好的作品,一直到今天,我仍然认为这些作品充满了特色与创意。

一个星期六的周末,凡內芮又热情地邀请我至她家的牧场烤肉。她的家族是德州有名的石油大亨,拥有庞大的牧场。她的家庭虽然极为富有,但她的穿着、所开的车、与她谦诚待人的态度,更让我加倍地打从心底佩服她。凡內芮知道我对音乐的执着。然而,面对那遥远的音乐界及整个美国陌生的唱片市场,我们一点管道都没有。此时,我们两个人坐在德州的乡下,我们哪知道下一步该如何走。突然间,她冒出了一句话:

” Visualize ,What you are doing in 5 years?﹙想像你五年后在做什么?﹚”

我愣了一下。

她转过身来,手指着我说:”嘿!告诉我,你心目中“最希望”五年后的你在做什么,你那个时候的生活是一个什么样子?”我还来不及回答,她又抢着说:”別急,你先仔细想想,完全想好,确定后再说出来。”我沉思了几分钟,开始告诉她:”第一,五年后,我希望能有一张唱片在市场上,而这张唱片很受欢迎,可以得到许多人的肯定。第二,我住在一个有很多很多音乐的地方,能天天与一些世界一流的乐师一起工作。”

凡內芮说:”你确定了吗?”

我慢慢稳稳地回答,而且拉了一个很长的Yesssssss!

凡內芮接着说:”好,既然你确定了,我们就把这个目标倒算回来。如果第五年,你有一张唱片在市场上,那么你的第四年一定是要跟一家唱片公司签上合约。”

“那么你的第三年一定是要有一个完整的作品,可以拿给很多很多的唱片公司听,对不对?”

“那么你的第二年,一定要有很棒的作品开始录音了。”

“那么你的第一年,就一定要把你所有要准备录音的作品全部编曲,排练就位准备好。”

“那么你的第六个月,就是要把那些没有完成的作品修饰好,然后让你自己可以逐一筛选。”

“那么你的第一个月就是要把目前这几首曲子完工。”

“那么你的第一个礼拜就是要先列出一整个清单,排出哪些曲子需要修改,哪些需要完工。”

“好了,我们现在不就已经知道你下个星期一要做什么了吗?”凡內芮笑笑地说。

“喔,对了。你还说你五年后,要生活在一个有很多音乐的地方,然后与许多一流的乐师一起忙着工作,对吗?”她急忙地补充说。”如果,你的第五年已经在与这些人一起工作,那么你的第四年照道理应该有你自己的一个工作室或录音室。那么你的第三年,可能是先跟这个圈子里的人在一起工作。那么你的第二年,应该不是住在德州,而是已经住在纽约或是洛杉机了。”

次年(一九七七年),我辞掉了令许多人羨慕的太空总署的工作,离开了休斯顿,搬到洛杉机。

说也奇怪:不敢说是恰好五年,但大约可说是第六年。一九八三年,我的唱片在亚洲开始销起来,我一天二十四小时几乎全都忙着与一些顶尖的音乐高手,日出日落地一起工作。

每当我在最困惑的时候,我会静下来问我自己:五年后你”最希望”看到你自己在做什么?

如果,你自己都不知道这个答案的话,你又如何要求別人或上帝为你做选择或开路呢?別忘了!在生命中,上帝已经把所有”选择”的权力交在我们的手上了。

如果,你对你的生命经常在问”为什么会这样?””为什么会那样?”的时候,你不妨试着问一下自己,你是否很”清清楚楚”地知道你自己要的是什么?

如果连你自己要的是什么都不知道的话,那么爱你的主又如何帮你安排呢?不是吗?

而在你旁边的人,再怎么热心地为你敲锣打鼓,爱你的主也顶多给一些慈悲的安慰。因为连你自己都还没有清楚地告诉他,你要的是什么?那么你又岂能无辜地怪上帝没有为你开路呢?不是吗?

有这样一篇调查似乎也说明了什么:

有一年,一群意气风发的天之骄子从美国哈佛大学毕业了,他们即将开始穿越各自的玉米地。他们的智力、学历、环境条件都相差无几。在临出校门前,哈佛对他们进行了一次关于人生目标的调查。结果是这样的:

27%的人,没有目标;60%的人,目标模糊;

10%的人,有清晰但比较短期的目标;

3%的人,有清晰而长远的目标。

以后的25年,他们穿越玉米地。25年后,哈佛再次对这群学生进行了跟踪调查。结果又是这样的:

3%的人,25年间他们朝着一个方向不懈努力,几乎都成为社会各界的成功人士,其中不乏行业领袖、社会精英;

10%的人,他们的短期目标不断地实现,成为各个领域中的专业人士,大都生活在社会的中上层;

60%的人,他们安稳地生活与工作,但都没有什么特别成绩,几乎都生活在社会的中下层;

剩下27%的人,他们的生活没有目标,过得很不如意,并且常常在抱怨他人、抱怨社会、抱怨这个“不肯给他们机会”的世界。

其实,他们之间的差别仅仅在于:25年前,他们中的一些人知道为什么要穿越玉米地,而另一些人则不清楚或不很清楚。

作者:佚名
来源:网络

评论关闭
发表于: os/software | 作者: | 日期: 2008/11/05 09:11
标签: ,

http://sites.google.com/site/loveipod2/Home/winemnc

评论关闭
发表于: java/j2ee | 作者: | 日期: 2008/11/05 06:11
标签:

package com.sitech.grp.web.actionbean;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.upload.FormFile;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.actions.DispatchAction;
import java.io.*;
import com.sitech.grp.model.Dgrpcustcontract;
import com.sitech.grp.web.formbean.DGrpContractForm;
import com.sitech.grp.service.IDGrpContractManager;
import sun.net.TelnetOutputStream;
import sun.net.ftp.FtpClient;

public class DGrpContractAction extends DispatchAction {
private IDGrpContractManager grpContractManager;
private FtpClient ftpClient;
// 查询集团合同信息
public ActionForward queryGrpContractMsg(ActionMapping mapping,
ActionForm form, HttpServletRequest request,
HttpServletResponse response) {
DGrpContractForm frm = (DGrpContractForm) form;
try {
Dgrpcustcontract dGrpContract = frm.getEntity();
frm.setResultList(grpContractManager
.queryGrpContractMsg(dGrpContract.getUnit_id()));
} catch (Exception e) {
System.out.println(e);
}
return mapping.findForward(“querygrpcontract”);
}

// 查询集团合同详细信息
public ActionForward querySingleContractMsg(ActionMapping mapping,
ActionForm form, HttpServletRequest request,
HttpServletResponse response) {
DGrpContractForm frm = (DGrpContractForm) form;
try {
Dgrpcustcontract dGrpContract = frm.getEntity();
dGrpContract = grpContractManager.get(dGrpContract.getUnit_id());
frm.setEntity(dGrpContract);
} catch (Exception e) {
System.out.println(“querySingleContractMsg=” + e);
}
return mapping.findForward(“querySingleContractMsg”);
}

// 更新集团合同信息
public ActionForward updateContractMsg(ActionMapping mapping,
ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws Exception{
DGrpContractForm frm = (DGrpContractForm) form;
TelnetOutputStream os = null;
FileInputStream is = null;
try {
Dgrpcustcontract dGrpContract = frm.getEntity();
// ——————————————–
String encoding = request.getCharacterEncoding();
if ((encoding != null) && (encoding.equalsIgnoreCase(“utf-8”))) {
response.setContentType(“text/html; charset=gb2312″);// 如果没有指定编码,编码格式为gb2312
}
FormFile file = frm.getFiles();// 取得上传的文件
if (file.getFileName().length() > 0) {
InputStream stream = file.getInputStream();// 把文件读入
// server:FTP服务器的IP地址;user:登录FTP服务器的用户名
// password:登录FTP服务器的用户名的口令;path:FTP服务器上的路径
ftpClient = new FtpClient();
String path=”/bboss/run/vippage/upload/contract/”;//上传文件路径
ftpClient.openServer(“10.161.1.58”);
ftpClient.login(“weblogic”, “asd123”);
//path是ftp服务下主目录的子目录
if (path.length() != 0)
ftpClient.cd(path);
//用2进制上传
ftpClient.binary();
//”upftpfile”用ftp上传后的新文件名
os = ftpClient.put(dGrpContract.getContract_id() + “-”
+ file.getFileName());
int bytesRead = 0;
byte[] buffer = new byte[8192];
while ((bytesRead = stream.read(buffer, 0, 8192)) != -1) {
os.write(buffer, 0, bytesRead);// 将文件写入服务器}
}

dGrpContract.setContract_file(file.getFileName());
}
// ——————————————–
grpContractManager.update(dGrpContract);
frm.setResultList(grpContractManager
.queryGrpContractMsg(dGrpContract.getUnit_id()));
frm.setOp_flag(“true”);
} catch (Exception e) {
frm.setOp_flag(“false”);
System.out.println(“updateContractMsg=” + e);
} finally {
if (is != null) {
is.close();
}
if (os != null) {
os.close();
}
}
return mapping.findForward(“querygrpcontract”);
}

public void setGrpContractManager(IDGrpContractManager grpContractManager) {
this.grpContractManager = grpContractManager;
}

}

评论关闭
发表于: arch/management | 作者: | 日期: 2008/11/05 06:11
标签:

2005年12月6日
只有在实际编程的时候体会OOAD的思想,才会发现OOAD的妙处。 More …

评论关闭
发表于: DB/ES | 作者: | 日期: 2008/11/05 06:11
标签:

我们将讨论各种用于访问ORACLE数据库的DDL和TCL语句。

查询
SELECT语句用于从数据库中查询数据,当在PL/SQL中使用SELECT语句时,要与INTO子句一起使用,查询的返回值被赋予INTO子句中的变量,变量的声明是在DELCARE中。SELECT INTO语法如下:
SELECT [DISTICT|ALL]{*|column[,column,…]}
INTO (variable[,variable,…] |record)
FROM {table|(sub-query)}[alias]
WHERE…………
PL/SQL中SELECT语句只返回一行数据。如果超过一行数据,那么就要使用显式游标(对游标的讨论我们将在后面进行),INTO子句中要有与SELECT子句中相同列数量的变量。INTO子句中也可以是记录变量。

%TYPE属性
在PL/SQL中可以将变量和常量声明为内建或用户定义的数据类型,以引用一个列名,同时继承他的数据类型和大小。这种动态赋值方法是非常有用的,比如变量引用的列的数据类型和大小改变了,如果使用了%TYPE,那么用户就不必修改代码,否则就必须修改代码。

例:
v_empno SCOTT.EMP.EMPNO%TYPE;
v_salary EMP.SALARY%TYPE;
 不但列名可以使用%TYPE,而且变量、游标、记录,或声明的常量都可以使用%TYPE。这对于定义相同数据类型的变量非常有用。
DELCARE
V_A NUMBER(5):=10;
V_B V_A%TYPE:=15;
V_C V_A%TYPE;
BEGIN
DBMS_OUTPUT.PUT_LINE
(‘V_A=’||V_A||’V_B=’||V_B||’V_C=’||V_C);
END

SQL>/
V_A=10 V_B=15 V_C=
PL/SQL procedure successfully completed.
SQL>

其他DML语句
其它操作数据的DML语句是:INSERT、UPDATE、DELETE和LOCK TABLE,这些语句在PL/SQL中的语法与在SQL中的语法相同。我们在前面已经讨论过DML语句的使用这里就不再重复了。在DML语句中可以使用任何在DECLARE部分声明的变量,如果是嵌套块,那么要注意变量的作用范围。

例:
CREATE OR REPLACE PROCEDURE FIRE_EMPLOYEE (pempno in number)
 AS
v_ename EMP.ENAME%TYPE;
BEGIN
 SELECT ename INTO v_ename
FROM emp
WHERE empno=p_empno;
INSERT INTO FORMER_EMP(EMPNO,ENAME)
VALUES (p_empno,v_ename);
DELETE FROM emp
WHERE empno=p_empno;
UPDATE former_emp
SET date_deleted=SYSDATE
WHERE empno=p_empno;

EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE(‘Employee Number Not Found!’);
END

DML语句的结果
当执行一条DML语句后,DML语句的结果保存在四个游标属性中,这些属性用于控制程序流程或者了解程序的状态。当运行DML语句时,PL/SQL打开一个内建游标并处理结果,游标是维护查询结果的内存中的一个区域,游标在运行DML语句时打开,完成后关闭。隐式游标只使用SQL%FOUND,SQL%NOTFOUND,SQL%ROWCOUNT三个属性.SQL%FOUND,SQL%NOTFOUND是布尔值,SQL%ROWCOUNT是整数值。

SQL%FOUND和SQL%NOTFOUND
在执行任何DML语句前SQL%FOUND和SQL%NOTFOUND的值都是NULL,在执行DML语句后,SQL%FOUND的属性值将是:

. TRUE :INSERT
. TRUE ELETE和UPDATE,至少有一行被DELETE或UPDATE.
. TRUE :SELECT INTO至少返回一行
当SQL%FOUND为TRUE时,SQL%NOTFOUND为FALSE。

SQL%ROWCOUNT
在执行任何DML语句之前,SQL%ROWCOUNT的值都是NULL,对于SELECT INTO语句,如果执行成功,SQL%ROWCOUNT的值为1,如果没有成功,SQL%ROWCOUNT的值为0,同时产生一个异常NO_DATA_FOUND.

SQL%ISOPEN
SQL%ISOPEN是一个布尔值,如果游标打开,则为TRUE, 如果游标关闭,则为FALSE.对于隐式游标而言SQL%ISOPEN总是FALSE,这是因为隐式游标在DML语句执行时打开,结束时就立即关闭。

事务控制语句
事务是一个工作的逻辑单元可以包括一个或多个DML语句,事物控制帮助用户保证数据的一致性。如果事务控制逻辑单元中的任何一个DML语句失败,那么整个事务都将回滚,在PL/SQL中用户可以明确地使用COMMIT、ROLLBACK、SAVEPOINT以及SET TRANSACTION语句。
COMMIT语句终止事务,永久保存数据库的变化,同时释放所有LOCK,ROLLBACK终止现行事务释放所有LOCK,但不保存数据库的任何变化,SAVEPOINT用于设置中间点,当事务调用过多的数据库操作时,中间点是非常有用的,SET TRANSACTION用于设置事务属性,比如read-write和隔离级等。

显式游标
当查询返回结果超过一行时,就需要一个显式游标,此时用户不能使用select into语句。PL/SQL管理隐式游标,当查询开始时隐式游标打开,查询结束时隐式游标自动关闭。显式游标在PL/SQL块的声明部分声明,在执行部分或异常处理部分打开,取数据,关闭。

使用游标
这里要做一个声明,我们所说的游标通常是指显式游标,因此从现在起没有特别指明的情况,我们所说的游标都是指显式游标。要在程序中使用游标,必须首先声明游标。

声明游标
语法:
CURSOR cursor_name IS select_statement;

在PL/SQL中游标名是一个未声明变量,不能给游标名赋值或用于表达式中。

例:
DELCARE
CURSOR C_EMP IS SELECT empno,ename,salary
FROM emp
WHERE salary>2000
ORDER BY ename;
……..
BEGIN
在游标定义中SELECT语句中不一定非要表可以是视图,也可以从多个表或视图中选择的列,甚至可以使用*来选择所有的列 。

打开游标
使用游标中的值之前应该首先打开游标,打开游标初始化查询处理。打开游标的语法是:
OPEN cursor_name
cursor_name是在声明部分定义的游标名。

例:
OPEN C_EMP;

关闭游标
语法:
CLOSE cursor_name

例:
CLOSE C_EMP;

从游标提取数据
从游标得到一行数据使用FETCH命令。每一次提取数据后,游标都指向结果集的下一行。语法如下:
FETCH cursor_name INTO variable[,variable,…]
对于SELECT定义的游标的每一列,FETCH变量列表都应该有一个变量与之相对应,变量的类型也要相同。

例:
SET SERVERIUTPUT ON
DECLARE
v_ename EMP.ENAME%TYPE;
v_salary EMP.SALARY%TYPE;
CURSOR c_emp IS SELECT ename,salary FROM emp;
BEGIN
OPEN c_emp;
FETCH c_emp INTO v_ename,v_salary;
DBMS_OUTPUT.PUT_LINE(‘Salary of Employee’|| v_ename ||’is’|| v_salary);
FETCH c_emp INTO v_ename,v_salary;
DBMS_OUTPUT.PUT_LINE(‘Salary of Employee’|| v_ename ||’is’|| v_salary);
FETCH c_emp INTO v_ename,v_salary;
DBMS_OUTPUT.PUT_LINE(‘Salary of Employee’|| v_ename ||’is’|| v_salary);
CLOSE c_emp;
END

这段代码无疑是非常麻烦的,如果有多行返回结果,可以使用循环并用游标属性为结束循环的条件,以这种方式提取数据,程序的可读性和简洁性都大为提高,下面我们使用循环重新写上面的程序:
SET SERVERIUTPUT ON
DECLARE
v_ename EMP.ENAME%TYPE;
v_salary EMP.SALARY%TYPE;
CURSOR c_emp IS SELECT ename,salary FROM emp;
BEGIN
OPEN c_emp;
LOOP
FETCH c_emp INTO v_ename,v_salary;
EXIT WHEN c_emp%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(‘Salary of Employee’|| v_ename ||’is’|| v_salary);
END

记录变量
定义一个记录变量使用TYPE命令和%ROWTYPE,关于%ROWsTYPE的更多信息请参阅相关资料。
记录变量用于从游标中提取数据行,当游标选择很多列的时候,那么使用记录比为每列声明一个变量要方便得多。
当在表上使用%ROWTYPE并将从游标中取出的值放入记录中时,如果要选择表中所有列,那么在SELECT子句中使用*比将所有列名列出来要安全得多。

例:
SET SERVERIUTPUT ON
DECLARE
R_emp EMP%ROWTYPE;
CURSOR c_emp IS SELECT * FROM emp;
BEGIN
OPEN c_emp;
LOOP
FETCH c_emp INTO r_emp;
EXIT WHEN c_emp%NOTFOUND;
DBMS_OUT.PUT.PUT_LINE(‘Salary of Employee’||r_emp.ename||’is’|| r_emp.salary);
END LOOP;
CLOSE c_emp;
END;

%ROWTYPE也可以用游标名来定义,这样的话就必须要首先声明游标:

SET SERVERIUTPUT ON
DECLARE
CURSOR c_emp IS SELECT ename,salary FROM emp;
R_emp c_emp%ROWTYPE;
BEGIN
OPEN c_emp;
LOOP
FETCH c_emp INTO r_emp;
EXIT WHEN c_emp%NOTFOUND;
DBMS_OUT.PUT.PUT_LINE(‘Salary of Employee’||r_emp.ename||’is’|| r_emp.salary);
END LOOP;
CLOSE c_emp;
END;

带参数的游标
与存储过程和函数相似,可以将参数传递给游标并在查询中使用。这对于处理在某种条件下打开游标的情况非常有用。它的语法如下:

CURSOR cursor_name[(parameter[,parameter],…)] IS select_statement;

定义参数的语法如下:
Parameter_name [IN] data_type[{:=|DEFAULT} value]

  与存储过程不同的是,游标只能接受传递的值,而不能返回值。参数只定义数据类型,没有大小。
另外可以给参数设定一个缺省值,当没有参数值传递给游标时,就使用缺省值。游标中定义的参数只是一个占位符,在别处引用该参数不一定可靠。

在打开游标时给参数赋值,语法如下:

OPEN cursor_name[value[,value]….];
参数值可以是文字或变量。

例:
DECALRE
CURSOR c_dept IS SELECT * FROM dept ORDER BY deptno;
CURSOR c_emp (p_dept VARACHAR2) IS
SELECT ename,salary
FROM emp
WHERE deptno=p_dept
ORDER BY ename
r_dept DEPT%ROWTYPE;
v_ename EMP.ENAME%TYPE;
v_salary EMP.SALARY%TYPE;
v_tot_salary EMP.SALARY%TYPE;
BEGIN
OPEN c_dept;
LOOP
FETCH c_dept INTO r_dept;
EXIT WHEN c_dept%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(‘Department:’|| r_dept.deptno||’-‘||r_dept.dname);
v_tot_salary:=0;
OPEN c_emp(r_dept.deptno);
LOOP
FETCH c_emp INTO v_ename,v_salary;
EXIT WHEN c_emp%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(‘Name:’|| v_ename||’ salary:’||v_salary);
v_tot_salary:=v_tot_salary+v_salary;
END LOOP;
CLOSE c_emp;
DBMS_OUTPUT.PUT_LINE(‘Toltal Salary for dept:’|| v_tot_salary);
END LOOP;
CLOSE c_dept;
END;

游标FOR循环
在大多数时候我们在设计程序的时候都遵循下面的步骤:
1、打开游标
2、开始循环
3、从游标中取值
4、检查那一行被返回
5、处理
6、关闭循环
7、关闭游标
可以简单的把这一类代码称为游标用于循环。但还有一种循环与这种类型不相同,这就是FOR循环,用于FOR循环的游标按照正常的声明方式声明,它的优点在于不需要显式的打开、关闭、取数据,测试数据的存在、定义存放数据的变量等等。游标FOR循环的语法如下:

FOR record_name IN
(corsor_name[(parameter[,parameter]…)]
| (query_difinition)
LOOP
statements
END LOOP;

下面我们用for循环重写上面的例子:
DECALRE
CURSOR c_dept IS SELECT deptno,dname FROM dept ORDER BY deptno;
CURSOR c_emp (p_dept VARACHAR2) IS
SELECT ename,salary
FROM emp
WHERE deptno=p_dept
ORDER BY ename
v_tot_salary EMP.SALARY%TYPE;
BEGIN
FOR r_dept IN c_dept LOOP
DBMS_OUTPUT.PUT_LINE(‘Department:’|| r_dept.deptno||’-‘||r_dept.dname);
v_tot_salary:=0;
FOR r_emp IN c_emp(r_dept.deptno) LOOP
DBMS_OUTPUT.PUT_LINE(‘Name:’ || v_ename || ‘salary:’ || v_salary);
v_tot_salary:=v_tot_salary+v_salary;
END LOOP;
DBMS_OUTPUT.PUT_LINE(‘Toltal Salary for dept:’|| v_tot_salary);
END LOOP;
END;

在游标FOR循环中使用查询
在游标FOR循环中可以定义查询,由于没有显式声明所以游标没有名字,记录名通过游标查询来定义。
DECALRE
v_tot_salary EMP.SALARY%TYPE;
BEGIN
FOR r_dept IN (SELECT deptno,dname FROM dept ORDER BY deptno) LOOP
DBMS_OUTPUT.PUT_LINE(‘Department:’|| r_dept.deptno||’-‘||r_dept.dname);
v_tot_salary:=0;
FOR r_emp IN (SELECT ename,salary
   FROM emp
   WHERE deptno=p_dept
   ORDER BY ename) LOOP
DBMS_OUTPUT.PUT_LINE(‘Name:’|| v_ename||’ salary:’||v_salary);
v_tot_salary:=v_tot_salary+v_salary;
END LOOP;
DBMS_OUTPUT.PUT_LINE(‘Toltal Salary for dept:’|| v_tot_salary);
END LOOP;
END;

游标中的子查询
语法如下:

CURSOR C1 IS SELECT * FROM emp
WHERE deptno NOT IN (SELECT deptno
FROM dept
WHERE dname!=’ACCOUNTING’);
可以看出与SQL中的子查询没有什么区别。

游标中的更新和删除
在PL/SQL中依然可以使用UPDATE和DELETE语句更新或删除数据行。显式游标只有在需要获得多行数据的情况下使用。PL/SQL提供了仅仅使用游标就可以执行删除或更新记录的方法。
UPDATE或DELETE语句中的WHERE CURRENT OF子串专门处理要执行UPDATE或DELETE操作的表中取出的最近的数据。要使用这个方法,在声明游标时必须使用FOR UPDATE子串,当对话使用FOR UPDATE子串打开一个游标时,所有返回集中的数据行都将处于行级(ROW-LEVEL)独占式锁定,其他对象只能查询这些数据行,不能进行UPDATE、DELETE或SELECT…FOR UPDATE操作。

语法:
FOR UPDATE [OF [schema.]table.column[,[schema.]table.column]..
[nowait]

在多表查询中,使用OF子句来锁定特定的表,如果忽略了OF子句,那么所有表中选择的数据行都将被锁定。如果这些数据行已经被其他会话锁定,那么正常情况下ORACLE将等待,直到数据行解锁。

在UPDATE和DELETE中使用WHERE CURRENT OF子串的语法如下:

WHERE{CURRENT OF cursor_name|search_condition}

例:
DELCARE
CURSOR c1 IS SELECT empno,salary
FROM emp
WHERE comm IS NULL
FOR UPDATE OF comm;
v_comm NUMBER(10,2);
BEGIN
FOR r1 IN c1 LOOP
IF r1.salary<500 THEN v_comm:=r1.salary*0.25; ELSEIF r1.salary<1000 THEN v_comm:=r1.salary*0.20; ELSEIF r1.salary<3000 THEN v_comm:=r1.salary*0.15; ELSE v_comm:=r1.salary*0.12; END IF; UPDATE emp; SET comm=v_comm WHERE CURRENT OF c1l; END LOOP; END

评论关闭
发表于: os/software | 作者: | 日期: 2008/11/04 02:11
标签:

最简单的办法:
1 开始—运行—gpedit.msc
2 用户配置—管理模板—桌面—双击“从桌面删除‘回收站’选择已启用
3 刷新桌面

评论关闭