SQL> select * from test;
TEST
--------------------
sdd_kk
d'd
dfsfsa
dffa%asfs
12345
1%2345
1%54321
2%54321
%%54321
A&B
已选择9行。
SQL> select * from test where test like 'sdd\_%' escape '\';
TEST
--------------------
sdd_kk
转义字符为'\';
SQL> select * from test where test like 'sdd=_%' escape '=';
TEST
--------------------
sdd_kk
转义字符为'=';
SQL> select * from test where test like 'sddd_%' escape 'd';
未选定行
转义字符为d,没有实现转义功能;
但是'&'不能通过转义字符查找:
SQL> select * from test where test like '%\&%' escape'\';
select * from test where test like '%\&%' escape'\'
*
第 1 行出现错误:
ORA-01424: 转义符之后字符缺失或非法
可以通过另外的方式进行转义:
SQL> select ascii('&') from dual;
ASCII('&')
----------
38
SQL> select * from test where test like '%'||chr(38)||'%';
TEST
--------------------
A&B
' 的转义:
SQL> select * from test where test like '%''%';
TEST
--------------------
d'd
特殊符号的数据的插入
SQL> insert into test values('test&test'); 输入 test 的值: test 原值 1: insert into test values('test&test') 新值 1: insert into test values('testtest') -虽然插入,但是数据不对。 已创建 1 行。 SQL> show define define "&" (hex 26) SQL> set define off SQL> show define define OFF SQL> insert into test values('test&test'); 已创建 1 行。 SQL> show escape escape OFF SQL> set escape on SQL> show escape escape "\" (hex 5c) SQL> insert into test values('test\&test'); 已创建 1 行。 SQL> select * from test; TEST -------------------- sdd_kk d'd dfsfsa dffa%asfs 12345 1%2345 1%54321 2%54321 %%54321 A&B testtest TEST -------------------- test&test test&test 已选择13行。 SQL> commit; 提交完成。 SQL> select * from test; TEST -------------------- sdd_kk d'd dfsfsa dffa%asfs 12345 1%2345 1%54321 2%54321 %%54321 A&B testtest TEST -------------------- test&test test&test 已选择13行。 SQL> insert into test values('test\%test'); 已创建 1 行。 SQL> insert into test values('test\_test'); 已创建 1 行。 SQL> insert into test values('test\'test); insert into test values('test'test) * 第 1 行出现错误: ORA-00917: 缺失逗号 SQL> insert into test values('test''test'); 已创建 1 行。 SQL> select * from test; TEST -------------------- sdd_kk d'd dfsfsa dffa%asfs 12345 1%2345 1%54321 2%54321 %%54321 A&B testtest TEST -------------------- test&test test&test test%test test_test test'test 已选择16行。
连接符‘||’导致了新一轮的转义:连接符号‘||’左右的单引号没有任何的关系,除非‘||’是作为字符串的一部分(这在动态SQL中很常见)。
SQL> SELECT 'ORACLE'||'''' FROM DUAL;
'ORACLE'||''
----------
ORACLE'
个人理解,'ORACLE'||'''' 后面的“''''”应该认为是一个字符串(即前后单引号,中间是“''”串,而中间又是密集单引号,因此第一个为转义功能)
SQL> SELECT 'ORACLE''''' FROM DUAL;
'ORACLE'''''
------------
ORACLE''
对于第一个,前两个单引号配对,后面四个单引号按照上面的第一条原则分配,既:SELECT 'ORACLE'||'''' FROM DUAL;
对于第二个,由于第二个单引号后面存在单引号,所以就不与第一个配对,而是充当了转义的角色。既:SELECT 'ORACLE''''' FROM DUAL;
注意:如果是 '/' 作为检索字符, 必须 用 '/' 作为转义符, 正斜扛也一样.
- select * from wan_test where psid like '%//%' escape '/'
带in的关联子查询是多余的,因为in子句和子查询中相关的操作的功能是一样的。如:
select staff_name from staff_member where staff_id in
(select staff_id from staff_func where staff_member.staff_id=staff_func.staff_id);
为非关联子查询指定exists子句是不适当的,因为这样会产生笛卡乘积。如:
select staff_name from staff_member where staff_id
exists (select staff_id from staff_func);
not in 和not exists
如果查询语句使用了not in 那么内外表都进行全表扫描,没有用到索引;
而not extsts 的子查询依然能用到表上的索引。
所以无论哪个表大,用not exists都比not in要快。
尽量不要使用not in子句。使用minus 子句都比not in 子句快,虽然使用minus子句要进行两次查询:
select staff_name from staff_member where staff_id in (select staff_id from staff_member minus select staff_id from staff_func where func_id like '81%');
in 与 "=" 的区别
select name from student where name in ('zhang','wang','li','zhao');
与
select name from student where name='zhang' or name='li' or name='wang' or name='zhao'
的结果是相同的。
有两个简单例子,以说明 “exists”和“in”的效率问题
1) select * from T1 where exists(select * from T2 where T1.a=T2.a) ;
T1数据量小而T2数据量非常大时,T1<<T2 时,1) 的查询效率高。
2) select * from T1 where T1.a in (select T2.a from T2) ;
T1数据量非常大而T2数据量小时,T1>>T2 时,2) 的查询效率高。
---------------------------------------------------------------
今天市场报告有个sql及慢,运行需要20多分钟,如下:
update p_container_decl cd
set cd.ANNUL_FLAG=\'0001\',ANNUL_DATE = sysdate
where exists(
select 1
from (
select tc.decl_no,tc.goods_no
from p_transfer_cont tc,P_AFFIRM_DO ad
where tc.GOODS_DECL_NO = ad.DECL_NO
and ad.DECL_NO = \'sssssssssssssssss\'
) a
where a.decl_no = cd.decl_no
and a.goods_no = cd.goods_no
)
上面涉及的3个表的记录数都不小,均在百万左右。根据这种情况,我想到了前不久看的tom的一篇文章,说的是exists和in的区别,in 是把外表和那表作hash join,而exists是对外表作loop,每次loop再对那表进行查询。
这样的话,in适合内外表都很大的情况,exists适合外表结果集很小的情况。
而我目前的情况适合用in来作查询,于是我改写了sql,如下:
update p_container_decl cd
set cd.ANNUL_FLAG=\'0001\',ANNUL_DATE = sysdate
where (decl_no,goods_no) in
(
select tc.decl_no,tc.goods_no
from p_transfer_cont tc,P_AFFIRM_DO ad
where tc.GOODS_DECL_NO = ad.DECL_NO
and ad.DECL_NO = ‘ssssssssssss’
)
让市场人员测试,结果运行时间在1分钟内。问题解决了,看来exists和in确实是要根据表的数据量来决定使用。
--------------------------------------------------------------------------
select 1 from ..., sql语句中的1代表什么意思?查出来是个什么结果?
select 1 from table;与select anycol(目的表集合中的任意一行) from table;与select * from table 从作用上来说是没有差别的,都是查看是否有记录,一般是作条件查询用的。select 1 from 中的1是一常量(可以为任意数值),查到的所有行的值都是它,但从效率上来说,1>anycol>*,因为不用查字典表。
测试场景:(转自网络文献)
table表是一个数据表,假设表的行数为10行。
1:select 1 from table 增加临时列,每行的列值是写在select后的数,这条sql语句中是1
2:select count(1) from table 管count(a)的a值如何变化,得出的值总是table表的行数
3:select sum(1) from table 计算临时列的和
1* select 1 from emp where empno=7369 or empno=7499 scott@WENCHAOD> / 1 ---------- 1 1----
例1:
让我们在一个简单的例子。下面是一个使用EXISTS条件的SQL语句,:
SELECT *
FROM suppliers
WHERE EXISTS
(select *
from orders
where suppliers.supplier_id = orders.supplier_id);
这个SELECT语句将返回供应商表中与订单表中至少有一条记录是supplier_id相同的的供应商信息。
例2 – NOT EXISTS
EXISTS 条件也可以与NOT运算符结合。
For example,
SELECT *
FROM suppliers
WHERE not exists (select * from orders Where suppliers.supplier_id = orders.supplier_id);
USE pubs GO SELECT DISTINCT pub_name FROM publishers WHERE EXISTS (SELECT * FROM titles WHERE pub_id = publishers.pub_id AND type = 'business') GO -- Or, using the IN clause: USE pubs GO SELECT distinct pub_name FROM publishers WHERE pub_id IN (SELECT pub_id FROM titles WHERE type = 'business') GO
in的SQL语句 SELECT id, category_id, htmlfile, title, convert(varchar(20),begintime,112) as pubtime FROM tab_oa_pub WHERE is_check=1 and category_id in (select id from tab_oa_pub_cate where no='1') order by begintime desc 修改为exists的SQL语句 SELECT id, category_id, htmlfile, title, convert(varchar(20),begintime,112) as pubtime FROM tab_oa_pub WHERE is_check=1 and exists (select id from tab_oa_pub_cate where tab_oa_pub.category_id=convert(int,no) and no='1') order by begintime desc