﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-JAVA历程-文章分类-Jdbc、Jdo、Database方面 </title><link>http://www.blogjava.net/shichengjun1984/category/21570.html</link><description>希望我的这个博客能给那些想在java的海洋中拼搏的人有所帮助。谢谢光临！</description><language>zh-cn</language><lastBuildDate>Fri, 11 Apr 2008 05:03:58 GMT</lastBuildDate><pubDate>Fri, 11 Apr 2008 05:03:58 GMT</pubDate><ttl>60</ttl><item><title>Oracle 10G 中的"回收站"</title><link>http://www.blogjava.net/shichengjun1984/articles/192113.html</link><dc:creator>I LOVE JAVA</dc:creator><author>I LOVE JAVA</author><pubDate>Fri, 11 Apr 2008 03:16:00 GMT</pubDate><guid>http://www.blogjava.net/shichengjun1984/articles/192113.html</guid><wfw:comment>http://www.blogjava.net/shichengjun1984/comments/192113.html</wfw:comment><comments>http://www.blogjava.net/shichengjun1984/articles/192113.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/shichengjun1984/comments/commentRss/192113.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/shichengjun1984/services/trackbacks/192113.html</trackback:ping><description><![CDATA[<div class="tit">&nbsp;</div>
<table style="table-layout: fixed">
    <tbody>
        <tr>
            <td>
            <div class="cnt" id="blog_text">
            <p style="font-weight: bold; font-size: 9pt; margin: 0in; color: #333333; text-decoration: underline"></p>
            <p style="font-size: 9pt; margin: 0in; color: #333333">作者：Fenng </p>
            <p style="font-size: 9pt; margin: 0in; color: #333333">日期：11-Jan-2004 　</p>
            <p style="font-size: 9pt; margin: 0in; color: #333333">出处：<a href="http://www.dbanotes.net/">http://www.dbanotes.net</a></p>
            <p style="font-size: 9pt; margin: 0in; color: #333333">版本：1.0 $29-Oct-2004$</p>
            <p style="font-size: 9pt; margin: 0in; color: #333333">在Oracle 10g数据库中，引入了一个回收站(Recycle Bin)的数据库对象。 </p>
            <p style="font-size: 9pt; margin: 0in; color: #333333">回收站，从原理上来说就是一个数据字典表，放置用户Drop掉的数据库对象信息。用户进行Drop操作的对象并没有被数据库删除，仍然会占用空间。除非是由于用户手工进行Purge或者因为存储空间不够而被数据库清掉。数据库有了这样的功能，能够减少很多不必要的麻烦。常常看到开发人员误把表删除，急急忙忙找DBA 来想办法的情况。相信随着10G的大范围应用，这种情形应该比较少见了，我们可以充分利用10g的闪回(FLASHBACK,闪回，回闪?)功能来避免大量的人工误操作。</p>
            <p style="font-size: 9pt; margin: 0in; color: #333333">DBA管理上的相关信息可以从USER_recyclebin(DBA_recyclebin)中获取。 </p>
            <p style="font-size: 9pt; margin: 0in; color: #333333">为了便于测试,我们创建了一个表空间Foo,大小为1M,创建了一个用户Foo,默认的表空间为Foo. </p>
            <p style="font-size: 9pt; margin: 0in 0in 0in 0.5in; color: #333333">SQL&gt; CONNECT foo/foo;<br />
            Connected.<br />
            SQL&gt; SELECT table_name FROM user_tables;<br />
            no rows selected<br />
            SQL&gt;<br />
            SQL&gt; DESC user_recyclebin<br />
            Name Null? Type<br />
            ----------------------------------------- -------- -------------------<br />
            OBJECT_NAME NOT NULL VARCHAR2(30)<br />
            ORIGINAL_NAME VARCHAR2(32)<br />
            OPERATION VARCHAR2(9)<br />
            TYPE VARCHAR2(25)<br />
            TS_NAME VARCHAR2(30)<br />
            CREATETIME VARCHAR2(19)<br />
            DROPTIME VARCHAR2(19)<br />
            DROPSCN NUMBER<br />
            PARTITION_NAME VARCHAR2(32)<br />
            CAN_UNDROP VARCHAR2(3)<br />
            CAN_PURGE VARCHAR2(3)<br />
            RELATED NOT NULL NUMBER<br />
            BASE_OBJECT NOT NULL NUMBER<br />
            PURGE_OBJECT NOT NULL NUMBER<br />
            SPACE NUMBER<br />
            SQL&gt;<br />
            </p>
            <p style="font-size: 9pt; margin: 0in; color: #333333">user_recyclebin大多是自解释的,相对比较容易理解. </p>
            <p style="font-size: 9pt; margin: 0in 0in 0in 0.5in; color: #333333">SQL&gt; SELECT object_name FROM user_recyclebin;<br />
            no rows selected<br />
            SQL&gt;<br />
            SQL&gt; SELECT object_name FROM user_recyclebin;<br />
            no rows selected<br />
            SQL&gt; CREATE TABLE foo AS SELECT * FROM DUAL;<br />
            Table created.<br />
            SQL&gt; SELECT table_name FROM user_tables;<br />
            TABLE_NAME<br />
            ----------------------------------------------<br />
            FOO<br />
            SQL&gt; DROP TABLE foo;<br />
            Table dropped.<br />
            SQL&gt; SELECT table_name FROM user_tables;<br />
            no rows selected<br />
            SQL&gt; SHOW recyclebin<br />
            ORIGINAL NAME RECYCLEBIN NAME OBJECT TYPE DROP TIME<br />
            ---------------- ------------------------------ ------------ -------------------<br />
            FOO BIN$V3f/oYUITrCEF2cotS5JaA==$0 TABLE 2004-10-30:14:37:39<br />
            SQL&gt;<br />
            </p>
            <p style="font-size: 9pt; margin: 0in; color: #333333">SQL*Plus命令SHOW recyclebin等价于这条SQL: </p>
            <p style="font-size: 9pt; margin: 0in 0in 0in 0.5in; color: #333333">SQL&gt; SELECT original_name, object_name, TYPE, droptime FROM user_recyclebin;<br />
            ORIGINAL_NAME OBJECT_NAME TYPE DROPTIME<br />
            --------------- ------------------------------ ---------- --------------------<br />
            FOO BIN$V3f/oYUITrCEF2cotS5JaA==$0 TABLE 2004-10-30:14:37:39<br />
            SQL&gt;<br />
            SQL&gt; DESC "BIN$V3f/oYUITrCEF2cotS5JaA==$0"<br />
            Name Null? Type<br />
            ----------------------------------------- -------- ----------------<br />
            DUMMY VARCHAR2(1)<br />
            SQL&gt;<br />
            </p>
            <p style="font-size: 9pt; margin: 0in; color: #333333">当一个表被删除并移动到"回收站"中，它的名字要进行一些转换。这样的目的显而易见是为了避免同类对象名称的重复。(这一点和Windows操作系统的回收站不同，Windows中的回收站经过了特殊的处理，操作系统文件可以重名。) </p>
            <p style="font-size: 9pt; margin: 0in; color: #333333">转换后的名字格式如下:</p>
            <p style="font-size: 9pt; margin: 0in 0in 0in 0.5in; color: #333333">BIN$unique_id$version </p>
            <ul style="margin-top: 0in; margin-bottom: 0in; margin-left: 1in; direction: ltr; unicode-bidi: embed" type="disc">
                <li style="margin-top: 0px; font-size: 10pt; margin-bottom: 0px; vertical-align: middle"><span style="font-size: 9pt; color: #333333">其中BIN代表RecycleBin </span>
                <li style="margin-top: 0px; font-size: 10pt; margin-bottom: 0px; vertical-align: middle"><span style="font-size: 9pt; color: #333333">unique_id是数据库中该对象的唯一标志，26个字符长度 </span>
                <li style="margin-top: 0px; font-size: 10pt; margin-bottom: 0px; vertical-align: middle"><span style="font-size: 9pt; color: #333333">version表示该对象的版本号</span> </li>
            </ul>
            <p style="font-size: 9pt; margin: 0in 0in 0in 0.5in; color: #333333">注：在10g beta 版本中，名字格式如下： </p>
            <p style="font-size: 9pt; margin: 0in 0in 0in 0.5in; color: #333333">RB$$objn$object_type$version<br />
            </p>
            <p style="font-size: 9pt; margin: 0in 0in 0in 0.5in; color: #333333">其中的RB,代表Recycle Bin. objn为表的目录对象号. object_type表示对象类型. version表示版本号. 由数据库指定。</p>
            <p style="font-size: 9pt; margin: 0in; color: #333333">下面我们验证一下回收站里数据库对象名字的唯一性: </p>
            <p style="font-size: 9pt; margin: 0in 0in 0in 0.5in; color: #333333">SQL&gt; CREATE TABLE foo AS SELECT * FROM DUAL;<br />
            Table created.<br />
            SQL&gt; SELECT table_name FROM user_tables;<br />
            TABLE_NAME<br />
            ------------------------------------------------------------<br />
            FOO<br />
            SQL&gt; DROP TABLE foo;<br />
            Table dropped.<br />
            SQL&gt; SHOW recyclebin<br />
            ORIGINAL NAME RECYCLEBIN NAME OBJECT TYPE DROP TIME<br />
            ---------------- ------------------------------ ------------ -------------------<br />
            FOO BIN$VL+ZsqVlQF6R2nYnwAqtvw==$0 TABLE 2004-10-30:15:01:42<br />
            FOO BIN$V3f/oYUITrCEF2cotS5JaA==$0 TABLE 2004-10-30:14:37:39<br />
            SQL&gt;<br />
            </p>
            <p style="font-size: 9pt; margin: 0in; color: #333333">能看出来，虽然源表名字相同，在回收站里的对象名字是不同的。 </p>
            <p style="font-weight: bold; font-size: 10pt; margin: 0in; color: #333333">针对Recycle Bin对象的操作</p>
            <p style="font-size: 9pt; margin: 0in; color: #333333">已经放到回收站里的表是不能用drop 命令删除的(注意对象名字上的双引号)： </p>
            <p style="font-size: 9pt; margin: 0in 0in 0in 0.5in; color: #333333">SQL&gt; DROP table "BIN$V3f/oYUITrCEF2cotS5JaA==$0"<br />
            2 /<br />
            DROP table "BIN$V3f/oYUITrCEF2cotS5JaA==$0"<br />
            *<br />
            ERROR at line 1:<br />
            ORA-38301: can not perform DDL/DML over objects in Recycle Bin<br />
            SQL&gt;<br />
            </p>
            <p style="font-size: 9pt; margin: 0in; color: #333333">如果要清掉该对象,使用purge命令： </p>
            <p style="font-size: 9pt; margin: 0in 0in 0in 0.5in; color: #333333">SQL&gt; PURGE table "BIN$V3f/oYUITrCEF2cotS5JaA==$0"<br />
            2 /<br />
            Table purged.<br />
            SQL&gt; SELECT object_name, original_name FROM user_recyclebin;<br />
            OBJECT_NAME ORIGINAL_NAME<br />
            ------------------------------ ---------------<br />
            BIN$VL+ZsqVlQF6R2nYnwAqtvw==$0 FOO<br />
            SQL&gt;<br />
            </p>
            <p style="font-size: 9pt; margin: 0in; color: #333333">对象已经清掉。如果直接清空所有的Recycle Bin中的对象： </p>
            <p style="font-size: 9pt; margin: 0in 0in 0in 0.5in; color: #333333">SQL&gt; PURGE RECYCLEBIN;<br />
            Recyclebin purged.<br />
            SQL&gt; SELECT object_name, original_name FROM user_recyclebin;<br />
            no rows selected<br />
            SQL&gt;<br />
            </p>
            <p style="font-size: 9pt; margin: 0in; color: #333333">恢复表，用回闪表的功能： </p>
            <p style="font-size: 9pt; margin: 0in 0in 0in 0.5in; color: #333333">SQL&gt; FLASHBACK TABLE foo TO BEFORE DROP;<br />
            Flashback complete.<br />
            SQL&gt;SELECT table_name FROM user_tables;<br />
            TABLE_NAME<br />
            ------------------------------------------------------------<br />
            FOO<br />
            SQL&gt;<br />
            </p>
            <p style="font-size: 9pt; margin: 0in 0in 0in 0.5in; color: #333333">注:在10g Beta版本中，使用Undrop命令来做到这一点.</p>
            <p style="font-size: 9pt; margin: 0in; color: #333333">有的时候，可能同一个名字的表被删除到回收站中: </p>
            <p style="font-size: 9pt; margin: 0in 0in 0in 0.5in; color: #333333">SQL&gt; DROP TABLE FOO;<br />
            Table dropped.<br />
            SQL&gt; SHOW RECYCLEBIN<br />
            ORIGINAL NAME RECYCLEBIN NAME OBJECT TYPE DROP TIME<br />
            ---------------- ------------------------------ ------------ -------------------<br />
            FOO BIN$lfTbzOjISXaw8u0BIO7pNA==$0 TABLE 2004-10-30:15:18:03<br />
            SQL&gt; CREATE TABLE foo AS SELECT * FROM DUAL;<br />
            Table created.<br />
            SQL&gt; DROP TABLE foo;<br />
            Table dropped.<br />
            SQL&gt; SHOW RECYCLEBIN<br />
            ORIGINAL NAME RECYCLEBIN NAME OBJECT TYPE DROP TIME<br />
            ---------------- ------------------------------ ------------ -------------------<br />
            FOO BIN$J63QaUaKTmC1glat+imjeg==$0 TABLE 2004-10-30:15:18:50<br />
            FOO BIN$lfTbzOjISXaw8u0BIO7pNA==$0 TABLE 2004-10-30:15:18:03<br />
            SQL&gt; FLASHBACK TABLE FOO TO BEFORE DROP;<br />
            Flashback complete.<br />
            SQL&gt; SHOW RECYCLEBIN<br />
            ORIGINAL NAME RECYCLEBIN NAME OBJECT TYPE DROP TIME<br />
            ---------------- ------------------------------ ------------ -------------------<br />
            FOO BIN$lfTbzOjISXaw8u0BIO7pNA==$0 TABLE 2004-10-30:15:18:03<br />
            SQL&gt;<br />
            </p>
            <p style="font-size: 9pt; margin: 0in; color: #333333">默认的恢复是第一个被删除的FOO表。如果要恢复指定的表，可以在FLASHBACK TABLE 后面加上指定的RECYCLEBIN 参数指定其他的名字: </p>
            <p style="font-size: 9pt; margin: 0in 0in 0in 0.5in; color: #333333">SQL&gt; FLASHBACK TABLE "BIN$lfTbzOjISXaw8u0BIO7pNA==$0" TO BEFORE DROP;<br />
            FLASHBACK TABLE "BIN$lfTbzOjISXaw8u0BIO7pNA==$0" TO BEFORE DROP<br />
            *<br />
            ERROR at line 1:<br />
            ORA-38312: original name is used by an existing object<br />
            SQL&gt; FLASHBACK TABLE "BIN$lfTbzOjISXaw8u0BIO7pNA==$0" TO BEFORE DROP<br />
            2 RENAME TO foo2;<br />
            Flashback complete.<br />
            SQL&gt;<br />
            </p>
            </div>
            </td>
        </tr>
    </tbody>
</table>
<img src ="http://www.blogjava.net/shichengjun1984/aggbug/192113.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/shichengjun1984/" target="_blank">I LOVE JAVA</a> 2008-04-11 11:16 <a href="http://www.blogjava.net/shichengjun1984/articles/192113.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Oracle 执行定时备份</title><link>http://www.blogjava.net/shichengjun1984/articles/191190.html</link><dc:creator>I LOVE JAVA</dc:creator><author>I LOVE JAVA</author><pubDate>Mon, 07 Apr 2008 02:45:00 GMT</pubDate><guid>http://www.blogjava.net/shichengjun1984/articles/191190.html</guid><wfw:comment>http://www.blogjava.net/shichengjun1984/comments/191190.html</wfw:comment><comments>http://www.blogjava.net/shichengjun1984/articles/191190.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/shichengjun1984/comments/commentRss/191190.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/shichengjun1984/services/trackbacks/191190.html</trackback:ping><description><![CDATA[利用任务计划、批处理文件和ORACLE的EXP导出功能，可以根据日期自动生成ORACLE备份文件，大大方便了ORACLE数据备份。:<br />
1、建立批处理文件backup.bat\.<br />
exp system/manager file=d:\backup\oracle\oracle%date:~0,10%.dmp owner=system log=d:\backup\oracle\oracle%date:~0,10%.log<br />
将生成oracle2006-01-09.dmp文件<br />
exp system/manager file=d:\backup\oracle\oracle%date:~11,3%.dmp owner=system log=d:\backup\oracle\oracle%date:~11,3%.log<br />
将生成oracle星期一.dmp文件，则每周循环保留一个备份文件，共7个备份文件循环<br />
2、添加一个任务计划<br />
利用任务计划向导，根据备份策略设置自动执行任务的时间频率（例如每天零时），执行d:\oracle\backup.bat<br />
3、以后每天将在目录中生成形如&#8220;oracle2005-08-31.dmp和oracle2005-08-31.log&#8221;的备份和日志文件。<br />
说明：<br />
1、%date%的值在不同的系统、语言版本下可能是不一样的，控制面板里面区域选项的设定也会改变%date%的值。请先在命令行中测试 echo %date% 的返回值。%date:~4,10% 是返回日期函数，~后的第一个参数是要截取的起始位置（从0开始），第二个参数是要截取的长度，如没有则是截取到最后，参数可酌情修改。<br />
2、如需要准确的时间做为文件名，请用%time%函数，参数同上。<br />
<br />
&nbsp;http://tb.blog.csdn.net/TrackBack.aspx?PostId=1442858
<img src ="http://www.blogjava.net/shichengjun1984/aggbug/191190.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/shichengjun1984/" target="_blank">I LOVE JAVA</a> 2008-04-07 10:45 <a href="http://www.blogjava.net/shichengjun1984/articles/191190.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>36.oracle常用命令</title><link>http://www.blogjava.net/shichengjun1984/articles/146226.html</link><dc:creator>I LOVE JAVA</dc:creator><author>I LOVE JAVA</author><pubDate>Tue, 18 Sep 2007 10:26:00 GMT</pubDate><guid>http://www.blogjava.net/shichengjun1984/articles/146226.html</guid><wfw:comment>http://www.blogjava.net/shichengjun1984/comments/146226.html</wfw:comment><comments>http://www.blogjava.net/shichengjun1984/articles/146226.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/shichengjun1984/comments/commentRss/146226.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/shichengjun1984/services/trackbacks/146226.html</trackback:ping><description><![CDATA[<p>1.登陆系统用户<br />
sqlplus 然后输入系统用户名和密码<br />
登陆别的用户<br />
conn 用户名/密码;<br />
2.创建表空间<br />
create tablespace 空间名<br />
datafile 'c:\空间名' size 15M&nbsp;&nbsp;--表空间的存放路径,初始值为15M<br />
autoExtend on next 10M&nbsp;&nbsp;--空间的自动增长的值是10M<br />
permanent online;&nbsp;&nbsp;--永久使用<br />
3.创建用户<br />
create user shi&nbsp;&nbsp;&nbsp;--创建用户名为shi<br />
identified by scj&nbsp;&nbsp;--创建密码为scj<br />
default tablespace 表空间名&nbsp;--默认表空间名<br />
temporary tablespace temp&nbsp;--临时表空间为temp<br />
profile default&nbsp;&nbsp;&nbsp;--受profile文件的限制<br />
quota unlimited on 表空间名;&nbsp;--在表空间下面建表不受限制<br />
4.创建角色<br />
create role 角色名 identified by 密码;<br />
5.给角色授权<br />
grant create session to 角色名；--给角色授予创建会话的权限<br />
grant 角色名 to 用户名；&nbsp;--把角色授予用户<br />
6.给用户授予权限<br />
grant create session,resource to shi;--给shi用户授予所有权限<br />
grant create table to shi;&nbsp;--给shi用户授予创建表的权限<br />
7.select table_name from user_tables;&nbsp;&nbsp; 察看当前用户下的所有表 <br />
8.select tablespace_name from user_tablespaces; 察看当前用户下的 表空间<br />
9.select username from dba_users;察看所有用户名称命令 必须用sys as sysdba登陆<br />
10.创建表<br />
create table 表名<br />
(<br />
id int not null,<br />
name varchar2(20) not null<br />
)tablespace 表空间名&nbsp;&nbsp;--所属的表空间<br />
storage<br />
(<br />
&nbsp;&nbsp; initial 64K&nbsp;&nbsp;&nbsp;--表的初始值<br />
&nbsp;&nbsp; minextents 1&nbsp;&nbsp;&nbsp;--最小扩展值<br />
&nbsp;&nbsp; maxextents unlimited&nbsp;&nbsp;--最大扩展值<br />
);<br />
11.--为usrs表添加主键和索引<br />
alter table users<br />
add constraint pk primary key (ID);<br />
12.为已经创建users表添加外键<br />
alter table users<br />
&nbsp; add constraint fk_roleid foreign key (roleid)<br />
&nbsp; references role(role_id) on delete cascad;&nbsp;--下边写主表的列<br />
&nbsp;&nbsp;&nbsp;on delete cascad是创建级联<br />
13.把两个列连接起来<br />
select concat(name,id) from 表名；&nbsp;&nbsp;--把name和id连接起来<br />
14.截取字符串<br />
select column(name,'李') from 表名；&nbsp;&nbsp;--把name中的&#8216;李&#8217;去掉<br />
15.运行事务之前必须写<br />
set serveroutput on;&nbsp;&nbsp;--打开输入输出（不写的话,打印不出信息）<br />
16.while的应用<br />
declare&nbsp;&nbsp;&nbsp;--声明部分<br />
ccc number:=1;&nbsp;&nbsp;--复职<br />
a number:=0;<br />
begin&nbsp;&nbsp;&nbsp;--事务的开始<br />
while ccc&lt;=100 loop&nbsp;--循环<br />
if((ccc mod 3)=0) then&nbsp;--条件<br />
&nbsp;dbms_output.put_line(ccc||',');&nbsp;&nbsp;&nbsp; --打印显示<br />
&nbsp;a:=a+ccc;<br />
end if;&nbsp;&nbsp;&nbsp;--结束if<br />
ccc:=ccc+1;<br />
end loop;&nbsp;&nbsp;--结束循环<br />
dbms_output.put_line(a);&nbsp;<br />
end;&nbsp;&nbsp;&nbsp;--结束事务<br />
/&nbsp;&nbsp;&nbsp;<br />
17.select into &nbsp;的用法&nbsp;--只能处理一行结果集<br />
declare<br />
&nbsp; name varchar(30);<br />
begin<br />
&nbsp;select username into name<br />
&nbsp;from users<br />
&nbsp;where id=2;<br />
dbms_output.put_line('姓名为：'||name);<br />
end;<br />
/<br />
18.利用%rowtype属性可以在运行时方便的声明记录变量和其他结构<br />
Set serveroutput on;<br />
Declare<br />
&nbsp;&nbsp; utype users%rowtype;<br />
Begin<br />
Select * into utype from users where id=20;<br />
Dbms_output.put_line('姓名'|| utype.username);<br />
Dbms_output.put_line('生日'|| utype.brithday);<br />
end;<br />
/&nbsp;&nbsp;&nbsp;--%rowtype想当于复制一个表<br />
19.游标的定义和使用<br />
Declare<br />
Cursor ucur is select * from users; --声明游标<br />
Us users%rowtype;--定义与游标想匹配的变量<br />
Begin<br />
Open ucur;--打开游标<br />
Fetch ucur into us;<br />
While ucur %found loop --使用循环遍历游标的查询结果<br />
Dbms_output.put_line('姓名：'||us.username||'生日'||us.brithday);<br />
Fetch ucur into us;<br />
End loop;<br />
Close ucur; --关闭游标<br />
End;<br />
20.插入值时，sql语句里取得系统的当前时间用 sysdate</p>
<p>=======================================<br />
%found在前一条的fetch语句至少对应数据库的一行时，%found属性值为true，否则为false;<br />
% notfound 在前一条fetch语句没有对应的数据库行时，%notfound属性值为true，否则为false;<br />
%isopen 在游标打开时%isopen属性值为true；否则为false;<br />
%rowcount显示迄今为止从显示游标中取出的行数</p>
<p>20.<br />
删除<br />
drop tablespace 空间名 including contents;&nbsp;--删除表空间和里面的内容<br />
drop table 表名&nbsp;&nbsp;&nbsp;--删除表<br />
drop user 用户名&nbsp;&nbsp;--删除用户</p>
<p>&nbsp;</p>
<img src ="http://www.blogjava.net/shichengjun1984/aggbug/146226.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/shichengjun1984/" target="_blank">I LOVE JAVA</a> 2007-09-18 18:26 <a href="http://www.blogjava.net/shichengjun1984/articles/146226.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>8.数据库菜鸟不可不看 简单SQL语句小结</title><link>http://www.blogjava.net/shichengjun1984/articles/119701.html</link><dc:creator>I LOVE JAVA</dc:creator><author>I LOVE JAVA</author><pubDate>Thu, 24 May 2007 05:22:00 GMT</pubDate><guid>http://www.blogjava.net/shichengjun1984/articles/119701.html</guid><wfw:comment>http://www.blogjava.net/shichengjun1984/comments/119701.html</wfw:comment><comments>http://www.blogjava.net/shichengjun1984/articles/119701.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/shichengjun1984/comments/commentRss/119701.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/shichengjun1984/services/trackbacks/119701.html</trackback:ping><description><![CDATA[a.用as关键字：select name as '姓名' from students order by age
<p>　　b.直接表示：select name '姓名' from students order by age</p>
<p>　　2.精确查找:</p>
<p>　　a.用in限定范围：select * from students where native in ('湖南', '四川') </p>
<p>　　b.between...and：select * from students where age between 20 and 30</p>
<p>　　c.&#8220;=&#8221;：select * from students where name = '李山' </p>
<p>　　d.like:select * from students where name like '李%' (注意查询条件中有&#8220;%&#8221;，则说明是部分匹配，而且还有先后信息在里面，即查找以&#8220;李&#8221;开头的匹配项。所以若查询有&#8220;李&#8221;的所有对象，应该命令：'%李%';若是第二个字为李，则应为'_李%'或'_李'或'_李_'。)</p>
<p>　　e.[]匹配检查符：select * from courses where cno like '[AC]%' (表示或的关系，与"in(...)"类似，而且"[]"可以表示范围，如：select * from courses where cno like '[A-C]%')</p>
<p>　　3.对于时间类型变量的处理</p>
<p>　　a.smalldatetime：直接按照字符串处理的方式进行处理，例如：<br>select * from students where birth &gt; = '1980-1-1' and birth &lt;= '1980-12-31' </p>
<p>　　4.集函数</p>
<p>　　a.count()求和，如：select count(*) from students (求学生总人数)</p>
<p>　　b.avg(列)求平均，如：select avg(mark) from grades where cno=&#8217;B2&#8217;</p>
<p>　　c.max(列)和min(列)，求最大与最小</p>
<p>　　5.分组group</p>
<p>　　常用于统计时，如分组查总数：<br>select gender,count(sno) <br>from students<br>group by gender<br>(查看男女学生各有多少)</p>
<p>　　注意：从哪种角度分组就从哪列"group by"</p>
<p>　　对于多重分组，只需将分组规则罗列。比如查询各届各专业的男女同学人数 ，那么分组规则有：届别(grade)、专业(mno)和性别(gender)，所以有"group by grade, mno, gender"</p>
<p>select grade, mno, gender, count(*)<br>from students<br>group by grade, mno, gender</p>
<p>　　通常group还和having联用，比如查询1门课以上不及格的学生，则按学号(sno)分类有：</p>
<p>select sno,count(*) from grades <br>where mark&lt;60<br>group by sno<br>having count(*)&gt;1 </p>
<p>　　6.UNION联合</p>
<p>　　合并查询结果，如：</p>
<p>SELECT * FROM students<br>WHERE name like &#8216;张%&#8217;<br>UNION [ALL]<br>SELECT * FROM students<br>WHERE name like &#8216;李%&#8217;</p>
<p>　　7.多表查询</p>
<p>　　a.内连接</p>
<p>select g.sno,s.name,c.coursename <br>from grades g JOIN students s ON g.sno=s.sno<br>JOIN courses c ON g.cno=c.cno<br>(注意可以引用别名)<br>b.外连接<br>b1.左连接<br>select courses.cno,max(coursename),count(sno) <br>from courses LEFT JOIN grades ON courses.cno=grades.cno <br>group by courses.cno</p>
<p>　　左连接特点：显示全部左边表中的所有项目，即使其中有些项中的数据未填写完全。</p>
<p>　　左外连接返回那些存在于左表而右表中却没有的行，再加上内连接的行。</p>
<p>　　b2.右连接</p>
<p>　　与左连接类似</p>
<p>　　b3.全连接</p>
<p>select sno,name,major <br>from students FULL JOIN majors ON students.mno=majors.mno</p>
<p>　　两边表中的内容全部显示</p>
<p>　　c.自身连接</p>
<p>select c1.cno,c1.coursename,c1.pno,c2.coursename <br>from courses c1,courses c2 where c1.pno=c2.cno</p>
<p>　　采用别名解决问题。</p>
<p>　　d.交叉连接</p>
<p>select lastname+firstname from lastname CROSS JOIN firstanme</p>
<p>　　相当于做笛卡儿积</p>
<p>　　8.嵌套查询</p>
<p>　　a.用关键字IN,如查询李山的同乡：</p>
<p>select * from students<br>where native in (select native from students where name=&#8217; 李山&#8217;) </p>
<p>　　b.使用关键字EXIST,比如，下面两句是等价的：</p>
<p>select * from students<br>where sno in (select sno from grades where cno=&#8217;B2&#8217;)</p>
<p>select * from students where exists <br>(select * from grades where <br>grades.sno=students.sno AND cno=&#8217;B2&#8217;)</p>
<p>　　9.关于排序order</p>
<p>　　a.对于排序order，有两种方法：asc升序和desc降序</p>
<p>　　b.对于排序order,可以按照查询条件中的某项排列，而且这项可用数字表示，如：</p>
<p>select sno,count(*) ,avg(mark) from grades <br>group by sno<br>having avg(mark)&gt;85<br>order by 3 </p>
<p>　　10.其他</p>
<p>　　a.对于有空格的识别名称，应该用"[]"括住。</p>
<p>　　b.对于某列中没有数据的特定查询可以用null判断，如select sno,courseno from grades where mark IS NULL</p>
<p>　　c.注意区分在嵌套查询中使用的any与all的区别，any相当于逻辑运算&#8220;||&#8221;而all则相当于逻辑运算&#8220;&amp;&amp;&#8221;</p>
<p>　　d.注意在做否定意义的查询是小心进入陷阱：</p>
<p>　　如，没有选修&#8216;B2&#8217;课程的学生 ：</p>
<p>select students.*<br>from students, grades<br>where students.sno=grades.sno<br>AND grades.cno &lt;&gt; &#8217;B2&#8217; </p>
<p>　　上面的查询方式是错误的，正确方式见下方：</p>
<p>select * from students<br>where not exists (select * from grades <br>where grades.sno=students.sno AND cno='B2') </p>
<p>　　11.关于有难度多重嵌套查询的解决思想：</p>
<p>　　如，选修了全部课程的学生：</p>
<p>select *<br>from students<br>where not exists ( select *<br>from courses<br>where NOT EXISTS <br>(select *<br>from grades<br>where sno=students.sno<br>AND cno=courses.cno))</p>
<p>　　最外一重：从学生表中选，排除那些有课没选的。用not exist。由于讨论对象是课程，所以第二重查询从course表中找，排除那些选了课的即可。<br></p>
<img src ="http://www.blogjava.net/shichengjun1984/aggbug/119701.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/shichengjun1984/" target="_blank">I LOVE JAVA</a> 2007-05-24 13:22 <a href="http://www.blogjava.net/shichengjun1984/articles/119701.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>8.数据库菜鸟不可不看 简单SQL语句小结</title><link>http://www.blogjava.net/shichengjun1984/articles/119702.html</link><dc:creator>I LOVE JAVA</dc:creator><author>I LOVE JAVA</author><pubDate>Thu, 24 May 2007 05:22:00 GMT</pubDate><guid>http://www.blogjava.net/shichengjun1984/articles/119702.html</guid><wfw:comment>http://www.blogjava.net/shichengjun1984/comments/119702.html</wfw:comment><comments>http://www.blogjava.net/shichengjun1984/articles/119702.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/shichengjun1984/comments/commentRss/119702.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/shichengjun1984/services/trackbacks/119702.html</trackback:ping><description><![CDATA[a.用as关键字：select name as '姓名' from students order by age
<p>　　b.直接表示：select name '姓名' from students order by age</p>
<p>　　2.精确查找:</p>
<p>　　a.用in限定范围：select * from students where native in ('湖南', '四川') </p>
<p>　　b.between...and：select * from students where age between 20 and 30</p>
<p>　　c.&#8220;=&#8221;：select * from students where name = '李山' </p>
<p>　　d.like:select * from students where name like '李%' (注意查询条件中有&#8220;%&#8221;，则说明是部分匹配，而且还有先后信息在里面，即查找以&#8220;李&#8221;开头的匹配项。所以若查询有&#8220;李&#8221;的所有对象，应该命令：'%李%';若是第二个字为李，则应为'_李%'或'_李'或'_李_'。)</p>
<p>　　e.[]匹配检查符：select * from courses where cno like '[AC]%' (表示或的关系，与"in(...)"类似，而且"[]"可以表示范围，如：select * from courses where cno like '[A-C]%')</p>
<p>　　3.对于时间类型变量的处理</p>
<p>　　a.smalldatetime：直接按照字符串处理的方式进行处理，例如：<br>select * from students where birth &gt; = '1980-1-1' and birth &lt;= '1980-12-31' </p>
<p>　　4.集函数</p>
<p>　　a.count()求和，如：select count(*) from students (求学生总人数)</p>
<p>　　b.avg(列)求平均，如：select avg(mark) from grades where cno=&#8217;B2&#8217;</p>
<p>　　c.max(列)和min(列)，求最大与最小</p>
<p>　　5.分组group</p>
<p>　　常用于统计时，如分组查总数：<br>select gender,count(sno) <br>from students<br>group by gender<br>(查看男女学生各有多少)</p>
<p>　　注意：从哪种角度分组就从哪列"group by"</p>
<p>　　对于多重分组，只需将分组规则罗列。比如查询各届各专业的男女同学人数 ，那么分组规则有：届别(grade)、专业(mno)和性别(gender)，所以有"group by grade, mno, gender"</p>
<p>select grade, mno, gender, count(*)<br>from students<br>group by grade, mno, gender</p>
<p>　　通常group还和having联用，比如查询1门课以上不及格的学生，则按学号(sno)分类有：</p>
<p>select sno,count(*) from grades <br>where mark&lt;60<br>group by sno<br>having count(*)&gt;1 </p>
<p>　　6.UNION联合</p>
<p>　　合并查询结果，如：</p>
<p>SELECT * FROM students<br>WHERE name like &#8216;张%&#8217;<br>UNION [ALL]<br>SELECT * FROM students<br>WHERE name like &#8216;李%&#8217;</p>
<p>　　7.多表查询</p>
<p>　　a.内连接</p>
<p>select g.sno,s.name,c.coursename <br>from grades g JOIN students s ON g.sno=s.sno<br>JOIN courses c ON g.cno=c.cno<br>(注意可以引用别名)<br>b.外连接<br>b1.左连接<br>select courses.cno,max(coursename),count(sno) <br>from courses LEFT JOIN grades ON courses.cno=grades.cno <br>group by courses.cno</p>
<p>　　左连接特点：显示全部左边表中的所有项目，即使其中有些项中的数据未填写完全。</p>
<p>　　左外连接返回那些存在于左表而右表中却没有的行，再加上内连接的行。</p>
<p>　　b2.右连接</p>
<p>　　与左连接类似</p>
<p>　　b3.全连接</p>
<p>select sno,name,major <br>from students FULL JOIN majors ON students.mno=majors.mno</p>
<p>　　两边表中的内容全部显示</p>
<p>　　c.自身连接</p>
<p>select c1.cno,c1.coursename,c1.pno,c2.coursename <br>from courses c1,courses c2 where c1.pno=c2.cno</p>
<p>　　采用别名解决问题。</p>
<p>　　d.交叉连接</p>
<p>select lastname+firstname from lastname CROSS JOIN firstanme</p>
<p>　　相当于做笛卡儿积</p>
<p>　　8.嵌套查询</p>
<p>　　a.用关键字IN,如查询李山的同乡：</p>
<p>select * from students<br>where native in (select native from students where name=&#8217; 李山&#8217;) </p>
<p>　　b.使用关键字EXIST,比如，下面两句是等价的：</p>
<p>select * from students<br>where sno in (select sno from grades where cno=&#8217;B2&#8217;)</p>
<p>select * from students where exists <br>(select * from grades where <br>grades.sno=students.sno AND cno=&#8217;B2&#8217;)</p>
<p>　　9.关于排序order</p>
<p>　　a.对于排序order，有两种方法：asc升序和desc降序</p>
<p>　　b.对于排序order,可以按照查询条件中的某项排列，而且这项可用数字表示，如：</p>
<p>select sno,count(*) ,avg(mark) from grades <br>group by sno<br>having avg(mark)&gt;85<br>order by 3 </p>
<p>　　10.其他</p>
<p>　　a.对于有空格的识别名称，应该用"[]"括住。</p>
<p>　　b.对于某列中没有数据的特定查询可以用null判断，如select sno,courseno from grades where mark IS NULL</p>
<p>　　c.注意区分在嵌套查询中使用的any与all的区别，any相当于逻辑运算&#8220;||&#8221;而all则相当于逻辑运算&#8220;&amp;&amp;&#8221;</p>
<p>　　d.注意在做否定意义的查询是小心进入陷阱：</p>
<p>　　如，没有选修&#8216;B2&#8217;课程的学生 ：</p>
<p>select students.*<br>from students, grades<br>where students.sno=grades.sno<br>AND grades.cno &lt;&gt; &#8217;B2&#8217; </p>
<p>　　上面的查询方式是错误的，正确方式见下方：</p>
<p>select * from students<br>where not exists (select * from grades <br>where grades.sno=students.sno AND cno='B2') </p>
<p>　　11.关于有难度多重嵌套查询的解决思想：</p>
<p>　　如，选修了全部课程的学生：</p>
<p>select *<br>from students<br>where not exists ( select *<br>from courses<br>where NOT EXISTS <br>(select *<br>from grades<br>where sno=students.sno<br>AND cno=courses.cno))</p>
<p>　　最外一重：从学生表中选，排除那些有课没选的。用not exist。由于讨论对象是课程，所以第二重查询从course表中找，排除那些选了课的即可。<br></p>
<img src ="http://www.blogjava.net/shichengjun1984/aggbug/119702.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/shichengjun1984/" target="_blank">I LOVE JAVA</a> 2007-05-24 13:22 <a href="http://www.blogjava.net/shichengjun1984/articles/119702.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>10.浅谈数据库设计技巧(下)</title><link>http://www.blogjava.net/shichengjun1984/articles/119698.html</link><dc:creator>I LOVE JAVA</dc:creator><author>I LOVE JAVA</author><pubDate>Thu, 24 May 2007 05:15:00 GMT</pubDate><guid>http://www.blogjava.net/shichengjun1984/articles/119698.html</guid><wfw:comment>http://www.blogjava.net/shichengjun1984/comments/119698.html</wfw:comment><comments>http://www.blogjava.net/shichengjun1984/articles/119698.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/shichengjun1984/comments/commentRss/119698.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/shichengjun1984/services/trackbacks/119698.html</trackback:ping><description><![CDATA[三、多用户及其权限管理的设计<br>　　开发<a href="http://www.knowsky.com/sql.asp">数据库</a>管理类的软件，不可能不考虑多用户和用户权限设置的问题。尽管目前市面上的大、中型的后台数据库系统软件都提供了多用户，以及细至某个数据库内某张表的权限设置的功能，我个人建议：一套成熟的数据库管理软件，还是应该自行设计用户管理这块功能，原因有二：<br>　　1.那些大、中型后台数据库系统软件所提供的多用户及其权限设置都是针对数据库的共有属性，并不一定能完全满足某些特例的需求；<br>　　2.不要过多的依赖后台数据库系统软件的某些特殊功能，多种大、中型后台数据库系统软件之间并不完全兼容。否则一旦日后需要转换数据库平台或后台数据库系统软件版本升级，之前的架构设计很可能无法重用。
<p>　　下面看看如何自行设计一套比较灵活的多用户管理模块，即该数据库管理软件的系统管理员可以自行添加新用户，修改已有用户的权限，删除已有用户。首先，分析用户需求，列出该数据库管理软件所有需要实现的功能；然后，根据一定的联系对这些功能进行分类，即把某类用户需使用的功能归为一类；最后开始建表：<br>　　<br>功能表(Function_table)<br>名称　　　　　类型　　　　约束条件　　　说明<br>f_id&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp; 　&nbsp;&nbsp; 无重复　　&nbsp;&nbsp; 功能标识，主键<br>f_name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char(20)&nbsp;&nbsp;&nbsp; 不允许为空&nbsp;&nbsp; 功能名称，不允许重复<br>f_desc&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char(50)&nbsp;&nbsp;&nbsp; 允许为空&nbsp;&nbsp;&nbsp;&nbsp; 功能描述</p>
<p>用户组表(User_group)<br>名称　　　　　类型　　　　约束条件　　　说明<br>group_id&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 无重复&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 用户组标识，主键<br>group_name&nbsp;&nbsp;&nbsp; char(20)&nbsp;&nbsp;&nbsp; 不允许为空&nbsp;&nbsp;&nbsp; 用户组名称<br>group_power&nbsp;&nbsp; char(100)&nbsp;&nbsp; 不允许为空&nbsp;&nbsp;&nbsp; 用户组权限表，内容为功能表f_id的集合</p>
<p>用户表(User_table)<br>名称　　　　　类型　　　　约束条件　　　说明<br>user_id&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 无重复&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 用户标识，主键<br>user_name&nbsp;&nbsp;&nbsp;&nbsp; char(20)&nbsp;&nbsp;&nbsp; 无重复&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 用户名<br>user_pwd&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char(20)&nbsp;&nbsp;&nbsp; 不允许为空&nbsp;&nbsp;&nbsp; 用户密码<br>user_type&nbsp;&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 不允许为空&nbsp;&nbsp;&nbsp; 所属用户组标识，和User_group.group_id关联</p>
<p>　　采用这种用户组的架构设计，当需要添加新用户时，只需指定新用户所属的用户组；当以后系统需要添加新功能或对旧有功能权限进行修改时，只用操作功能表和用户组表的记录，原有用户的功能即可相应随之变化。当然，这种架构设计把数据库管理软件的功能判定移到了前台，使得前台开发相对复杂一些。但是，当用户数较大(10人以上)，或日后软件升级的概率较大时，这个代价是值得的。</p>
<p><br>　　四、简洁的批量m:n设计<br>　　碰到m:n的关系，一般都是建立3个表，m一个，n一个，m:n一个。但是，m:n有时会遇到批量处理的情况，例如到图书馆借书，一般都是允许用户同时借阅n本书，如果要求按批查询借阅记录，即列出某个用户某次借阅的所有书籍，该如何设计呢？让我们建好必须的3个表先：</p>
<p>书籍表(Book_table)<br>名称　　　　　类型　　　　约束条件　　　说明<br>book_id&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 无重复&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 书籍标识，主键<br>book_no&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char(20)&nbsp;&nbsp;&nbsp; 无重复&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 书籍编号<br>book_name&nbsp;&nbsp;&nbsp;&nbsp; char(100)&nbsp;&nbsp; 不允许为空&nbsp;&nbsp;&nbsp; 书籍名称<br>&#8230;&#8230;</p>
<p>借阅用户表(Renter_table)<br>名称　　　　　类型　　　　约束条件　　　说明<br>renter_id&nbsp;&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 无重复&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 用户标识，主键<br>renter_name&nbsp;&nbsp; char(20)&nbsp;&nbsp;&nbsp; 不允许为空&nbsp;&nbsp;&nbsp; 用户姓名<br>&#8230;&#8230;</p>
<p>借阅记录表(Rent_log)<br>名称　　　　　类型　　　　约束条件　　　说明<br>rent_id&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 无重复&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 借阅记录标识，主键<br>r_id&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 不允许为空&nbsp;&nbsp;&nbsp; 用户标识，和Renter_table.renter_id关联<br>b_id&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 不允许为空&nbsp;&nbsp;&nbsp; 书籍标识，和Book_table.book_id关联<br>rent_date&nbsp;&nbsp;&nbsp;&nbsp; datetime&nbsp;&nbsp;&nbsp; 不允许为空&nbsp;&nbsp;&nbsp; 借阅时间<br>&#8230;&#8230;</p>
<p>　　为了实现按批查询借阅记录，我们可以再建一个表来保存批量借阅的信息，例如：</p>
<p>批量借阅表(Batch_rent)<br>名称　　　　　类型　　　　约束条件　　　说明<br>batch_id&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 无重复&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 批量借阅标识，主键<br>batch_no&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 不允许为空&nbsp;&nbsp;&nbsp; 批量借阅编号，同一批借阅的batch_no相同<br>rent_id&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 不允许为空&nbsp;&nbsp;&nbsp; 借阅记录标识，和Rent_log.rent_id关联<br>batch_date&nbsp;&nbsp;&nbsp; datetime&nbsp;&nbsp;&nbsp; 不允许为空&nbsp;&nbsp;&nbsp; 批量借阅时间</p>
<p>　　这样的设计好吗？我们来看看为了列出某个用户某次借阅的所有书籍，需要如何查询？首先检索批量借阅表(Batch_rent)，把符合条件的的所有记录的rent_id字段的数据保存起来，再用这些数据作为查询条件带入到借阅记录表(Rent_log)中去查询。那么，有没有什么办法改进呢？下面给出一种简洁的批量设计方案，不需添加新表，只需修改一下借阅记录表(Rent_log)即可。修改后的记录表(Rent_log)如下：</p>
<p>借阅记录表(Rent_log)<br>名称　　　　　类型　　　　约束条件　　　说明<br>rent_id&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 无重复&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 借阅记录标识，主键<br>r_id&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 不允许为空&nbsp;&nbsp;&nbsp; 用户标识，和Renter_table.renter_id关联<br>b_id&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 不允许为空&nbsp;&nbsp;&nbsp; 书籍标识，和Book_table.book_id关联<br>batch_no&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 不允许为空&nbsp;&nbsp;&nbsp; 批量借阅编号，同一批借阅的batch_no相同<br>rent_date&nbsp;&nbsp;&nbsp;&nbsp; datetime&nbsp;&nbsp;&nbsp; 不允许为空&nbsp;&nbsp;&nbsp; 借阅时间<br>&#8230;&#8230;</p>
<p>　　其中，同一次借阅的batch_no和该批第一条入库的rent_id相同。举例：假设当前最大rent_id是64，接着某用户一次借阅了3本书，则批量插入的3条借阅记录的batch_no都是65。之后另外一个用户租了一套碟，再插入出租记录的rent_id是68。采用这种设计，查询批量借阅的信息时，只需使用一条标准T_SQL的嵌套查询即可。当然，这种设计不符合3NF，但是和上面标准的3NF设计比起来，哪一种更好呢？答案就不用我说了吧。</p>
<p><br>　　五、冗余数据的取舍<br>　　上篇的&#8220;树型关系的数据表&#8221;中保留了一个冗余字段，这里的例子更进一步——添加了一个冗余表。先看看例子：我原先所在的公司为了解决员工的工作餐，和附近的一家小餐馆联系，每天吃饭记账，费用按人数平摊，月底由公司现金结算，每个人每个月的工作餐费从工资中扣除。当然，每天吃饭的人员和人数都不是固定的，而且，由于每顿工作餐的所点的菜色不同，每顿的花费也不相同。例如，星期一中餐5人花费40元，晚餐2人花费20，星期二中餐6人花费36元，晚餐3人花费18元。为了方便计算每个人每个月的工作餐费，我写了一个简陋的就餐记账管理程序，数据库里有3个表：</p>
<p>员工表(Clerk_table)<br>名称　　　　　类型　　　　约束条件　　　说明<br>clerk_id&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 无重复&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 员工标识，主键<br>clerk_name&nbsp;&nbsp;&nbsp; char(10)&nbsp;&nbsp;&nbsp; 不允许为空&nbsp;&nbsp;&nbsp; 员工姓名</p>
<p>每餐总表(Eatdata1)<br>名称　　　　　类型　　　　约束条件　　　说明<br>totle_id&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 无重复&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 每餐总表标识，主键<br>persons&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char(100)&nbsp;&nbsp; 不允许为空&nbsp;&nbsp;&nbsp; 就餐员工的员工标识集合<br>eat_date&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; datetime&nbsp;&nbsp;&nbsp; 不允许为空&nbsp;&nbsp;&nbsp; 就餐日期<br>eat_type&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char(1)&nbsp;&nbsp;&nbsp;&nbsp; 不允许为空&nbsp;&nbsp;&nbsp; 就餐类型，用来区分中、晚餐<br>totle_price&nbsp;&nbsp; money&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 不允许为空&nbsp;&nbsp;&nbsp; 每餐总花费<br>persons_num&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 不允许为空&nbsp;&nbsp;&nbsp; 就餐人数</p>
<p>就餐计费细表(Eatdata2)<br>名称　　　　　类型　　　　约束条件　　　说明<br>id&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 无重复&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 就餐计费细表标识，主键<br>t_id&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 不允许为空&nbsp;&nbsp;&nbsp; 每餐总表标识，和Eatdata1.totle_id关联<br>c_id&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 不允许为空&nbsp;&nbsp;&nbsp; 员工标识标识，和Clerk_table.clerk_id关联<br>price&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; money&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 不允许为空&nbsp;&nbsp;&nbsp; 每人每餐花费</p>
<p>　　其中，就餐计费细表(Eatdata2)的记录就是把每餐总表(Eatdata1)的一条记录按就餐员工平摊拆开，是个不折不扣的冗余表。当然，也可以把每餐总表(Eatdata1)的部分字段合并到就餐计费细表(Eatdata2)中，这样每餐总表(Eatdata1)就成了冗余表，不过这样所设计出来的就餐计费细表重复数据更多，相比来说还是上面的方案好些。但是，就是就餐计费细表(Eatdata2)这个冗余表，在做每月每人餐费统计的时候，大大简化了编程的复杂度，只用类似这么一条查询语句即可统计出每人每月的寄餐次数和餐费总帐：</p>
<p>SELECT clerk_name AS personname,COUNT(c_id) as eattimes,SUM(price) AS ptprice FROM Eatdata2 JOIN Clerk_tabsle ON (c_id=clerk_id) JOIN eatdata1 ON (totleid=tid) WHERE eat_date&gt;=CONVERT(datetime,'"&amp;the_date&amp;"') AND eat_date&lt;DATEADD(month,1,CONVERT(datetime,'"&amp;the_date&amp;"')) GROUP BY c_id</p>
<p>　　想象一下，如果不用这个冗余表，每次统计每人每月的餐费总帐时会多麻烦，程序效率也够呛。那么，到底什么时候可以增加一定的冗余数据呢？我认为有2个原则：</p>
<p>　　１、用户的整体需求。当用户更多的关注于，对数据库的规范记录按一定的算法进行处理后，再列出的数据。如果该算法可以直接利用后台数据库系统的内嵌函数来完成，此时可以适当的增加冗余字段，甚至冗余表来保存这些经过算法处理后的数据。要知道，对于大批量数据的查询，修改或删除，后台数据库系统的效率远远高于我们自己编写的代码。<br>　　２、简化开发的复杂度。现代软件开发，实现同样的功能，方法有很多。尽管不必要求程序员精通绝大部分的开发工具和平台，但是还是需要了解哪种方法搭配哪种开发工具的程序更简洁，效率更高一些。冗余数据的本质就是用空间换时间，尤其是目前硬件的发展远远高于软件，所以适当的冗余是可以接受的。不过我还是在最后再强调一下：不要过多的依赖平台和开发工具的特性来简化开发，这个度要是没把握好的话，后期维护升级会栽大跟头的。</p>
<img src ="http://www.blogjava.net/shichengjun1984/aggbug/119698.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/shichengjun1984/" target="_blank">I LOVE JAVA</a> 2007-05-24 13:15 <a href="http://www.blogjava.net/shichengjun1984/articles/119698.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>9.浅谈数据库设计技巧(上)</title><link>http://www.blogjava.net/shichengjun1984/articles/119696.html</link><dc:creator>I LOVE JAVA</dc:creator><author>I LOVE JAVA</author><pubDate>Thu, 24 May 2007 05:08:00 GMT</pubDate><guid>http://www.blogjava.net/shichengjun1984/articles/119696.html</guid><wfw:comment>http://www.blogjava.net/shichengjun1984/comments/119696.html</wfw:comment><comments>http://www.blogjava.net/shichengjun1984/articles/119696.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/shichengjun1984/comments/commentRss/119696.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/shichengjun1984/services/trackbacks/119696.html</trackback:ping><description><![CDATA[说到<a href="http://www.knowsky.com/sql.asp">数据库</a>，我认为不能不先谈数据结构。1996年，在我初入大学学习计算机编程时，当时的老师就告诉我们说：计算机程序＝数据结构＋算法。尽管现在的程序开发已由面向过程为主逐步过渡到面向对象为主，但我还是深深赞同8年前老师的告诉我们的公式：计算机程序＝数据结构＋算法。面向对象的程序开发，要做的第一件事就是，先分析整个程序中需处理的数据，从中提取出抽象模板，以这个抽象模板设计类，再在其中逐步添加处理其数据的函数(即算法)，最后，再给类中的数据成员和函数划分访问权限，从而实现封装。
<p>　　数据库的最初雏形据说源自美国一个奶牛场的记账薄(纸质的，由此可见，数据库并不一定是存储在电脑里的数据^_^)，里面记录的是该奶牛场的收支账目，程序员在将其整理、录入到电脑中时从中受到启发。当按照规定好的数据结构所采集到的数据量大到一定程度后，出于程序执行效率的考虑，程序员将其中的检索、更新维护等功能分离出来，做成单独调用的模块，这个模块后来就慢慢发展、演变成现在我们所接触到的数据库管理系统(DBMS)——程序开发中的一个重要分支。</p>
<p>　　下面进入正题，首先按我个人所接触过的程序给数据库设计人员的功底分一下类：<br>　　１、没有系统学习过数据结构的程序员。这类程序员的作品往往只是他们的即兴玩具，他们往往习惯只设计有限的几个表，实现某类功能的数据全部塞在一个表中，各表之间几乎毫无关联。网上不少的免费管理软件都是这样的东西，当程序功能有限，数据量不多的时候，其程序运行起来没有什么问题，但是如果用其管理比较重要的数据，风险性非常大。<br>　　２、系统学习过数据结构，但是还没有开发过对程序效率要求比较高的管理软件的程序员。这类人多半刚从学校毕业不久，他们在设计数据库表结构时，严格按照教科书上的规定，死扣E-R图和3NF(别灰心，所有的数据库设计高手都是从这一步开始的)。他们的作品，对于一般的access型轻量级的管理软件，已经够用。但是一旦该系统需要添加新功能，原有的数据库表差不多得进行大换血。<br>　　３、第二类程序员，在经历过数次程序效率的提升，以及功能升级的折腾后，终于升级成为数据库设计的老鸟，第一类程序员眼中的高人。这类程序员可以胜任二十个表以上的中型商业数据管理系统的开发工作。他们知道该在什么样的情况下保留一定的冗余数据来提高程序效率，而且其设计的数据库可拓展性较好，当用户需要添加新功能时，原有数据库表只需做少量修改即可。<br>　　４、在经历过上十个类似数据库管理软件的重复设计后，第三类程序员中坚持下来没有转行，而是希望从中找出&#8220;偷懒&#8221;窍门的有心人会慢慢觉悟，从而完成量变到质变的转换。他们所设计的数据库表结构有一定的远见，能够预测到未来功能升级所需要的数据，从而预先留下伏笔。这类程序员目前大多晋级成数据挖掘方面的高级软件开发人员。<br>　　５、第三类程序员或第四类程序员，在对现有的各家数据库管理系统的原理和开发都有一定的钻研后，要么在其基础上进行二次开发，要么自行开发一套有自主版权的通用数据库管理系统。</p>
<p>　　我个人正处于第三类的末期，所以下面所列出的一些设计技巧只适合第二类和部分第三类数据库设计人员。同时，由于我很少碰到有兴趣在这方面深钻下去的同行，所以文中难免出现错误和遗漏，在此先行声明，欢迎大家指正，不要藏私哦8)</p>
<p>　　一、树型关系的数据表<br>　　不少程序员在进行数据库设计的时候都遇到过树型关系的数据，例如常见的类别表，即一个大类，下面有若干个子类，某些子类又有子类这样的情况。当类别不确定，用户希望可以在任意类别下添加新的子类，或者删除某个类别和其下的所有子类，而且预计以后其数量会逐步增长，此时我们就会考虑用一个数据表来保存这些数据。按照教科书上的教导，第二类程序员大概会设计出类似这样的数据表结构：</p>
<p>类别表_1(Type_table_1)<br>名称　　　　　类型　　　　约束条件　　　说明<br>type_id&nbsp;&nbsp; 　&nbsp; int&nbsp;&nbsp;&nbsp; 　&nbsp;&nbsp; 无重复　　&nbsp;&nbsp; 类别标识，主键<br>type_name　　 char(50)&nbsp;&nbsp;&nbsp; 不允许为空&nbsp;&nbsp; 类型名称，不允许重复<br>type_father&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 不允许为空&nbsp;&nbsp; 该类别的父类别标识，如果是顶节点的话设定为某个唯一值</p>
<p>　　这样的设计短小精悍，完全满足3NF，而且可以满足用户的所有要求。是不是这样就行呢？答案是NO！Why？</p>
<p>　　我们来估计一下用户希望如何罗列出这个表的数据的。对用户而言，他当然期望按他所设定的层次关系一次罗列出所有的类别，例如这样：<br>总类别<br>　　类别1<br>　　　　类别1.1<br>　　　　　　类别1.1.1<br>　　　　类别1.2<br>　　类别2<br>　　　　类别2.1<br>　　类别3<br>　　　　类别3.1<br>　　　　类别3.2<br>　　&#8230;&#8230;</p>
<p>　　看看为了实现这样的列表显示(树的先序遍历)，要对上面的表进行多少次检索？注意，尽管类别1.1.1可能是在类别3.2之后添加的记录，答案仍然是N次。这样的效率对于少量的数据没什么影响，但是日后类型扩充到数十条甚至上百条记录后，单单列一次类型就要检索数十次该表，整个程序的运行效率就不敢恭维了。或许第二类程序员会说，那我再建一个临时数组或临时表，专门保存类型表的先序遍历结果，这样只在第一次运行时检索数十次，再次罗列所有的类型关系时就直接读那个临时数组或临时表就行了。其实，用不着再去分配一块新的内存来保存这些数据，只要对数据表进行一定的扩充，再对添加类型的数量进行一下约束就行了，要完成上面的列表只需一次检索就行了。下面是扩充后的数据表结构：</p>
<p>类别表_2(Type_table_2)<br>名称　　　　　类型　　　　约束条件　　　&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 说明<br>type_id&nbsp;&nbsp; 　&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp; 　&nbsp; 无重复　　&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 类别标识，主键<br>type_name　　 char(50)&nbsp;&nbsp;&nbsp; 不允许为空&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 类型名称，不允许重复<br>type_father&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 不允许为空&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 该类别的父类别标识，如果是顶节点的话设定为某个唯一值<br>type_layer&nbsp;&nbsp;&nbsp; char(6)&nbsp;&nbsp;&nbsp;&nbsp; 限定3层,初始值为000000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 类别的先序遍历，主要为减少检索数据库的次数</p>
<p>　　按照这样的表结构，我们来看看上面例子记录在表中的数据是怎样的：</p>
<p>type_id&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; type_name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; type_father&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; type_layer<br>1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 总类别&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 000000<br>2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 类别1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 010000<br>3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 类别1.1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 010100<br>4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 类别1.2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 010200<br>5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 类别2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 020000<br>6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 类别2.1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 020100<br>7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 类别3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 030000<br>8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 类别3.1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 030100<br>9&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 类别3.2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 030200<br>10&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 类别1.1.1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 010101<br>&#8230;&#8230;</p>
<p>　　现在按type_layer的大小来检索一下：SELECT * FROM Type_table_2 ORDER BY type_layer</p>
<p>列出记录集如下：</p>
<p>type_id&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; type_name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; type_father&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; type_layer<br>1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 总类别&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 000000<br>2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 类别1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 010000<br>3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 类别1.1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 010100<br>10&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 类别1.1.1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 010101<br>4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 类别1.2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 010200<br>5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 类别2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 020000<br>6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 类别2.1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 020100<br>7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 类别3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 030000<br>8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 类别3.1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 030100<br>9&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 类别3.2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 030200<br>&#8230;&#8230;</p>
<p>　　现在列出的记录顺序正好是先序遍历的结果。在控制显示类别的层次时，只要对type_layer字段中的数值进行判断，每2位一组，如大于0则向右移2个空格。当然，我这个例子中设定的限制条件是最多3层，每层最多可设99个子类别，只要按用户的需求情况修改一下type_layer的长度和位数，即可更改限制层数和子类别数。其实，上面的设计不单单只在类别表中用到，网上某些可按树型列表显示的论坛程序大多采用类似的设计。</p>
<p>　　或许有人认为，Type_table_2中的type_father字段是冗余数据，可以除去。如果这样，在插入、删除某个类别的时候，就得对type_layer 的内容进行比较繁琐的判定，所以我并没有消去type_father字段，这也正符合数据库设计中适当保留冗余数据的来降低程序复杂度的原则，后面我会举一个故意增加数据冗余的案例。</p>
<p>　　<br>　　二、商品信息表的设计<br>　　假设你是一家百货公司电脑部的开发人员，某天老板要求你为公司开发一套网上电子商务平台，该百货公司有数千种商品出售，不过目前仅打算先在网上销售数十种方便运输的商品，当然，以后可能会陆续在该电子商务平台上增加新的商品出售。现在开始进行该平台数据库的商品信息表的设计。每种出售的商品都会有相同的属性，如商品编号，商品名称，商品所属类别，相关信息，供货厂商，内含件数，库存，进货价，销售价，优惠价。你很快就设计出4个表：商品类型表(Wares_type)，供货厂商表(Wares_provider)，商品信息表(Wares_info)：</p>
<p>商品类型表(Wares_type)<br>名称　　　　　类型　　　　约束条件　　　&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 说明<br>type_id&nbsp;&nbsp; 　&nbsp; int&nbsp;&nbsp;&nbsp; 　&nbsp;&nbsp; 无重复　　&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 类别标识，主键<br>type_name　　 char(50)&nbsp;&nbsp;&nbsp; 不允许为空&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 类型名称，不允许重复<br>type_father&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 不允许为空&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 该类别的父类别标识，如果是顶节点的话设定为某个唯一值<br>type_layer&nbsp;&nbsp;&nbsp; char(6)&nbsp;&nbsp;&nbsp;&nbsp; 限定3层,初始值为000000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 类别的先序遍历，主要为减少检索数据库的次数</p>
<p>供货厂商表(Wares_provider)<br>名称　　　　　类型　　　　约束条件　　　&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 说明<br>provider_id&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp; 　&nbsp;&nbsp; 无重复　　&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 供货商标识，主键<br>provider_name char(100)&nbsp;&nbsp; 不允许为空&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 供货商名称</p>
<p>商品信息表(Wares_info)<br>名称　　　　&nbsp; 类型　　　　约束条件　　　&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 说明<br>wares_id&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp; 　&nbsp; 无重复　　&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 商品标识，主键<br>wares_name&nbsp;&nbsp;&nbsp;&nbsp; char(100)&nbsp; 不允许为空&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 商品名称<br>wares_type　　 int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 不允许为空　　　　　　　　　　 商品类型标识，和Wares_type.type_id关联<br>wares_info&nbsp;&nbsp;&nbsp;&nbsp; char(200)&nbsp; 允许为空&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 相关信息<br>provider&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 不允许为空&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 供货厂商标识，和Wares_provider.provider_id关联<br>setnum&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 初始值为1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 内含件数，默认为1<br>stock&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 初始值为0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 库存，默认为0<br>buy_price&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; money&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 不允许为空&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 进货价<br>sell_price&nbsp;&nbsp;&nbsp;&nbsp; money&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 不允许为空&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 销售价<br>discount&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; money&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 不允许为空&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 优惠价</p>
<p>　　你拿着这3个表给老板检查，老板希望能够再添加一个商品图片的字段，不过只有一部分商品有图片。OK，你在商品信息表(Wares_info)中增加了一个haspic的BOOL型字段，然后再建了一个新表——商品图片表(Wares_pic)：</p>
<p>商品图片表(Wares_pic)<br>名称　　　　&nbsp; 类型　　　　约束条件　　　&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 说明<br>pic_id&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp; 　&nbsp;&nbsp; 无重复　　&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 商品图片标识，主键<br>wares_id&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 不允许为空&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 所属商品标识，和Wares_info.wares_id关联<br>pic_address　 char(200)&nbsp;&nbsp; 不允许为空　　　　　　　　　　 图片存放路径</p>
<p>　　程序开发完成后，完全满足老板目前的要求，于是正式启用。一段时间后，老板打算在这套平台上推出新的商品销售，其中，某类商品全部都需添加&#8220;长度&#8221;的属性。第一轮折腾来了&#8230;&#8230;当然，你按照添加商品图片表的老方法，在商品信息表(Wares_info)中增加了一个haslength的BOOL型字段，又建了一个新表——商品长度表(Wares_length)：</p>
<p>商品长度表(Wares_length)<br>名称　　　　&nbsp; 类型　　　　约束条件　　　&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 说明<br>length_id&nbsp;&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp; 　&nbsp;&nbsp; 无重复　　&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 商品图片标识，主键<br>wares_id&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 不允许为空&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 所属商品标识，和Wares_info.wares_id关联<br>length　&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char(20)&nbsp;&nbsp;&nbsp; 不允许为空　　　　　　　　　　 商品长度说明</p>
<p>　　刚刚改完没多久，老板又打算上一批新的商品，这次某类商品全部需要添加&#8220;宽度&#8221;的属性。你咬了咬牙，又照方抓药，添加了商品宽度表(Wares_width)。又过了一段时间，老板新上的商品中有一些需要添加&#8220;高度&#8221;的属性，你是不是开始觉得你所设计的数据库按照这种方式增长下去，很快就能变成一个迷宫呢？那么，有没有什么办法遏制这种不可预见性，但却类似重复的数据库膨胀呢？我在阅读《敏捷软件开发：原则、模式与实践》中发现作者举过类似的例子：7.3　&#8220;Copy&#8221;程序。其中，我非常赞同敏捷软件开发这个观点：在最初几乎不进行预先设计，但是一旦需求发生变化，此时作为一名追求卓越的程序员，应该从头审查整个架构设计，在此次修改中设计出能够满足日后类似修改的系统架构。下面是我在需要添加&#8220;长度&#8221;的属性时所提供的修改方案：</p>
<p>　　去掉商品信息表(Wares_info)中的haspic字段，添加商品额外属性表(Wares_ex_property)和商品额外信息表(Wares_ex_info)2个表来完成添加新属性的功能。</p>
<p>商品额外属性表(Wares_ex_property)<br>名称　　　　&nbsp; 类型　　　　约束条件　　　&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 说明<br>ex_pid&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp; 　&nbsp;&nbsp; 无重复　　&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 商品额外属性标识，主键<br>p_name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char(20)&nbsp;&nbsp;&nbsp; 不允许为空&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 额外属性名称</p>
<p>商品额外信息表(Wares_ex_info)<br>名称　　　　&nbsp;&nbsp;&nbsp; 类型　　　　约束条件　　　&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 说明<br>ex_iid&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp; 　&nbsp;&nbsp; 无重复　　&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 商品额外信息标识，主键<br>wares_id&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 不允许为空&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 所属商品标识，和Wares_info.wares_id关联<br>property_id　&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 不允许为空　　　　　　　　　　 商品额外属性标识，和Wares_ex_property.ex_pid关联<br>property_value&nbsp; char(200)&nbsp;&nbsp; 不允许为空&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 商品额外属性值</p>
<p>　　在商品额外属性表(Wares_ex_property)中添加2条记录：<br>ex_pid&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p_name<br>1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 商品图片<br>2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 商品长度</p>
<p>　　再在整个电子商务平台的后台管理功能中追加一项商品额外属性管理的功能，以后添加新的商品时出现新的属性，只需利用该功能往商品额外属性表(Wares_ex_property)中添加一条记录即可。不要害怕变化，被第一颗子弹击中并不是坏事，坏的是被相同轨道飞来的第二颗、第三颗子弹击中。第一颗子弹来得越早，所受的伤越重，之后的抵抗力也越强8)(待续)</p>
<img src ="http://www.blogjava.net/shichengjun1984/aggbug/119696.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/shichengjun1984/" target="_blank">I LOVE JAVA</a> 2007-05-24 13:08 <a href="http://www.blogjava.net/shichengjun1984/articles/119696.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>7.Oracle PL/SQL入门之案例实践</title><link>http://www.blogjava.net/shichengjun1984/articles/119639.html</link><dc:creator>I LOVE JAVA</dc:creator><author>I LOVE JAVA</author><pubDate>Thu, 24 May 2007 03:18:00 GMT</pubDate><guid>http://www.blogjava.net/shichengjun1984/articles/119639.html</guid><wfw:comment>http://www.blogjava.net/shichengjun1984/comments/119639.html</wfw:comment><comments>http://www.blogjava.net/shichengjun1984/articles/119639.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/shichengjun1984/comments/commentRss/119639.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/shichengjun1984/services/trackbacks/119639.html</trackback:ping><description><![CDATA[某<a href="http://www.knowsky.com/sql.asp">数据库</a>有两张表，是关于某公司员工资料、薪水和部门信息的，它们分别是emp表和dept表，两张表的结构如下：
<p>　　要求如下：</p>
<p>　　1、按照上表结构建立相应的表，并每张表写入5组合法数据。</p>
<p>　　2、操纵相关表，使得&#8220;技术部&#8221;的员工的薪水上涨20%。</p>
<p>　　3、建立日志，追踪薪水变动情况。</p>
<p>　　4、建立测试包。</p>
<p>　　二． 案例的分析与实现</p>
<p>　　从前面案例的介绍不难看出，要求1考察点为基本SQL语句；要求2主要考察复合查询；要求3是考察触发器的应用；要求4的考察面相对多一些，不仅考察了包的创建，而且也考察了在PL/SQL中的测试方法。了解了这些考察的知识点，就可以一一去解决。</p>
<p>　　要求1：</p>
<p>　　首先根据前面表的结构可以创建两张表：</p>
<p>　　——创建员工表</p>
<p>create table emp (emp_id number(5), emp_name varchar2(20), emp_salary number(4)); </p>
<p>　　——部门表</p>
<p>create table dept (dept_id number(3), dept_name varchar2(20), emp_id number(5)); </p>
<p>　　建立了表之后就可以往表里面写数据了，这里把添加表记录的代码写入到相应的存储过程。</p>
<p>/*给emp表添加记录的存储过程*/<br>create or replace procedure ins_table_emp(p_emp_id number,p_emp_name varchar2,p_emp_salary number) as<br>v_emp_id number:=p_emp_id;<br>v_emp_name varchar2(20):=p_emp_name;<br>v_emp_salary number:=p_emp_salary;<br>begin<br>　insert into emp values (v_emp_id,v_emp_name,v_emp_salary);<br>end ins_table_emp;</p>
<p>/*给dept表添加记录的存储过程*/<br>create or replace procedure ins_table_dept(p_dept_id number,p_dept_name varchar2,p_emp_id number) as<br>　v_dept_id number:=p_dept_id;<br>　v_dept_name varchar2(20):=p_dept_name;<br>　v_emp_id number:=p_emp_id;<br>begin<br>　insert into dept values (v_dept_id,v_dept_name,v_emp_id);<br>end ins_table_emp;</p>
<p>/*调用相应的存储过程实现记录添加*/<br>begin<br>　ins_table_emp(10000,'',4000);<br>　ins_table_emp(10001,'??&#232;y',2300);<br>　ins_table_emp(10002,'3?t',3500);<br>　ins_table_emp(10003,'&#224;???',3500);<br>　ins_table_emp(10004,'&#225;?&#242;?',3500);</p>
<p>　ins_table_dept(111,'DD?t2?',10000);<br>　ins_table_dept(111,'DD?t2?',10001);<br>　ins_table_dept(111,'DD?t2?',10002);<br>　ins_table_dept(112,'??&#234;?2?',10003);<br>　ins_table_dept(113,'&#234;D3?2?',10004);<br>end; </p>
<p>　　要求2：</p>
<p>　　给指定部门的员工加薪，这实际上是一个复合查询，首先需要把所有该部门的员工塞选出来，然后对这些员工的薪水进行相应的改动。依照这一思路，代码如下：</p>
<p>　　（需要注意的是：将要加薪的部门作为参数，这样的存储过程更有灵活性。）</p>
<p>create or replace procedure add_salary(p_dept_name varchar2) as<br>v_dept_name varchar2(20):=p_dept_name;<br>begin<br>　update emp set emp.EMP_SALARY=emp.EMP_SALARY*1.2 where emp.EMP_ID in (select emp.EMP_ID from emp,dept where emp.EMP_ID=dept.EMP_ID and dept.DEPT_ID='??&#234;?2?'); <br>end add_salary; </p>
<p>　　要求3：</p>
<p>　　建立日志对薪水的变动情况形成一个追踪，也就是说，如果对某个职员的薪水进行变更就应该将其相应的变更记录全部记下来。如果对emp表的salary字段创建一个触发器，来监视对salary的更改，把每次更改进行记录，这样就达到了要求3的目的了。</p>
<p>create or replace trigger print_salary_change 　<br>before delete or insert or update on emp　　--触发事件<br>for each row　　　　　　　　　　　　　　　　　　-- 每修改一行都需要调用此过程</p>
<p>declare 　　　　　　　　　　--只有触发器的声明需要declare，过程和函数都不需要<br>salary_balance number;<br>begin<br>--:new 与:old分别代表该行在修改前和修改后的记录<br>salary_balance=:new.salary=:old.salary;<br>dbms_output.PUT_LINE('old salary is: '|| :old.salary);<br>dbms_output.PUT_LINE('old salary is: '|| :new.salary);<br>dbms_output.PUT_LINE('old salary is: '|| to_char(salary_balance));<br>end print_salary_change; </p>
<p>　　要求4：</p>
<p>　　与其他语言（c/c++等）相比，PL/SQL的测试有其不同之处，归纳下来有三种方法：</p>
<p>　　1、使用DBMS_OUTPUT包的PUT_LINE方法来显示中间变量，以此来观察程序是否存在逻辑错误。</p>
<p>　　2、插入测试表的方法。即创建一个临时的中间表，然后把所有涉及到的中间变量的结果都作为记录插入到中间表中，这样可以查询表中的结果来观察程序的执行情况。</p>
<p>　　3、使用异常处理手段，对可疑的程序段使用begin &#8230; end ，然后可以在exception里进行异常捕获处理。</p>
<p>　　这里准备使用第二种方法来建立一个测试包，PL/SQL里包的概念类似于面向对象里的类的概念，包将一组操作和属性封装在一起，不仅增强了程序的模块化，而且由于封装了更多的操作和属性而提高了执行效能。建立一个PL/SQL需要两个步骤：首先要建立包头，类似于建立一个类的头文件，里面主要对包中的过程，函数和变量的声明；第二部分主要是包体部分，实现前面声明的过程和函数，另外还需要对包进行初始化等工作。</p>
<p>　　根据这一思路，建立测试包如下：</p>
<p>/*包头部分*/<br>create or replace package debug as <br>procedure debug(v_description varchar2,v_valueOfvariable varchar2)<br>　procedure reset;<br>　v_numberOfLine number;<br>end debug;<br>/*包体部分*/<br>create or replace package body debug as <br>procedure debug(v_description varchar2,v_valueOfvariable varchar2) is <br>begin<br>　insert into debugtable <br>　values(v_numberOfLine,v_description,v_valueOfvariable);<br>　v_numberOfLine:=v_numberOfLine+1;<br>end debug;<br>procedure reset is <br>begin <br>　v_numberOfLine:=1;<br>　delete from debugtable;<br>end reset;<br>/*初始化部分*/<br>begin <br>　reset;<br>end debug; </p>
<img src ="http://www.blogjava.net/shichengjun1984/aggbug/119639.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/shichengjun1984/" target="_blank">I LOVE JAVA</a> 2007-05-24 11:18 <a href="http://www.blogjava.net/shichengjun1984/articles/119639.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>5.新手入门 Windows下Oracle安装图解</title><link>http://www.blogjava.net/shichengjun1984/articles/119636.html</link><dc:creator>I LOVE JAVA</dc:creator><author>I LOVE JAVA</author><pubDate>Thu, 24 May 2007 03:16:00 GMT</pubDate><guid>http://www.blogjava.net/shichengjun1984/articles/119636.html</guid><wfw:comment>http://www.blogjava.net/shichengjun1984/comments/119636.html</wfw:comment><comments>http://www.blogjava.net/shichengjun1984/articles/119636.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/shichengjun1984/comments/commentRss/119636.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/shichengjun1984/services/trackbacks/119636.html</trackback:ping><description><![CDATA[安装要求：
<p>&nbsp;&nbsp;&nbsp; 硬件要求：</p>
<p>&nbsp;&nbsp;&nbsp; Intel奔腾处理器；<br>&nbsp;&nbsp;&nbsp; 最少128 MB 内存（推荐256 MB ）；</p>
<p>&nbsp;&nbsp;&nbsp; 交换空间：</p>
<p>&nbsp;&nbsp;&nbsp; 对于大多数系统，推荐两倍于内存数量或至少400MB；</p>
<p>&nbsp;&nbsp;&nbsp; 典型安装： </p>
<p>&nbsp;&nbsp;&nbsp; 750 MB</p>
<p>&nbsp;&nbsp;&nbsp; 最小安装：</p>
<p>&nbsp;&nbsp;&nbsp; 675 MB </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 最大安装：</p>
<p>&nbsp;&nbsp;&nbsp; 1000MB</p>
<p>&nbsp;&nbsp;&nbsp; 软件要求：</p>
<p>&nbsp;&nbsp;&nbsp; <a href="http://www.knowsky.com/article.asp?typeid=60"><u><font color=#0000ff>Linux</font></u></a>内核版本2.2或更高；<br>&nbsp;&nbsp;&nbsp; windows NT 4.0以上<a href="http://www.knowsky.com/system.asp"><u><font color=#0000ff>操作系统</font></u></a></p>
<p>&nbsp;&nbsp;&nbsp; Oracle下载：<a href="http://www.oracle.com/"><u><font color=#0000ff>WWW.ORACLE.COM</font></u></a> 上面有，不过要事先注册一个免费用户。下载到的安装文件为oracle816nt.zip（大小441MB）。<br></p>
<p>&nbsp;&nbsp;&nbsp; <strong><font color=#008080>安装过程：</font></strong></p>
<p>&nbsp;&nbsp;&nbsp; 将下载到的安装文件解压，双击setup.exe开始出现安装界面。</p>
<p>
<table align=center>
    <tbody>
        <tr>
            <td><img src="http://www.dhwy88.cn/Article/UploadFiles/200702/200727141046290.jpg" border=1></td>
        </tr>
        <tr>
            <td align=middle>安装初始界面（点击看大图）</td>
        </tr>
    </tbody>
</table>
</p>
<p>&nbsp;&nbsp;&nbsp; 1、接着进入安装向导，如果已安装有Oracle，可以在这一步进行卸载</p>
<p>
<table align=center>
    <tbody>
        <tr>
            <td><img src="http://www.dhwy88.cn/Article/UploadFiles/200702/200727141046713.jpg" border=1></td>
        </tr>
        <tr>
            <td align=middle>安装向导（点击看大图）</td>
        </tr>
    </tbody>
</table>
</p>
<p>&nbsp;&nbsp;&nbsp; 2、在下图的向导界面中点击&#8220;已安装产品&#8230;&#8221;,可以查阅本机是否已安装Oracle其它版本，以免造成冲突</p>
<p>
<table align=center>
    <tbody>
        <tr>
            <td><img src="http://www.dhwy88.cn/Article/UploadFiles/200702/200727141046594.jpg" border=1></td>
        </tr>
        <tr>
            <td align=middle>版本查阅（点击看大图）</td>
        </tr>
    </tbody>
</table>
</p>
<p>&nbsp;&nbsp;&nbsp; 3、如显示未安装任何相同版本，则可以放心安装，在图上中点击&#8220;关闭&#8221;，再按&#8220;下一步&#8221;，进入如下图所示的界面，在这一步里是确定安装文件所在路径即安装到本机硬盘所在路径，选择完成后点&#8220;下一步&#8221;。</p>
<p>
<table align=center>
    <tbody>
        <tr>
            <td><img src="http://www.dhwy88.cn/Article/UploadFiles/200702/200727141046420.jpg" border=1></td>
        </tr>
        <tr>
            <td align=middle>确认安装路径（点击看大图）</td>
        </tr>
    </tbody>
</table>
</p>
<p>&nbsp;&nbsp;&nbsp; 4、接着安装程序开始加载必要的安装信息</p>
<p>
<table align=center>
    <tbody>
        <tr>
            <td><img src="http://www.dhwy88.cn/Article/UploadFiles/200702/200727141046778.jpg" border=1></td>
        </tr>
    </tbody>
</table>
</p>
<p>&nbsp;&nbsp;&nbsp; 5、接着出现安装选项。&#8220;Oracle 8i Enterprise Edition 8.1.6.0.0&#8221;为数据库主程序，包括管理工具、实用程序和基本的客户机软件等，默认首先安装；第二项为客户端管理工具；第三项为服务器端管理工具。按其默认选项点击&#8220;下一步&#8221;</p>
<p>
<table align=center>
    <tbody>
        <tr>
            <td><img src="http://www.dhwy88.cn/Article/UploadFiles/200702/200727141046730.jpg" border=1></td>
        </tr>
        <tr>
            <td align=middle>组件安装选项（点击看大图）</td>
        </tr>
    </tbody>
</table>
</p>
<p>&nbsp;&nbsp;&nbsp; 6、接着是安装类型的选择。一般按其默认，就选&#8220;典型&#8221;吧。</p>
<p>
<table align=center>
    <tbody>
        <tr>
            <td><img src="http://www.dhwy88.cn/Article/UploadFiles/200702/200727141046662.jpg" border=1></td>
        </tr>
        <tr>
            <td align=middle>安装类型（点击看大图）</td>
        </tr>
    </tbody>
</table>
</p>
<p>&nbsp;&nbsp;&nbsp; 7、命名数据库。全局数据库名：指唯一在你的网络域中区别于其他数据库的完整数据库名，例如：sales.acme.com其中sales是你想要调用的数据库名，而acme.com是数据库所在的网络域。而系统标识符(SID)，是指唯一在你的网络域中区别于其他数据库的数据库实例名。SID域缺省为全局数据库名的数据库部分(上例的sales)( 最长8个字符或输入一个.)。你可以接受或改变缺省值。输入完成后点&#8220;下一步&#8221;，安装程序开始处理数据库标识。</p>
<p>
<table align=center>
    <tbody>
        <tr>
            <td><img src="http://www.dhwy88.cn/Article/UploadFiles/200702/200727141047610.jpg" border=1></td>
        </tr>
        <tr>
            <td align=middle>命名数据库（点击看大图）</td>
        </tr>
    </tbody>
</table>
</p>
<p>&nbsp;&nbsp;&nbsp; 8、接着出现的是对要安装的Oracle版本的一个全局认识，包括前面所做安装选择等。到这里，才表示将准备正式向本机安装程序。</p>
<p>
<table align=center>
    <tbody>
        <tr>
            <td><img src="http://www.dhwy88.cn/Article/UploadFiles/200702/200727141047782.jpg" border=1></td>
        </tr>
        <tr>
            <td align=middle>安装摘要（点击看大图）</td>
        </tr>
    </tbody>
</table>
</p>
<p>&nbsp;&nbsp;&nbsp; 9、首先安装的是教学帮助：</p>
<p>
<table align=center>
    <tbody>
        <tr>
            <td><img src="http://www.dhwy88.cn/Article/UploadFiles/200702/200727141047720.jpg" border=1></td>
        </tr>
        <tr>
            <td align=middle>速成教学安装步骤（点击看大图）</td>
        </tr>
    </tbody>
</table>
</p>
<p>&nbsp;&nbsp;&nbsp; 10、接着是选择工具配置，同样按其默认即可。</p>
<p>
<table align=center>
    <tbody>
        <tr>
            <td><img src="http://www.dhwy88.cn/Article/UploadFiles/200702/200727141047455.jpg" border=1></td>
        </tr>
        <tr>
            <td align=middle>配置工具（点击看大图）</td>
        </tr>
    </tbody>
</table>
</p>
<p>&nbsp;&nbsp;&nbsp; 11、一切准备妥当之后，开始创建数据库及初始化。</p>
<p>
<table align=center>
    <tbody>
        <tr>
            <td><img src="http://www.dhwy88.cn/Article/UploadFiles/200702/200727141048625.jpg" border=1></td>
        </tr>
        <tr>
            <td align=middle>创建数据库（点击看大图）</td>
        </tr>
    </tbody>
</table>
</p>
<p>&nbsp;&nbsp;&nbsp; 12、经过几分钟，当弹出下面的安装提示时，表示数据库创建完成，并显示出相关信息。</p>
<p>
<table align=center>
    <tbody>
        <tr>
            <td><img src="http://www.dhwy88.cn/Article/UploadFiles/200702/200727141048833.jpg" border=1></td>
        </tr>
        <tr>
            <td align=middle>安装完成信息（点击看大图）</td>
        </tr>
    </tbody>
</table>
</p>
<p>&nbsp;&nbsp;&nbsp; 13、在&#8220;开始&#8221;-&#8220;程序&#8221;里找到Oracle程序条，即可选择相应的程序登录数据库啦。至此，整个安装过程全部结束。</p>
<p>
<table align=center>
    <tbody>
        <tr>
            <td><img src="http://www.dhwy88.cn/Article/UploadFiles/200702/200727141048544.jpg" border=1></td>
        </tr>
        <tr>
            <td align=middle>安装完成（点击看大图）</td>
        </tr>
    </tbody>
</table>
</p>
<p>&nbsp;&nbsp;&nbsp; <font color=#008080><strong>补充：Oracle的卸载</strong></font></p>
<p><strong><font color=#008080>&nbsp;&nbsp;&nbsp; </font></strong>同样以<a href="http://www.knowsky.com/article.asp?typeid=59"><u><font color=#0000ff>Windows 2000</font></u></a>为例。</p>
<p>
<table align=center>
    <tbody>
        <tr>
            <td><img src="http://www.dhwy88.cn/Article/UploadFiles/200702/200727141048102.jpg" border=1></td>
        </tr>
        <tr>
            <td align=middle>Oracle的卸载（点击看大图）</td>
        </tr>
    </tbody>
</table>
</p>
<p>&nbsp;&nbsp;&nbsp; (1)、开始－＞设置－＞控制面板－＞管理工具－＞服务&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 停止所有Oracle服务。</p>
<p>&nbsp;&nbsp;&nbsp; (2)、开始－＞程序－＞Oracle - OraHome81－＞Oracle Installation Products－＞Universal Installer 卸装所有Oracle产品</p>
<p>&nbsp;&nbsp;&nbsp; (3)、运行regedit，选择HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE，按del键删除这个入口。</p>
<p>&nbsp;&nbsp;&nbsp; (4)、运行regedit，选择HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services，滚动这个列表，删除所有Oracle入口。</p>
<p>&nbsp;&nbsp;&nbsp; (5)、从桌面上、STARTUP（启动）组、程序菜单中，删除所有有关Oracle的组和图标</p>
<p>&nbsp;&nbsp;&nbsp; (6)、重新启动计算机，重起后才能完全删除Oracle所在目录</p>
<p>&nbsp;&nbsp;&nbsp; (7)、删除与Oracle有关的文件，选择Oracle所在的缺省目录C:\Oracle，删除这个入口目录及所有子目录，并从Windows 2000目录（一般为C:\WINNT）下删除以下文件：ORACLE.INI、oradim80.INI</p>
<img src ="http://www.blogjava.net/shichengjun1984/aggbug/119636.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/shichengjun1984/" target="_blank">I LOVE JAVA</a> 2007-05-24 11:16 <a href="http://www.blogjava.net/shichengjun1984/articles/119636.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>4.SQL数据查询语言</title><link>http://www.blogjava.net/shichengjun1984/articles/119626.html</link><dc:creator>I LOVE JAVA</dc:creator><author>I LOVE JAVA</author><pubDate>Thu, 24 May 2007 03:08:00 GMT</pubDate><guid>http://www.blogjava.net/shichengjun1984/articles/119626.html</guid><wfw:comment>http://www.blogjava.net/shichengjun1984/comments/119626.html</wfw:comment><comments>http://www.blogjava.net/shichengjun1984/articles/119626.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/shichengjun1984/comments/commentRss/119626.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/shichengjun1984/services/trackbacks/119626.html</trackback:ping><description><![CDATA[<font face=宋体 size=2>=============================================================<br>SELECT 基本语法结构<br>=============================================================<br>SELECT[predicate]{*|table.*|[table.]]field [,[table.]field2[,...]}<br>[AS alias1 [,alias2[,...]]]<br>[INTO new_table_name]<br>FROM tableexpression [, ...]<br>[WHERE...]<br>[GROUP BY...]<br>[ORDER BY...][ASC | DESC] ]</font>
<p><br><font face=宋体 color=#000000 size=2>predicate--&gt;指定返回记录(行)的数量,可选:ALL,TOP<br>* ---------&gt;指定表中所有字段(列).<br>table -----&gt;指定表的名称.<br>field -----&gt;指定表中字段(列)的名称<br>[AS alias] -替代表中实际字段(列)名称的化名.<br>[INTO new_table_name]--&gt;创建新表及名称.<br>tableexpression----&gt;表的名称.<br>[GROUP BY...]表示以该字段的值分组<br>[ORDER BY...]表示按升序排列,降序选 DESC;</font></p>
<p><font face=宋体 color=#000000 size=2>------------------------------------------------------------<br>1 选择列<br>------------------------------------------------------------<br>sql语句在access中的输入方法<br>(1)选择"查询"--&gt;新建--&gt;默认设计视图--&gt;点击确定<br>(2)关闭"显示表对话框" <br>(3)在菜单拦选择"视图"---&gt;SQL视图 ,就可以输入SQL语句了</font></p>
<br><br><font face=宋体 color=#000000 size=2>示例1_1_选择所有字段<br>SELECT *<br>FROM useres; </font>
<p><font face=宋体 color=#000000 size=2>示例1_2_选择部分字段</font></p>
<p><font face=宋体 color=#000000 size=2>SELECT user_name,real_name,submit_date<br>FROM useres;<br></font></p>
<p><font face=宋体 color=#000000 size=2>示例1_3查询两个表中的字段</font></p>
<p><font face=宋体 color=#000000 size=2>SELECT 图书信息表.图书条码, 借书信息表.图书条码<br>FROM 图书信息表, 借书信息表;</font></p>
<p><font face=宋体 color=#000000 size=2></font>&nbsp;</p>
<p><font face=宋体 color=#000000 size=2>示例解读:<br>通过上面简单示例我们体会到<br>(1) SELECT 子句选择列表,它指出查询结果集所包含的字段(列)及其属性,选择所有列时用通配府*,选择部分列时要用逗号隔开<br>(2) FROM 子句指出查询的表名,要指定多个表时中间用逗号隔开<br></font></p>
<p><font face=宋体 color=#000000 size=2>------------------------------------------------------------<br>2 TOP指定返回记录数量<br>------------------------------------------------------------<br>示例1_4_返回记录数量<br>SELECT TOP 3 *<br>FROM useres;<br></font></p>
<p><font face=宋体 color=#000000 size=2>-------------------------------------------------------------<br>3 AS派生新字段<br>-------------------------------------------------------------<br>示例1_5_派生新字段<br>SELECT user_name,(submit_date+30) AS new_date<br>FROM useres;<br></font></p>
<p><font face=宋体 color=#000000 size=2>------------------------------------------------------------<br>4 WHERE指定条件进行筛选 <br>------------------------------------------------------------<br>示例1_6等号查找指定记录<br>SELECT *<br>FROM useres<br>WHERE useres.real_name="红红";<br></font></p>
<p><font face=宋体 color=#000000 size=2>示例1_7年龄大于30的人<br>SELECT * <br>FROM useres<br>WHERE age&gt;30</font></p>
<p><font face=宋体 color=#000000 size=2>从上面可以看出,在根据条件进行筛选时,要用到运算符,常见的运算符如下所示:</font></p>
<p><font face=宋体 color=#000000 size=2>1 比较运算符<br>= 等于<br>&lt;&gt; 不等于<br>&gt; 大于<br>&lt; 小于<br>&lt;= 小于等于<br>&gt;= 大于等于</font></p>
<p><font face=宋体 color=#000000 size=2>2 逻辑运算符<br>ALL 所有条件都为true则返回true<br>AND 两个条件都为true则返回true <br>OR 有一个条件为true则返回true <br>NOT 对值取反<br>ANY 所有条件中只要有一个为true则返回true <br>BETWEEN 只要操作数在指定的范围内,则返回true<br>IN 只要操作数等于表达式中的一个,则返回true<br>LIKE 如果操作数与模式相匹配,则返回true<br>SOME 在一系列的比较中,有些为true则返回true</font></p>
<p><font face=宋体 color=#000000 size=2>示例1_8_某日以前注册用户<br>SELECT * <br>FROM useres<br>WHERE submit_date&lt;#2004-12-30#</font></p>
<p><font face=宋体 color=#000000 size=2>示例1_9_某时间段注册用户<br>SELECT * <br>FROM useres<br>WHERE submit_date BETWEEN #2004-1-1# AND #2005-5-1#</font></p>
<p><font face=宋体 color=#000000 size=2>示例1_10_按关键字查找<br>SELECT * <br>FROM useres<br>WHERE useres.real_name LIKE "*李*"</font></p>
<p><font face=宋体 color=#000000 size=2>------------------<br>IN与OR的区别<br>-----------------<br>示例_IN筛选字段中的记录</font></p>
<p><font face=宋体 color=#000000 size=2>SELECT real_name,submit_date<br>FROM useres<br>WHERE real_name In("小李","小张")<br></font></p>
<p><font face=宋体 color=#000000 size=2>示例_OR筛选字段中的记录</font></p>
<p><font face=宋体 color=#000000 size=2>SELECT real_name,submit_date<br>FROM useres<br>WHERE real_name="小李" OR real_name="小张"<br></font></p>
<p><font face=宋体 color=#000000 size=2>------------------------------------------------------------<br>5 GROUP BY分组结果集<br>------------------------------------------------------------<br>示例1_12_GROUPBY分组结果集<br>SELECT sex, SUM(age) AS age之SUM<br>FROM useres<br>GROUP BY useres.sex<br>ORDER BY SUM(age) DESC;</font></p>
<p><font face=宋体 color=#000000 size=2>示例解读:<br>按字段"sex"下的记录对新"字段"age之SUM"进行分组.<br>ORDER BY...DESC用来指定按降序排列</font></p>
<p><font face=宋体 color=#000000 size=2>本例中的sum为SQL中的聚合函数(对一组值进行操作,返回单一的汇总值),下面是常用的几个聚合函数:</font></p>
<p><font face=宋体 color=#000000 size=2>1 SUM 求总和函数</font></p>
<p><font face=宋体 color=#000000 size=2>格式:<br>SUM([ALL|DISTINCT] expression)<br>参数:<br>ALL 对所有值求总和,默认为ALL<br>DISTINCT 求总和时排除重复项<br>expression 值或表达式,可以是变量,字段,函数等</font></p>
<p><font face=宋体 color=#000000 size=2>2 AVG 求平均值函数<br>格式:<br>AVG([ALL|DISTINCT] expression)<br>参数:<br>ALL 对所有值求平均,默认为ALL<br>DISTINCT 求平均时排除重复项<br>expression 值或表达式,可以是变量,字段,函数等</font></p>
<p><font face=宋体 color=#000000 size=2>3 MIN和MAX函数分别为求最小值和最大值,格式和上面类似.</font></p>
<p><font face=宋体 color=#000000 size=2>4 COUNT 行计数函数<br>格式:<br>COUNT({[ALL|DISTINCT] expression|*})<br>ALL 表示计算除了NULL以外的其他项,为默认选项<br>DISTINCT 表示COUNT返回唯一非空值的数量<br>expression 为表达式,不能是txte,image,ntxt和uniqueidentifier类型的数据.</font></p>
<p><font face=宋体 color=#000000 size=2>示例1_13_AVG求平均值函数</font></p>
<p><font face=宋体 color=#000000 size=2>SELECT sex, AVG(age) AS age之AVG<br>FROM useres<br>GROUP BY useres.sex<br>ORDER BY AVG(age) DESC;<br></font></p>
<p><font face=宋体 color=#000000 size=2>示例1_14_COUNT返回记录数量</font></p>
<p><font face=宋体 color=#000000 size=2>SELECT COUNT(*) <br>FROM useres</font></p>
<p><font face=宋体 color=#000000 size=2>示例1_15_按性别分组记录数量</font></p>
<p><font face=宋体 color=#000000 size=2>SELECT sex, COUNT(*)<br>FROM useres<br>GROUP BY sex;<br></font></p>
<p><font face=宋体 color=#000000 size=2>------------------------------------------------------------<br>6 DISTINCT从尾部除去重复记录<br>------------------------------------------------------------</font></p>
<p><font face=宋体 color=#000000 size=2>SELECT DISTINCT real_name<br>FROM useres</font></p>
<p><font face=宋体 color=#000000 size=2>------------------------------------------------------------<br>7 组合查询<br>------------------------------------------------------------<br>当需要从多个表中查询时,可以使用组合查询<br>SELECT useres.real_name, logtime.log_time<br>FROM useres, logtime<br>WHERE (((useres.real_name)=[logtime].[real_name]));</font></p>
<img src ="http://www.blogjava.net/shichengjun1984/aggbug/119626.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/shichengjun1984/" target="_blank">I LOVE JAVA</a> 2007-05-24 11:08 <a href="http://www.blogjava.net/shichengjun1984/articles/119626.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>3.数据库基础语句</title><link>http://www.blogjava.net/shichengjun1984/articles/119614.html</link><dc:creator>I LOVE JAVA</dc:creator><author>I LOVE JAVA</author><pubDate>Thu, 24 May 2007 02:59:00 GMT</pubDate><guid>http://www.blogjava.net/shichengjun1984/articles/119614.html</guid><wfw:comment>http://www.blogjava.net/shichengjun1984/comments/119614.html</wfw:comment><comments>http://www.blogjava.net/shichengjun1984/articles/119614.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/shichengjun1984/comments/commentRss/119614.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/shichengjun1984/services/trackbacks/119614.html</trackback:ping><description><![CDATA[<p><font face=宋体 color=#000000 size=3>create database FySql<br>use FySql<br>创建表命令<br>create table Users<br>(<br>UserId int primary key not null,<br>UserName varchar(20) not null,<br>passwd varchar(20) not null,<br>sex bit not null,<br>birthday datetime null,<br>RegTime datetime,<br>)</font></p>
<font face=宋体>删除表的代码<br>drop table users1<br>drop table users2</font>
<p><font face=宋体 color=#000000 size=3>插入表users的数据的几种方法<br>insert users values(1,'fangsong','123','20020101',20)<br>insert users1(id,username,passwd,birthday,age) values(2,'fenxji','123','20020401',30)<br>insert into users1 values(1,'women','123','20020103',30)</font></p>
<p><br><font face=宋体 color=#000000 size=3>插入数据命令<br>insert into Users values(1,'liuhu','123',1,'19770522','20061114')<br>insert into Users values(2,'分手','123',1,'19790602','20061113')<br>insert into Users values(3,'柳叶','123',0,'19780512','20061004')</font></p>
<p><font face=宋体 color=#000000 size=3>insert into Users values(5,'人类','123',0,'19751102','20061006')<br>insert into Users values(6,'飞儿','123',0,'19780503','20061007')<br>insert into Users values(7,'构飞','123',1,'19830301','20051004')</font></p>
<p><font face=宋体 color=#000000 size=3></font>&nbsp;</p>
<p><font face=宋体 color=#000000 size=3>检索数据的方法-选出数据</font></p>
<p><br><font face=宋体 color=#000000 size=3>select * from Users<br>select Userid,UserName,passwd,sex,birthday from users<br>select [Userid],[UserName],[password],[sex],[birthday] from [users]<br>select "Userid","UserName","password","sex","birthday" from "users"<br>select userId 用户id,username 用户名,sex 性别 from users<br>select userId as 用户id,username as 用户名,sex as&nbsp; 性别 from users</font></p>
<p><font face=宋体 color=#000000 size=3>select UserId 用户id,UserName 用户名,sex 性别,birthday as 生日 from users<br>下面只返回一个字段里面的唯一值<br>select distinct sex from users<br>select top 5 * from users<br>select top 5 percent * from users</font></p>
<p><font face=宋体 color=#000000 size=3></font>&nbsp;</p>
<p><br><font face=宋体 color=#000000 size=3>用函数进行统计<br>select count(*)&nbsp; from Users<br>select count(birthday)&nbsp; from Users<br>select max(UserId) 最大用户id from users<br>select max(UserId) 最小用户id from users<br>select sum(UserId) 所有id的和 from users<br>select avg(UserId) 所有id的和 from users<br>select UserId+sex, "UserName"+"Password" from users</font></p>
<p><font face=宋体 color=#000000 size=3></font>&nbsp;</p>
<p><font face=宋体 color=#000000 size=3></font>&nbsp;</p>
<p><font face=宋体 color=#000000 size=3></font>&nbsp;</p>
<p><font face=宋体 color=#000000 size=3>带条件检索数据</font></p>
<p><font face=宋体 color=#000000 size=3>(1)查出放松的资料<br>select * from Users where Username='放松' <br>select userId,UserName,password from Users where UserName='放松'</font></p>
<p><font face=宋体 color=#000000 size=3>查出性别是女的并且UserId小于等于6的姓名,and代表且,or代表或者<br>select UserName from Users where sex=0 and UserId&lt;=6</font></p>
<p><font face=宋体 color=#000000 size=3>查出1978年前出生的数据(含1978年)<br>select *&nbsp; from users where year(birthday)&lt;'1980'</font></p>
<p><font face=宋体 color=#000000 size=3>查出1978年前出生的数据(含1978年),但是列名改为中文的哈,(用as 或空格作为别名),并且只显示年份<br>select userId,UserName,password,sex,year(birthday) as 出生年份 from users where year(birthday)&lt;'1980'</font></p>
<p><font face=宋体 color=#000000 size=3>查出在今年注册的用户<br>select UserId,userName from Users where datediff(yy,regtime,getdate())&lt;1<br>查出在本月注册的用户<br>select UserId,userName from Users where datediff(mm,regtime,getdate())&lt;1</font></p>
<p><font face=宋体 color=#000000 size=3>查出在今天注册的用户<br>select UserId,userName from Users where datediff(dd,regtime,getdate())&lt;1</font></p>
<p><font face=宋体 color=#000000 size=3>查出本月注册的用户数<br>select count(*) from Users where datediff(mm,regtime,getdate())&lt;1<br>--或<br>select count(*) as 注册的用户数&nbsp; from Users where datediff(mm,regtime,getdate())&lt;1</font></p>
<p><font face=宋体 color=#000000 size=3>此外 &gt;=,&lt;= &lt;&gt; !&gt; !&lt; between and&nbsp; not between and&nbsp; 或in(a,b,c) not in(a,b,c)<br>注意in ===or</font></p>
<img src ="http://www.blogjava.net/shichengjun1984/aggbug/119614.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/shichengjun1984/" target="_blank">I LOVE JAVA</a> 2007-05-24 10:59 <a href="http://www.blogjava.net/shichengjun1984/articles/119614.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>2.安装sql挂起问题解决办法</title><link>http://www.blogjava.net/shichengjun1984/articles/119603.html</link><dc:creator>I LOVE JAVA</dc:creator><author>I LOVE JAVA</author><pubDate>Thu, 24 May 2007 02:50:00 GMT</pubDate><guid>http://www.blogjava.net/shichengjun1984/articles/119603.html</guid><wfw:comment>http://www.blogjava.net/shichengjun1984/comments/119603.html</wfw:comment><comments>http://www.blogjava.net/shichengjun1984/articles/119603.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/shichengjun1984/comments/commentRss/119603.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/shichengjun1984/services/trackbacks/119603.html</trackback:ping><description><![CDATA[<p><font face=宋体 color=#000000 size=2>以前装过sql server，后来删掉的。</font></p>
<p><font face=宋体 color=#000000 size=2>1）在添加/删除程序中彻底删除sql server。 </font></p>
<p><font face=宋体 color=#000000 size=2>2）将没有删除的sql server目录也删除掉。 </font></p>
<p><font face=宋体 color=#000000 size=2>3）打开注册表编辑器，在HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Session Manager中找到PendingFileRenameOperations项目，并删除它。这样就可以清除安装暂挂项目。 </font></p>
<p><font face=宋体 color=#000000 size=2>4）删除注册表中跟sql server相关的键。</font></p>
<p><font face=宋体 color=#000000 size=2>其实估计只要做第3步就可以搞定，这样就可以清除安装暂挂项目。以上是网络搜索的资料，我直接做第3步，就可以安装了</font></p>
<img src ="http://www.blogjava.net/shichengjun1984/aggbug/119603.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/shichengjun1984/" target="_blank">I LOVE JAVA</a> 2007-05-24 10:50 <a href="http://www.blogjava.net/shichengjun1984/articles/119603.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>6、java连接 sql server 数据库</title><link>http://www.blogjava.net/shichengjun1984/articles/117307.html</link><dc:creator>I LOVE JAVA</dc:creator><author>I LOVE JAVA</author><pubDate>Mon, 14 May 2007 04:53:00 GMT</pubDate><guid>http://www.blogjava.net/shichengjun1984/articles/117307.html</guid><wfw:comment>http://www.blogjava.net/shichengjun1984/comments/117307.html</wfw:comment><comments>http://www.blogjava.net/shichengjun1984/articles/117307.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/shichengjun1984/comments/commentRss/117307.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/shichengjun1984/services/trackbacks/117307.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 第一种</p>
<p>import java.sql.Connection;<br>import java.sql.DriverManager;<br>import java.sql.ResultSet;<br>import java.sql.SQLException;<br>import java.sql.Statement;<br>public class Conn {<br>&nbsp;private static Conn conn = null;<br>&nbsp;public static Conn getInstance() { <br>&nbsp;&nbsp;if (conn == null) conn = new Conn();<br>&nbsp;&nbsp;return conn; <br>&nbsp;}&nbsp;<br>&nbsp;public static Connection getCon() {&nbsp;&nbsp;<br>&nbsp;&nbsp;String driver = "com.microsoft.jdbc.sqlserver.SQLServerDriver";&nbsp;<br>&nbsp;&nbsp;String username = "<span style="FONT-FAMILY: Times New Roman">用户名</span>";&nbsp;<br>&nbsp;&nbsp;String password = "密码";&nbsp;<br>&nbsp;&nbsp;String url = "jdbc:microsoft:sqlserver://127.0.0.1:1433;DatabaseName=pubs";<br>&nbsp;&nbsp;Connection con = null;<br>&nbsp;&nbsp;try {<br>&nbsp;&nbsp;&nbsp;Class.forName(driver);<br>&nbsp;&nbsp;&nbsp;con = DriverManager.getConnection(url, username, password);&nbsp;<br>&nbsp;&nbsp;&nbsp;Statement stmt=con.createStatement(); <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ResultSet rs=stmt.executeQuery("select job_desc from jobs"); <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while(rs.next()) { <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(rs.getString(1));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //conn.close();<br>&nbsp;&nbsp;} catch (ClassNotFoundException e) {&nbsp;<br>&nbsp;&nbsp;&nbsp;e.printStackTrace();<br>&nbsp;&nbsp;} catch (SQLException e) {&nbsp;<br>&nbsp;&nbsp;&nbsp;e.printStackTrace();&nbsp;<br>&nbsp;&nbsp;}<br>&nbsp;&nbsp;return con;&nbsp;<br>&nbsp;}<br>&nbsp;public static void main(String[] args) {&nbsp;&nbsp;<br>&nbsp;&nbsp;System.out.println(getCon());<br>&nbsp;}<br>}</p>
<p>&nbsp;运行这个例子还需要导入3个jar包，分别是mssqlserver.jar、msutil.jar和msbase.jar，可以到微软的网站去下载（<a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=07287B11-0502-461A-B138-2AA54BFDC03A&amp;displaylang=en" target=_blank><u><font color=#800080>http://www.microsoft.com/downloads/details.aspx?FamilyId...38-2AA54BFDC03A&amp;displaylang=en</font></u></a>），如果你下载的是setup.exe，还需要安装它，安装后会生成上面的三个jar文件。此JDBC驱动实现了&nbsp;JDBC&nbsp;2.0。<br><br><br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 第二种 用JDBC连接数据库，须创建数据源<br><br>JDBC技术事实上是一种能通过JAVA语言访问任何结构化数据库的应用程序接口(API)(Sun这样说的，我也不知道是不是真的),而且现在的JDBC 3.0据Sun说也能访问Execel等电子表格程序! <br><br>JDBC对于数据库的访问有四种方式，我们这里只是介绍两种： <br><br>第一种是通过ODBC做为&#8220;桥&#8221;(Bridge)对数据库访问，第二种是直接对数据库访问。<br><br>我们先来看看第一种JDBC&lt;--&gt;ODBC访问的流程：<br><br>JDBC Driver Mannager-&gt;JDBC&lt;-&gt;ODBC桥-&gt;ODBC-&gt;数据库客户机驱动库-&gt;数据库服务器-&gt;返回查询结果，在这种访问中值的我们注意的是虽然JAVA是"Write Once ,Run Anywhere"，但是如果通过这种访问的话，需要客户端必须设置ODBC和有相应的数据库客户机的驱动，当你看了下面的另外一个流程的时候或许你会想：明明下一种更方面，为什么还要有这个东西的产生！呵呵，因为，未必所有的数据库服务器提供商都提供下面的JDBC驱动程序（给JDBC访问提供相应的接口），所以就有了JDBC&lt;-&gt;ODBC Bridge。 <br><br>接着再让我们来看看第二种访问流程： <br><br>JDBC Driver Mannager-&gt;局部JDBC驱动-&gt;客户端数据库-&gt;数据库服务器-&gt;返回查询结果，这种访问事实上是转换JDBC调用为相应的数据库（Oracle, Sybase, Informix, DB2, 和其他的数据库数据库管理系统）的客户端API调用（这么说，不知道大家能不能懂，说简单点就好像ASP不是通过DSN对数据库访问而是通过OLEDB访问，说道这里我还是不知道大家能不能明白我的意思。哎呀，不要扔鸡蛋嘛!），这种方式的访问需要相应的数据库提供商提供相应的JDBC驱动程序，但是有一种好处，可以独立于odbc用于可以随处可Run的客户端的浏览器中的Applet程序。 <br>我们下面将给大家一个通过JDBC-ODBC桥数据库访问的实例，但是在看下面的事例前我想问大家一次:JDK1.3装了吗？数据库驱动装了吗（我使用的是SQLserver）？你该没有使用Linux吧？虽然java支持Linux，但是老兄我可没有使用Linux哟(这同JAVA的Write Once ,Run Anywhere没有关系)，由于使用了运行于Win下面的ODBC，我建议你看看这篇东西http://www.aspcn.com/showarticle.asp?id=112，否则你要是有了问题，出不了结果那岂不是要怪我（不过欲加之罪，何患无吃... ...），冤枉呀！</p>
<p>哎呀，说了这么多的废话，还是让我们来看看到底JDBC的调用吧！既然我们是通过odbc访问数据库，所以这个odbc是跑不了的，我们先来设置你的odbc：打开你的odbc数据源-&gt;选择系统dsn(Click加新的dsn-)-&gt;接下来输入选择数据库类型、输入dsn名:、选择服务器、连接数据库的方式、输入数据库的登陆用户和密码-&gt;测试连接，如果测试成功的话，那么你的dsn就建立好了，我的dsn名为Sqlserver.使用的是sqlserver7.0,以 &#8220;sa&#8221;登陆，密码为空。这些东西都是后面要用道的！ <br><br>好了下面让我们来看程序代码： （该代码已经通过运行）<br>//########################################################### <br>//代码开始 <br>//########################################################### <br><br>import java.sql.*; <br>//加载java数据连接包，java基本所有的数据库的调用的都在这个东西里面 <br><br>public class InsertCoffees { <br><br>public static void main(String args[]) { <br><br>String url = "jdbc:odbc:sqlserver"; <br>//取得连接的url名，注意sqlserver是dsn名 <br>Connection con; <br>//实例化一个Connection对象 <br>Statement stmt; <br>String query = "select * from col_link"; <br>//选择所有的Col_link表中的数据输出 <br><br>try { <br>Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); <br>//加载jdbc-odbc桥驱动 <br><br>} catch(java.lang.ClassNotFoundException e) { <br>System.err.print("ClassNotFoundException: "); <br>//加载jdbc-odbc桥错误 <br>System.err.println(e.getMessage()); <br>//其他错误 <br>} <br><br>try { <br><br>con = DriverManager.getConnection(url, "sa", ""); <br>//数据库连接 <br><br><br>stmt = con.createStatement(); <br>//Create 一个声明 <br>stmt.executeUpdate("CREATE TABLE col_link (sitename varchar (20) NULL ,siteurl varchar (50) NULL) "); <br>//执行了一个sql语句生成了一个表col_link的表 <br>stmt.executeUpdate("insert into col_link values('ASP中华网','http://www.aspcn.com')"); <br>stmt.executeUpdate("insert into col_link values('永远到底有多远','http://xuankong.com')"); <br>//执行一个insert into语句 <br>stmt.executeUpdate("update col_link set siteurl='http://www.aspcn.com/xuankong/xuankongt.jpg' where siteurl='http://xuankong.com'"); <br>//执行一个update语句，更新数据库 <br>ResultSet rs = stmt.executeQuery(query); <br>//返回一个结果集 <br>System.out.println("Col_link表中的数据如下(原始数据)"); <br>//下面的语句使用了一个while循环打印出了col_link表中的所有的数据 <br>System.out.println("站点名 "+" "+"站点地址"); <br>System.out.println("---------------"+" "+"----------------"); <br>while (rs.next()) { <br>String s = rs.getString("sitename"); <br>String f = rs.getString("siteurl"); <br>//取得数据库中的数据 <br>System.out.println(s + " " + f); <br>/*String t = rs.getString(1); <br>String l = rs.getString(2); <br>System.out.println(t + " " + l);*/ <br>/*jdbc提供了两种方法识别字段，一种是使用getXXX(注意这里的getXXX表示取不同类型字段的不同的方法)获得字段名， <br>第二种*是通过字段索引，在这里我把第二种方法注释了*/ <br>/*你可以访问这个连接获得getxxx的用法：http://java.sun.com/docs/books/tutorial/jdbc/basics/_retrievingTable.html*/ <br>} <br>stmt.close(); <br>con.close(); <br>//上面的语句关闭声明和连接 <br>} catch(SQLException ex) { <br>System.err.println("SQLException: " + ex.getMessage()); <br>//显示数据库连接错误或者查询错误 <br>} <br>} <br>} </p>
<img src ="http://www.blogjava.net/shichengjun1984/aggbug/117307.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/shichengjun1984/" target="_blank">I LOVE JAVA</a> 2007-05-14 12:53 <a href="http://www.blogjava.net/shichengjun1984/articles/117307.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>1、可能会让你写一段Jdbc连Oracle的程序,并实现数据查询.</title><link>http://www.blogjava.net/shichengjun1984/articles/110257.html</link><dc:creator>I LOVE JAVA</dc:creator><author>I LOVE JAVA</author><pubDate>Thu, 12 Apr 2007 11:10:00 GMT</pubDate><guid>http://www.blogjava.net/shichengjun1984/articles/110257.html</guid><wfw:comment>http://www.blogjava.net/shichengjun1984/comments/110257.html</wfw:comment><comments>http://www.blogjava.net/shichengjun1984/articles/110257.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/shichengjun1984/comments/commentRss/110257.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/shichengjun1984/services/trackbacks/110257.html</trackback:ping><description><![CDATA[<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">答</span><span lang=EN-US>:</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">程序如下：</span><span lang=EN-US> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>package hello.ant; </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>import java.sql.*; </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>public class jdbc </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>{ </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>String dbUrl=jdbc:oracle:thin:@127.0.0.1:1521:orcl; </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>String theUser=admin; </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>String thePw=manager; </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>Connection c=null; </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>Statement conn; </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>ResultSet rs=null; </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>public jdbc() </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>{ </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>try{ </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>Class.forName(oracle.jdbc.driver.OracleDriver).newInstance(); </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>c = DriverManager.getConnection(dbUrl,theUser,thePw); </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>conn=c.createStatement(); </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>}catch(Exception e){ </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>e.printStackTrace(); </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>} </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>} </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>public boolean executeUpdate(String sql) </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>{ </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>try </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>{ </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>conn.executeUpdate(sql); </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>return true; </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>} </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>catch (SQLException e) </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>{ </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>e.printStackTrace(); </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>return false; </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>} </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>} </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>public ResultSet executeQuery(String sql) </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>{ </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>rs=null; </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>try </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>{ </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>rs=conn.executeQuery(sql); </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>} </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>catch (SQLException e) </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>{ </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>e.printStackTrace(); </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>} </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>return rs; </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>} </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>public void close() </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>{ </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>try </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>{ </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>conn.close(); </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>c.close(); </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>} </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>catch (Exception e) </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>{ </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>e.printStackTrace(); </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>} </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>} </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>public static void main(String[] args) </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>{ </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>ResultSet rs; </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>jdbc conn = new jdbc(); </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>rs=conn.executeQuery(select * from test); </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>try{ </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>while (rs.next()) </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>{ </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>System.out.println(rs.getString(id)); </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>System.out.println(rs.getString(name)); </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>} </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>}catch(Exception e) </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>{ </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>e.printStackTrace(); </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>} </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>} </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>} </span></p>
<img src ="http://www.blogjava.net/shichengjun1984/aggbug/110257.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/shichengjun1984/" target="_blank">I LOVE JAVA</a> 2007-04-12 19:10 <a href="http://www.blogjava.net/shichengjun1984/articles/110257.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>