oracle数据库菜鸟教程oracle:数据关联问题

oracle中,如何查看数据库中的表之间的关系图?
[问题点数:20分,结帖人samyp1234]
本版专家分:25
结帖率 97.29%
CSDN今日推荐
本版专家分:693
本版专家分:3067
2008年7月 Oracle大版内专家分月排行榜第三
本版专家分:25
本版专家分:1785
本版专家分:1785
本版专家分:282
本版专家分:48
本版专家分:84
本版专家分:157
本版专家分:0
本版专家分:0
匿名用户不能发表回复!|
其他相关推荐扫一扫体验手机阅读
Oracle 数据库 实例之间的关系及一些名词解释(上)
6、口令文件(Password file)用于验证特权用户(具有SYSDBA、SYSOPER权限的特殊数据库用户)二、逻辑数据库结构(Logical database structure)数据库逻辑结构包含表空间、段、段(extent)、数据块。1、表空间(Tablespace)-------下面对实例和数据库做详细的诠释:在Oracle领域中有两个词很容易混淆,这就是“实例”(instance)和“数据库”(database)。作为Oracle术语,这两个词的定义如下:q数据库(database):物理操作系统文件或磁盘(disk)的集合。使用Oracle 10g的自动存储管理(Automatic Storage Management,ASM)或RAW分区时,数据库可能不作为操作系统中单独的文件,但定义仍然不变。q实例(instance):一组Oracle后台进程/线程以及一个共享内存区,这些内存由同一个计算机上运行的线程/进程所共享。这里可以维护易失的、非持久性内容(有些可以刷新输出到磁盘)。就算没有磁盘存储,数据库实例也能存在。也许实例不能算是世界上最有用的事物,不过你完全可以把它想成是最有用的事物,这有助于对实例和数据库划清界线。这两个词有时可互换使用,不过二者的概念完全不同。实例和数据库之间的关系是:数据库可以由多个实例装载和打开,而实例可以在任何时间点装载和打开一个数据库。实际上,准确地讲,实例在其整个生存期中最多能装载和打开一个数据库!稍后就会介绍这样的一个例子。是不是更糊涂了?我们还会做进一步的解释,应该能帮助你搞清楚这些概念。实例就是一组操作系统进程(或者是一个多线程的进程)以及一些内存。这些进程可以操作数据库;而数据库只是一个文件集合(包括数据文件、临时文件、重做日志文件和控制文件)。在任何时刻,一个实例只能有一组相关的文件(与一个数据库关联)。大多数情况下,反过来也成立:一个数据库上只有一个实例对其进行操作。不过,Oracle的真正应用集群(Real Application Clusters,RAC)是一个例外,这是Oracle提供的一个选项,允许在集群环境中的多台计算机上操作,这样就可以有多台实例同时装载并打开一个数据库(位于一组共享物理磁盘上)。由此,我们可以同时从多台不同的计算机访问这个数据库。Oracle RAC能支持高度可用的系统,可用于构建可扩缩性极好的解决方案。一个实例在其生存期中最多只能装载和打开一个数据库。要想再打开这个(或其他)数据库,必须先丢弃这个实例,并创建一个新的实例。重申一遍:实例是一组后台进程和共享内存。数据库是磁盘上存储的数据集合。实例“一生”只能装载并打开一个数据库。数据库可以由一个或多个实例(使用RAC)装载和打开。前面提到过,大多数情况下,实例和数据库之间存在一种一对一的关系。可能正因如此,才导致人们很容易将二者混淆。从大多数人的经验看来,数据库就是实例,实例就是数据库。不过,在许多测试环境中,情况并非如此。在我的磁盘上,可以有5个不同的数据库。测试主机上任意时间点只会运行一个Oracle实例,但是它访问的数据库每天都可能不同(甚至每小时都不同),这取决于我的需求。只需有不同的配置文件,我就能装载并打开其中任意一个数据库。在这种情况下,任何时刻我都只有一个“实例”,但有多个数据库,在任意时间点上只能访问其中的一个数据库。所以,你现在应该知道,如果有人谈到实例,他指的就是Oracle的进程和内存。提到数据库时,则是说保存数据的物理文件。可以从多个实例访问一个数据库,但是一个实例一次只能访问一个数据库。1.oracle数据库系统中,DBMS可以管理多个数据库实例吗?还是需要一个oracle服务管理一个实例?oracle里面一个数据库系统可以又多个实例。你可以运行dbca,在界面里面你可以看到可以创建新的实例,但是大多数情况下,oracle都只是建立一个实例。2需要建立教务数据库,财务数据库两个db,是可以的,不过通常的做法是建再2个用户放在不同的tablespaces上面。一个用户存储教务数据库表数据,一个存放财务数据库表数据。3.oracle中的schema属于哪个层次?schema简单来讲,你可以理解成一个用户以及用户所拥有的所有对象。其实就相当于sqlserver的库。4.oracle中这样做。create user Tgrant [connect,……]to Tcreate table……创建属于此用户的表及其他对象,那么这个用户数否可以代表为一个应用db?同3一样,你可以这样理解成一个用户以及用户下面所有的对象其实就是sqlserver中的db了,实际生产环境中,为了减少成本和充分利用oracle数据库的资源,我们都是一个项目一个用户,一个应用一个用户,然后在不同的用户下面建立相应的表、视图、存储过程、存储函数、序列等等。下面来看一个简单的例子。假设我们刚安装了Oracle 10g10.1.0.3。我们执行一个纯软件安装,不包括初始的“启动”数据库,除了软件以外什么都没有。通过pwd命令可以知道当前的工作目录(这个例子使用一个Linux平台的计算机)。我们的当前目录是dbs(如果在Windows平台上,则是database目录)。执行ls–l命令显示出这个目录为“空”。其中没有init.ora 文件,也没有任何存储参数文件(stored parameter file,SPFILE);存储参数文件将在第3章详细讨论。使用ps(进程状态)命令,可以看到用户ora10g运行的所有进程,这里假设ora10g是Oracle软件的所有者。此时还没有任何Oracle数据库进程。然后使用ipcs命令,这个UNIX命令可用于显示进程间的通信设备,如共享内存、信号量等。目前系统中没有使用任何通信设备。然后启动SQL*Plus(Oracle的命令行界面),并作为SYSDBA连接(SYSDBA账户可以在数据库中做任何事情)。连接成功后,SQL*Plus报告称我们连上了一个空闲的实例:我们的“实例”现在只包括一个Oracle服务器进程,见以下输出中粗体显示的部分。此时还没有分配共享内存,也没有其他进程。现在来启动实例:这里提示的文件就是启动实例时必须要有的一个文件,我们需要有一个参数文件(一种简单的平面文件,后面还会详细说明),或者要有一个存储参数文件。现在就来创建参数文件,并放入启动数据库实例所需的最少信息(通常还会指定更多的参数,如数据库块大小、控制文件位置,等等)。然后再回到SQL*Plus:这里对startup命令加了nomount选项,因为我们现在还不想真正“装载”数据库(要了解启动和关闭的所有选项,请参见SQL*Plus文档)。注意在Windows上运行startup命令之前,还需要使用oradim.exe实用程序执行一条服务创建语句。现在就有了所谓的“实例”。运行数据库所需的后台进程都有了,如进程监视器(process monitor,PMON)、日志写入器(log writer,LGWR)等,这些进程将在第5章详细介绍。再使用ipcs命令,它会首次报告指出使用了共享内存和信号量,这是UNIX上的两个重要的进程间通信设备:注意,我们还没有“数据库”呢!此时,只有数据库之名(在所创建的参数文件中),而没有数据库之实。如果试图“装载”这个数据库,就会失败,因为数据库根本就不存在。下面就来创建数据库。有人说创建一个Oracle数据库步骤很繁琐,真是这样吗?我们来看看:这里创建数据库就是这么简单。但在实际中,也许要使用一个稍有些复杂的CREATE DATABASE命令,因为可能需要告诉Oracle把日志文件、数据文件、控制文件等放在哪里。不过,我们现在已经有了一个完全可操作的数据库了。可能还需要运行$ORACLE_HOME/rdbms/admin/ catalog.sql脚本和其他编录脚本(catalog script)来建立我们每天使用的数据字典(这个数据库中还没有我们使用的某些视图,如ALL_OBJECTS),但不管怎么说,数据库已经有了。可以简单地查询一些Oracle V$视图(具体就是V$DATAFILE、V$LOGFILE和V$CONTROLFILE),列出构成这个数据库的文件:Oracle使用默认设置,把所有内容都放在一起,并把数据库创建为一组持久的文件。如果关闭这个数据库,再试图打开,就会发现数据库无法打开:一个实例在其生存期中最多只能装载和打开一个数据库。要想再打开这个(或其他)数据库,必须先丢弃这个实例,并创建一个新的实例。重申一遍:1.实例是一组后台进程和共享内存。2.数据库是磁盘上存储的数据集合。3.实例“一生”只能装载并打开一个数据库。4.数据库可以由一个或多个实例(使用RAC)装载和打开。前面提到过,大多数情况下,实例和数据库之间存在一种一对一的关系。可能正因如此,才导致人们很容易将二者混淆。从大多数人的经验看来,数据库就是实例,实例就是数据库。不过,在许多测试环境中,情况并非如此。在我的磁盘上,可以有5个不同的数据库。测试主机上任意时间点只会运行一个Oracle实例,但是它访问的数据库每天都可能不同(甚至每小时都不同),这取决于我的需求。只需有不同的配置文件,我就能装载并打开其中任意一个数据库。在这种情况下,任何时刻我都只有一个“实例”,但有多个数据库,在任意时间点上只能访问其中的一个数据库。所以,你现在应该知道,如果有人谈到实例,他指的就是Oracle的进程和内存。提到数据库时,则是说保存数据的物理文件。可以从多个实例访问一个数据库,但是一个实例一次只能访问一个数据库。----
<span type="1" blog_id="1360377" userid='
231篇文章,69W+人气,3粉丝
MySQL全通晓
¥51.00105人订阅
高并发架构之路
¥51.00136人订阅
<span type="1" blog_id="1360377" userid='查看:5753|回复:18
oracle数据库中:
有表A和表B(关联关系为:A.TID=B.ATOBTID& &&&且A.TID在数据库中为自增,A表中每增加一条数据,则A.TID自增1)
目前表A与表B为一对多关系,现想将表A与表B修改为一对一的关系(即需要根据B表向A表中插入记录)
求大神指点,本人对数据库方面的脚本一窍不通,最好是能提供详细的解决方案
详细说明:
<font color="#)现在A表中的TID对应关联了B表中的N条记录,但实际应该是1对1的关系,这是前期设计的时候遗留的问题,所以现在需要弄成1对1的关系.
2)A:B如果是1:N,那需要向A表中插入N-1条对应的A的记录,这些记录唯一不同的就是A.TID,这个TID是主键,每次在最大值的基础上自增 1
3)另外,还需要将B中的另外N-1条记录中的B.B.ATOBTID与刚才插入的到A表的N-1条记录的TID,进行一一对应上
目前数据库关联关系
(10.72 KB)
更新后数据库关联关系
高级工程师
引用:原帖由 simlink_zhaojh 于
11:05 发表
oracle数据库中:
有表A和表B(关联关系为:A.TID=B.ATOBTID& &&&且A.TID在数据库中为自增,A表中每增加一条数据,则A.TID自增1)
目前表A与表B为一对多关系,现想将表A与表B修改为一对一的关系(即需要根据B表向A表中插入记录)
求大 ... A表最终结果的TID是否可以全是新值,而不保留原来的旧值?
引用:原帖由 bfc99 于
12:31 发表
A表最终结果的TID是否可以全是新值,而不保留原来的旧值? 但是如果弃用旧值,全是新值的话实现起来容易的多,也可以,但最好的方式是:B表中应该有一条记录对应原来的A表中的旧的TID值。
您如果有方案的话,可以帮忙理下吗,谢谢
高级工程师
引用:原帖由 simlink_zhaojh 于
13:36 发表
但是如果弃用旧值,全是新值的话实现起来容易的多,也可以,但最好的方式是:B表中应该有一条记录对应原来的A表中的旧的TID值。
您如果有方案的话,可以帮忙理下吗,谢谢 ... 1、创建一个序列seq_a_tid,从A表中最大的TID的下一个开始,步长为1.用于在后面生成所需的TID。
2、备份相关表,以备后用。
3、A表和B表左关联,创建处理中间表。
& &create table temp_table as
& &select a.tid a_tid,seq_a_tid.nextval new_tid,a.xingming,a.xingbie,
& && && & b.tid b_tid,b.atobtid,b.address,0 flag
& &from a left join b on a.tid=b.
4、在中间表中标记需要修改A表TID和B表ATOBTID值的行。
& &update temp_table
& &&&set flag=1
& &&&where b_tid not in (select min(tid) from b group by atobtid);
5、将中间表中flag列为1的记录的a_tid和atobid修改为new_tid的值。
& &update temp_table
& &&&set a_tid=new_tid,
& && && &atobtid=new_tid
& &where flag=1;
6、将修改后的temp_table表中的记录,分别插回A表和B表
& &insert into a select a_tid,xingming,xingbie from temp_table where flag=1;
& &insert into b select b_tid,atobtid,address from temp_table where flag=1;
7、检查和验证数据的正确性和完整性,若有错误,参考temp_table进行分析和处理。
引用:原帖由 bfc99 于
17:11 发表
1、创建一个序列seq_a_tid,从A表中最大的TID的下一个开始,步长为1.用于在后面生成所需的TID。
2、备份相关表,以备后用。
3、A表和B表左关联,创建处理中间表。
& &create table temp_table as
& &select a.tid a_tid,seq ... 非常感谢提供的方案,很详细,我明天好好研究下,如果有不明白的地方还得再请教。
高级工程师
引用:原帖由 simlink_zhaojh 于
17:25 发表
非常感谢提供的方案,很详细,我明天好好研究下,如果有不明白的地方还得再请教。 更正一下,第6步对B表的处理应该是更新,不是插入。通过TID关联。
&&set atobtid=(select new_tid from temp_table t where b.tid=t.b_tid and t.flag=1)
&&where exists (select 1 from temp_table t where t.tid=b.tid and t.flag=1);
引用:原帖由 bfc99 于
09:28 发表
更正一下,第6步对B表的处理应该是更新,不是插入。通过TID关联。
&&set atobtid=(select new_tid from temp_table t where b.tid=t.b_tid and t.flag=1)
&&where exists (select 1 from temp_table t where t ... 谢谢!今天来了一直在处理其他问题,还没来得及研究
引用:原帖由 bfc99 于
09:28 发表
更正一下,第6步对B表的处理应该是更新,不是插入。通过TID关联。
&&set atobtid=(select new_tid from temp_table t where b.tid=t.b_tid and t.flag=1)
&&where exists (select 1 from temp_table t where t ... 这个方案完全满足需求,非常感谢!
但是我在正式库(大概有100多万条数据)中执行的时候,当执行到第4步的时候,执行了一个多小时还没执行完,不知道能从哪些方面进行优化下?
4、在中间表中标记需要修改A表TID和B表ATOBTID值的行。
& &update temp_table
& &&&set flag=1
& &&&where b_tid not in (select min(tid) from b group by atobtid);
高级工程师
引用:原帖由 simlink_zhaojh 于
17:06 发表
这个方案完全满足需求,非常感谢!
但是我在正式库(大概有100多万条数据)中执行的时候,当执行到第4步的时候,执行了一个多小时还没执行完,不知道能从哪些方面进行优化下?
4、在中间表中标记需要修改A表TID和B表ATOBTID值的行 ... 提供该语句的执行计划和统计信息。
引用:原帖由 bfc99 于
18:18 发表
提供该语句的执行计划和统计信息。 用sql/plus直接执行语句就卡死了,这个截图是通过pl/sql获得的执行计划的信息。
就是执行的这个语句
4、在中间表中标记需要修改A表TID和B表ATOBTID值的行。
& &update temp_table
& &&&set flag=1
& &&&where b_tid not in (select min(tid) from b group by atobtid);
单独执行where之前的语句的执行计划是后面的图中显示
update temp_table
& &&&set flag=1
(18.31 KB)
(11.95 KB)
本帖最后由 simlink_zhaojh 于
13:48 编辑
高级工程师
引用:原帖由 simlink_zhaojh 于
13:39 发表
用sql/plus直接执行语句就卡死了,这个截图是通过pl/sql获得的执行计划的信息。
就是执行的这个语句
4、在中间表中标记需要修改A表TID和B表ATOBTID值的行。
& &update temp_table
& &&&set flag=1
& &&&where b_tid ... 试试把NOT IN改成IN:
& &update temp_table
& &&&set flag=1
& &&&where b_tid in (select min(tid) from b group by atobtid);
但此后所有条件中有“flag=1”的条件处,要改写为“flag&&1 or flag is null”
高级工程师
引用:原帖由 simlink_zhaojh 于
13:39 发表
用sql/plus直接执行语句就卡死了,这个截图是通过pl/sql获得的执行计划的信息。
就是执行的这个语句
4、在中间表中标记需要修改A表TID和B表ATOBTID值的行。
& &update temp_table
& &&&set flag=1
& &&&where b_tid ... 或者在第3步创建临时表时,增加对数据进行过滤的操作,只将需要处理的数据加入。从而取消第4步的操作。
create table temp_table as
& &select a.tid a_tid,seq_a_tid.nextval new_tid,a.xingming,a.xingbie,
& && && & b.tid b_tid,b.atobtid,b.address,1 flag
& &from a left join b on a.tid=b.atobtid
& &where b.tid not in (select min(tid) from b group by atobtid);
引用:原帖由 bfc99 于
14:26 发表
试试把NOT IN改成IN:
& &update temp_table
& &&&set flag=1
& &&&where b_tid in (select min(tid) from b group by atobtid);
但此后所有条件中有“flag=1”的条件处,要改写为“flag1 or flag is null ... 谢谢了,就去掉了一个not立马就提速了。
引用:原帖由 simlink_zhaojh 于
14:40 发表
谢谢了,就去掉了一个not立马就提速了。 update b
&&set atobtid=(select new_tid from temp_table t where b.tid=t.b_tid and t.flag=0)
&&where exists (select 1 from temp_table t where t.tid=b.tid and t.flag=0);
这条语句执行的时候也一直在运行中,但是看了执行计划也还好,但就是一直在执行中,后来我把这个语句的where条件去掉了,改成了下面的,还是不行,不知道什么原因?
&&set atobtid=(select new_tid from temp_table t where b.tid=t.b_tid and t.flag=0)【没有看太明白where exits这个语句的意思,是不是去掉跟加上是一个效果呢?】
(12.38 KB)
本帖最后由 simlink_zhaojh 于
17:11 编辑
高级工程师
引用:原帖由 simlink_zhaojh 于
17:07 发表
&&set atobtid=(select new_tid from temp_table t where b.tid=t.b_tid and t.flag=0)
&&where exists (select 1 from temp_table t where t.tid=b.tid and t.flag=0);
这条语句执行的时候也一直在 ... 1、可以改用merge into语句试试
& &merge into b
& &using (select b_tid,new_tid from temp_table where flag&&1 or flag is null) t1
& &on (b.tid=t1.b_tid)
& &when matched then
& &&&update set b.atobtid=t1.new_
2、如果没有exists语句,对于B表中那些不能根据“t.tid=b.tid and t.flag=0”匹配上的记录的atobtid列的值,会被置为空。举例来说:
假设a表的内容如下:
id& &&&col1
b表内容如下:
id& & col1
现在要求用b表的col1列内容更新a表中与其id相一致的记录。所以,更新后,a表的内容应为:
id& &&&col1
但如果你是用如下语句更新的,则结果就会不一样:
update a set col1 = (select col1 from b where b.id=a.id);
结果变为:
id& &&&col1
而如果是用如下语句更新,则可以实现我们预期的结果:
update a set col1=(select col1 from b where a.id=b.id)
where exists (select 1 from a.id=b.id);
引用:原帖由 bfc99 于
09:32 发表
1、可以改用merge into语句试试
& &merge into b
& &using (select b_tid,new_tid from temp_table where flag1 or flag is null) t1
& &on (b.tid=t1.b_tid)
& &when matched then
& &&&update set b.atobtid=t1.n ... 解释的很详细,非常感谢!
这个问题目前基本弄好了,目前就还剩下一个表合并删除并修改关联关系的问题,跟这个问题有点儿类似,但我自己弄了下,把数据库中很多记录的关联关系都弄乱了,很多记录在产品中都找不到了(您如果方便的话,帮忙再看看,谢谢,才注册51CTO论坛,不清楚发帖规则,貌似应该新发一张贴的,我一会儿新发一张贴,然后把链接补到这儿吧)
这个问题我卡在了,不知道怎么批量的把B.ATOBTID的366的值怎么改成365
A表中存在多条冗余记录(根据local,HID,PID 进行判断是否同一条记录:local,HID必须相同,PID为空或NULL的情况可归到任意相同local,HID的记录下,local为U的所有记录均不进行处理。)
关联关系A.TID=B.ATOBTID
1、将B表中的记录的B.ATOTID 的值修改为要保留的唯一一条记录的TID
2、删除A表中冗余的记录,只保留一条记录。
(32.15 KB)
本帖最后由 simlink_zhaojh 于
15:23 编辑
引用:原帖由 bfc99 于
09:32 发表
1、可以改用merge into语句试试
& &merge into b
& &using (select b_tid,new_tid from temp_table where flag1 or flag is null) t1
& &on (b.tid=t1.b_tid)
& &when matched then
& &&&update set b.atobtid=t1.n ... 问题链接:
引用:原帖由 simlink_zhaojh 于
11:48 发表
解释的很详细,非常感谢!
这个问题目前基本弄好了,目前就还剩下一个表合并删除并修改关联关系的问题,跟这个问题有点儿类似,但我自己弄了下,把数据库中很多记录的关联关系都弄乱了,很多记录在产品中都找不到了(您如果方便 ... 这个问题我卡在了,不知道怎么把B.ATOBTID的366的值怎么改成365
高级工程师
引用:原帖由 simlink_zhaojh 于
15:21 发表
这个问题我卡在了,不知道怎么把B.ATOBTID的366的值怎么改成365 你是说那个新问题吗?如果是的话,最好在那个贴子上回复,这样便于其它网友查阅和讨论。oracle数据库先将两张表关联查询,得到的结果再和第三张表关联查询,SQL语句怎么写?最好给个范例? - 知乎有问题,上知乎。知乎作为中文互联网最大的知识分享平台,以「知识连接一切」为愿景,致力于构建一个人人都可以便捷接入的知识分享网络,让人们便捷地与世界分享知识、经验和见解,发现更大的世界。2被浏览<strong class="NumberBoard-itemValue" title="分享邀请回答赞同 添加评论分享收藏感谢收起兵胜非常事,要善于总结
多个关联连接,出现无查询结果---经验(oracle数据库)
文章来源:
我的是多个做个左关联,出现无查询结果,其实每个关联的表都有数据
SELECT C.*,T.*,B.*,P.*
FROM JX_CLASSROOM_INFO C, JX_TEACHFUN_INFO T ,ZC_TEACHBUILD_INFO B,XX_CAMPUS_INFO P
C.FUNID=T.FUNID(+) AND
C.BUILDID=B.BUILDID(+) AND C.CAMPUSID=P.CAMPUSID(+)
AND C.ISDEL='0'AND T.ISDEL='0' AND B.ISDEL='0' AND P.ISDEL='0'
order by C.ROOMID
按关联原则,如果主表几条数据,就会产生几条结果,但此处不同。
此语句查询无查询结果,是由于标志位的原因
1.如果JX_TEACHFUN_INFO T表的T.ISDEL='1', 而此时虽然达到了C.FUNID=T.FUNID(+) ,但要求T.ISDEL='0'就会使总结果减少一条
2.达到了C.FUNID=T.FUNID(+) ,但是JX_TEACHFUN_INFO T表对应的记录被物理删除了,如果再加上T.ISDEL='0'就会使总结果减少一条
没有更多推荐了,}

我要回帖

更多关于 oracle数据库删除表中数据 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信