Oracle 11g 虚拟列 Virtual Column介绍

Oracle 11G 虚拟列 Virtual Column

Oracle 11G 在表中引入了虚拟列,虚拟列是一个表达式,在运行时计算,不存储在数据库中,不能更新虚拟列的值。

定义一个虚拟列的语法:

	column_name [datatype] [GENERATED ALWAYS] AS [expression] [VIRTUAL]

1.虚拟列可以用在select,update,delete语句的where条件中,但是不能用于DML语句
2.可以基于虚拟列来做分区
3. 可以在虚拟列上建索引,oracle的函数索引就类似。
4. 可以在虚拟列上建约束

创建一个带虚拟列的表:

	CREATE TABLE EMPLOYEE
	(
		empl_id        NUMBER,
		empl_nm        VARCHAR2(50),
		monthly_sal    NUMBER(10,2),
		bonus          NUMBER(10,2),
		total_sal      NUMBER(10,2) GENERATED ALWAYS AS (monthly_sal*12 + bonus)
	);

 total_sal就是一个虚拟列

查看下表定义内容:

	SELECT column_name, data_type, data_length, data_default, virtual_column
	  FROM user_tab_cols
	 WHERE table_name = ‘EMPLOYEE‘;

	COLUMN_NAME | DATA_TYPE | DATA_LENGTH | DATA_DEFAULT             | VIRTUAL_COLUMN
	EMPL_ID     | NUMBER    | 22          | null                     | NO
	EMPL_NM     | VARCHAR2  | 50          | null                     | NO
	MONTHLY_SAL | NUMBER    | 22          | null                     | NO
	BONUS       | NUMBER    | 22          | null                     | NO
	TOTAL_SAL   | NUMBER    | 22          | "MONTHLY_SAL"*12+"BONUS" | YES        

virtual_column是yes,表示是虚拟列,我们也可以在建表语句加上VIRTUAL,显示声明为虚拟列

	DROP TABLE EMPLOYEE PURGE;

	CREATE OR REPLACE FUNCTION get_empl_total_sal ( p_monthly_sal   NUMBER,
													p_bonus         NUMBER)
	   RETURN NUMBER
	DETERMINISTIC
	IS
	BEGIN
	   RETURN p_monthly_sal * 12 + p_bonus;
	END;

	CREATE TABLE EMPLOYEE
	(empl_id     NUMBER,
	 empl_nm     VARCHAR2(50),
	 monthly_sal NUMBER(10,2),
	 bonus       NUMBER(10,2),
	 total_sal   NUMBER(10,2) AS (get_empl_total_sal(monthly_sal, bonus)) VIRTUAL
	);

我们可以在虚拟列上创建索引

	CREATE INDEX idx_total_sal ON employee(total_sal);

	SELECT index_name, index_type
	  FROM user_indexes
	 WHERE table_name = ‘EMPLOYEE‘;

	INDEX_NAME     INDEX_TYPE
	IDX_TOTAL_SAL  FUNCTION-BASED NORMAL

这个函数也是表定义内容

	DROP FUNCTION get_empl_total_sal;

	SELECT * FROM employee;
	*
	Error at line 0
	ORA-00904: "schema"."GET_EMPL_TOTAL_SAL": invalid identifier

可以添加一个虚拟列

	DROP TABLE EMPLOYEE PURGE;

	CREATE TABLE EMPLOYEE
	(empl_id     NUMBER,
	 empl_nm     VARCHAR2(50),
	 monthly_sal NUMBER(10,2),
	 bonus       NUMBER(10,2)
	);

	ALTER TABLE EMPLOYEE ADD (total_sal AS (monthly_sal * 12 + bonus));

这个新列的类型时不确定的,是根据表达式来推断的。

	INSERT INTO employee (empl_id, empl_nm, monthly_sal, bonus)
	   WITH DATA AS
			(SELECT 100 empl_id, ‘AAA‘ empl_nm, 20000 monthly_sal, 3000 bonus
			   FROM DUAL
			 UNION
			 SELECT 200, ‘BBB‘, 12000, 2000
			   FROM DUAL
			 UNION
			 SELECT 300, ‘CCC‘, 32100, 1000
			   FROM DUAL
			 UNION
			 SELECT 400, ‘DDD‘, 24300, 5000
			   FROM DUAL
			 UNION
			 SELECT 500, ‘EEE‘, 12300, 8000
			   FROM DUAL)
	   SELECT *
		 FROM DATA;

	SELECT * FROM employee;

	EMPL_ID | EMPL_NM | MONTHLY_SAL | BONUS | TOTAL_SAL
	100     | AAA     | 20000       | 3000  | 243000
	200     | BBB     | 12000       | 2000  | 146000
	300     | CCC     | 32100       | 1000  | 386200
	400     | DDD     | 24300       | 5000  | 296600
	500     | EEE     | 12300       | 8000  | 155600

在虚拟列上执行update语句是不允许的

	UPDATE employee
	   SET total_sal = 2000;

	ORA-54017: UPDATE operation disallowed on virtual columns

能够从虚拟列上收集表的统计信息

	EXEC DBMS_STATS.GATHER_TABLE_STATS(user, ‘EMPLOYEE‘);

	SELECT column_name, num_distinct,
		   display_raw (low_value, data_type)  low_value,
		   display_raw (high_value, data_type) high_value
	  FROM dba_tab_cols
	 WHERE table_name = ‘EMPLOYEE‘;

	COLUMN_NAME | NUM_DISTINCT | LOW_VALUE | HIGH_VALUE
	TOTAL_SAL   | 5            | 146000    | 386200
	BONUS       | 5            | 1000      | 8000
	MONTHLY_SAL | 5            | 12000     | 32100
	EMPL_NM     | 5            | AAA       | EEE
	EMPL_ID     | 5            | 100       | 500

基于虚拟列的分区

	DROP TABLE EMPLOYEE PURGE;

	CREATE TABLE employee
	(empl_id     NUMBER,
	 empl_nm     VARCHAR2(50),
	 monthly_sal NUMBER(10,2),
	 bonus       NUMBER(10,2),
	 total_sal   NUMBER(10,2) AS (monthly_sal*12 + bonus)
	)
	PARTITION BY RANGE (total_sal)
		(PARTITION sal_200000 VALUES LESS THAN (200000),
		 PARTITION sal_400000 VALUES LESS THAN (400000),
		 PARTITION sal_600000 VALUES LESS THAN (600000),
		 PARTITION sal_800000 VALUES LESS THAN (800000),
		 PARTITION sal_default VALUES LESS THAN (MAXVALUE));

	INSERT INTO employee (empl_id, empl_nm, monthly_sal, bonus)
	   WITH DATA AS
			(SELECT 100 empl_id, ‘AAA‘ empl_nm, 20000 monthly_sal, 3000 bonus
			   FROM DUAL
			 UNION
			 SELECT 200, ‘BBB‘, 12000, 2000
			   FROM DUAL
			 UNION
			 SELECT 300, ‘CCC‘, 32100, 1000
			   FROM DUAL
			 UNION
			 SELECT 400, ‘DDD‘, 24300, 5000
			   FROM DUAL
			 UNION
			 SELECT 500, ‘EEE‘, 12300, 8000
			   FROM DUAL)
	   SELECT *
		 FROM DATA;

	EXEC DBMS_STATS.GATHER_TABLE_STATS(user,‘EMPLOYEE‘,granularity => ‘PARTITION‘);

	SELECT   table_name, partition_name, num_rows
		FROM user_tab_partitions
	   WHERE table_name = ‘EMPLOYEE‘
	ORDER BY partition_name;

	TABLE_NAME | PARTITION_NAME | NUM_ROWS
	EMPLOYEE   | SAL_200000     | 2
	EMPLOYEE   | SAL_400000     | 3
	EMPLOYEE   | SAL_600000     | 0
	EMPLOYEE   | SAL_800000     | 0
	EMPLOYEE   | SAL_DEFAULT    | 0

在分区情况下,不能更新虚拟列引用的列

	UPDATE employee
	   SET monthly_sal = 30000
	 WHERE empl_id = 500;

	ORA-14402: updating partition key column would cause a partition change

如果在分区情况能够更新,则需要设置ENABLE ROW MOVEMENT

	ALTER TABLE employee ENABLE ROW MOVEMENT;

	UPDATE employee
	   SET monthly_sal = 80000
	 WHERE empl_id = 500;

	1 row updated.

不能基于函数表达式的虚拟列上的分区

	CREATE TABLE employee_new
	(empl_id     NUMBER,
	 empl_nm     VARCHAR2(50),
	 monthly_sal NUMBER(10,2),
	 bonus       NUMBER(10,2),
	 total_sal   NUMBER(10,2) AS (get_empl_total_sal(monthly_sal, bonus))
	)
	PARTITION BY RANGE (total_sal)
		(PARTITION sal_200000 VALUES LESS THAN (200000),
		 PARTITION sal_400000 VALUES LESS THAN (400000),
		 PARTITION sal_600000 VALUES LESS THAN (600000),
		 PARTITION sal_800000 VALUES LESS THAN (800000),
		 PARTITION sal_default VALUES LESS THAN (MAXVALUE));

	ORA-54021: Cannot use PL/SQL expressions in partitioning or subpartitioning columns
时间: 2024-10-29 19:09:39

Oracle 11g 虚拟列 Virtual Column介绍的相关文章

[oracle 11g 新特性] virtual column虚拟列

总结:虚拟列可以使用于一些特殊场合,实质是类似于函数列(即以 表中已有的列 经过函数运算得来),“虚拟列不存储在数据库中,是在执行查询时由oracle后台计算出来返回给用户”,因此虚拟列不会增加存储空间,但是由于需要计算,需要消耗额外的CPU Time. ---创建表时使用虚拟列 SQL> create table test4(id number,name varchar2(300),hash_id as(ora_hash(id))); Table created ---alter 表新增虚拟列

Oracle 11g虚拟列上建分区

在Oracle 11g上,可以在虚拟列上做分区,这个特性还比较有用,下面来做一个测试: SQL> select * from v$version; BANNER -------------------------------------------------------------------------------- Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production PL/SQL Rele

Oracle 11g新特性之--虚拟列(Virtual Column)

Oracle 11g新特性之--虚拟列(Virtual Column) Oracle 11G虚拟列Virtual Column介绍 Oracle 11G 在表中引入了虚拟列,虚拟列是一个表达式,在运行时计算,不存储在数据库中,不能更新虚拟列的值. 定义一个虚拟列的语法: column_name [datatype] [GENERATED ALWAYS] AS [expression] [VIRTUAL] 1.虚拟列可以用在select,update,delete语句的where条件中,但是不能用

Oracle 虚拟列 子分区 virtual column partition

Oracle 11g 虚拟列子分区实验 以下两个create 语句均为创建成功: 需求描述: 项目要求对3个字段进行分区,如时间,小时,还有个区域ID,便联想到虚拟列. drop table test_part purge;   create table test_part  (t_time date,  hour number,  city_id number,  hour_city varchar2(108) GENERATED ALWAYS AS(to_char(hour)||'|'||t

数据的虚拟列-让数据库中的C字段等于a+b

直接用update aaaaa aa set aa.f = (aa.a+aa.b)就行了 ======================================= 引出来的新知识--虚拟列 虚拟列的好处是:如果c=a+b那插入数据时:值只插入a=1,b=2;那么c会自动是3 oracle temporary table and virtual column (2013-07-31 15:06:55) 转载▼ 标签: oracle 学习 临时表 虚拟列 分类: Oracle基础学习 表是数据

Oracle 11g从入门到精通pdf

下载地址:网盘下载 内容要点 编辑 本书是针对Oracle公司最新推出的大型数据库管理系统Oracle 11g编写的,循环渐进地介绍了Oracle的基本知识.其内容包括四大部分:Oracle的基本概念,非模式对象的管理,模式对象的管理,数据库的安全与恢复等.本书强调理论结合实际,将数据库理论中的重要内容和Oracle 11g 的实现结合起来介绍. 目录 编辑 第1章 了解Oracle 1.1 Oracle中的基本概念 1.1.1 数据库 1.1.2 实例 1.1.3 用户与模式 1.2 Orac

Oracle 11g 新特性(一)-- 虚拟列

数据库版本: Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - 64bit Oracle11g 增加了虚拟列的新特性, 具体说明如下: 1> 只能在堆组织表(普通表)上创建虚拟列,不能在索引组织表.外部表.临时表上创建虚拟列 2> 虚拟列不能是LOB或者RAW类型 3> 虚拟列的值并不是真实存在的,只有用到时,才根据表达式计算出虚拟列的值,磁盘上并不存放 4> 可把虚拟列当做分区关键字建立分区表,这是ORACLE

Oracle 11g新特性虚拟列分区

现在有个需求:一个单据表要按照月份来分区,如果是在Oracle 10g上,只能再加一个字段.在Oracle 11g以后就不一样了,可以用虚拟列处理. SQL> select * from v$version; BANNER -------------------------------------------------------------------------------- Oracle Database 11g Enterprise Edition Release 11.2.0.1.0

ORACLE虚拟索引(Virtual Index)

ORACLE虚拟索引(Virtual Index)   虚拟索引概念 虚拟索引(Virtual Indexes)是一个定义在数据字典中的假索引(fake index),它没有相关的索引段.虚拟索引的目的是模拟索引的存在而不用真实的创建一个完整索引.这允许开发者创建虚拟索引来查看相关执行计划而不用等到真实创建完索引才能查看索引对执行计划的影响,并且不会增加存储空间的使用.如果我们观察到优化器生成了一个昂贵的执行计划并且SQL调整指导建议我们对某些的某列创建索引,但在生产数据库环境中创建索引与测试并