我有SQL查询。当我声明变量并运行查询时,它会生成39行,但是当我使用文字值而不是变量并运行查询时,它会产生三行。怎么会这样?
以下是带变量的查询和结果
declare
fromnode number :=1;
CURRENTESTIMATE number :=0;
begin
for ts in (SELECT e.fromnode,e.tonode,e.weight
FROM TS_DIJNODEESTIMATE N
INNER JOIN TS_EDGE E ON N.ID=E.TONODE
WHERE N.DONE=0 AND E.FROMNODE=fromnode AND (CURRENTESTIMATE+E.WEIGHT)<N.ESTIMATE)
loop
dbms_output.put_line(ts.fromnode || ',' || ts.tonode || ',' || ts.weight);
end loop;
end;
结果是
1,2,1306
1,5,2161
1,6,2661
2,3,919
2,4,629
3,2,919
3,4,435
3,5,1225
3,7,1983
4,2,629
4,3,435
5,3,1225
5,6,1483
5,7,1258
6,5,1483
6,7,1532
6,8,661
7,3,1983
7,5,1258
7,6,1532
7,9,2113
7,12,2161
8,6,661
8,9,1145
8,10,1613
9,7,2113
9,8,1145
9,10,725
9,11,383
9,12,1709
10,8,1613
10,9,725
10,11,338
11,9,383
11,10,338
11,12,2145
12,7,2161
12,9,1709
12,11,2145
使用文字而不是变量:
declare
fromnode number :=1;
CURRENTESTIMATE number :=0;
begin
for ts in (SELECT e.fromnode,e.tonode,e.weight
FROM TS_DIJNODEESTIMATE N
INNER JOIN TS_EDGE E ON N.ID=E.TONODE
WHERE N.DONE=0 AND E.FROMNODE=1 AND (0+E.WEIGHT)<N.ESTIMATE)
loop
dbms_output.put_line(ts.fromnode || ',' || ts.tonode || ',' || ts.weight);
end loop;
end;
结果是
1,2,1306
1,5,2161
1,6,2661
期望的结果是第二个结果。
答案 0 :(得分:2)
您应该将变量fromnode
的名称更改为my_fromnode
或类似名称。
在E.FROMNODE=fromnode
实际上将列与本身进行比较并返回true
的内部查询中。
答案 1 :(得分:1)
问题在于命名:您为变量提供了与表列相同的名称:
E.FROMNODE=fromnode
Oracle的范围规则使用最近的匹配来解析名称,从最里面开始,向外和向上工作。查询中最近的命名空间是表,因此它首先尝试将fromnode
解析为表列。名称适合,因此编译器不再进一步查看。
有效地,您的WHERE子句过滤器在逻辑上与1 = 1
相同,这就是为什么您获得更多行的原因。这不应该是一个惊喜,因为它是记录的行为。 PL / SQL文档涵盖了变量标识符名称here的范围以及与变量名here的交互。关键点是Alex Poole的亮点:
&#34;如果SQL语句引用属于列和局部变量或形式参数的名称,则列名优先。&#34;
您认为通过将fromnode
置于小写但PL / SQL不区分大小写的情况下避免了这种情况。正确的方法是使用命名约定,例如标识带有前缀的变量:V表示变量 - v_fromnode
- 或L表示本地 - l_fromnode
- 都是常见约定。