oracle修改物化視圖字段,獲取物化視圖字段的修改矢量(一)

當表建立了物化視圖日志之后,表的DML修改會被記錄到物化視圖日志中,而物化視圖日志則包含了一個修改矢量,來記錄哪個列被修改。

在文章

列的修改矢量可以通過2的N次方來獲得,也就是POWER(2, N)。而N的值,就是列的位置。但是如果存在一些隱藏的列,通過DBA_TAB_COLUMNS來獲取列的位置就存在問題,比如:

SQL> CREATE TABLE T_PERSON OF T_PERSON_TYP

2? (ID PRIMARY KEY);

Table created.

SQL> SELECT COLUMN_ID

2? FROM DBA_TAB_COLUMNS

3? WHERE WNER = USER

4? AND TABLE_NAME = 'T_PERSON'

5? AND COLUMN_NAME = 'AGE';

COLUMN_ID

----------

3

SQL> SELECT INTCOL#

2? FROM SYS.COL$

3? WHERE NAME = 'AGE'

4? AND OBJ# =

5? (SELECT OBJECT_ID

6? FROM DBA_OBJECTS

7? WHERE WNER = USER

8? AND OBJECT_NAME = 'T_PERSON'

9? AND OBJECT_TYPE = 'TABLE');

INTCOL#

----------

5

SQL> CREATE MATERIALIZED VIEW LOG ON T_PERSON;

Materialized view log created.

SQL> INSERT INTO T_PERSON VALUES (1, 'ABC', 18, 'BCD');

1 row created.

SQL> UPDATE T_PERSON SET AGE = 20 WHERE ID = 1;

1 row updated.

SQL> COL CHANGE_VECTOR$$ FORMAT A30

SQL> SELECT * FROM MLOG$_T_PERSON;

ID SNAPTIME$$???? D O CHANGE_VECTOR$$

---------- -------------- - - ------------------------------

1 01-1月-00???? I N FE

1 01-1月-00???? U U 20

SQL> SELECT TO_CHAR(POWER(2, 5), 'XX') FROM DUAL;

TO_

---

20

SQL> SELECT TO_CHAR(POWER(2, 3), 'XX') FROM DUAL;

TO_

---

8

很顯然,物化視圖日志中獲取的列的偏移量是通過SYS.COL$視圖的INTCOL#列獲取的,而不是通過DBA_TAB_COLUMNS視圖。

表SYS.COL$中INTCOL#的值,就是我們要計算的N,得到POWER(2, N)后,通過TO_CHAR轉換為16進制的RAW,就是這個列對應的偏移量。

不過還需要注意一點,CHANGE_VECTOR$$中的偏移量和直接TO_CHAR得到的結果還是有區別的,首先二者的排列順序就有區別:

SQL> DROP TABLE T_PERSON PURGE;

Table dropped.

SQL> DROP TYPE T_PERSON_TYP;

Type dropped.

SQL> CREATE TABLE T_PERSON

2? (ID NUMBER PRIMARY KEY,

3? NAME VARCHAR2(30),

4? ADDR01 VARCHAR2(30),

5? ADDR02 VARCHAR2(30),

6? ADDR03 VARCHAR2(30),

7? ADDR04 VARCHAR2(30),

8? ADDR05 VARCHAR2(30),

9? ADDR06 VARCHAR2(30),

10? ADDR07 VARCHAR2(30),

11? ADDR08 VARCHAR2(30),

12? ADDR09 VARCHAR2(30),

13? ADDR10 VARCHAR2(30),

14? ADDR11 VARCHAR2(30),

15? ADDR12 VARCHAR2(30),

16? ADDR13 VARCHAR2(30),

17? ADDR14 VARCHAR2(30),

18? ADDR15 VARCHAR2(30),

19? ADDR16 VARCHAR2(30),

20? ADDR17 VARCHAR2(30),

21? ADDR18 VARCHAR2(30),

22? AGE NUMBER);

Table created.

SQL> CREATE MATERIALIZED VIEW LOG ON T_PERSON;

Materialized view log created.

SQL> SELECT TO_CHAR(POWER(2, INTCOL#), 'XXXXXX')

2? FROM SYS.COL$

3? WHERE NAME = 'AGE'

4? AND OBJ# =

5? (SELECT OBJECT_ID

6? FROM DBA_OBJECTS

7? WHERE WNER = USER

8? AND OBJECT_NAME = 'T_PERSON'

9? AND OBJECT_TYPE = 'TABLE');

TO_CHAR

-------

200000

SQL> INSERT INTO T_PERSON

2? (ID, NAME, AGE)

3? VALUES (1, 'A', 15);

1 row created.

SQL> UPDATE T_PERSON SET AGE = 18;

1 row updated.

SQL> SELECT * FROM MLOG$_T_PERSON;

ID SNAPTIME$$???? D O CHANGE_VECTOR$$

---------- -------------- - - ------------------------------

1 01-1月-00???? I N FEFFFF

1 01-1月-00???? U U 000020

顯然物化視圖日志中的偏移量是逆向的,好在Oracle的內置函數REVERSE也支持RAW類型,省得自己編寫這個函數了:

SQL> SELECT REVERSE(LTRIM(TO_CHAR(POWER(2, INTCOL#), 'XXXXXX')))

2? FROM SYS.COL$

3? WHERE NAME = 'AGE'

4? AND OBJ# =

5? (SELECT OBJECT_ID

6? FROM DBA_OBJECTS

7? WHERE WNER = USER

8? AND OBJECT_NAME = 'T_PERSON'

9? AND OBJECT_TYPE = 'TABLE');

REVERSE

-------

000002

這里還有問題,REVERSE采用字符串的反轉方法,而這時需要RAW類型的反轉:

SQL> SELECT REVERSE(CAST(LTRIM(TO_CHAR(POWER(2, INTCOL#), 'XXXXXX')) AS RAW(255)))

2? FROM SYS.COL$

3? WHERE NAME = 'AGE'

4? AND OBJ# =

5? (SELECT OBJECT_ID

6? FROM DBA_OBJECTS

7? WHERE WNER = USER

8? AND OBJECT_NAME = 'T_PERSON'

9? AND OBJECT_TYPE = 'TABLE');

REVERSE(CAST(LTRIM(TO_CHAR(POWER(2,INTCOL#),'XXXXXX'))ASRAW(255)))

------------------------------------------------------------------

000020

下面還有一些問題,首先就是TO_CHAR后結果的前綴0問題:

SQL> UPDATE T_PERSON SET ADDR08 = 5;

1 row updated.

SQL> SELECT * FROM MLOG$_T_PERSON;

ID SNAPTIME$$???? D O CHANGE_VECTOR$$

---------- -------------- - - ------------------------------

1 01-1月-00???? I N FEFFFF

1 01-1月-00???? U U 000020

1 01-1月-00???? U U 000400

SQL> SELECT REVERSE(CAST(LTRIM(TO_CHAR(POWER(2, INTCOL#), 'XXXXXX')) AS RAW(255)))

2? FROM SYS.COL$

3? WHERE NAME = 'ADDR08'

4? AND OBJ# =

5? (SELECT OBJECT_ID

6? FROM DBA_OBJECTS

7? WHERE WNER = USER

8? AND OBJECT_NAME = 'T_PERSON'

9? AND OBJECT_TYPE = 'TABLE');

REVERSE(CAST(LTRIM(TO_CHAR(POWER(2,INTCOL#),'XXXXXX'))ASRAW(255)))

------------------------------------------------------------------

0004

在TO_CHAR的時候使用’0X’作為參數可以避免前綴0的問題:

SQL> SELECT REVERSE(CAST(LTRIM(TO_CHAR(POWER(2, INTCOL#), '0XXXXX')) AS RAW(255)))

2? FROM SYS.COL$

3? WHERE NAME = 'ADDR08'

4? AND OBJ# =

5? (SELECT OBJECT_ID

6? FROM DBA_OBJECTS

7? WHERE WNER = USER

8? AND OBJECT_NAME = 'T_PERSON'

9? AND OBJECT_TYPE = 'TABLE');

REVERSE(CAST(LTRIM(TO_CHAR(POWER(2,INTCOL#),'0XXXXX'))ASRAW(255)))

------------------------------------------------------------------

000400

但是另一個麻煩的問題又出現了,就是執行TO_CHAR的時候需要指定多少個X,X的個數如果少了會報錯,個數多了結果又不正確。

其中X的個數由表中總的列數來決定,具體算法為:

SQL> SELECT FLOOR(LOG(256, POWER(2, COUNT(*)))) + 1

2? FROM SYS.COL$

3? WHERE OBJ# =

4? (SELECT OBJECT_ID

5? FROM DBA_OBJECTS

6? WHERE WNER = USER

7? AND OBJECT_NAME = 'T_PERSON'

8? AND OBJECT_TYPE = 'TABLE');

FLOOR(LOG(256,POWER(2,COUNT(*))))+1

-----------------------------------

3

將上面的結果整合在一起:

SQL> SELECT REVERSE(CAST(LTRIM(TO_CHAR(NUM, RPAD('0X', CNT * 2, 'X'))) AS RAW(255)))

2? FROM

3? (

4???? SELECT POWER(2, INTCOL#) NUM,

5???????????? FLOOR(LOG(256, POWER(2, COUNT(*) OVER()))) + 1 CNT,

6???????????? NAME

7???? FROM SYS.COL$

8???? WHERE OBJ# =

9???? (

10???????????? SELECT OBJECT_ID

11???????????? FROM DBA_OBJECTS

12???????????? WHERE WNER = USER

13???????????? AND OBJECT_NAME = 'T_PERSON'

14???????????? AND OBJECT_TYPE = 'TABLE'

15???? )

16? )

17? WHERE NAME = 'ADDR13';

REVERSE(CAST(LTRIM(TO_CHAR(NUM,RPAD('0X',CNT*2,'X')))ASRAW(255)))

-----------------------------------------------------------------

008000

SQL> SELECT REVERSE(CAST(LTRIM(TO_CHAR(NUM, RPAD('0X', CNT * 2, 'X'))) AS RAW(255)))

2? FROM

3? (

4???? SELECT POWER(2, INTCOL#) NUM,

5???????????? FLOOR(LOG(256, POWER(2, COUNT(*) OVER()))) + 1 CNT,

6???????????? NAME

7???? FROM SYS.COL$

8???? WHERE OBJ# =

9???? (

10???????????? SELECT OBJECT_ID

11???????????? FROM DBA_OBJECTS

12???????????? WHERE WNER = USER

13???????????? AND OBJECT_NAME = 'T_PERSON'

14???????????? AND OBJECT_TYPE = 'TABLE'

15???? )

16? )

17? WHERE NAME = 'AGE';

REVERSE(CAST(LTRIM(TO_CHAR(NUM,RPAD('0X',CNT*2,'X')))ASRAW(255)))

-----------------------------------------------------------------

000020

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/392195.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/392195.shtml
英文地址,請注明出處:http://en.pswp.cn/news/392195.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

聚合 數據處理_R中聚合的簡介:強大的數據處理工具

聚合 數據處理by Satyam Singh Chauhan薩蒂揚辛格喬漢(Satyam Singh Chauhan) R中聚合的簡介:強大的數據處理工具 (An introduction to aggregates in R: a powerful tool for playing with data) Data Visualization is not just about colors and graphs. It’s …

大數據 notebook_Dockerless Notebook:數據科學期待已久的未來

大數據 notebookData science is hard. Data scientists spend hours figuring out how to install that Python package on their laptops. Data scientists read many pages of Google search results to connect to that database. Data scientists write a detailed docume…

【NGN學習筆記】6 代理(Proxy)和背靠背用戶代理(B2BUA)

1. 什么是Proxy模式? 按照RFC3261中的定義,Proxy服務器是一個中間的實體,它本身即作為客戶端也作為服務端,為其他客戶端提供請求的轉發服務。一個Proxy服務器首先提供的是路由服務,也就是說保證請求被發到更加”靠近”…

分布與并行計算—并行計算π(Java)

并行計算π public class pithread extends Thread {private static long mini1000000000;private long start,diff;double sum0;double cur1/(double)mini;public pithread(long start,long diff) {this.startstart;this.diffdiff;}Overridepublic void run() {long istart;f…

linux復制文件跳過相同,Linux cp指令,怎么跳過相同的文件

1、使用cp命令的-n參數即可跳過相同的文件 。2、cp命令使用詳解:1)、用法:cp [選項]... [-T] 源文件 目標文件或:cp [選項]... 源文件... 目錄或:cp [選項]... -t 目錄 源文件...將源文件復制至目標文件,或將多個源文件…

eclipse類自動生成注釋

1.創建新類時自動生成注釋 window->preference->java->code styple->code template 當你選擇到這部的時候就會看見右側有一個框顯示出code這個選項,你點開這個選項,點一下他下面的New …

rman恢復

--建表create table sales( product_id number(10), sales_date date, sales_cost number(10,2), status varchar2(20));--插數據insert into sales values (1,sysdate-90,18.23,inactive);commit; --啟用rman做全庫備份 運行D:\autobackup\rman\backup_orcl.bat 生成…

微軟大數據_我對Microsoft的數據科學采訪

微軟大數據Microsoft was one of the software companies that come to hire interns at my university for 2021 summers. This year, it was the first time that Microsoft offered any Data Science Internship for pre-final year undergraduate students.微軟是到2021年夏…

再次檢查打印機名稱 并確保_我們的公司名稱糟透了。 這是確保您沒有的方法。...

再次檢查打印機名稱 并確保by Dawid Cedrych通過戴維德塞德里奇 我們的公司名稱糟透了。 這是確保您沒有的方法。 (Our company name sucked. Here’s how to make sure yours doesn’t.) It is harder than one might think to find a good business name. Paul Graham of Y …

linux中文本查找命令,Linux常用的文本查找命令 find

一、常用的文本查找命令grep、egrep命令grep:文本搜索工具,根據用戶指定的文本模式對目標文件進行逐行搜索,先是能夠被模式匹配到的行。后面跟正則表達式,讓grep工具相當強大。-E之后還支持擴展的正則表達式。# grep [options] …

分布與并行計算—日志挖掘(Java)

日志挖掘——處理數據、計費統計 1、讀取附件中日志的內容,找出自己學號停車場中對應的進出車次數(in/out配對的記錄數,1條in、1條out,視為一個車次,本日志中in/out為一一對應,不存在缺失某條進或出記錄&a…

《人人都該買保險》讀書筆記

內容目錄: 1.你必須知道的保險知識 2.家庭理財的必需品 3.保障型保險產品 4.儲蓄型保險產品 5.投資型保險產品 6.明明白白買保險 現在我所在的公司Manulife是一家金融保險公司,主打業務就是保險,因此我需要熟悉一下保險的基礎知識&#xff0c…

Linux下查看txt文檔

當我們在使用Window操作系統的時候,可能使用最多的文本格式就是txt了,可是當我們將Window平臺下的txt文本文檔復制到Linux平臺下查看時,發現原來的中文所有變成了亂碼。沒錯, 引起這個結果的原因就是兩個平臺下,編輯器…

如何擊敗騰訊_擊敗股市

如何擊敗騰訊個人項目 (Personal Proyects) Note from Towards Data Science’s editors: While we allow independent authors to publish articles in accordance with our rules and guidelines, we do not endorse each author’s contribution. You should not rely on an…

滑塊 組件_組件制作:如何使用鏈接的輸入創建滑塊

滑塊 組件by Robin Sandborg羅賓桑德伯格(Robin Sandborg) 組件制作:如何使用鏈接的輸入創建滑塊 (Component crafting: how to create a slider with a linked input) Here at Stacc, we’re huge fans of React and the render-props pattern. When it came time…

配置靜態IPV6 NAT-PT

一.概述: IPV6 NAT-PT( Network Address Translation - Port Translation)應用與ipv4和ipv6網絡互訪的情況,根據參考鏈接配置時出現一些問題,所以記錄下來。參考鏈接:http://www.cisco.com/en/US/tech/tk648/tk361/technologies_c…

linux 線程與進程 pid,linux下線程所屬進程號問題

這一段看《unix環境高級編程》,一個關于線程的小例子。#include#include#includepthread_t ntid;void printids(const char *s){pid_t pid;pthread_t tid;pidgetpid();tidpthread_self();printf("%s pid %u tid %u (0x%x)n",s,(unsigned int)pid,(unsigne…

python3虛擬環境中解決 ModuleNotFoundError: No module named '_ssl'

前提是已經安裝了openssl 問題 當我在python3虛擬環境中導入ssl模塊時報錯,報錯如下: (py3) [rootlocalhost Python-3.6.3]# python3 Python 3.6.3 (default, Nov 19 2018, 14:18:18) [GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux Type "help…

python 使用c模塊_您可能沒有使用(但應該使用)的很棒的Python模塊

python 使用c模塊by Adam Goldschmidt亞當戈德施密特(Adam Goldschmidt) 您可能沒有使用(但應該使用)的很棒的Python模塊 (Awesome Python modules you probably aren’t using (but should be)) Python is a beautiful language, and it contains many built-in modules that…

分布與并行計算—生產者消費者模型實現(Java)

在實際的軟件開發過程中,經常會碰到如下場景:某個模塊負責產生數據,這些數據由另一個模塊來負責處理(此處的模塊是廣義的,可以是類、函數、線程、進程等)。產生數據的模塊,就形象地稱為生產者&a…