Oracle高级查询及数据库对象

📅 2026/8/11 10:51:15
Oracle高级查询及数据库对象
Oracle高级查询及数据库对象一 知识点概要[1 Oracle的函数(★★★★)](#_二 Oracle的函数)[① 什么是函数](#_2.1 什么是函数)[② 函数的分类](#_2.2 函数的分类)[③ 字符函数](#_2.3 字符函数)[④ 数字函数](#_2.4 数字函数)[⑤ 转换函数](#_2.5 转换函数)[⑥ 日期函数](#_2.6 日期函数)[⑦ 其它函数](#_2.7 其它函数)[⑧ 组(聚合)函数](#_2.8 分组函数)[2 Oracle的高级查询(★★★★)](#_三 Oracle多表连接)二 Oracle的函数2.1 什么是函数函数指对一堆逻辑的打包能够支持传入的参数根据参数得到一定的结果那么,在oracle中都有什么函数有什么类型的函数函数有什么分类2.2 函数的分类2.2.1 单行与多行除了聚合(组)函数其它全是单行函数Oracle的函数咱们可以简单分成再种多行函数与单行函数如下图:函数单行函数多行函数2.2.1.1 什么是单行函数简单理解对单行数据进行是操作得到单行数据; 比如concat连接函数concat 连接函数得到的效果; 使用concat 不会影响行数以前100行使用concat之后得到的结果也是100行。单行函数 在执行获得结果后。可以支持传入参数【列和表达式】针对每一行单独做运算。最终不会影响结果的行数。单行函数特点:1接收参数返回一个值2对每一行返回行起作用3每一行返回一个结果4可以修改数据类型5可以使用嵌套 concat(concat(col1,col2),col2)除了concat 这样的单行函数以外还有其他的单行函数比如字符处理函数比如有时要求用户名全部大写或者小写或者需要得到一个人的姓这些都需要字符函数进行处理字符函数中也存在分类2.2.1.2 什么是多行函数多行函数简单理解对多行数据进行操作最后返回一个数据比如count函数Count 针对过滤后的结果 支持传入表的列名或者常量对所有行的记录统一处理。最终只会得到一个结果,会影响结果行数;多行函数 : 在执行获得结果后。可以支持传入参数【列和表达式】针对每一行整体统计做运算。一般来说,最终只会产生1行数据咱们所说的单行与多行是指这个函数操作的数据是单行还是多行(不是说的结果)2.2.1.3 单行、多行分别用在哪扩展理解与练习比如concat 用在哪里? 可以放在select 后把它的姓和名连接起来单行函数:select 关键字之后where 之后的条件上where 之后单行函数 如下姓名中有e或者a的员工?把姓名组合起来查询select * from employeeswhere first_name || last_name like ‘%e%’or first_name || last_name like ‘%a%’使用函数Select * from employeesWhereconcat(first_name,last_name)like ‘%e%’Or first_name || last_name like ‘%a%’;多行函数:针对Select 关键之后 比如count函数 统计所有行 放在select之后使用多行函数 得到就一个结果那我放在where 后面 有意义吗Where 是针对每一行 而多行函数 返回结果只有一行如果放在where 之后执行一次是一个结果执行二次还是同一个结果所以没有意义.2.2.2 函数功能分类可以分为字符函数、数字函数转换函数日期函数组函数其它函数字符(串)函数拼接字符串截取字符串全变大写全变小写首字母大写…数字(number)函数四舍五入舍掉转换函数字符《–》日期 字符《–》数字日期函数拿到年月日时分秒组函数sum,count,max…其它函数2.3 字符函数字符函数分为大小写转换函数与字符处理函数2.3.1 大小写转换函数大小写转换函数:Lower(列|表达式) 全部转换小写Upper(列|表达式) 全部转换大写Initcap(列|表达式) 首字母大写练习案例select ‘Hello world’ from dual;大写selectupper(‘Hello world’) from dual;小写selectlower(‘Hello world’) from dual;练习案例1,查询first_name为randall的员工工资分析我们查询的时候不需要关心名称中的大小写问题select * from employees wherelower(first_name) ‘randall’;练习案例2,客户在输入名字的时候可以不会在意名称的大小写比如Wang Xiaoer假设现在在发送邮件需要按照正规的格式输出姓名请使用SQL处理分析我们可以插入一条小写的名字然后使用首字母大写查询出来格式更完整insert into employees(employee_id,first_name,last_name,email,phone_number,hire_date,job_id)values(300,‘wang’,‘xiaoer’,‘xxxqq.com’,‘1895236541’,sysdate,‘SH_CLERK’)查询select initcap(first_name)||’ ||initcap(last_name) from employees;2.3.2 字符处理函数1、CONCAT(strexp, strexp): 连接两个字符串2、Substr(str,start_index,length) :从指定的位置截取指定长度的字符串3、LENGTH(strexp):返回字符串的长度LENGTHB(strexp):返回字节的长度4、LPAD( string1, padded_length,pad_string pad_string pad_string ) 在列的左边粘贴字符其中string1是需要粘贴字符的字符串padded_length是返回的字符串的数量如果这个数量比原字符串的长度要短lpad函数将会把字符串截取成padded_length;pad_string是个可选参数这个字符串是要粘贴到string1的左边如果这个参数未写lpad函数将会在string1的左边粘贴空格。5、RPAD(粘贴字符) RPAD 在列的右边粘贴字符6、Trim():截取字符串两端指定字符Trim(‘s’ from ‘string’);可以指定从字符串两边要截取的特殊字符2.3.2.1 CONCAT(strexp, strexp):连接两个字符串注意在Oracle中只能连接两个字符串(MySQL中可以任何加字符串)这里可以使用函数嵌套的方式错误方式select concat(‘123’,‘456’,789) from dualORA-00909: 参数个数无效正确方式(嵌套)select concat(concat(‘123’,‘456’),‘789’) from dual;2.3.2.2 Substr(str,start_index,length)从指定的位置截取指定长度的字符串Str:的字符串start_index从第几个开始(第1开始计算)如果是0和1效果是一样的如果是负数从倒数第几个字符开始Length截取几个字母(长度)案例一select substr(‘123456789’,0,4) from dual;结果1234案例二select substr(‘123456789’,1,4) from dual;结果1234上面两个例子大家看到两个结果都是1234在SQL中很多参数是应该从1开始计算的而且从1开始计算也更加符合我们的计算因此建议大家从1开始计算。比如我们拿到从4到7的数案例三select substr(‘123456789’,4,4) from dual;结果45672.3.2.3 LENGTH(strexp)返回字符串的长度案例一select length(‘admin’) from dual; --结果5select length(‘中国’) from dual; --结果2还有一个针对字节的LENGTHB(strexp):返回字节的长度案例二select lengthb(‘admin’) from dual; --结果5select lengthb(‘中国’) from dual; --结果4练习案例隐藏部分员工姓名例如Julia Dellinger取前三位Jul加最后三位ger中间补5位’*得到Jul*****ger分析拿到前三位拿到后三位中间补齐select subStr(first_name,1,3)||‘*****’||subStr(last_name,-3) from employees注意起始位置是可以写负数的(从负几开始)思考 select subStr(‘123456789’,-5,3) from dual; 值是多少现在问大家一个问题如果我们要在中间加50个*那怎么做如果自己去写的话实在是太麻烦了而且容易写错。因此真有这个需求的话可以用到下一个函数LPAD2.3.2.4 LPAD( string1, padded_length,pad_string pad_string pad_string )在列的左边粘贴字符其中string1是需要粘贴字符的字符串padded_length是返回的字符串的数量如果这个数量比原字符串的长度要短lpad函数将会把字符串截取成padded_length;pad_string是个可选参数这个字符串是要粘贴到string1的左边如果这个参数未写lpad函数将会在string1的左边粘贴空格。案例一结果加上Lap的结果在前面多了一些空格而且是加上hello刚好10个字符案例二select Lpad(‘hello’,10,‘*’) from dual;结果*****hello案例三完成前面提出的50个*select subStr(first_name,1,3)||Lpad(‘’,50,‘’)||subStr(last_name,-3) from employees注意第一个参数不能为空2.3.2.5 RPAD(粘贴字符)RPAD 在列的右边粘贴字符这个效果和LPAD一样只是字符加在右边2.3.3.6 Trim():截取字符串两端特殊字符(默认截取空格)Trim(‘s’ from ‘string’);可以指定从字符串两边要截取的特殊字符案例一select trim(’ hello world ) from dual;结果hello world案例二select trim(‘-’ from ‘----hello world----’) from dual;结果hello world2.4 数字函数Round传回一个数值,该数值是按照指定的小数位数进行四舍五入运算的结果。TRUNC函数返回处理后的数值其工作机制与ROUND函数极为类似只是该函数不对指定小数前或后的部分做相应舍去选择处理而统统截去modnumber1number2两个数值相除并返回其余数。运算符执行 number1 除以 number2 操作。2.4.1 Round传回一个数值,该数值是按照指定的小数位数进行四舍五入运算的结果。语法ROUND( number, decimal_places )number : 需四舍五入处理的数值decimal_places : 四舍五入 , 小数取几位 ( 预设为 0 )案例ROUND(45.926, 2) 45.93案例一select round(445.3434,2) from dual; - 445.34案例二select round(445.3434,-2) from dual; - 4002.4.2 TRUNC函数返回处理后的数值其工作机制与ROUND函数极为类似只是该函数不对指定小数前或后的部分做相应舍入选择处理而统统截去。语法TRUNC( number, decimal_places )number : 要截取的数值decimal_places : 小数取几位 ( 预设为 0 )案例TRUNC(45.926, 2) 45.92案例select TRUNC(445.3484,2) from dual; - 445.342.4.3 modnumber1number2两个数值相除并返回其余数。运算符执行 number1 除以 number2 操作。案例一select mod(100,5) from dual; - 0案例二select mod(100,6) from dual; - 42.4.4 数字函数练习题作业题在POS系统中都会有这样一个功能在系统中可以设置找零的方式比如常见的有下面几种1角以下四舍五入2元以下四舍五入3不管分4不管角5不管元请思考实现这些功能的方法2.5 转换函数转换函数分两种隐式与显示转换函数数字与字符之间的转换/日期与字符之间的转换2.5.1 隐式转换看下面的案例理解select ‘555’ || 6 from dual; 5556select ‘555’6 from dual; 561必需知道内部的机制才能知道最后的结果。咱们并不推荐使用这种方式。注虽然可以使用隐式数据类型转换但是还是建议执行显式的数据类型转换以确保SQL语句的可靠性。2.5.2 显示函数转换从下图咱们可以看到 NUMBER(数字)CHARACTER(字符串)DATE(日期)是可以相互转换的TO_NUMBER: 字符串转成数字**TO_CHAR:**数字转换成字符串/日期转换成字符串TO_DATE:字符串转换成日期2.5.1 数字与字符的转换2.5.1.1 to_charA 数字转换成字符串语法to_char(number,’fmt’)大家应该可以看得出来前面是number,后面是格式。Number很好理解那么格式到底是怎么回事呢请看下图数字格式控制符描述9代表一位数字如果当前位有数字显示数字否则不显示(小数部分仍然会强制显示00强制显示该位如果当前位有数字显示数字否则显示0$增加美元符号显示L增加本地货币符号显示.小数点符号,千分位符号 3,000,000,000.00咱们例出了下面几个案例来帮助理解案例一把一个110.110 变成一个字符串select to_char(110.110) from dual;这个得到的结果不正确的因为默认转换直接把最后一位省去了select to_char(110.110,‘999.999’) from dual;9在这里代表的就是占位并且小数点强制显示案例二把把一个110.110 变成一000110.110select to_char(110.110,‘000999.999’) from dual;0也代表的就是占位并且所有数字强制显示从上面两个案例中咱们可以想到9肯定比0的情况要用得多一点。那么0可能会用到什么情况下呢 这就需要我们把0与下面的千分位符号结合进来使用案例二财务看千分位的工资等(财务看这个就很习惯了)select to_char(110.110,‘000,000.000’) from dual;结果 000,110.110下面再来研究**$与L**使用美元打印用户工资select first_name,to_char(salary,‘$999999.99’) from employees;使用本地货币符号打印工资select first_name,to_char(salary,‘L999999.99’) from employees;使用财务习惯打印工资select first_name,to_char(salary,‘L000,000.00’) from employees;2.5.1.2 to_number使用to_number函数将字符转换为数字语法to_number(char,′fmt′, ‘fmt’,′fmt′))案例一把3100.00 转回成数字select to_number(‘3100.00’,‘L9999.99’) from dual;这个的转换正好是和to_char是相应的。格式设定一样。2.5.2 日期与字符的转换下面是转换的格式格式控制符描述YYYY YYY YY以数字表示全年(分别代表4位、三位、两位)的数字年YEAR年的拼写MM(mm)两位数字月MONTH月的全拼MON月名称的缩写DD数字日DAY星期的全拼D星期中的第几天DY表示三位缩写的星期格式控制符描述HHHH12一天中的第几个小时12进制表示法HH24一天中的第几个小时取值为00~23MI一小时中的分钟SS一分钟中的秒AM显示上午或下午2.5.2.1 TO_CHAR 函数操作日期TO_CHAR(date, ‘fmt’) 是字符类型的函数转化日期为字符格式(‘fmt’)1、必须用单引号括起来,并且是大小写敏感2、可包含任何有效的日期格式3、fmt值的宽度正好能容纳所有的有效数字案例一拿到日期的年Select to_char(sysdate,‘YYYY’) from dual;Select to_char(sysdate,‘Year’) from dual;其它咱们可以把上述表中的效果都显示查看一下1999年入职的员工…案例二查询出1999/10/15入职的员工select * from employees where to_char(HIRE_DATE,‘YYYY-MM-dd’)‘1999-10-15’;案例三打印出xxxx年xx月xx日 xx:xx:xx格式的日期和时间Select to_char(sysdate,‘yyyy年mm月dd日’) from dual注如果添加中文需要在中文上使用双引号包裹案例四查询出1995年3月至2000年8月入职的员工select * from employeeswhere to_char(hire_date,‘YYYY-MM’) between ‘1995-03’ and ‘2000-06’;刚才咱们讲的都是将日期转换成字符串大家想一下怎么把字符串转成日期呢select to_date(‘2005-05-12 18’,‘yyyy-MM-dd hh24’) from dual;自己反推一下即可。2.6 日期函数**add_months(**date_value,number_of_months):用于从一个日期值增加或减少一些月份select add_months(sysdate,12) “明年今日” from dual;select add_months(sysdate,-12) “去年今日” from dual;current_date:返回当前会话时区中的当前日期select sessiontimezone,current_date from dual;alter session set time_zone‘-11:00’//修改当前会话时区extract(date_field from datetime_value):找出日期或间隔值的字段值select extract(month from sysdate) “当前月份” from dual;last_day(date_value):返回指定日期中的月份的最后一天的日期select last_day(‘2000-02-01’) “润月” from dual;next_day( date, weekday ):返回指定时间的下一个星期的指定星期对应的日期select next_day(sysdate,‘星期一’) from dual;如果今天是星期三下一个星期四就是明天months_between(f,s) 日期f和s间相差月数select months_between(sysdate,‘04-5月-09’)from dual;2.7 其它函数1 NVL函数NVL(expr1,expr2)将空值转换为替换的值支持多种数据格式可以是日期,字符,数字NVL的两个参数数据类型必须匹配 ,否则出错。NVL(comm,0)NVL(hiredate,‘01-JAN-97’)NVL(job,‘No Job Yet’)select NVL(null,‘01-JAN-97’) from dual案例查询员工所有工资2 NVL2函数NVL2(expr0,expr1,expr2)如果expr0不为Null,返回expr1, 为Null,返回expr2.expr0可以为任何数据类型研究下面代码的结果SELECT last_name, salary, commission_pct,NVL2(commission_pct,‘SALCOMM’, ‘SAL’) incomeFROM employees WHERE department_id IN (50, 80);结果是如果这个人有奖金点那就他的工资就是工资奖金如果这个人没有奖金点那就他的工资就没有奖金3 NULLIFNULLIF(expr1,expr2)比较两个表达式如果相等返回空值如果不等返回第一个表达式。研究下面代码的结果SELECT first_name, LENGTH(first_name) “expr1”,last_name, LENGTH(last_name) “expr2”,NULLIF(LENGTH(first_name), LENGTH(last_name)) resultFROM employees;两个名称长度相等返回空两个名称不相等 返回第一个名称的长度4 COALESCECOALESCE(expr1,expr2,…,exprn)返回表达式列表里的第一个非空表达式的值表达式列表可以包含很多表达式,当第一个满足值非空时返回这个表达式的值。expr1,expr2,…,exprn的数据类型必须一致研究下面代码的结果SELECT last_name,COALESCE(commission_pct, salary, 10) commFROM employeesORDER BY commission_pct;如果奖金点存在返回奖金点如果奖金点不存在返回工资如果工资都不存在给10块钱以后做开发有这么一个要求用户有几个电话号码字段咋们要拿到其中一个有值的公司电话手机家里座机手机2…SelectCOALESCE(workphone,mobile,homephone) from employee5 CASE表达式实现逻辑的IF-THEN-ELSECASE exprWHEN v1 THEN result1WHEN v2 THEN result2 WHEN vn THEN resultn ELSE defaultResult END 案例分析 SELECT last_name, case job_id when ‘总经理’ then 1.15*salary when ‘副总经理’ then 1.20*salary else salary end 工资 FROM employees; 练习题 打印公司员工工资等级5000以下D5000-10000C;10000-15000B;15000以上A select last_name,salary, case trunc(nvl(salary,0)/5000) when 0 then ‘D’ when 1 then ‘C’ when 2 then ‘B’ else ‘A’ end from employees #### 6 DECODE函数 DECODE函数类似于一系列CASE 或 IF-THEN-ELSE 语句 DECODE(col/expression, search1, result1 [, search2, result2,…,default, default,default案例分析SELECT last_name,salary,decode(job_id,‘总经理’,1.15*salary,‘副总经理’,1.10*salary,salary) 工资FROM employees;练习题打印公司员工工资等级5000以下D5000-10000C;10000-15000B;15000以上Aselect last_name,salary,decode(trunc(salary/5000),0,‘D’,1,‘C’,2,‘B’,‘A’)from employees2.8 分组函数分组函数 就我们所说的多行函数 我们看一下 max . 求员工表中工资的最高值就相当于我们把整个公司的员工分了一个组 求最大值查询公司员工工资的总和工资的最大值最小值平均值2.8.1 常用分组函数(通用)AVG (DISTINCT∣ALLDISTINCT|ALLDISTINCT∣ALLn)COUNT ({ *|DISTINCT∣ALLDISTINCT|ALLDISTINCT∣ALLexpr})MAX (DISTINCT∣ALLDISTINCT|ALLDISTINCT∣ALLexpr)MIN (DISTINCT∣ALLDISTINCT|ALLDISTINCT∣ALLexpr)SUM (DISTINCT∣ALLDISTINCT|ALLDISTINCT∣ALLn)1,查询出公司所有员工的平均工资2,计算公司平均奖金点(即提成比)注意空值不参与运算这里咱们计算平均提成可以看到差距是很大的select avg(commission_pct),sum(commission_pct)/count(employee_id) from employees;正确的统计方式select avg(nvl(commission_pct,0)) from employees;2.8.2 分组分析先分组再统计查询出每一个部门的最高工资select max(salary),department_id from employees group by department_id查询出每一个部门的平均工资select avg(salary),department_id from employees group by department_id查询平均工资高于8000的部门和其平均工资select avg(salary),department_id from employees group by department_idhaving avg(salary)8000分析练习题查询在95969798年各进公司多少人select count(employee_id),to_char(hire_date,‘yy’) from employeesgroup by to_char(hire_date,‘yy’)having to_char(hire_date,‘yy’) in(‘95’,‘96’,‘97’,‘98’)order by to_char(hire_date,‘yy’)select count(employee_id),to_char(hire_date,‘yy’) from employeeswhere to_char(hire_date,‘yy’) in(‘95’,‘96’,‘97’,‘98’)group by to_char(hire_date,‘yy’)order by to_char(hire_date,‘yy’)三 Oracle多表连接隐式内连接Select * from product, productdir多什么需要多表连接Select * from student , teacher where (消除笛卡尔积)Select * form student join teacher on (消除笛卡尔积)Select * from student left join teacher on (消除笛卡尔积)Select * from student right join teacher on (消除笛卡尔积)笛卡尔积,内连,外连(左外连,右外连,全连接),消除笛卡尔积3.1 等值连接我们看一下 练习使用join on (条件)这个是一个 标准的 等值连接如果是老板 … 得到一个信息 老板的上面没有人所以他的经理为空我们添加一个 left 就会 多出一行 老板左外连接最后结果:3.2 非等值连接查询与员工工资等级(非等值连接)select first_name,salary,grade_level from employees empleft join job_grades graon emp.salary between gra.lowest_sal and gra.highest_sal我看一下 下面练习查询 John 的部门同事信息 怎么查询?首先jones.last_name ‘Jones’ 过滤出一条 jones的信息Jones.department_id emp.department_id 关联查询出 emp表下面的和jones 部门相同的员工信息展示 就emp表的信息 就是 所得到的结果添加一个 emp.last_name ‘Jones’ 就排除Jonesselect emp.first_name,emp.department_idfrom employees empjoin employees jones on(jones.department_id emp.department_id and jones.last_name‘Jones’)where emp.last_name ! ‘Jones’四 (存储)过程-- 预编译的SQL代码段封装重复传参调用–DROP PROCEDURE myProc;–过程是预编译的– 注意Oracle的存储过程中是不能写查询结果集的select语句CREATE OR REPLACE PROCEDURE myProc(vid number,vname nvarchar2,vusername out nvarchar2)ASCURSOR mycur IS SELECT * FROM USERS;BEGIN/* 游标的遍历操作 */FOR user IN mycur LOOPDBMS_OUTPUT.put_line(user.NAME || ’ ’ || user.USERNAME);END LOOP;/*SELECT USERNAME INTO vusername FROM USERSWHERE ID vid AND NAME vname; */END myProc;declaretest nvarchar2(20);beginmyProc(null,null,test);end;–调用存储过程select * from users;declareval nvarchar2(20);BEGINmyProc(7,‘xiaoming’,val);dbms_output.put_line(‘对应用户的昵称’ || val);END;CREATE OR REPLACE PROCEDURE testProcASBEGIN/**/DBMS_OUTPUT.put_line(‘HELLO PROC!’);DBMS_OUTPUT.put_line(‘HELLO,good luck!’);– SELECT * FROM USERS;(此句放置在存储过程中无效!!)END testProc;– 存储过程的调用一定放在begin…end语句块中来调用begintestProc();end;五SQL自定义异常处理DECLAREtemp_ex exception; – 自定义异常类型的对象temp_ext_num integer;BEGINselect count(id) into t_num from USERS where id70;if t_num1 thenRAISE temp_ex; – 用SQL语句抛出异常end if;dbms_output.put_line(‘该用户不存在’);–捕获异常exceptionwhen temp_ex thendbms_output.put_line(‘该用户已存在’);END;六 函数案例根据输入的不同条件返回不同的房源平均价格SELECT * FROM STREET;SELECT * FROM HOUSE;–创建函数FunctionCREATE OR REPLACE FUNCTION calAvgPrice(latestDate DATE,streetName VARCHAR2)–声明函数的返回类型RETURN NUMBER AS avgPrice NUMBER : 0;BEGINSELECT AVG(PRICE) INTO avgPrice FROM HOUSE hINNER JOIN STREET st ON h.STREET_ID st.IDWHERE PUBDATE latestDate AND NAME LIKE ‘%’||streetName||‘%’;–切记函数一定要返回数值RETURN avgPrice;END;调用函数DECLAREmyAvgPrice number : 0;BEGINmyAvgPrice : calAvgPrice(TO_DATE(‘2011-01-01 00:00:00’,‘yyyy-MM-dd hh24:mi:ss’),‘商业’);DBMS_OUTPUT.put_line(‘查询平均房价’ || myAvgPrice);END;七 数据库(远程)链接用system建立一个其他帐号CREATE USER tomIDENTIFIED BY tom;–DEFAULT TABLESPACE ZF_SPACE;用具有管理员权限的用户(如system)给tom授权GRANT CONNECT,RESOURCE TO tom;GRANT CREATE DATABASE LINK TO tom;用tom登录身份为tom创建一个数据库链来看xiaoming的数据CREATE DATABASE LINK useXiaoMingCONNECT TO xiaoming IDENTIFIED BY xiaomingusing’ (DESCRIPTION (ADDRESS_LIST (ADDRESS (PROTOCOL TCP)(HOST 127.0.0.1)(PORT 1521)))(CONNECT_DATA (SERVICE_NAME orcl)))’ ;CREATE DATABASE LINK toGongGongCONNECT TO gong IDENTIFIED BY gongusing’ (DESCRIPTION (ADDRESS_LIST (ADDRESS (PROTOCOL TCP)(HOST 192.168.1.6)(PORT 1521)))(CONNECT_DATA (SERVICE_NAME GONGJUN)))’ ;以tom的登录身份去远程访问远程用户所持有的数据库对象select * from myusertoGongGong;