- 浏览: 190174 次
- 性别:
- 来自: 上海
文章分类
最新评论
Dashboard > 流程空间 > home > SQLMAP编写规范以及一些常见的SQL问题
Page Operations
View Edit Attachments (0) Info
Browse Space
Pages Labels Attachments Mail News Templates Advanced
Add Content
Add Page Add News Welcome 李文学 | History | Preferences | Log Out
流程空间
SQLMAP编写规范以及一些常见的SQL问题
Added by 李文学, last edited by 李文学 on 五月 18, 2007 (view change) Labels: (None) EDIT
Add Labels
Enter labels to add to this page:
Tip: Looking for a label? Just start typing.
select语句中*号的问题
1。表连接时,绝不允许写select * ,否则按照编码错误Bug处理。
2。单表查询,一般情况下可以使用select * ,但以下几种情况禁用:
a、表中包含lob字段(BLOB、CLOB、LONG、LONG RAW等)。
b、表中包含长度较大的字段,如varchar2(1000)以上的字段,但该SQL实际上并不需要取出该字段的值。
c、字段数量很多,但实际要用的字段很少,比如表有50个字段,而你实际只用5个,并且该sql目前没有被重用。
d、DBA要求优化调整的。
严格要求使用正确类型的变量,杜绝oracle做隐式类型转换的情况
1。推荐在sqlmap的变量中指定变量的数据类型,如:
select * from iw_user where iw_user_id = #userid:VARCHAR#2。其中,对于时间类型的字段,必须使用TO_DATE进行赋值(当前时间可直接用sysdate表示),不允许下列这些错误用法:
错误的写法(使用date类型的变量):
select * from iw_account_log where trans_account = #transaccount:varchar#
and trans_dt >= #dateBegin:date#
and trans_dt < #dateEnd:date# 错误的写法(使用包含sysdate的表达式):
select * from iw_account_log where trans_account = #transaccount:varchar#
and trans_dt >= trunc(sysdate - 1)
and trans_dt < sysdate + 1 错误的写法(将to_date函数和数字进行算术运算):
select * from iw_account_log where trans_account = #transaccount:varchar#
and trans_dt >= to_date(#dateBegin:varchar#, 'yyyy-mm-dd hh24:mi:ss')
and trans_dt < to_date(#dateBegin:varchar#, 'yyyy-mm-dd hh24:mi:ss') + 1 正确的写法:
select * from iw_account_log where trans_account = #transaccount:varchar#
and trans_dt >= to_date(#dateBegin:varchar#, 'yyyy-mm-dd hh24:mi:ss')
and trans_dt < to_date(#dateEnd:varchar#, 'yyyy-mm-dd hh24:mi:ss') /*或 trans_dt < sysdate */3。对于变量数据类型错误导致SQL严重性能问题的,按严重的编码错误Bug处理!
杜绝循环调用
例如:在迭代的过程中,使用同一SQL反复查询DB,如:
while (listObj.hasnext()) {
SELECT * FROM beyond_trade_process WHERE (trade_no = ?)
......
} 这样不仅效率不高,还造成交互过于频繁,严重情况会导致服务器LOAD增加
解决方式:
1。如果该查询是使用唯一键(如上例),参考后面的STR2VARLIST或STR2NUMLIST的用法
2。联系DBA协助分析解决方式
3。违反本条规范,属较严重Bug,如是前台应用应立即予以修复
绑定变量和替代变量
在Ibatis中:
绑定变量用 #变量名# 表示
替代变量用 $变量名$ 表示
注意几点:
1。通常,应使用绑定变量,尤其是具体取值变化范围较大的变量,如iw_user_id = #userid#。
2。取值范围很小(比如枚举字段),并且通常取值会比较固定,在DBA预先同意的情况下使用替代变量,或者干脆使用常量。
3。当一个绑定变量在实际使用中实际取值总是为某一固定常量时,应当直接使用常量而不是变量,关于这点,可在具体使用时咨询DBA
4。在order by子句中,通常使用替代变量而不是绑定变量。
5。IN子句,使用"iterate + 数组类型变量"的方式实现绑定变量,例如:
<isNotEmpty prepend="and" property="userIds">
<iterate property="userIds" open="t.creator in (" close=")" conjunction=",">
#userIds[]#
</iterate>
</isNotEmpty>将生成 t.creator in (:1, :2, :3, :4, :5 ...) 的语句
在字段上加函数的问题
1。通常,不允许在字段上添加函数或者表达式,如:
错误的写法:
select * from iw_account_log where to_char ( trans_dt, 'yyyy-mm-dd') = '2007-04-04';
select qty from product where p_id + 12 = 168; 正确的写法:
select * from iw_account_log
where trans_dt >= to_date ( '2007-04-04', 'yyyy-mm-dd') and trans_dt < to_date ( '2007-04-05', 'yyyy-mm-dd');
select qty from product where p_id = 168 - 12;2。如果是业务要求的除外,但需要在编写时咨询DBA
3。特别注意,当表连接时,用于连接的两个表的字段如果数据类型不一致,则必须在一边加上类型转换的函数,如
错误的写法(a.id是number类型,而b.operator_number是char类型):
select count(*) from adm_user a, adm_action_log b where a.id = b.operator_number and a.username = '小钗'; 正确的写法:
select count(*) from adm_user a, adm_action_log b where to_char(a.id) = b.operator_number and a.username = '小钗';
select count(*) from adm_user a, adm_action_log b where a.id = to_number(b.operator_number) and a.username = '小钗'; 上面两种写法哪个正确?遇到这种情况时必须咨询DBA!
表连接
1。不使用ANSI连接,如inner join、left join、right join、full outer join,而使用(+)来表示外连接
错误的写法:
select a.*, b.goods_title from iw_account_log a left join beyond_trade_base b on a.TRANS_OUT_ORDER_NO = b.trade_no
where a.trans_code = '6003' and a.trans_account = #transacnt:varchar# and a.trans_dt > to_date(...) 正确的写法:
select a.*, b.goods_title from iw_account_log a, beyond_trade_base b
where a.TRANS_OUT_ORDER_NO = b.trade_no(+) and a.trans_code = '6003'
and a.trans_account = #transacnt:varchar# and a.trans_dt > to_date(...)SQLMAP的其它编写规范
1。对表的记录进行更新的时候,必须包含对gmt_modified字段的更新,并且不要使用dynamic标记,如:
错误的写法:
update BD_CONTACTINFO
<dynamic prepend="set">
......
<isNotNull prepend="," property="gmtModified">
GMT_MODIFIED = #gmtModified:TIMESTAMP#
</isNotNull>
</dynamic>
where ID = #id# 正确的写法(当然,这里更推荐直接更新为sysdate):
update BD_CONTACTINFO
set GMT_MODIFIED = #gmtModified:TIMESTAMP#
<dynamic>
......
</dynamic>
where ID = #id#2。不允许在where后添加1=1这样的无用条件,where可以写在prepend属性里,如:
错误的写法:
select count(*) from BD_CONTRACT t where 1=1
<dynamic>
......
</dynamic> 正确的写法:
select count(*) from BD_CONTRACT t
<dynamic prepend="where">
......
</dynamic>3。对大表进行查询时,在SQLMAP中需要加上对空条件的判断语句,具体可在遇到时咨询DBA,如:
性能上不保险的写法:
select count(*) from iw_user usr
<dynamic prepend="where">
<isNotEmpty prepend="AND" property="userId">
usr.iw_user_id = #userId:varchar#
</isNotEmpty>
<isNotEmpty prepend="AND" property="email">
usr.email = #email:varchar#
</isNotEmpty>
<isNotEmpty prepend="AND" property="certType">
usr.cert_type = #certType:varchar#
</isNotEmpty>
<isNotEmpty prepend="AND" property="certNo">
usr.cert_no = #certNo:varchar#
</isNotEmpty>
</dynamic> 性能上较保险的写法(防止那些能保证查询性能的关键条件都为空):
select count(*) from iw_user usr
<dynamic prepend="where">
<isNotEmpty prepend="AND" property="userId">
usr.iw_user_id = #userId:varchar#
</isNotEmpty>
<isNotEmpty prepend="AND" property="email">
usr.email = #email:varchar#
</isNotEmpty>
<isNotEmpty prepend="AND" property="certType">
usr.cert_type = #certType:varchar#
</isNotEmpty>
<isNotEmpty prepend="AND" property="certNo">
usr.cert_no = #certNo:varchar#
</isNotEmpty>
<isEmpty property="userId">
<isEmpty property="email">
<isEmpty property="certNo">
query not allowed
</isEmpty>
</isEmpty>
</isEmpty>
</dynamic> 另外,对查询表单的查询控制建议使用web层进行控制而不是客户端脚本(JAVASCRIPT/VBSCRIPT)
聚合函数常见问题
1。不要使用count(1)代替count(*)
2。count(column_name)计算该列不为NULL的记录条数
3。count(distinct column_name)计算该列不为NULL的不重复值数量
4。count()函数不会返回NULL,但sum()函数可能返回NULL,可以使用nvl(sum(qty),0)来避免返回NULL
NULL的使用
1。理解NULL的含义,是"不确定",而不是"空"
2。查询时,使用is null或者is not null
3。更新时,使用等于号,如:update tablename set column_name = null
STR2NUMLIST、STR2VARLIST函数的使用:
1。适用情况:使用唯一值(或者接近唯一值)批量取数据时,能够大大减少和数据库的交互次数
2。编写规范:a表必须放在from list的第一位,并且必须在select后加上下面的hint
注意一:参数是由各个交易号拼成的字符串,以逗号间隔,不要有空格
注意二:函数的参数是一个字符串,长度不能超过4000个字节
注意三:函数生成的表只有一个字段,名字是column_value
注意四:生成表的column_value字段是varchar2类型,如果希望是number类型,请使用str2numlist函数,并将vartabletype替换为numtabletype
错误的写法(缺少hint):
select a.column_value, b.goods_title
from TABLE(CAST(str2varlist(:1) as vartabletype)) a, beyond_trade_base b
where a.column_value = b.trade_no; 错误的写法(函数生成的表必须放在from list的第一位):
select /*+ ordered use_nl(a,b) */ a.column_value, b.goods_title
from beyond_trade_base b, TABLE(CAST(str2varlist(:1) as vartabletype)) a
where a.column_value = b.trade_no; 正确的写法:
select /*+ ordered use_nl(a,b) */ a.column_value, b.goods_title
from TABLE(CAST(str2varlist(:1) as vartabletype)) a, beyond_trade_base b
where a.column_value = b.trade_no; 如果要求返回的结果记录条数和参数中交易号的个数一致,可使用外连接:
select /*+ ordered use_nl(a,b) */ a.column_value, b.goods_title
from TABLE(CAST(str2varlist(:1) as vartabletype)) a, beyond_trade_base b
where a.column_value = b.trade_no (+); 如果参数内的值不唯一,可能返回多行,而并不需要返回多行,可考虑使用聚合函数:
select /*+ ordered use_nl(a,b) */
a.column_value, min(b.goods_title) goods_title
from TABLE(CAST(str2varlist(:1) as vartabletype)) a, beyond_trade_base b
where a.column_value = b.out_trade_no (+)
group by a.column_value; 使用该函数与使用IN的区别:
1。IN返回的结果是无序的,而该函数返回的结果是以参数中各值的顺序为顺序的
2。IN返回的结果是不重复的,而该函数返回的结果可重复,取决于输入的参数
分页查询的使用
1。分页通常是先执行COUNT语句然后执行分页语句,当COUNT返回值为0的时候,应当避免执行后面的分页语句
2。有时,只须执行分页语句而无须执行COUNT语句,就不要执行COUNT语句,例如,用户下载excel格式的账户明细
3。有时,在分页前除了要统计COUNT还需要统计SUM,这些WHERE子句一致的统计应该在一条SQL中查出,而不是分多次统计
4。包含排序逻辑的分页查询写法,必须是三层select嵌套:
错误的写法:
SELECT t1.*
FROM (SELECT t.*, ROWNUM rnum
FROM beyond_trade_base t
WHERE seller_account = :1
AND gmt_create >= TO_DATE (:2, 'yyyy-mm-dd')
AND gmt_create < TO_DATE (:3, 'yyyy-mm-dd')
ORDER BY gmt_create DESC) t1
WHERE rnum >= :4 AND rnum < :5 正确的写法:
SELECT t2.*
FROM (SELECT t1.*, ROWNUM rnum
FROM (SELECT t.*
FROM beyond_trade_base t
WHERE seller_account = :1
AND gmt_create >= TO_DATE (:2, 'yyyy-mm-dd')
AND gmt_create < TO_DATE (:3, 'yyyy-mm-dd')
ORDER BY gmt_create DESC) t1
WHERE ROWNUM <= :4) t2
WHERE rnum >= :55。不包含排序逻辑的分页查询写法,则是两层select嵌套,但对rownum的范围指定仍然必须在不同的查询层次指定:
错误的写法:
SELECT t1.*
FROM (SELECT t.*, ROWNUM rnum
FROM beyond_trade_base t
WHERE seller_account = :1
AND gmt_create >= TO_DATE (:2, 'yyyy-mm-dd')
AND gmt_create < TO_DATE (:3, 'yyyy-mm-dd')) t1
WHERE rnum >= :4 AND rnum <= :5 正确的写法:
SELECT t1.*
FROM (SELECT t.*, ROWNUM rnum
FROM beyond_trade_base t
WHERE seller_account = :1
AND gmt_create >= TO_DATE (:2, 'yyyy-mm-dd')
AND gmt_create < TO_DATE (:3, 'yyyy-mm-dd')
AND ROWNUM <= :4) t1
WHERE rnum >= :56。注意下面两种写法的逻辑含义是不同的:
按交易创建时间排序(倒序),然后再取前10条:
SELECT t2.*
FROM (SELECT t1.*, ROWNUM rnum
FROM (SELECT t.*
FROM beyond_trade_base t
WHERE seller_account = :1
AND gmt_create >= TO_DATE (:2, 'yyyy-mm-dd')
AND gmt_create < TO_DATE (:3, 'yyyy-mm-dd')
ORDER BY gmt_create DESC) t1
WHERE ROWNUM <= 10) t2
WHERE rnum >= 1 随机取10条,然后在这10条中按照交易创建时间排序(倒序):
SELECT t1.*
FROM (SELECT t.*, ROWNUM rnum
FROM beyond_trade_base t
WHERE seller_account = :1
AND gmt_create >= TO_DATE (:2, 'yyyy-mm-dd')
AND gmt_create < TO_DATE (:3, 'yyyy-mm-dd')
AND ROWNUM <= 10
ORDER BY gmt_create DESC) t1
WHERE rnum >= 17。先连接后分页与先分页后连接
性能较差:
SELECT t2.*
FROM (SELECT t1.*, ROWNUM rnum
FROM (SELECT a.*, b.receive_fee
FROM beyond_trade_base a, beyond_trade_process b
WHERE a.trade_no = b.trade_no(+)
AND a.seller_account = :1
AND a.gmt_create >= TO_DATE (:2, 'yyyy-mm-dd')
AND a.gmt_create < TO_DATE (:3, 'yyyy-mm-dd')
ORDER BY a.gmt_create DESC) t1
WHERE ROWNUM <= :4) t2
WHERE rnum >= :5 性能较好:
SELECT /*+ ordered use_nl(a,b) */
a.*, b.receive_fee
FROM (SELECT t2.*
FROM (SELECT t1.*, ROWNUM rnum
FROM (SELECT t.*
FROM beyond_trade_base t
WHERE seller_account = :1
AND gmt_create >= TO_DATE (:2, 'yyyy-mm-dd')
AND gmt_create < TO_DATE (:3, 'yyyy-mm-dd')
ORDER BY gmt_create DESC) t1
WHERE ROWNUM <= :4) t2
WHERE rnum >= :5) a,
beyond_trade_process b
WHERE a.trade_no = b.trade_no(+) 后面这种写法的适用情况:
a、where子句中的查询条件都是针对beyond_trade_base表的(否则得到的结果将不相同)
b、关联beyond_trade_process表时,用的是该表的主键或者唯一键字段(否则将改变结果集的条数)
Add Comment
Page Operations
View Edit Attachments (0) Info
Browse Space
Pages Labels Attachments Mail News Templates Advanced
Add Content
Add Page Add News Welcome 李文学 | History | Preferences | Log Out
流程空间
SQLMAP编写规范以及一些常见的SQL问题
Added by 李文学, last edited by 李文学 on 五月 18, 2007 (view change) Labels: (None) EDIT
Add Labels
Enter labels to add to this page:
Tip: Looking for a label? Just start typing.
select语句中*号的问题
1。表连接时,绝不允许写select * ,否则按照编码错误Bug处理。
2。单表查询,一般情况下可以使用select * ,但以下几种情况禁用:
a、表中包含lob字段(BLOB、CLOB、LONG、LONG RAW等)。
b、表中包含长度较大的字段,如varchar2(1000)以上的字段,但该SQL实际上并不需要取出该字段的值。
c、字段数量很多,但实际要用的字段很少,比如表有50个字段,而你实际只用5个,并且该sql目前没有被重用。
d、DBA要求优化调整的。
严格要求使用正确类型的变量,杜绝oracle做隐式类型转换的情况
1。推荐在sqlmap的变量中指定变量的数据类型,如:
select * from iw_user where iw_user_id = #userid:VARCHAR#2。其中,对于时间类型的字段,必须使用TO_DATE进行赋值(当前时间可直接用sysdate表示),不允许下列这些错误用法:
错误的写法(使用date类型的变量):
select * from iw_account_log where trans_account = #transaccount:varchar#
and trans_dt >= #dateBegin:date#
and trans_dt < #dateEnd:date# 错误的写法(使用包含sysdate的表达式):
select * from iw_account_log where trans_account = #transaccount:varchar#
and trans_dt >= trunc(sysdate - 1)
and trans_dt < sysdate + 1 错误的写法(将to_date函数和数字进行算术运算):
select * from iw_account_log where trans_account = #transaccount:varchar#
and trans_dt >= to_date(#dateBegin:varchar#, 'yyyy-mm-dd hh24:mi:ss')
and trans_dt < to_date(#dateBegin:varchar#, 'yyyy-mm-dd hh24:mi:ss') + 1 正确的写法:
select * from iw_account_log where trans_account = #transaccount:varchar#
and trans_dt >= to_date(#dateBegin:varchar#, 'yyyy-mm-dd hh24:mi:ss')
and trans_dt < to_date(#dateEnd:varchar#, 'yyyy-mm-dd hh24:mi:ss') /*或 trans_dt < sysdate */3。对于变量数据类型错误导致SQL严重性能问题的,按严重的编码错误Bug处理!
杜绝循环调用
例如:在迭代的过程中,使用同一SQL反复查询DB,如:
while (listObj.hasnext()) {
SELECT * FROM beyond_trade_process WHERE (trade_no = ?)
......
} 这样不仅效率不高,还造成交互过于频繁,严重情况会导致服务器LOAD增加
解决方式:
1。如果该查询是使用唯一键(如上例),参考后面的STR2VARLIST或STR2NUMLIST的用法
2。联系DBA协助分析解决方式
3。违反本条规范,属较严重Bug,如是前台应用应立即予以修复
绑定变量和替代变量
在Ibatis中:
绑定变量用 #变量名# 表示
替代变量用 $变量名$ 表示
注意几点:
1。通常,应使用绑定变量,尤其是具体取值变化范围较大的变量,如iw_user_id = #userid#。
2。取值范围很小(比如枚举字段),并且通常取值会比较固定,在DBA预先同意的情况下使用替代变量,或者干脆使用常量。
3。当一个绑定变量在实际使用中实际取值总是为某一固定常量时,应当直接使用常量而不是变量,关于这点,可在具体使用时咨询DBA
4。在order by子句中,通常使用替代变量而不是绑定变量。
5。IN子句,使用"iterate + 数组类型变量"的方式实现绑定变量,例如:
<isNotEmpty prepend="and" property="userIds">
<iterate property="userIds" open="t.creator in (" close=")" conjunction=",">
#userIds[]#
</iterate>
</isNotEmpty>将生成 t.creator in (:1, :2, :3, :4, :5 ...) 的语句
在字段上加函数的问题
1。通常,不允许在字段上添加函数或者表达式,如:
错误的写法:
select * from iw_account_log where to_char ( trans_dt, 'yyyy-mm-dd') = '2007-04-04';
select qty from product where p_id + 12 = 168; 正确的写法:
select * from iw_account_log
where trans_dt >= to_date ( '2007-04-04', 'yyyy-mm-dd') and trans_dt < to_date ( '2007-04-05', 'yyyy-mm-dd');
select qty from product where p_id = 168 - 12;2。如果是业务要求的除外,但需要在编写时咨询DBA
3。特别注意,当表连接时,用于连接的两个表的字段如果数据类型不一致,则必须在一边加上类型转换的函数,如
错误的写法(a.id是number类型,而b.operator_number是char类型):
select count(*) from adm_user a, adm_action_log b where a.id = b.operator_number and a.username = '小钗'; 正确的写法:
select count(*) from adm_user a, adm_action_log b where to_char(a.id) = b.operator_number and a.username = '小钗';
select count(*) from adm_user a, adm_action_log b where a.id = to_number(b.operator_number) and a.username = '小钗'; 上面两种写法哪个正确?遇到这种情况时必须咨询DBA!
表连接
1。不使用ANSI连接,如inner join、left join、right join、full outer join,而使用(+)来表示外连接
错误的写法:
select a.*, b.goods_title from iw_account_log a left join beyond_trade_base b on a.TRANS_OUT_ORDER_NO = b.trade_no
where a.trans_code = '6003' and a.trans_account = #transacnt:varchar# and a.trans_dt > to_date(...) 正确的写法:
select a.*, b.goods_title from iw_account_log a, beyond_trade_base b
where a.TRANS_OUT_ORDER_NO = b.trade_no(+) and a.trans_code = '6003'
and a.trans_account = #transacnt:varchar# and a.trans_dt > to_date(...)SQLMAP的其它编写规范
1。对表的记录进行更新的时候,必须包含对gmt_modified字段的更新,并且不要使用dynamic标记,如:
错误的写法:
update BD_CONTACTINFO
<dynamic prepend="set">
......
<isNotNull prepend="," property="gmtModified">
GMT_MODIFIED = #gmtModified:TIMESTAMP#
</isNotNull>
</dynamic>
where ID = #id# 正确的写法(当然,这里更推荐直接更新为sysdate):
update BD_CONTACTINFO
set GMT_MODIFIED = #gmtModified:TIMESTAMP#
<dynamic>
......
</dynamic>
where ID = #id#2。不允许在where后添加1=1这样的无用条件,where可以写在prepend属性里,如:
错误的写法:
select count(*) from BD_CONTRACT t where 1=1
<dynamic>
......
</dynamic> 正确的写法:
select count(*) from BD_CONTRACT t
<dynamic prepend="where">
......
</dynamic>3。对大表进行查询时,在SQLMAP中需要加上对空条件的判断语句,具体可在遇到时咨询DBA,如:
性能上不保险的写法:
select count(*) from iw_user usr
<dynamic prepend="where">
<isNotEmpty prepend="AND" property="userId">
usr.iw_user_id = #userId:varchar#
</isNotEmpty>
<isNotEmpty prepend="AND" property="email">
usr.email = #email:varchar#
</isNotEmpty>
<isNotEmpty prepend="AND" property="certType">
usr.cert_type = #certType:varchar#
</isNotEmpty>
<isNotEmpty prepend="AND" property="certNo">
usr.cert_no = #certNo:varchar#
</isNotEmpty>
</dynamic> 性能上较保险的写法(防止那些能保证查询性能的关键条件都为空):
select count(*) from iw_user usr
<dynamic prepend="where">
<isNotEmpty prepend="AND" property="userId">
usr.iw_user_id = #userId:varchar#
</isNotEmpty>
<isNotEmpty prepend="AND" property="email">
usr.email = #email:varchar#
</isNotEmpty>
<isNotEmpty prepend="AND" property="certType">
usr.cert_type = #certType:varchar#
</isNotEmpty>
<isNotEmpty prepend="AND" property="certNo">
usr.cert_no = #certNo:varchar#
</isNotEmpty>
<isEmpty property="userId">
<isEmpty property="email">
<isEmpty property="certNo">
query not allowed
</isEmpty>
</isEmpty>
</isEmpty>
</dynamic> 另外,对查询表单的查询控制建议使用web层进行控制而不是客户端脚本(JAVASCRIPT/VBSCRIPT)
聚合函数常见问题
1。不要使用count(1)代替count(*)
2。count(column_name)计算该列不为NULL的记录条数
3。count(distinct column_name)计算该列不为NULL的不重复值数量
4。count()函数不会返回NULL,但sum()函数可能返回NULL,可以使用nvl(sum(qty),0)来避免返回NULL
NULL的使用
1。理解NULL的含义,是"不确定",而不是"空"
2。查询时,使用is null或者is not null
3。更新时,使用等于号,如:update tablename set column_name = null
STR2NUMLIST、STR2VARLIST函数的使用:
1。适用情况:使用唯一值(或者接近唯一值)批量取数据时,能够大大减少和数据库的交互次数
2。编写规范:a表必须放在from list的第一位,并且必须在select后加上下面的hint
注意一:参数是由各个交易号拼成的字符串,以逗号间隔,不要有空格
注意二:函数的参数是一个字符串,长度不能超过4000个字节
注意三:函数生成的表只有一个字段,名字是column_value
注意四:生成表的column_value字段是varchar2类型,如果希望是number类型,请使用str2numlist函数,并将vartabletype替换为numtabletype
错误的写法(缺少hint):
select a.column_value, b.goods_title
from TABLE(CAST(str2varlist(:1) as vartabletype)) a, beyond_trade_base b
where a.column_value = b.trade_no; 错误的写法(函数生成的表必须放在from list的第一位):
select /*+ ordered use_nl(a,b) */ a.column_value, b.goods_title
from beyond_trade_base b, TABLE(CAST(str2varlist(:1) as vartabletype)) a
where a.column_value = b.trade_no; 正确的写法:
select /*+ ordered use_nl(a,b) */ a.column_value, b.goods_title
from TABLE(CAST(str2varlist(:1) as vartabletype)) a, beyond_trade_base b
where a.column_value = b.trade_no; 如果要求返回的结果记录条数和参数中交易号的个数一致,可使用外连接:
select /*+ ordered use_nl(a,b) */ a.column_value, b.goods_title
from TABLE(CAST(str2varlist(:1) as vartabletype)) a, beyond_trade_base b
where a.column_value = b.trade_no (+); 如果参数内的值不唯一,可能返回多行,而并不需要返回多行,可考虑使用聚合函数:
select /*+ ordered use_nl(a,b) */
a.column_value, min(b.goods_title) goods_title
from TABLE(CAST(str2varlist(:1) as vartabletype)) a, beyond_trade_base b
where a.column_value = b.out_trade_no (+)
group by a.column_value; 使用该函数与使用IN的区别:
1。IN返回的结果是无序的,而该函数返回的结果是以参数中各值的顺序为顺序的
2。IN返回的结果是不重复的,而该函数返回的结果可重复,取决于输入的参数
分页查询的使用
1。分页通常是先执行COUNT语句然后执行分页语句,当COUNT返回值为0的时候,应当避免执行后面的分页语句
2。有时,只须执行分页语句而无须执行COUNT语句,就不要执行COUNT语句,例如,用户下载excel格式的账户明细
3。有时,在分页前除了要统计COUNT还需要统计SUM,这些WHERE子句一致的统计应该在一条SQL中查出,而不是分多次统计
4。包含排序逻辑的分页查询写法,必须是三层select嵌套:
错误的写法:
SELECT t1.*
FROM (SELECT t.*, ROWNUM rnum
FROM beyond_trade_base t
WHERE seller_account = :1
AND gmt_create >= TO_DATE (:2, 'yyyy-mm-dd')
AND gmt_create < TO_DATE (:3, 'yyyy-mm-dd')
ORDER BY gmt_create DESC) t1
WHERE rnum >= :4 AND rnum < :5 正确的写法:
SELECT t2.*
FROM (SELECT t1.*, ROWNUM rnum
FROM (SELECT t.*
FROM beyond_trade_base t
WHERE seller_account = :1
AND gmt_create >= TO_DATE (:2, 'yyyy-mm-dd')
AND gmt_create < TO_DATE (:3, 'yyyy-mm-dd')
ORDER BY gmt_create DESC) t1
WHERE ROWNUM <= :4) t2
WHERE rnum >= :55。不包含排序逻辑的分页查询写法,则是两层select嵌套,但对rownum的范围指定仍然必须在不同的查询层次指定:
错误的写法:
SELECT t1.*
FROM (SELECT t.*, ROWNUM rnum
FROM beyond_trade_base t
WHERE seller_account = :1
AND gmt_create >= TO_DATE (:2, 'yyyy-mm-dd')
AND gmt_create < TO_DATE (:3, 'yyyy-mm-dd')) t1
WHERE rnum >= :4 AND rnum <= :5 正确的写法:
SELECT t1.*
FROM (SELECT t.*, ROWNUM rnum
FROM beyond_trade_base t
WHERE seller_account = :1
AND gmt_create >= TO_DATE (:2, 'yyyy-mm-dd')
AND gmt_create < TO_DATE (:3, 'yyyy-mm-dd')
AND ROWNUM <= :4) t1
WHERE rnum >= :56。注意下面两种写法的逻辑含义是不同的:
按交易创建时间排序(倒序),然后再取前10条:
SELECT t2.*
FROM (SELECT t1.*, ROWNUM rnum
FROM (SELECT t.*
FROM beyond_trade_base t
WHERE seller_account = :1
AND gmt_create >= TO_DATE (:2, 'yyyy-mm-dd')
AND gmt_create < TO_DATE (:3, 'yyyy-mm-dd')
ORDER BY gmt_create DESC) t1
WHERE ROWNUM <= 10) t2
WHERE rnum >= 1 随机取10条,然后在这10条中按照交易创建时间排序(倒序):
SELECT t1.*
FROM (SELECT t.*, ROWNUM rnum
FROM beyond_trade_base t
WHERE seller_account = :1
AND gmt_create >= TO_DATE (:2, 'yyyy-mm-dd')
AND gmt_create < TO_DATE (:3, 'yyyy-mm-dd')
AND ROWNUM <= 10
ORDER BY gmt_create DESC) t1
WHERE rnum >= 17。先连接后分页与先分页后连接
性能较差:
SELECT t2.*
FROM (SELECT t1.*, ROWNUM rnum
FROM (SELECT a.*, b.receive_fee
FROM beyond_trade_base a, beyond_trade_process b
WHERE a.trade_no = b.trade_no(+)
AND a.seller_account = :1
AND a.gmt_create >= TO_DATE (:2, 'yyyy-mm-dd')
AND a.gmt_create < TO_DATE (:3, 'yyyy-mm-dd')
ORDER BY a.gmt_create DESC) t1
WHERE ROWNUM <= :4) t2
WHERE rnum >= :5 性能较好:
SELECT /*+ ordered use_nl(a,b) */
a.*, b.receive_fee
FROM (SELECT t2.*
FROM (SELECT t1.*, ROWNUM rnum
FROM (SELECT t.*
FROM beyond_trade_base t
WHERE seller_account = :1
AND gmt_create >= TO_DATE (:2, 'yyyy-mm-dd')
AND gmt_create < TO_DATE (:3, 'yyyy-mm-dd')
ORDER BY gmt_create DESC) t1
WHERE ROWNUM <= :4) t2
WHERE rnum >= :5) a,
beyond_trade_process b
WHERE a.trade_no = b.trade_no(+) 后面这种写法的适用情况:
a、where子句中的查询条件都是针对beyond_trade_base表的(否则得到的结果将不相同)
b、关联beyond_trade_process表时,用的是该表的主键或者唯一键字段(否则将改变结果集的条数)
Add Comment
发表评论
-
oracle 查看执行计划的方式
2016-12-20 18:16 388一、通过PL/SQL Dev工具 1、直接File- ... -
pl/sql 乱码解决
2016-08-25 16:25 332select userenv('language') from ... -
使用MySQL Proxy解决MySQL主从同步延迟
2016-08-15 16:26 541使用MySQL Proxy解决MySQL主从同步延迟 ... -
分库分表
2016-07-03 12:30 539第1章 引言 随着互联网 ... -
select for update
2016-03-30 17:45 632xjr80C7HA3olbVr3y6H3t5--AcosrkB ... -
数据库超时
2016-03-07 10:37 480 -
oracle merge into
2016-03-04 16:16 426/*Merge into 详细介绍 MERGE语句是Oracl ... -
oracle 分区表
2016-03-02 14:59 432(1) 表空间及分区表的 ... -
oracle 组合索引使用
2016-01-14 20:33 895在Oracle中可以创建组合索引,即同时包含两个或两个以上列的 ... -
oracle 索引
2016-01-14 20:24 653一、 ROWID的概念 存储了row在数据文件中的具体位置: ... -
oracle 查看sql执行计划
2016-01-14 14:06 393如果要分析某条SQL的性能问题,通常我们要先看SQL的执行计划 ... -
oracle sql调优 执行计划固化 排序等 SQL Plan Baseline
2015-11-14 16:13 14271.对查询进行优化,应 ... -
oracle 字段类型 收录
2015-11-02 19:52 775字段类型 中文说明 限制条件 其它说明 CHAR 固定长度字符 ... -
oracle trunc 函数
2015-08-25 17:57 571Oracle trunc()函数的用法 --Oracle t ... -
oracle 分析函数
2015-08-03 12:49 612oracle分析函数--SQL*PLUS环 ... -
跨数据库事务研究
2015-05-12 11:16 873两种方案: 1、分布式 ... -
Oracle的悲观锁和乐观锁
2015-04-22 13:27 457为了得到最大的性能, ... -
MySQL数据库MyISAM和InnoDB存储引擎的比较
2015-04-21 13:49 493MySQL有多种存储引擎,MyISAM和InnoDB是其中常用 ... -
nosql学习
2015-04-20 09:56 5621、NoSQL数据库概念 NoSQL ... -
sql distinctt group by 分析
2015-04-14 15:28 567在表中,可能会包含重复值。这并不成问题,不过,有时您也许希望仅 ...
相关推荐
DB2还允许一些独特的SQL写法,例如,`AnyOneTable`表示任意一个存在的表,这在某些特定情况下非常有用。但需要注意,这种用法并不推荐在生产环境中频繁使用,因为可能会带来不必要的性能影响。 变量的声明和赋值在...
### SQL写法——数据修改:条件 INSERT ALL 与 INSERT FIRST 在数据库操作中,SQL(Structured Query Language)作为处理关系型数据库的标准语言,其功能强大且应用广泛。本文将详细介绍如何利用Oracle数据库中的...
sql学习 索引去哪儿_请注意这写法是案例非笑话.sql
### 实现 Oracle 连接 SQL Server 的方法...需要注意的是,在实际操作过程中可能会遇到各种各样的问题,比如权限问题、网络配置等,因此建议在配置过程中仔细检查每一个步骤,并参考官方文档或寻求专业技术人员的帮助。
### SQL Server 2008连接字符串写法详解 #### 一、概述 在与SQL Server 2008进行交互时,正确设置连接字符串至关重要。连接字符串定义了应用程序如何与数据库建立通信,并包含了诸如服务器地址、数据库名称、身份...
以上内容主要介绍了 SQL Server 中存储过程中的一些基本语法和操作方法,包括变量定义及赋值、表和临时表的操作、循环以及条件语句等,这些知识点对于理解和使用 SQL Server 存储过程至关重要。
SqlServer2005和SqlServer2000连接驱动,我已经验证过没有问题, 2005 driverName = "com.microsoft.sqlserver.jdbc.SQLServerDriver" URL = "jdbc:sqlserver://localhost:1433;...一定要注意写法的差别。
这里需要注意的是,在HQL中,类名首字母通常大写,以区别于普通的Java变量或SQL字段名。 #### HQL与NSQL的区别 1. **语法风格**:HQL更加面向对象,语法结构与Java类及其属性紧密相关;而NSQL则遵循标准SQL语法。 ...
5. 索引的使用,避免对索引列进行计算,注意比较值与索引列数据类型的一致性。 6. 尽量避免相同语句由于书写格式的不同,而导致多次语法分析,尽量使用 Bind 变量。 7. 尽量使用共享的 SQL 语句。 8. 查询的 Where ...
保证数据库性能的sql语句写法,注意事项,使得我们在书写时避免使数据库低效率的执行命令
第三,注意SQL的写法。使用JOIN操作时,确保正确指定JOIN条件,并优先选择小表作为驱动表,以减少数据处理量。此外,避免在SELECT语句中使用*,而是明确指定需要的字段,这样可以减少数据传输量,提高执行效率。 第...
在配置Navicat Premium 的界面时,需要注意端口号的写法,正确的写法是将端口号写在 IP 地址后面,使用英文状态下的逗号分隔,例如:192.168.1.1,1433。 在配置了 Navicat Premium 的界面后,需要配置高级选项,...
以下是具体的SQL语法转换的一些关键点: 1. 数据库对象命名:在SQL Server中,表和列名通常用方括号包围(如 `[TableName]` 和 `[ColumnName]`),而在Oracle中,它们用双引号包围(如 `"TableName"` 和 `"Column...
需要注意的是,实际应用中还需要考虑数据库的具体版本和表结构,以及索引的设置,这些因素都可能影响分页查询的效率。 总的来说,选择哪种分页方法取决于数据库版本、数据量、索引策略以及对性能的要求。在SQL ...
总之,SQL SERVER中的时间条件式查询需要注意日期和时间的精确匹配,以及正确处理当前日期和时间范围。使用适当的函数和比较运算符,可以确保查询的准确性和效率。在实际应用中,还需要根据具体需求和数据结构,调整...
MySQL全文搜索是数据库管理系统中的一种高级搜索功能,它允许用户...但要注意,为了优化性能和搜索结果,可能需要进行一些额外的配置和优化,例如调整`FULLTEXT`索引的最小词长、停用词列表,以及使用合适的分词算法。
使用注意事项 - 触发器可能导致性能下降,因为它们增加了数据库操作的复杂性。 - 触发器中的事务处理必须谨慎,否则可能导致死锁或其他并发问题。 - 由于触发器是透明的,可能隐藏了业务逻辑,使得调试和维护变得...
### SQL执行超长语句详解 在数据库管理与开发过程中,编写SQL语句是必不可少的一环。...通过采取上述提到的一些策略和技术手段,可以有效缓解因超长SQL语句带来的问题与挑战,最终实现更高效的数据处理与分析能力。
MySql 与 SqlServer 的一些常用用法的差别 MySql 和 SqlServer 是两种常用的关系型数据库管理系统,每种数据库管理系统都有其自己的特点和使用方法。作为一名开发者,了解它们之间的差别是非常重要的。本文将详细...
ANSI(美国国家标准局)注意到SQL的重要性,开始制定SQL的标准化,分为多个阶段,其中SQL 86和SQL 92是两个重要的里程碑。SQL 86标准的写法是早期数据库系统,如Oracle和DB2所采用的,而SQL 92标准则引入了更清晰、...