PL/SQL的一些问题
2008-01-16 23:35
190 查看
1. Rownum
PL/SQL User's Guid and Reference中的描述:
ROWNUM returns a number indicating the order in which a row was selected from a table. The first row selected has a ROWNUM of 1, the second row has a ROWNUM of 2, and so on. If a SELECT statement includes an ORDER BY clause, ROWNUMs are assigned to the retrieved rows before the sort is done; use a subselect to get the first n sorted rows. The value of ROWNUM increases only when a row is retrieved, so the only meaningful uses of ROWNUM in a WHERE clause are:
... WHERE ROWNUM < constant;
... WHERE ROWNUM <= constant;
就是说Rownum是在读取记录时赋值,是在Order By操作之前,所以如果要排序,然后取一定位置的记录集,必须使用子查询。WHERE ROWNUM < constant1 AND ROWNUM>constant2;,如果constant2大于1,这个语句永远返回不了任何记录,必须使用子查询解决。
2. 关于排序的几个问题
DISTINCT
Select Distinct A From(
Select * From ATEST Order By B
)t2
上面语句子查询里面的Order By是没有作用的,因为外层查询的Distinct操作将重新排序。
HASH JOIN
跟Distinct一样,如果在子查询里面使用了Order By,外层查询有Hash Join出现,则子查询里面的Order By也无效,因为Hash算法会导致返回的结果集重新排序(Distinct操作也应当是使用Hash算法实现的)。Hash算法结果的排序应当依赖于从probe input读取记录的顺序,但算法本身的实现方式也可能造成影响,另外Hash的两个输入可能经过优化器的动态选择,所以结果的排序具有不确定性。
例如下面的写法:
Select ...
From(
Select t1.*,Rownum As RowIndex
From (Select * From A Where ... Order By ...)t1
Where t1.RowIndex>:startIndex And t1.RowIndex<=:endIndex
)t2
Left Join B On ...
出发点是好的:先从A中按照条件和排序规则取出指定页数的记录集,然后再和B关联,降低关联算法的数据运算量。大部分情况下结果会是正确的,因为Oracle将优先采用Nested Loop方式进行关联,这种算法不会影响排序(Merge也不会影响排序),但如果子查询返回的记录集太大、B表上没有用于关联的索引、或索引没有维护等,就可能采用Hash算法,这时返回结果的排序就不一定正确了。
上面的问题在需要分页的语句中容易发生的。SQL Server对子查询中使用Order By有限制,所以情况好一点,Oracle的PL/SQL没有这方面限制,所以开发的时候很容易被忽视,而发布之后被最终用户发现。
3. 关键字冲突问题
相比Oracle,SQL Server对关键字冲突的处理要宽松很多,Oracle则要求严格
例如Create Table A( Id Number(8), "Level" Number(2));可以创建表,但select id,"Level" from a则会报错"Level"标识符无效
ORM处理方法参考:
首先,表名、字段名不能与Oracle关键字冲突,ORM需要处理的,是避免对象名、属性名(考虑对象、属性与表名、字段名不同的情况)、参数名的冲突问题
NHibernate对查询中的表、字段、参数都重新命名,例如生成的SQL类似如下
select t_0.OrgCode as t_0_0,t_0.ItemNo as t_0_1
,t_1.ItemName as t_1_0,t_1.ItemUOM as t_1_1
from dbo.TblOrgItem t_0
inner join dbo.TblItem t_1 on t_0.ItemID=t_1.oid
where t_0.OrgCode=@p_0 and t_1.ItemName like @p_1
在NHibernate内部新的名称和原对象的对应关系是清晰的, t_1_0这个字段会设置到dob.TblItem对应对象的相应属性上
4. 语法细节差异
4.1 select a.* from TableA as a,这个语句SQL Server正常,而Oracle会报错,因为Oracle指定Table的别名不能使用AS关键字
PL/SQL User's Guid and Reference中的描述:
ROWNUM returns a number indicating the order in which a row was selected from a table. The first row selected has a ROWNUM of 1, the second row has a ROWNUM of 2, and so on. If a SELECT statement includes an ORDER BY clause, ROWNUMs are assigned to the retrieved rows before the sort is done; use a subselect to get the first n sorted rows. The value of ROWNUM increases only when a row is retrieved, so the only meaningful uses of ROWNUM in a WHERE clause are:
... WHERE ROWNUM < constant;
... WHERE ROWNUM <= constant;
就是说Rownum是在读取记录时赋值,是在Order By操作之前,所以如果要排序,然后取一定位置的记录集,必须使用子查询。WHERE ROWNUM < constant1 AND ROWNUM>constant2;,如果constant2大于1,这个语句永远返回不了任何记录,必须使用子查询解决。
2. 关于排序的几个问题
DISTINCT
Select Distinct A From(
Select * From ATEST Order By B
)t2
上面语句子查询里面的Order By是没有作用的,因为外层查询的Distinct操作将重新排序。
HASH JOIN
跟Distinct一样,如果在子查询里面使用了Order By,外层查询有Hash Join出现,则子查询里面的Order By也无效,因为Hash算法会导致返回的结果集重新排序(Distinct操作也应当是使用Hash算法实现的)。Hash算法结果的排序应当依赖于从probe input读取记录的顺序,但算法本身的实现方式也可能造成影响,另外Hash的两个输入可能经过优化器的动态选择,所以结果的排序具有不确定性。
例如下面的写法:
Select ...
From(
Select t1.*,Rownum As RowIndex
From (Select * From A Where ... Order By ...)t1
Where t1.RowIndex>:startIndex And t1.RowIndex<=:endIndex
)t2
Left Join B On ...
出发点是好的:先从A中按照条件和排序规则取出指定页数的记录集,然后再和B关联,降低关联算法的数据运算量。大部分情况下结果会是正确的,因为Oracle将优先采用Nested Loop方式进行关联,这种算法不会影响排序(Merge也不会影响排序),但如果子查询返回的记录集太大、B表上没有用于关联的索引、或索引没有维护等,就可能采用Hash算法,这时返回结果的排序就不一定正确了。
上面的问题在需要分页的语句中容易发生的。SQL Server对子查询中使用Order By有限制,所以情况好一点,Oracle的PL/SQL没有这方面限制,所以开发的时候很容易被忽视,而发布之后被最终用户发现。
3. 关键字冲突问题
相比Oracle,SQL Server对关键字冲突的处理要宽松很多,Oracle则要求严格
例如Create Table A( Id Number(8), "Level" Number(2));可以创建表,但select id,"Level" from a则会报错"Level"标识符无效
ORM处理方法参考:
首先,表名、字段名不能与Oracle关键字冲突,ORM需要处理的,是避免对象名、属性名(考虑对象、属性与表名、字段名不同的情况)、参数名的冲突问题
NHibernate对查询中的表、字段、参数都重新命名,例如生成的SQL类似如下
select t_0.OrgCode as t_0_0,t_0.ItemNo as t_0_1
,t_1.ItemName as t_1_0,t_1.ItemUOM as t_1_1
from dbo.TblOrgItem t_0
inner join dbo.TblItem t_1 on t_0.ItemID=t_1.oid
where t_0.OrgCode=@p_0 and t_1.ItemName like @p_1
在NHibernate内部新的名称和原对象的对应关系是清晰的, t_1_0这个字段会设置到dob.TblItem对应对象的相应属性上
4. 语法细节差异
4.1 select a.* from TableA as a,这个语句SQL Server正常,而Oracle会报错,因为Oracle指定Table的别名不能使用AS关键字
相关文章推荐
- 写PL/SQL程序时碰到的一些问题
- PL/SQL Developer 使用oracle_client 连接虚拟机oracle的一些问题
- PL/SQL 安装出现的一些问题
- pl/sql程序编写中遇到的一些问题及解决办法
- PL/SQL 面试的一些问题(一)
- 写PL/SQL程序时碰到的一些问题
- PL/SQL中复制中文再粘贴出现乱码问题的解决
- pl/sql查询数据出现中文乱码问题的解决办法
- PL/SQL的逻辑值问题
- Oracle 11gR2 及PL/SQL Developer 安装使用遇到的问题
- PL/SQL中复制中文再粘贴出现乱码问题的解决【转】
- pl/sql developer 执行输出时中文乱码问题
- 新PL/SQL程序包问题探讨
- 本机PL/SQL连接另一台主机ORACLE过程及遇到的各种问题
- pl/sql中文乱码问题
- PL SQL developer 乱码问题
- PL/SQL远程登录Oracle时遇到问题(一)
- PL/SQL 基础---一些高阶用法
- pl/sql显示乱码问题
- 【20180523】ProxySQL+MHA的配置以及一些问题描述