`

Oracle 11G 虚拟列 Virtual Column介绍

 
阅读更多

原文链接:http://www.javaarch.net/jiagoushi/705.htm

 

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

 

 

分享到:
评论

相关推荐

    Oracle11g中文文档.zip

    oracle11g官方中文帮助 Oracle 11g:ORACLE ACTIVE DATA GUARD.pdf Oracle Database 11g 高可用性.pdf Oracle 数据库 11g 中的分区.pdf Oracle 数据库 11g :真正应用测试与可管理性概述.pdf Oracle 数据库 11g...

    oracle11g官方中文文档完整版

    Oracle 11g 官方中文文档 包括一下部分文档: Oracle 11g:ORACLE ACTIVE DATA GUARD.pdf Oracle Database 11g 高可用性.pdf Oracle 数据库 11g :真正应用测试与可管理性概述.pdf Oracle 数据库 11g 中的分区....

    oracle10G和oracle11G的OCI.dll

    在Oracle 10G和11G版本中,oci.dll扮演了至关重要的角色,为应用程序提供了访问数据库的底层接口。Navicat是一款流行的数据库管理工具,它利用oci.dll来连接并操作Oracle数据库。 Oracle 10G是Oracle公司在2003年...

    oracle11g 百度盘下载

    在这个“Oracle11g 百度盘下载”资源中,用户可以获取到Oracle 11g的安装包,以便在自己的计算机上搭建数据库环境。下面将详细阐述Oracle 11g的一些核心特性和关键知识点。 1. **数据库版本**:Oracle 11g是Oracle...

    Linux安装oracle11G

    本文将详细介绍如何在Linux系统中安装oracle11G。 一、挂盘 在安装oracle11G之前,需要挂载安装盘。使用mount命令将安装盘挂载到/mnt目录下,例如: [root@zjh ~]# mount /dev/cdrom /mnt 然后,使用rpm命令安装...

    个人版oracle 11g安装图解

    "Oracle 11g 安装图解" 本文将指导读者如何下载和安装 Oracle 11g 数据库,通过截屏图的形式展示安装过程,帮助读者顺利安装 Oracle 11g 数据库。 一、前提条件 在安装 Oracle 11g 之前,需要确保系统满足以下...

    Red hat linux 安装oracle 11g

    本文将详细介绍如何在 Red Hat Linux 中安装 Oracle 11g。首先,需要准备好安装环境,包括关闭防火墙、检查 RPM 包是否安装等。然后,安装 Oracle 11g 的过程可以分为多个步骤,包括安装前准备、安装 Oracle 软件、...

    oracle11G的linux下的离线安装教程.pdf

    "Oracle 11g 在 Linux 下的离线安装教程" 一、查看和修改主机名称 在 Oracle 11g 的安装过程中,需要查看和修改主机名称。可以使用 hostname 命令来查看当前主机名称,并使用 hostname 命令来修改主机名称。 二、...

    oracle 11g 下载地址

    根据提供的文件信息,本文将围绕Oracle 11g的下载及其相关知识点进行详细介绍。Oracle 11g是一款功能强大的数据库管理系统,它为企业级应用提供了稳定、高效的数据存储和管理服务。 ### Oracle 11g简介 Oracle 11g...

    欧拉系统安装oracle 11g

    本资源摘要信息将详细介绍欧拉系统安装 Oracle 11g 的过程,包括安装依赖包、安装 Oracle 11g 等步骤。 安装依赖包 在安装 Oracle 11g 之前,需要安装一些依赖包,以确保安装过程的顺利进行。这些依赖包包括: 1....

    Oracle 11g Concepts中英文对照.pdf

    为帮助用户更好地理解和使用 Oracle 11g,我们将从以下几个方面对 Oracle 11g 的概念进行详细介绍。 数据库管理系统(DBMS) 数据库管理系统(DBMS)是指管理和存储数据的软件系统。DBMS 提供了一个强大的平台,...

    Oracle数据库11g各版本介绍及功能比较

    Oracle 数据库 11g 各版本介绍及功能比较 Oracle 数据库 11g 提供了多个版本供选择,包括标准版、企业版等。这些版本都使用相同的通用代码库构建,这意味着企业的数据库管理软件可以轻松地从规模较小的单一处理器...

    中标麒麟linux安装oracle11G.docx

    中标麒麟Linux安装Oracle 11G 知识点1:中标麒麟Linux简介 中标麒麟Linux是一个基于开源操作系统的国产操作系统,具有高性价比、易用性强、安全性高的特点。中标麒麟Linux主要应用于政府、企业、教育、医疗等领域...

    Oracle11g_64位_Linux版本下载.txt

    ### Oracle11g_64位_Linux版本下载知识点详解 #### 一、Oracle11g简介 Oracle Database 11g(简称Oracle11g)是甲骨文公司(Oracle Corporation)推出的一款关系型数据库管理系统。Oracle11g继承了Oracle10g的优秀...

    Oracle11g彻底卸载方法

    在本文中,我们将详细介绍如何彻底卸载Oracle11g,避免手动清理注册表的复杂步骤。 首先,彻底卸载Oracle11g需要遵循一定的顺序,以确保所有组件都被正确移除。以下是一步一步的指南: 1. **停止Oracle服务**:在...

    Oracle11g中文文档

    Oracle11g是一款由甲骨文公司开发的关系型数据库管理系统,是Oracle数据库产品线中的一个重要版本。本套中文文档全面涵盖了Oracle11g的各项特性和功能,为学习和使用Oracle11g数据库提供了详实的参考资料。以下是...

    oracle 11g客户端免安装

    Oracle 11g客户端是Oracle数据库的一个轻量级版本,主要供开发人员和DBA用于连接到Oracle服务器,进行数据库管理、查询以及开发工作。它无需进行完整的安装过程,简化了部署,使得用户可以直接将其解压到指定位置,...

    oracle11g 客户端 windows 64位

    Oracle 11g客户端是Oracle数据库的一个重要组成部分,主要用于连接到Oracle服务器进行数据查询、管理和其他操作。在Windows 64位操作系统上安装这个客户端,可以让开发者和DBA在本地环境中进行高效的数据处理和分析...

Global site tag (gtag.js) - Google Analytics