|
我在继承的应用程序中遇到了如下查询:/ n3 ~8 f; y* Q+ i' P5 N
Select *8 c9 _4 g7 X# U+ v6 \
From foo
, p; W! J# y: a; A1 Wwhere
b" \) W8 n7 @ ^8 O 1 1
; Z, Z4 m: P3 q' U% f正如我解析的那样,它应该不返回任何内容(1 ) N4 k+ n* d4 U- J7 K$ {
1应评估为false,正确)。但是(至少在我的Oracle机器上),它返回了中所有内容的完整列表foo。当我在MSAccess /1 ]* R! {1 {) {, p8 `
Jet和MSSQL中尝试相同的操作时,我得到了预期的行为。为什么对Oracle有所不同(为什么原始开发人员要这样做)?) C, `# U n; H+ Q3 C
注意:我对使用“ where 1 = 1”的+ s和-s有一些迷信,它引起了全表扫描。但是我不认为这是原始开发人员的意图。
) m0 U- k' X4 s/ F ?" N. b( s" H5 @小更新:+ r W+ @+ ?5 ?5 C' P7 b
在这种情况下foo是一个视图。当我在实际的表上尝试相同的操作时,我得到了期望的结果(无行)。
& e! E; ^; P3 D8 F, U$ X d更新2:9 ^: J) [4 R2 L
我一直在兔子洞后面跟踪代码,并确定他正在做的所有事情都是试图获取字段/列的名称。我仍然不知道为什么它要返回完整的记录集。但仅适用于视图。
6 N" y9 l- u' s8 J/ O4 x) D从字面上看,他是在字符串中构建查询,然后将其传递给另一个函数以不更改地执行。- n9 `; b1 |5 `1 L/ r' ^& E
'VB6
6 a) `( m7 A$ ^strSQL = "SELECT * FROM " & strTableName & " WHERE 1 1" U2 |6 F7 _# @* ^3 H
在这种情况下,strTableName包含视图的名称。; r' E- \& T; R0 B
更新3:
' q: I: E( @% k4 c$ w2 B作为参考,这是我遇到的问题之一(我更改了字段/表/模式名称)
Y' s6 c' T qCREATE OR REPLACE FORCE VIEW scott.foo (field1,8 ]* Q6 u/ ~7 l+ }/ j ]
field2,7 V: \7 R7 z# _1 g7 L5 Q$ T& C
field4,
' b& [% p+ k! m. Q) ]; A" f/ v field5,# r. u }! a9 p
field12,
0 g( j. Z* k" M6 W/ S4 g! K field8,
3 [, L7 X7 Q! q field6,
1 p, \5 [( Y2 M |6 f+ F field7," l. F% V" c; A/ i
field16,
* `4 C5 ^: b, Z field11,( Q0 c% [. y2 n! ^7 O2 o
field13,4 ]& a. `1 X+ s, C$ E
field14,
5 ]* H5 E! o9 N4 a* K field15,3 z! Y2 g5 ^6 X) H" y7 L
field17; `2 \- [2 f( n3 A0 Z
)4 Z0 S2 `! X) M
AS U! O( J( m$ j7 |" u7 G
SELECT bar.field1,
5 r$ u9 i" c, W bar.field2,/ c. |* O9 n3 h6 {3 u
DECODE
" @) S. W; T e% h) D! Q# {4 `! M# a (yadda.field9, NULL, 'N',
% V% k. Y- q# O+ m DECODE (yadda.field3, NULL, 'Y', 'N')
* |2 }) E3 G& N% |8 @& K ) AS field4,
8 @' I5 L7 h2 }0 X bar.field5,
& B* `, ` s2 m snafu.field6," J9 W) h {4 N9 y8 w V
DECODE% }4 o# m. x, @1 s8 P
(snafu.field6,6 m# i# J5 b( |6 s* ?
NULL,0 E \4 O0 H5 l
bar.field8,# M" A6 U3 P6 m3 g7 W0 N
bar.field84 O. L2 r% p; L' V
- snafu.field6
- }% w% ~. @, P3 v9 w, T0 j1 N. R ) AS field7," F0 P* [1 G- s+ M
DECODE' U; u2 z6 z& C1 N
(yadda.field10,/ F. _% w& r6 E1 y( ?
NULL,
4 e* X5 n5 n# m) e W1 W bar.field12,7 X1 X0 f# j7 b Y! A2 c" M7 Y. W
yadda.field10
# s, m3 d* \* K$ p ) AS field11, t5 X8 R3 W8 o I+ `) p' r3 I
DECODE/ M- W4 N* Q+ E
(SIGN ( yadda.field10 - bar.field12),) _; j2 P B" u8 h0 A/ P4 V
NULL, 'N', 1, 'N', 0, 'N', -1, 'Y'4 ]8 e9 E# X2 t7 z2 b! Y& D
) AS field13,
! b3 }8 K/ M* N5 I i; h bar.field14,
5 E3 u B) g: B. S* W# ^ ADD_MONTHS* D2 y4 r0 S* G
(DECODE (yadda.field10, NULL, bar.field12, yadda.field10
[8 v Q- e+ G" h# e2 J9 c# Q5 E ),- R) @! n" U8 V+ R
bar.field14 * 120 v2 ~9 ]" u5 z
) AS field15,
8 g" R7 R. m% I FROM clbuttic,
8 t3 f0 `2 S, v' x bar,& p; a _1 Q" Z9 G( B% n
yadda,/ t6 ` o0 t2 Q9 j% E; `' s/ H1 ]; }
snafu
V8 C0 A u, t1 [& ~ WHERE clbuttic.asset_type = bar.asset_type# _! m3 w% [; K: N( {
AND bar.field16 = yadda.field9(+)% S _8 o, ^1 L+ `+ i3 A; T
AND bar.field1 = snafu.field1(+)
, v. T! ~% S7 z3 e: k9 A AND (bar.field17 IS NULL)- B' ]7 G2 J# q" H* {
;
$ S" e( |' e8 Q9 [- F追加Order By
" \0 g/ M1 }0 {/ N1(或在foo上的select中的某些列名称)似乎使Oracle相信我可以将空集还给我。这是一个长期解决方案,而不是短期解决方案(更改代码并重新部署是主要的PITA)。我希望在数据库方面有一个鲜为人知的设置,或者在视图中出了一些问题,这是造成这种奇怪行为的原因。
* z( C: |. _1 P1 b* g* T. q
2 ^, k. s# y: n' K) h" @解决方案:
5 S: v$ e; ~! Y: y; L7 b
% r* g: @( v# h6 ^1 p5 p) R! g9 d s; \
+ T) h) z2 y* i: G" @& C6 N) S
在Oracle优化器的视图合并代码中,它肯定看起来像是个错误。我敢打赌,您只能通过包含外部联接的视图来获得此效果。您ORDER
# w# J1 c) ?$ i' }9 T7 K! ?. TBY可以解决它,因为它实际上会强制NO_MERGE视图。) N0 d& {& s2 y0 Y& Z' Y# m5 X9 R
但是,我不会在视图中放置一个ORDER) y" t1 }; P# r, _/ k+ z! m
BY或一个NO_MERGE提示,因为(取决于您的数据量)它可能会降低使用该视图的其他查询的性能。您应该在外部查询中添加一个no_merge提示: w& ]& |5 @; A; n* [ h4 F
Select /*+ NO_MERGE(foo) */ *$ V* o* q0 f7 q' ~9 ?9 s6 x2 B
From foo! r3 j, z+ p- _8 x5 f; y
where
0 g& \, M7 l; f0 F# c" x$ ] 1 1+ m3 g& J: I, G6 _( B; P
您还应该在Oracle支持下提高SR,因为这绝对是一个错误。该查询永远不应该返回任何行,无论您从中选择什么内容,或者内部有多复杂。永远不能。
; r2 m" k0 x, O- ~( X0 f我无法复制它,因此它可能已在我使用的版本中修复。您正在使用的数据库版本是什么? |
|