默认情况下,oracle的分区表对于分区字段是不允许进行update操作的,如果有对分区字段行进update,就会报错——ORA-14402: 更新分区关键字列将导致分区的更改。但是可以通过打开表的row movement属性来允许对分区字段的update操作。
我们提供的服务有:成都网站设计、网站建设、微信公众号开发、网站优化、网站认证、前郭ssl等。为上千余家企事业单位解决了网站和推广的问题。提供周到的售前咨询和贴心的售后服务,是有科学管理、有技术的前郭网站制作公司
例:创建分区表test_part进行实验
create table TEST_PART
(
A1 NUMBERnot null,
A2 DATE not null,
A3 VARCHAR2(6) not null,
A4 DATE not null,
A5 NUMBER not null,
)
partition by range (A1)
(
partition P1 values less than (1000),
partition P2 values less than (2000),
partition P3 values less than (3000),
partition P4 values less than (4000),
partition P5 values less than (5000),
partition P6 values less than (MAXVALUE)
);
插入如下的数据
SQL select * from test_part;
A1 A2 A3 A4 A5
---------- ----------- ------ ----------- ----------
123 2006-06-30 123456 2006-06-30 123
456 2006-06-30 asdfgh 2006-06-30 456
1 2006-06-30 234123 2006-06-30 1
2 2006-06-30 234234 2006-06-30 2
1234 2006-06-30 456789 2006-06-30 1234
1111 2006-06-30 ewrqwe 2006-06-30 1111
2222 2006-06-30 fdafda 2006-06-30 2222
3333 2006-06-30 342342 2006-06-30 3333
5678 2006-06-30 qwerty 2006-06-30 5678
9 rows selected
分区P1、P2的数据分别为:
SQL select rowid,t.* from test_part partition(p1) t;
ROWID A1 A2 A3 A4 A5
------------------ ---------- ----------- ------ ----------- ----------
AAAGLoAAGAAAtsEAAB 456 2006-06-30 asdfgh 2006-06-30 456
AAAGLoAAGAAAtsEAAC 1 2006-06-30 234123 2006-06-30 1
AAAGLoAAGAAAtsEAAD 2 2006-06-30 234234 2006-06-30 2
AAAGLoAAGAAAtsEAAE 123 2006-06-30 123456 2006-06-30 123
SQL select rowid,t.* from test_part partition(p2) t;
ROWID A1 A2 A3 A4 A5
------------------ ---------- ----------- ------ ----------- ----------
AAAGLwAAGAAA+8MAAC 1234 2006-06-30 456789 2006-06-30 1234
AAAGLwAAGAAA+8MAAD 1111 2006-06-30 ewrqwe 2006-06-30 1111
直接update提示错误
SQL update test_part set a1=1123 where a1=123;
update test_part set a1=1123 where a1=123
ORA-14402: 更新分区关键字列将导致分区的更改
打开row movement属性
SQL alter table test_part enable row movement;
Table altered
再次执行update操作
SQL update test_part set a1=1123 where a1=123;
1 row updated
执行是成功的并迁移到分区P2上了,且这时候rowid也发生了变化
SQL select rowid,t.* from test_part partition(p2) t;
ROWID A1 A2 A3 A4 A5
------------------ ---------- ----------- ------ ----------- ----------
AAAGLwAAGAAA+8MAAC 1234 2006-06-30 456789 2006-06-30 1234
AAAGLwAAGAAA+8MAAD 1111 2006-06-30 ewrqwe 2006-06-30 1111
AAAGLwAAGAAA+8PAAB 1123 2006-06-30 123456 2006-06-30 123
SQL
enable row movement可以允许数据段的压缩、update分区字段的数据(跨分区的)
通过Update语句将A表的某列值修改为B表中的指定列的值时,所用的sql语句在Oracle和SQL Server中是不一样的,
代码如下:
Oracle中的语句:
UPDATE A
SET A.COL1=(SELECT B.COL1 from B where A.KEY=B.KEY [and 其它限制(可选)] )
where 其它条件
SQL Server中更新语句:
update A
SET A.COL1=B.COL1
FROM A,B where A.KEY=B.KEY where 其它条件限制
若关联条件为多个,where后面用and 连接指定条件即可
oracle定时更新(JOBS)
rm.pro_hrm_emp_info_job过程
需要每天都更新,所以先创建个procedure,再创建个job就可以实现定时更新
create or replace procedure rm.pro_hrm_emp_info_job is
zm
begin
update rm.hrm_emp_info
set ages = to_number(TRUNC(nvl((sysdate brith_date) / 365, 0))),
leng_serv = to_number(TRUNC(nvl((sysdate work_date) / 365, 0))),
ins_len_ser = to_number(TRUNC(nvl((sysdate ente_appe_date) / 365,
0)));
commit;
end pro_hrm_emp_info_job;
相应的`job
declare
jobno number;
begin
dbms_job.submit(jobno,’rm.pro_hrm_emp_info_job;’,trunc(sysdate),’trunc(sysdate)+1’);每天零点更新
commit;
end;
/
分解下job
dbms_job.submit(jobno, job号,由sys.jobseq生成
’rm.pro_hrm_emp_info_job;’, 要执行的procedure
trunc(sysdate), 下次要执行的时间
’trunc(sysdate)+1’); 每次间隔的时间,此处的1标识一天 也可1/1440每一分钟执行一次
查看
select * from sys.user_jobs;
其中创建的jobno(任务号)由sys.jobseq序列生成
主由packages中的sys.dbms_job执行
细节可以查看sys.dbms_job包内容。 ;
CentOS 7 64 位 Linux 发行版。我假设你已经在你的系统上安装了 Oracle 11g。
这里我会展示一下安装 Oracle 11g 时我的操作步骤。
我在 Oracle 11g 上选择 “Create and configure a database”,如下图所示。
然后我选择安装 Oracle 11g “Decktop Class”。如果是生产环境,你必须选择 “Server Class”。
然后你输入安装 Oracle 11g 的各种路径以及密码。下面是我自己的 Oracle 11g 安装配置。确保你正确输入了 Oracle 的密码。
下一步,我按照如下设置 Inventory Directory。
到这里,我已经向你展示了我安装 Oracle 11g 所做的工作,因为我们开始想升级到 12c。
让我们将 Oracle 11g 升级到 Oracle 12c 吧。
你需要从该链接上下载两个 zip 文件。下载并解压两个文件到相同目录。文件名为 linuxamd6412cdatabase_1of2.zip linuxamd6412cdatabase_2of2.zip。提取或解压完后,它会创建一个名为 database 的文件夹。
注意:升级到 12c 之前,请确保在你的 CentOS 上已经安装了所有必须的软件包,并且所有的路径变量也已经正确配置,还有其它前提条件也已经满足。
下面是必须使用正确版本安装的一些软件包
binutils
compat-libstdc++
gcc
glibc
libaio
libgcc
libstdc++
make
sysstat
unixodbc
在因特网上搜索正确的 rpm 版本。
你也可以用一个查询处理多个软件包,然后在输出中查找正确版本。例如,在终端中输入下面的命令:
rpm -q binutils compat-libstdc++ gcc glibc libaio libgcc libstdc++ make sysstat unixodbc
你的系统中必须安装了以下软件包(版本可能或新或旧)
binutils-2.23.52.0.1-12.el7.x86_64
compat-libcap1-1.10-3.el7.x86_64
gcc-4.8.2-3.el7.x86_64
gcc-c++-4.8.2-3.el7.x86_64
glibc-2.17-36.el7.i686
glibc-2.17-36.el7.x86_64
glibc-devel-2.17-36.el7.i686
glibc-devel-2.17-36.el7.x86_64
ksh
libaio-0.3.109-9.el7.i686
libaio-0.3.109-9.el7.x86_64
libaio-devel-0.3.109-9.el7.i686
libaio-devel-0.3.109-9.el7.x86_64
libgcc-4.8.2-3.el7.i686
libgcc-4.8.2-3.el7.x86_64
libstdc++-4.8.2-3.el7.i686
libstdc++-4.8.2-3.el7.x86_64
libstdc++-devel-4.8.2-3.el7.i686
libstdc++-devel-4.8.2-3.el7.x86_64
libXi-1.7.2-1.el7.i686
libXi-1.7.2-1.el7.x86_64
libXtst-1.2.2-1.el7.i686
libXtst-1.2.2-1.el7.x86_64
make-3.82-19.el7.x86_64
sysstat-10.1.5-1.el7.x86_64
你也需要 unixODBC-2.3.1 或更新版本的驱动。
我希望你安装 Oracle 11g 的时候已经在你的 CentOS 7 上创建了名为 oracle 的用户。让我们以用户 oracle 登录 CentOS。以用户 oracle 登录到 CentOS 之后,在你的 CentOS上打开一个终端。
使用终端更改工作目录并导航到你解压两个 zip 文件的目录。在终端中输入以下命令开始安装 12c。
./runInstaller
如果一切顺利,你会看到类似下面的截图,已经开始安装 12c。
然后你可以选择跳过更新或者下载最近更新。如果是生产服务器,建议你必须更新。我这里选择跳过。
现在,选择升级现有数据库。
对于语言,这里已经有 English。点击下一步继续,或者你可以根据你的需要添加语言。
现在,选择企业版。你可以根据你的需求选择。
然后选择软件位置路径,这些都是不言自明的。
对于第七步,像下面这样使用默认的选择继续下一步。
在第九步中,你会看到一个类似下面这样的总结报告。
如果一切正常,你可以点击第九步中的 install 开始安装,进入第十步。
其中你可能会遇到一些错误,你需要通过谷歌找到这些错误的解决方法。你可能遇到的问题会有很多,因此我没有在这里详细介绍。
要有耐心,一步一步走下来最后它会告诉你成功了。否则,在谷歌上搜索做必要的操作解决问题。再一次说明,由于你可能会遇到的错误有很多,我无法在这里提供所有详细介绍。
现在,只需要按照下面屏幕指令配置监听器。
数据库升级助手
配置完监听器之后,它会启动数据库升级助手Database Upgrade Assistant。选择 Upgrade Oracle Database。
在第二步,你会发现它显示了 11g 的位置路径以及 12c 的位置路径。同时你也会发现它指示说从原来的 Oracle Home Release 11 安装 Oracle Home Release 12.点击下一步进入步骤三。
按照屏幕上的说明完成安装。
在最后一步,你会看到一个成功窗口,其中你会看到成功升级了 oracle 数据库。
一个忠告:对于你的生产服务器,在升级到 12c 之前,请确保你已经在其它平台上测试过,以便你能修复升级过程中遇到的所有错误。永远不要尝试一无所知的时候就升级生产服务器。
用scott用户打开两个窗口
1、外键无索引时,子表更新外键未提交,主表更新非子表引用的主键时被阻塞
会话1:
create table t1 (x int primary key);
insert into t1 values(1);
insert into t1 values(2);
insert into t1 values(3);
commit;
create table t2(y int references t1);
insert into t2 values(1);
commit;
update t2 set y=2 where y=1;
会话2:
update t1 set x=4 where x=3; //会话被阻塞
2、外键有索引时,子表更新外键未提交,主表更新非子表引用的主键时不会被阻塞
会话1:
create index t2_index on t2(y) ; //创建外键索引
update t2 set y=2 where y=1;
会话2:
update t1 set x=4 where x=3;
已更新 1 行;//可以正常更新
3、外键有无索引,对于子表更新外键未提交,主表更新相对应的主键无影响,更新主键的session都会被阻塞
会话1:
update t2 set y=2 where y=1;
会话2:
update t1 set x=4 where x=1; //更新子表已引用的
会话被阻塞。
会话1:
update t2 set y=2 where y=1;
会话2:
update t1 set x=4 where x=2 ; //更新子表将要引用的
会话被阻塞。――很好理解,主表要判断是否违反约束
二、更新子表非外键列未提交
1、外键无索引,更新主表已被外键引用的主键时,更新主键的session被阻塞
会话1:
create table t1 (x int primary key,x1 int);
insert into t1 values(1,1);
insert into t1 values(2,2);
insert into t1 values(3,3);
commit ;
create table t2(y int references t1,y1 int);
insert into t2 values(1,1);
commit ;
update t2 set y1=2 where y1=1;
会话2:
update t1 set x=4 where x=1; //更新外键引用的主键
会话被阻塞。
2、外键有索引,更新主表已被外键引用的主键时,更新主键的session不会被阻塞而报约束错误
会话1:
create index t2_index on t2(y);
update t2 set y1=2 where y1=1;
会话2:
update t1 set x=4 where x=1
*
ERROR 位于第 1 行:
ORA-02292: 违反完整约束条件 (SCOTT.SYS_C001607) - 已找到子记录日志
3、外键无索引,更新主表未被外键引用的主键时,更新主键的session被阻塞
会话1:
drop index t2_index;
update t2 set y1=2 where y1=1
会话2:
update t1 set x=4 where x=2;
会话被阻塞。
4、外键有索引,更新主表未被外键引用的主键时,更新主键的session不会被阻塞
会话1:
create index t2_index on t2(y);
update t2 set y1=2 where y1=1;
会话2:
update t1 set x=4 where x=2;
已更新 1 行。
另外在一个主表有on delete cascade,子表没有外键索引时,对主表操作会级联到子表,子表将进行全表扫描。
总结:在需要更新主键的情况下,最好是创建子表的外键索引。
1、update emp A,emp2 B set B.comm=A.comm WHERE B.empno=A.empno;
2、update emp2 B set B.comm=(select A.comm emp A where A.empno=B.empno group by A.comm);
如果不增加group by,存在重复值会报错。
3、将所有id存为一个文件或者指定id
spoll id.txt
select empno from emp;
spool off
写个shell
#!/bin/sh
cid=$1
if [ -z "$1" ];then
echo "Usage : $0 id.txt"
exit 1;
fi
for id in `cat id.txt`;do
echo -e "update emp2 B set B.comm=(select A.comm from emp A where A.empno='$id')
where B.id='$id';"
done | sqlplus -s 'user/123456'